| name | securing-aws-lambda-execution-roles |
| description | 通过实施最小权限(Least Privilege)IAM 策略、应用权限边界(Permission Boundary)、限制基于资源的策略、使用 IAM Access Analyzer 验证权限,以及通过 SCP 强制执行角色规范,保护 AWS Lambda 执行角色(Execution Role)。
|
| domain | cybersecurity |
| subdomain | cloud-security |
| tags | ["cloud-security","aws","lambda","iam","least-privilege","execution-roles"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
保护 AWS Lambda 执行角色
适用场景
- 部署新 Lambda 函数并定义其 IAM 执行角色时
- 修复安全审计中发现的过度宽松 Lambda 角色时
- 为无服务器架构实施最小权限访问模式时
- 为跨团队的 Lambda 函数构建可复用的 IAM 模板时
- Security Hub 或 Prowler 报告 Lambda 函数具有过多权限时
不适用于:保护 Lambda 函数调用安全(使用基于资源的策略和 API Gateway 授权器)、Lambda 代码安全(使用 SAST 工具),或 Lambda 网络安全(使用 VPC 配置和安全组)。
前置条件
- 具有策略创建、角色修改和 Access Analyzer 操作权限的 IAM 权限
- 已在账户中启用 AWS IAM Access Analyzer
- 已为 Lambda 启用 CloudTrail 数据事件,以捕获实际 API 使用情况
- 需要审计和范围化权限的现有 Lambda 函数
- 了解每个函数所需的 AWS 服务交互
工作流程
步骤 1:审计当前 Lambda 执行角色权限
枚举所有 Lambda 函数及其关联的 IAM 角色,识别权限过度的函数。
aws lambda list-functions \
--query 'Functions[*].[FunctionName,Role]' --output table
for func in $(aws lambda list-functions --query 'Functions[*].FunctionName' --output text); do
role_arn=$(aws lambda get-function-configuration --function-name "$func" --query 'Role' --output text)
role_name=$(echo "$role_arn" | awk -F'/' '{print $NF}')
echo "=== $func -> $role_name ==="
aws iam list-attached-role-policies --role-name "$role_name" \
--query 'AttachedPolicies[*].[PolicyName,PolicyArn]' --output table
for policy in $(aws iam list-role-policies --role-name "$role_name" --query 'PolicyNames' --output text); do
echo " 内联策略: $policy"
aws iam get-role-policy --role-name "$role_name" --policy-name "$policy" \
--query 'PolicyDocument' --output json
done
done
步骤 2:使用 CloudTrail 分析实际 API 使用情况
使用 CloudTrail 和 IAM Access Analyzer 确定函数实际使用的 API 操作。
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=Username,AttributeValue=LAMBDA_ROLE_NAME \
--start-time 2026-01-23T00:00:00Z \
--end-time 2026-02-23T00:00:00Z \
--query 'Events[*].[EventTime,EventName,EventSource]' \
--output table | sort -k2 | uniq -f1
aws accessanalyzer start-policy-generation \
--policy-generation-details '{
"principalArn": "arn:aws:iam::ACCOUNT:role/lambda-execution-role",
"cloudTrailDetails": {
"trailArn": "arn:aws:cloudtrail:us-east-1:ACCOUNT:trail/management-trail",
"startTime": "2026-01-23T00:00:00Z",
"endTime": "2026-02-23T00:00:00Z"
}
}'
aws accessanalyzer get-generated-policy \
--job-id JOB_ID \
--query 'generatedPolicyResult.generatedPolicies[*].policy'
步骤 3:创建最小权限执行策略
构建范围化的 IAM 策略,仅授予每个函数所需的特定操作和资源。
cat > lambda-scoped-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadInputBucket",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::input-data-bucket",
"arn:aws:s3:::input-data-bucket/*"
]
},
{
"Sid": "WriteDynamoDB",
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:BatchWriteItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:ACCOUNT:table/results-table"
},
{
"Sid": "CloudWatchLogs",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-1:ACCOUNT:log-group:/aws/lambda/my-function:*"
}
]
}
EOF
aws iam create-policy \
--policy-name lambda-my-function-policy \
--policy-document file://lambda-scoped-policy.json
cat > lambda-trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [{
: ,
: {: },
: ,
: {
: {
:
}
}
}]
}
EOF
aws iam create-role \
--role-name lambda-my-function-role \
--assume-role-policy-document file://lambda-trust-policy.json
aws iam attach-role-policy \
--role-name lambda-my-function-role \
--policy-arn arn:aws:iam::ACCOUNT:policy/lambda-my-function-policy
步骤 4:应用权限边界
实施权限边界,为 Lambda 执行角色设置最大权限上限。
cat > lambda-permission-boundary.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowedServices",
"Effect": "Allow",
"Action": [
"s3:GetObject", "s3:PutObject", "s3:ListBucket",
"dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:UpdateItem",
"sqs:SendMessage", "sqs:ReceiveMessage", "sqs:DeleteMessage",
"sns:Publish",
"secretsmanager:GetSecretValue",
"kms:Decrypt", "kms:GenerateDataKey",
"logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents",
"xray:PutTraceSegments", "xray:PutTelemetryRecords"
],
"Resource": "*"
},
{
"Sid": "DenyPrivilegeEscalation",
"Effect": "Deny",
"Action": [
"iam:CreateUser", "iam:CreateRole", "iam:CreatePolicy",
"iam:AttachRolePolicy", "iam:AttachUserPolicy",
"iam:PutRolePolicy", "iam:PutUserPolicy",
"iam:CreateAccessKey", "iam:PassRole",
, ,
],
:
}
]
}
EOF
aws iam create-policy \
--policy-name lambda-permission-boundary \
--policy-document file://lambda-permission-boundary.json
aws iam put-role-permissions-boundary \
--role-name lambda-my-function-role \
--permissions-boundary arn:aws:iam::ACCOUNT:policy/lambda-permission-boundary
步骤 5:使用 IAM Access Analyzer 验证策略
使用 Access Analyzer 根据安全最佳实践验证策略。
aws accessanalyzer validate-policy \
--policy-document file://lambda-scoped-policy.json \
--policy-type IDENTITY_POLICY \
--query 'findings[*].[findingType,issueCode,learnMoreLink]' --output table
aws accessanalyzer check-no-new-access \
--new-policy-document file://lambda-scoped-policy.json \
--existing-policy-document file://old-broad-policy.json \
--policy-type IDENTITY_POLICY
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::ACCOUNT:role/lambda-my-function-role \
--action-names iam:CreateUser iam:PassRole s3:GetObject dynamodb:PutItem \
--query 'EvaluationResults[*].[EvalActionName,EvalDecision]' --output table
步骤 6:使用 SCP 强制执行角色规范
应用服务控制策略(SCP),防止 Lambda 函数使用过度宽泛的角色。
cat > scp-deny-lambda-admin.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyLambdaAdminRole",
"Effect": "Deny",
"Action": "lambda:CreateFunction",
"Resource": "*",
"Condition": {
"ForAnyValue:StringLike": {
"lambda:FunctionArn": "*"
},
"ArnLike": {
"iam:PassedToService": "lambda.amazonaws.com"
}
}
},
{
"Sid": "RequirePermissionBoundary",
"Effect": "Deny",
"Action": [
"iam:CreateRole",
"iam:AttachRolePolicy",
"iam:PutRolePolicy"
],
"Resource": "arn:aws:iam::*:role/lambda-*",
"Condition": {
"StringNotEquals": {
"iam:PermissionsBoundary": "arn:aws:iam::*:policy/lambda-permission-boundary"
}
}
}]
}
EOF
aws organizations create-policy \
--name "lambda-role-guardrails" \
--type SERVICE_CONTROL_POLICY \
--content file://scp-deny-lambda-admin.json
核心概念
| 术语 | 定义 |
|---|
| 执行角色(Execution Role) | Lambda 在函数执行期间承担的 IAM 角色,定义函数可以执行的所有 AWS API 操作 |
| 最小权限(Least Privilege) | 仅授予函数执行预期操作所需的最低权限的安全原则 |
| 权限边界(Permission Boundary) | 设置执行角色最大权限的 IAM 策略,即使身份策略授予了更广泛的访问权限也能生效 |
| IAM Access Analyzer | 基于实际 CloudTrail 使用情况生成最小权限策略并验证策略安全问题的 AWS 服务 |
| 资源范围化策略(Resource-Scoped Policy) | 指定精确资源 ARN 而非通配符的 IAM 策略,将访问限制为仅所需的特定资源 |
| 混淆副手防护(Confused Deputy Prevention) | 向信任策略添加 aws:SourceAccount 或 aws:SourceArn 条件,防止跨账户角色假冒攻击 |
工具与系统
- IAM Access Analyzer:从 CloudTrail 数据生成最小权限策略并验证策略安全性
- IAM Policy Simulator:在部署前针对特定 API 操作测试角色的有效权限
- CloudTrail:所有 API 调用的审计日志,用于确定函数实际使用的权限
- Prowler:包含 Lambda 角色权限和配置专项检查的安全工具
- Checkov:基础设施即代码扫描器,验证 CloudFormation/Terraform 中的 Lambda IAM 策略
常见场景
场景:将 Lambda 函数从 AdministratorAccess 降权至最小权限
场景背景:安全审计发现 12 个 Lambda 函数使用具有 AdministratorAccess 的共享执行角色。团队需要在不中断生产的情况下将每个函数限定到最低所需权限。
方法:
- 为 Lambda 启用 CloudTrail 数据事件,捕获每个函数的实际 API 使用情况
- 等待 30 天收集具有代表性的 API 调用样本
- 对每个函数的角色使用情况使用 IAM Access Analyzer 策略生成
- 根据实际 API 使用情况为每个函数创建独立的范围化策略
- 应用权限边界以限制最大权限上限
- 将范围化角色部署到演练环境并运行集成测试
- 以金丝雀部署方式发布到生产环境,并准备好回滚计划
- 在移除旧的宽泛角色前,使用 IAM Policy Simulator 进行验证
常见陷阱:某些 Lambda 函数可能只有每月触发一次的偶发代码路径(批处理作业、错误处理器)。30 天观察窗口可能遗漏罕见的 API 调用。结合 CloudTrail 数据审查函数代码,识别所有潜在的 API 调用。使用 Access Analyzer 的策略验证,而不仅仅依赖生成的策略。
输出格式
Lambda 执行角色安全报告
========================================
账户: 123456789012
审查日期: 2026-02-23
审计函数数: 34
角色权限摘要:
具有 AdministratorAccess 的函数: 3(严重)
具有 PowerUserAccess 的函数: 5(高危)
具有通配符操作的函数: 12(中危)
具有范围化策略的函数: 14(正常)
修复进度:
[x] payment-processor: 已范围化到 DynamoDB + S3 + KMS(3 个操作)
[x] order-notification: 已范围化到 SNS + SES(2 个操作)
[ ] data-pipeline: 正在从 30 天 CloudTrail 数据生成策略
[ ] image-resizer: 等待演练环境验证
权限边界状态:
已应用边界的函数: 14 / 34
未应用边界的函数: 20 / 34
策略验证结果:
有安全警告的策略: 4
有错误的策略: 0
有建议的策略: 12