aws-samples/sample-automated-iam-access-keys-lifecycle

GitHub: aws-samples/sample-automated-iam-access-keys-lifecycle

基于 AWS 原生服务构建的组织级 IAM 访问密钥自动化生命周期管理方案,通过人工审批流程安全地识别、禁用和删除未使用的访问密钥。

Stars: 0 | Forks: 0

# AWS IAM Access Key 生命周期管理与人工审批 一个组织级的自动化解决方案,用于使用 AWS Step Functions、IAM Access Analyzer、API Gateway、Lambda 和 CloudFormation StackSets 管理未使用的 IAM 访问密钥。此解决方案在永久删除前包含了一个人工参与的审批步骤。 ## 目录 1. [概述](#overview) 2. [架构](#architecture) 3. [工作流程](#workflow) 4. [前置条件](#prerequisites) 5. [部署](#deployment) 6. [配置参数](#configuration-parameters) 7. [安全](#security) 8. [成本](#cost) 9. [故障排除](#troubleshooting) ## 概述 此解决方案可自动识别、禁用和删除您的 AWS 组织中所有账户下未使用的 IAM 用户访问密钥。在永久删除之前,需要通过安全的电子邮件链接进行人工审批。 ### 主要功能 - **组织级覆盖**:管理所有 AWS 账户的访问密钥 - **人工参与**:删除前需要通过安全链接进行明确审批 - **安全第一**:在删除前禁用密钥,具有可配置的保留期 - **审批超时**:如果未获批准,执行将在 7 天后过期(密钥保持禁用状态,不会被删除) - **安全审批链接**:具有加密令牌验证的一次性使用 URL - **电子邮件通知**:接收禁用通知和审批请求 - **自动调度**:可通过 EventBridge 进行可选的定期执行 - **完整的审计跟踪**:X-Ray 跟踪和 CloudWatch 日志记录 ### 此解决方案的功能 1. 使用 Access Analyzer 监控未使用的 IAM 访问密钥 2. 自动禁用所有账户中未使用的密钥 3. 发送密钥已被禁用的通知 4. 等待一个可配置的保留期(默认:1 天) 5. 发送带有安全一次性链接的审批请求电子邮件 6. 等待人工审批(或在 7 天后超时) 7. 仅在审批后永久删除密钥 8. 提供完整的审计跟踪 ## 架构 ### 组件 **管理账户堆栈** (`management-account-template.yaml`): - **Step Functions 状态机**:通过人工审批编排工作流程 - **Lambda 函数**:处理审批请求和回调 - **API Gateway**:为审批链接提供 REST endpoint - **SNS 主题**:发送电子邮件通知 - **CloudWatch 告警**:监控执行失败情况 - **EventBridge 规则**:调度自动执行(可选) **目标账户堆栈集** (`target-account-template.yaml`): - **AccessKeyManagementRole**:用于密钥管理操作的跨账户 IAM 角色 ### 架构图 ``` Management Account ├─ Step Functions (orchestration) │ ├─ List unused keys (Access Analyzer) │ ├─ Disable keys (cross-account) │ ├─ Wait (hold period) │ ├─ Request approval (Lambda + task token) ⏸️ PAUSED │ └─ Delete keys (if approved) ├─ Lambda Functions │ ├─ Approval Request (sends email) │ └─ Approval Callback (handles link click) ├─ API Gateway (/approve endpoint) └─ SNS Topic (email notifications) Member Accounts └─ AccessKeyManagementRole (IAM permissions) Approval Flow: Email → Human clicks link → API Gateway → Lambda → Step Functions resumes → Keys deleted ``` ## 工作流程 ### 执行流程 1. **列出发现项**:查询 Access Analyzer 以获取未使用的访问密钥 2. **过滤密钥**:排除管理账户密钥(仅限成员账户) 3. **禁用密钥**:将所有账户的状态设置为 "Inactive" 4. **发送通知**:确认密钥已被禁用的电子邮件 5. **等待期**:可配置的保留期(默认:1 天) 6. **请求审批**:Lambda 发送带有安全一次性审批链接的电子邮件 - Step Functions 使用任务令牌模式在此处**暂停** - 等待审批期间不产生成本 7. **人工决定**: - **批准**:点击链接 → 密钥被删除 - **忽略**:7 天后超时 → 密钥保持禁用状态(不被删除) 8. **删除密钥**:永久移除访问密钥(仅在批准后) 9. **报告结果**:已处理密钥的摘要 ### 审批机制 该解决方案使用 Step Functions 的 `.waitForTaskToken` 模式: - Step Functions 生成加密安全的任务令牌 - 令牌嵌入在通过电子邮件发送的审批 URL 中 - 执行暂停(等待期间无成本) - 人工点击链接 → API Gateway → Lambda → `SendTaskSuccess()` - Step Functions 恢复并删除密钥 **令牌安全性**:一次性使用,7 天后自动过期,无法重复使用或被猜测 ## 前置条件 在部署此解决方案之前,请确保您具备: ### 必要条件 1. **AWS Organization**:具有多个账户的活跃 AWS Organization 2. **IAM Access Analyzer**:已配置组织级别的 Access Analyzer - 必须正在分析未使用的 IAM 用户访问密钥 - 记下 Analyzer ARN(格式:`arn:aws:access-analyzer:region:account:analyzer/name`) 3. **CloudFormation StackSets**:在您的组织中已启用 4. **管理员访问权限**:用于管理账户 5. **AWS CLI**:已安装并配置了适当的凭证 ### 需收集的信息 部署前,请收集以下内容: ``` # 获取你的 Organization ID aws organizations describe-organization --query 'Organization.Id' --output text # 示例输出: o-abc1234567 # 获取你的 Management Account ID aws sts get-caller-identity --query 'Account' --output text # 示例输出: 123456789012 # 获取你的 Root OU ID aws organizations list-roots --query 'Roots[0].Id' --output text # 示例输出: r-a1b2 # 列出 Access Analyzers aws accessanalyzer list-analyzers --query 'analyzers[*].[name,arn]' --output table ``` 记录这些值: - **组织 ID**:`o-__________` - **管理账户 ID**:`____________` - **根 OU ID**:`r-____` - **Access Analyzer ARN**:`arn:aws:access-analyzer:______:______:analyzer/______` - **部署区域**:`______` - **通知电子邮件**:`______@______` ## 部署 ### Lambda 函数 Lambda 函数代码直接嵌入在 CloudFormation 模板中,以便于部署。`lambda/` 目录中也提供了独立的 Python 文件,以供参考和本地测试: - `lambda/approval-request-handler.py` - 发送审批请求电子邮件 - `lambda/approval-callback-handler.py` - 处理审批链接回调 ### 部署过程 #### 阶段 1:目标账户角色 (StackSet) 这会将跨账户 IAM 角色部署到您组织中的所有账户。 **创建 StackSet:** ``` aws cloudformation create-stack-set \ --stack-set-name AccessKeyManagementRoles \ --template-body file://cloudformation-templates/target-account-stackset-template.yaml \ --parameters \ ParameterKey=ManagementAccountId,ParameterValue= \ ParameterKey=StepFunctionsExecutionRoleName,ParameterValue=StepFunctionsAccessKeyManagementRole \ ParameterKey=OrganizationId,ParameterValue= \ --capabilities CAPABILITY_NAMED_IAM \ --permission-model SERVICE_MANAGED \ --auto-deployment Enabled=true,RetainStacksOnAccountRemoval=false ``` **部署堆栈实例:** ``` aws cloudformation create-stack-instances \ --stack-set-name AccessKeyManagementRoles \ --deployment-targets OrganizationalUnitIds= \ --regions ``` **验证部署:** ``` # 检查操作状态 aws cloudformation describe-stack-set-operation \ --stack-set-name AccessKeyManagementRoles \ --operation-id # 列出所有 stack instances aws cloudformation list-stack-instances \ --stack-set-name AccessKeyManagementRoles ``` #### 阶段 2:管理账户堆栈 这将部署 Step Functions 状态机、Lambda 函数和 API Gateway。 **创建堆栈:** ``` aws cloudformation create-stack \ --stack-name AccessKeyManagementStateMachine \ --template-body file://cloudformation-templates/management-account-template.yaml \ --parameters \ ParameterKey=AnalyzerArn,ParameterValue= \ ParameterKey=NotificationEmail,ParameterValue= \ ParameterKey=OrganizationId,ParameterValue= \ ParameterKey=HoldPeriod,ParameterValue=1 \ ParameterKey=ApprovalTimeout,ParameterValue=7 \ ParameterKey=ScheduleIntervalDays,ParameterValue=7 \ ParameterKey=EnableScheduler,ParameterValue=true \ --capabilities CAPABILITY_NAMED_IAM ``` **监控堆栈创建:** ``` # 检查 stack 状态 aws cloudformation describe-stacks \ --stack-name AccessKeyManagementStateMachine \ --query 'Stacks[0].StackStatus' # 查看 stack 事件 aws cloudformation describe-stack-events \ --stack-name AccessKeyManagementStateMachine \ --max-items 20 ``` **获取堆栈输出:** ``` aws cloudformation describe-stacks \ --stack-name AccessKeyManagementStateMachine \ --query 'Stacks[0].Outputs' ``` 关键输出: - `StateMachineArn`:Step Functions 状态机的 ARN - `ApprovalApiUrl`:审批 API endpoint 的 URL - `NotificationTopicArn`:SNS 主题的 ARN - `ApprovalRequestFunctionArn`:审批请求 Lambda 的 ARN - `ApprovalCallbackFunctionArn`:审批回调 Lambda 的 ARN #### 阶段 3:SNS 订阅确认 1. 检查您的电子邮件以获取 AWS SNS 订阅确认 2. 点击 "Confirm subscription" 链接 3. 验证您看到了确认页面 ## 配置参数 ### 管理账户模板参数 | 参数 | 描述 | 默认值 | 有效范围 | 必填 | |-----------|-------------|---------|-------------|----------| | `AnalyzerArn` | 您的 Access Analyzer 的 ARN | - | 有效的 analyzer ARN | 是 | | `NotificationEmail` | 用于通知和审批的电子邮件 | - | 有效的电子邮件地址 | 是 | | `OrganizationId` | 您的 AWS Organization ID | - | 格式:o-xxxxxxxxxx | 是 | | `HoldPeriod` | 禁用与请求审批之间的天数 | 1 | 1-90 天 | 否 | | `ApprovalTimeout` | 等待审批直到过期前的天数 | 7 | 1-30 天 | 否 | | `ScheduleIntervalDays` | 自动运行间隔天数 | 7 | 1-365 天 | 否 | | `EnableScheduler` | 启用自动调度 | true | true/false | 否 | | `StateMachineName` | 状态机名称 | AccessKeyManagementStateMachine | - | 否 | | `ExecutionRoleName` | 执行角色名称 | StepFunctionsAccessKeyManagementRole | - | 否 | ### 目标账户模板参数 | 参数 | 描述 | 默认值 | 必填 | |-----------|-------------|---------|----------| | `ManagementAccountId` | 管理账户 ID | - | 是 | | `StepFunctionsExecutionRoleName` | 执行角色名称 | StepFunctionsAccessKeyManagementRole | 否 | | `AccessKeyManagementRoleName` | 目标角色名称 | AccessKeyManagementRole | 否 | ### 参数详情 **AnalyzerArn** - 格式:`arn:aws:access-analyzer:region:account-id:analyzer/analyzer-name` - 必须是组织级别的 analyzer - 必须配置为分析未使用的 IAM 用户访问密钥 - 查找您的 analyzer:`aws accessanalyzer list-analyzers` **NotificationEmail** - 必须是有效的电子邮件地址 - 将同时接收禁用通知和审批请求 - 确保您可以访问此电子邮件 - 如果未收到,请检查垃圾邮件/垃圾箱文件夹 **OrganizationId** - 格式:`o-` 后跟 10 个字母数字字符 - 查找您的 ID:`aws organizations describe-organization --query 'Organization.Id'` - 用于安全边界强制执行 **HoldPeriod** - 禁用密钥与请求审批之间的时间 - 给用户提供时间报告是否仍需要这些密钥 - 建议:1-7 天 - 较长的期限会延迟修复,但可提供更多的审查时间 **ApprovalTimeout** - 等待人工审批的最长时间 - 此时间过后,执行将过期(密钥不会被删除) - 在当前实现中固定为 7 天(604800 秒) - 不能超过 Step Functions 的最大执行时间 **ScheduleIntervalDays** - 工作流自动运行的频率 - 建议:7-30 天 - 越频繁 = 检测越快,电子邮件越多 - 越不频繁 = 电子邮件越少,检测越慢 **EnableScheduler** - 设置为 `true` 以启用自动调度 - 设置为 `false` 仅进行手动执行 - 可在部署后更改 ## 成本 请注意,您将因部署此解决方案以及消耗的任何 AWS 服务而被收费。决定确切定价的因素如下- ### 成本因素 **执行频率:** - 执行越频繁 = 成本越高 - 默认值:每 7 天 - 建议:7-30 天 **发现项数量:** - 未使用的密钥越多 = 状态转换越多 - Lambda 调用越多 - API 调用越多 **执行持续时间:** - Step Functions 按状态转换收费,而不是按持续时间收费 - 等待审批期间不收费(任务令牌模式) - 较长的保留期不会增加成本 **免费套餐权益:** - Lambda:每月 100 万次请求免费 - API Gateway:每月 100 万次请求免费(前 12 个月) - CloudWatch:10 个自定义指标免费 - X-Ray:每月 100,000 个跟踪免费 ## 安全 ### 安全最佳实践 1. **保护审批电子邮件** - 使用安全的电子邮件提供商 - 启用电子邮件加密 - 不要转发审批链接 - 使用后删除电子邮件 2. **限制访问权限** - 限制谁可以修改 CloudFormation 堆栈 - 限制对 Step Functions 控制台的访问 - 控制 Lambda 函数的修改 - 保护 SNS 主题订阅 ## 故障排除 ### 常见问题及解决方案 #### 未处理任何发现项 **症状:** - 执行立即完成 - 输出:“未找到未使用的 IAM 访问密钥” - 未收到任何电子邮件 **解决方案:** 1. 验证 Access Analyzer 是否已配置: aws accessanalyzer list-analyzers 2. 检查 analyzer 是否正在分析您的组织 3. 确保 analyzer 已完成初始扫描(可能需要数小时) 4. 验证参数中的 analyzer ARN 是否正确 5. 在控制台中检查 Access Analyzer 的发现项 #### 跨账户访问失败 **症状:** - 在 "UpdateAccessKey" 或 "DeleteAccessKey" 状态下执行失败 - 错误:“AccessDenied”或“AssumeRole failed” **解决方案:** 1. 验证 StackSet 是否部署成功: aws cloudformation list-stack-instances \ --stack-set-name AccessKeyManagementRoles 2. 检查目标账户中是否存在 `AccessKeyManagementRole` 3. 验证信任策略是否包含管理账户 4. 确认组织 ID 是否正确 5. 检查外部 ID 是否匹配 6. 验证角色是否具有所需的权限 #### 未收到电子邮件通知 **症状:** - 未收到任何电子邮件 - SNS 订阅未确认 **解决方案:** 1. 检查垃圾邮件/垃圾箱文件夹 2. 验证参数中的电子邮件地址 3. 确认 SNS 订阅: aws sns list-subscriptions-by-topic \ --topic-arn 4. 检查 SNS 主题是否存在 5. 验证 Lambda 是否有权发布到 S 6. 查看 Lambda 日志是否有错误 #### 审批链接无效 **症状:** - 点击链接显示错误页面 - 错误:“Invalid or expired approval token” **解决方案:** 1. 检查链接是否已使用过(一次性使用) 2. 验证执行未超时(7 天限制) 3. 检查 API Gateway 部署: aws apigateway get-deployments \ --rest-api-id 4. 查看 Lambda 回调函数日志: aws logs tail /aws/lambda/AccessKeyManagementStateMachine-ApprovalCallback 5. 验证 Lambda 是否具有调用 SendTaskSuccess 的权限 6. 检查 Step Functions 执行是否仍在运行 #### Step Functions 执行失败 **症状:** - 执行状态:“Failed” - 触发了 CloudWatch 告警 **解决方案:** 1. 在 Step Functions 控制台中查看执行详情 2. 检查执行事件历史记录以获取错误详情 3. 查看 CloudWatch Logs: aws logs filter-log-events \ --log-group-name /aws/lambda/AccessKeyManagementStateMachine-ApprovalRequest \ --filter-pattern "ERROR" 4. 检查 X-Ray 跟踪以获取详细的错误信息 5. 验证所有 IAM 权限是否正确 6. 确保 Access Analyzer ARN 有效 #### Lambda 函数错误 **症状:** - Lambda 调用失败 - CloudWatch Logs 中出现错误 **解决方案:** 1. 检查 Lambda 函数日志: aws logs tail /aws/lambda/ --follow 2. 验证环境变量是否设置正确 3. 检查 Lambda 执行角色权限 4. 确保 Lambda 具有网络连接(如果在 VPC 中) 5. 验证 Python 运行时版本兼容性 #### API Gateway 错误 **症状:** - 点击审批链接时出现 4xx 或 5xx 错误 - API Gateway 指标显示错误 **解决方案:** 1. 检查 API Gateway 日志(如果已启用) 2. 验证 Lambda 集成配置是否正确 3. 测试 API Gateway endpoint: curl -v "https://.execute-api..amazonaws.com/prod/approve?token=test" 4. 检查用于 API Gateway 调用的 Lambda 权限 5. 验证 API Gateway 部署是否处于活动状态 #### 执行超时问题 **症状:** - 在审批前执行超时 - 状态:“Succeeded”并带有超时消息 **解决方案:** 1. 如果在 7 天内未给出审批,这是预期行为 2. 密钥保持禁用状态但未被删除 3. 要更改超时时间,请修改状态机定义中的 `TimeoutSeconds` 4. 注意:不能超过 Step Functions 的最大值(1 年) 5. 考虑 7 天是否适合您的组织 ### 获取帮助 如果您仍然遇到问题: 1. **查看 AWS 文档** - [Step Functions 故障排除](https://docs.aws.amazon.com/step-functions/latest/dg/troubleshooting.html) - [Lambda 故障排除](https://docs.aws.amazon.com/lambda/latest/dg/lambda-troubleshooting.html) - [API Gateway 故障排除](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-troubleshooting.html) 2. **检查 CloudWatch Logs** - 所有 Lambda 函数都记录到 CloudWatch - 查找 ERROR 或 WARN 消息 - 检查时间戳是否与您的执行匹配 3. **验证配置** - 仔细检查所有参数 - 确保 ARN 正确 - 验证组织 ID - 确认电子邮件地址
标签:Access Analyzer, API Gateway, AWS, CloudFormation, CloudWatch, DPI, EventBridge, Human-in-the-Loop, IAM, Lambda, Serverless, StackSets, Step Functions, Streamlit, X-Ray, 人机协同, 安全合规, 安全基线, 审批工作流, 密钥轮换, 教学环境, 未使用密钥清理, 生命周期管理, 网络代理, 网络调试, 自动化, 访问控制, 身份与访问管理, 逆向工具