使用 Terraform 在 AWS Organizations 中集中管理 IAM 访问密钥 - AWS Prescriptive Guidance

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 Terraform 在 AWS Organizations 中集中管理 IAM 访问密钥

由 Aarti Rajput (AWS)、Chintamani Aphale (AWS)、T.V.R.L.Phani Kumar Dadi (AWS)、Pradip kumar Pandey (AWS)、Mayuri Shinde (AWS) 和 Pratap Kumar Nanda (AWS) 创作

摘要

注意: AWS CodeCommit 不再向新客户开放。的现有客户 AWS CodeCommit 可以继续照常使用该服务。了解更多

强制执行密钥和密码的安全规则是每个组织的一项基本任务。一项重要规则是定期轮换 AWS Identity and Access Management (IAM) 密钥以加强安全性。每当团队想要通过 AWS 命令行界面 (AWS CLI) 或 AWS 之外的应用程序访问 AWS 时,通常都会在本地创建和配置 AWS 访问密钥。为了维护整个组织的强大安全性,必须在满足要求后或定期更改或删除旧的安全密钥。管理组织中多个账户的密钥轮换的过程既耗时又乏味。这种模式可帮助您使用适用于 Terraform 的 Account Factory (AFT) 和 AWS 服务自动执行轮换流程。

该模式具有以下优点:

  • 从一个中心位置管理组织中所有账户的访问密钥 IDs 和私有访问密钥。

  • 自动轮换AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY环境变量。

  • 如果用户凭证遭到泄露,则强制续订。

该模式使用 Terraform 来部署 AWS Lambda 函数、 EventBridge 亚马逊规则和 IAM 角色。 EventBridge 规则定期运行并调用 Lambda 函数,该函数根据用户访问密钥的创建时间列出所有用户访问密钥。如果之前的密钥早于您定义的轮换周期(例如,45 天),其他 Lambda 函数会创建新的访问密钥 ID 和私有访问密钥,并使用亚马逊简单通知服务 (Amazon SNS) Simple Notification Service 和亚马逊简单电子邮件服务 (Amazon SES) Service (Amazon SES) 通知安全管理员。在 AWS Secrets Manager 中为该用户创建密钥,旧的私有访问密钥存储在 Secrets Manager 中,并配置访问旧密钥的权限。为了确保不再使用旧的访问密钥,在非活动期(例如 60 天,也就是我们的示例中密钥轮换后 15 天)后将其禁用。在缓冲期处于非活动状态之后(例如,在我们的示例中为 90 天或密钥轮换后 45 天),旧的访问密钥将从 AWS Secrets Manager 中删除。有关详细的架构和工作流程,请参阅 “架构” 部分。

先决条件和限制

架构

AFT 存储库

此模式使用 Account Factory for Terraform (AFT) 创建所有必需的 AWS 资源,并使用代码管道将资源部署到部署账户中。代码管道在两个存储库中运行:

  • 全局自定义包含 Terraform 代码,该代码将在所有在 AFT 注册的账户中运行。

  • 账户自定义包含将在部署账户中运行的 Terraform 代码。

资源详细信息

AWS CodePipeline 任务在部署账户中创建以下资源:

  • AWS EventBridge 规则和配置的规则

  • account-inventory Lambda 函数

  • IAM-access-key-rotation Lambda 函数

  • Notification Lambda 函数

  • 包含电子邮件模板的亚马逊简单存储服务 (Amazon S3) Service 存储桶

  • 必需的 IAM 政策

架构

该图阐释了以下内容:

