# Securing AWS Lambda Execution Roles

> 通过实施最小权限（Least Privilege）IAM 策略、应用权限边界（Permission Boundary）、限制基于资源的策略、使用 IAM Access Analyzer 验证权限，以及通过 SCP 强制执行角色规范，保护 AWS Lambda 执行角色（Execution Role）。

- Skill: `killvxk/securing-aws-lambda-execution-roles` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add killvxk/securing-aws-lambda-execution-roles`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/securing-aws-lambda-execution-roles/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/securing-aws-lambda-execution-roles

---


# 保护 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 角色，识别权限过度的函数。

```bash
# 列出所有 Lambda 函数及其执行角色
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 托管策略（通常范围过广）
  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 操作。

```bash
# 查询 CloudTrail 以获取 Lambda 执行角色实际进行的 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

# 使用 IAM Access Analyzer 策略生成（基于 CloudTrail 活动）
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 策略，仅授予每个函数所需的特定操作和资源。

```bash
# 示例：从 S3 读取并写入 DynamoDB 的函数的范围化策略
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": [{
    "Effect": "Allow",
    "Principal": {"Service": "lambda.amazonaws.com"},
    "Action": "sts:AssumeRole",
    "Condition": {
      "StringEquals": {
        "aws:SourceAccount": "ACCOUNT_ID"
      }
    }
  }]
}
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 执行角色设置最大权限上限。

```bash
# 创建限制 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",
        "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration",
        "sts:AssumeRole"
      ],
      "Resource": "*"
    }
  ]
}
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 根据安全最佳实践验证策略。

```bash
# 验证范围化策略
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 函数使用过度宽泛的角色。

```bash
# SCP 拒绝 Lambda 函数使用 AdministratorAccess
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` 的共享执行角色。团队需要在不中断生产的情况下将每个函数限定到最低所需权限。

**方法**：
1. 为 Lambda 启用 CloudTrail 数据事件，捕获每个函数的实际 API 使用情况
2. 等待 30 天收集具有代表性的 API 调用样本
3. 对每个函数的角色使用情况使用 IAM Access Analyzer 策略生成
4. 根据实际 API 使用情况为每个函数创建独立的范围化策略
5. 应用权限边界以限制最大权限上限
6. 将范围化角色部署到演练环境并运行集成测试
7. 以金丝雀部署方式发布到生产环境，并准备好回滚计划
8. 在移除旧的宽泛角色前，使用 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
```