在 AWS Organizations 中集中管理 IAM 访问密钥的架构
  1. 一条 EventBridge 规则每 24 小时调用一次 account-inventory Lambda 函数。

  2. account-inventoryLambda 函数向 AWS Organizations 查询所有 AWS 账户 IDs、账户名称和账户电子邮件的列表。 

  3. account-inventoryLambda 函数为每个 AWS 账户启动一个 IAM-access-key-auto-rotation Lambda 函数,并将元数据传递给该账户进行额外处理。

  4. IAM-access-key-auto-rotationLambda 函数使用假设的 IAM 角色来访问 AWS 账户。Lambda 脚本对账户中的所有用户及其 IAM 访问密钥进行审计。

  5. 部署 IAM-access-key-auto-rotation Lambda 函数时,IAM 密钥轮换阈值(轮换周期)被配置为环境变量。如果修改了轮换周期,则会使用更新的环境变量重新部署 IAM-access-key-auto-rotation Lambda 函数。您可以配置参数来设置轮换周期、旧密钥的非活动时间以及将删除旧密钥的非活动缓冲区(请参阅 Epic s 部分中的自定义代码管道参数)。

  6. IAM-access-key-auto-rotationLambda 函数根据访问密钥的配置来验证访问密钥的使用年限。如果 IAM 访问密钥的使用期限未超过您定义的轮换期,则 Lambda 函数将不采取任何进一步的操作。

  7. 如果 IAM 访问密钥的使用期限已超过您定义的轮换周期,IAM-access-key-auto-rotationLambda 函数将创建一个新密钥并轮换现有密钥。

  8. Lambda 函数将旧密钥保存在 Secrets Manager 中,并将权限限制为访问密钥偏离安全标准的用户。Lambda 函数还会创建基于资源的策略,该策略仅允许指定的 IAM 委托人访问和检索密钥。

  9. IAM-access-key-rotationLambda 函数调用 Lambda Notification 函数。

  10. NotificationLambda 函数查询 S3 存储桶以获取电子邮件模板,并动态生成包含相关活动元数据的电子邮件。

  11. NotificationLambda 函数调用 Amazon SES 以采取进一步行动。

  12.  Amazon SES 会向账户所有者的电子邮件地址发送包含相关信息的电子邮件。

工具

Amazon Web Services

  • AWS Identity and Access Management (AWS IAM) 通过控制验证和授权使用您 AWS 资源的用户,帮助您安全地管理对您 AWS 资源的访问。此模式需要 IAM 角色和权限。

  • AWS Lambda 是一项计算服务,可帮助您运行代码,而无需预置或管理服务器。它仅在需要时运行您的代码,并且能自动扩缩,因此您只需为使用的计算时间付费。

  • AWS Secrets Manager 帮助您将代码中的硬编码凭证(包括密码)替换为对 Secrets Manager 的 API 调用,以便以编程方式检索密钥。

  • Amazon Simple Email Service (Amazon SES) 可帮助您使用自己的电子邮件地址和域发送和接收电子邮件。

其他工具

  • Terraform 是一款基础设施即代码 (IaC) 工具 HashiCorp ,可帮助您创建和管理云和本地资源。

代码存储库

此模式的说明和代码可在 GitHub IAM 访问密钥轮换存储库中找到。您可以在 AWS Control Tower 中央部署账户中部署代码,以便从中央位置管理密钥轮换。

最佳实践

操作说明

Task描述所需技能

克隆存储库。

  1. 克隆 I AM 访问密钥轮换 GitHub 存储库:

    $ git clone https://github.com/aws-samples/centralized-iam-key-management-aws-organizations-terraform.git
  2. 确认存储库的本地副本包含三个文件夹:

    $ cd Iam-Access-keys-Rotation $ ls org-account-customization global-account-customization account-customization
DevOps 工程师
Task描述所需技能

配置引导账户。

作为 AFT 引导过程的一部分,你应该在本地计算机aft-bootstrap上有一个名为的文件夹。

  1. 手动将所有 Terraform 文件从本地 GitHub org-account-customization文件夹复制到您的aft-bootstrap文件夹。

  2. 运行 Terraform 命令在 AWS Control Tower 管理账户中配置全局跨账户角色:

    $ cd aft-bootstrap $ terraform init $ terraform apply —auto-approve
DevOps 工程师

配置全局自定义。

作为 AFT 文件夹设置的一部分,您应该在本地计算机aft-global-customizations上有一个名为的文件夹。

  1. 手动将所有 Terraform 文件从本地 GitHub global-account-customization文件夹复制到您的aft-global-customizations/terraform文件夹。

  2. 将代码推送到 AWS CodeCommit:

    $ git add * $ git commit -m "message" $ git push
DevOps 工程师

配置账户自定义。

作为 AFT 文件夹设置的一部分,您的本地计算机aft-account-customizations上有一个名为的文件夹。

  1. 使用您出售的账号创建一个文件夹。

  2. 手动将所有 Terraform 文件从本地 GitHub 帐户自定义文件夹复制到您的文件夹。aft-account-customizations/<vended account>/terraform

  3. 将代码推送到 AWS CodeCommit:

    $ git add * $ git commit -m "message" $ git push
DevOps 工程师
Task描述所需技能

为所有账户自定义非 TerraForm 代码管道参数。

aft-global-customizations/terraform/文件夹input.auto.tfvars中创建一个名为的文件并提供所需的输入数据。有关默认值,请参阅 GitHub 存储库中的文件

DevOps 工程师

为部署账户自定义代码管道参数。

aft-account-customizations/<AccountName>/terraform/文件夹input.auto.tfvars中创建一个名为的文件,然后将代码推送到 AWS CodeCommit。将代码推送到 AWS CodeCommit 会自动启动代码管道。

根据组织要求指定参数值,包括以下内容(默认值请参阅 Github 存储库中的文件):

  • s3_bucket_name— 电子邮件模板的唯一存储桶名称。

  • s3_bucket_prefix— S3 存储桶内的文件夹名称。

  • admin_email_address— 应接收通知的管理员的电子邮件地址。

  • org_list_account— 管理账户的账号。

  • rotation_period— 密钥应在多长时间后从活动状态轮换到非活动状态。

  • inactive_period— 应在多长天后停用轮换的密钥。此值必须大于的值rotation_period

  • inactive_buffer— 密钥轮换和停用之间的宽限期。

  • recovery_grace_period— 从停用密钥到删除密钥之间的宽限期。

  • dry_run_flag— 如果您想在不轮换密钥的情况下向管理员发送通知以进行测试,则设置为 true

  • store_secrets_in_central_account— 如果要将密钥存储在部署帐户中,则设置为 true。如果该变量设置为 false(默认),则密钥将存储在成员账户中。

  • credential_replication_region— 您要在其中部署 Lambda 函数的 AWS 区域和电子邮件模板的 S3 存储桶。

  • run_lambda_in_vpc— 设置为 true 可在 VPC 内运行 Lambda 函数。

  • vpc_id— 如果您想在 VPC 内运行 Lambda 函数,则为部署账户的 VPC ID。

  • vpc_cidr— 部署账户的 CIDR 范围。

  • subnet_id— 部署账户 IDs 的子网。

  • create_smtp_endpoint— 如果要启用电子邮件端点,则设置为 true

DevOps 工程师
Task描述所需技能

验证解决方案。

  1. 从 AWS 管理控制台登录部署账户。

  2. 打开 IAM 控制台,检查用户证书(访问密钥 IDs 和私有密钥)是否按指定轮换。

  3. 轮换 IAM 密钥后,请确认以下内容:

    • 旧值存储在 AWS Secrets Manager 中。

    • 机密名称的格式为Account_<account ID>_User_<username>_AccessKey

    • 您在admin_email_address参数中指定的用户会收到一封有关密钥轮换的电子邮件通知。

DevOps 工程师
Task描述所需技能

自定义电子邮件通知日期。

如果您想在禁用访问密钥之前的特定日期发送电子邮件通知,则可以使用以下更改更新 IAM-access-key-auto-rotation Lambda 函数:

  1. 定义一个名为的变量notify-period

  2. 在停用密钥main.py之前,请在中添加一个if条件:

    If (keyage>rotation-period-notify-period){ send_to_notifier(context, aws_account_id, account_name, resource_owner, resource_actions[resource_owner], dryrun, config.emailTemplateAudit) }
DevOps 工程师

故障排除

事务解决方案

account-inventoryLambda 任务在列出账户AccessDenied时失败。

如果遇到此问题,则必须验证权限:

  1. 登录新出售的账户,打开 Amazon CloudWatch 控制台,然后查看 CloudWatch 日志组/aws/lambda/account-inventory-lambda

  2. 在最新的 CloudWatch 日志中,确定导致访问被拒绝问题的账号。

  3. 登录 AWS Control Tower 管理账户并确认该角色allow-list-account已创建。

  4. 如果该角色不存在,请使用命令重新运行 Terraform 代码。terraform apply

  5. 选择 “可信账户” 选项卡,并验证同一个账户是否可信。

相关资源