View a markdown version of this page

使用 Terraform 在 AWS Organizations 中集中管理 IAM 访问密钥 - AWS 规范指引

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

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

Aarti Rajput、Chintamani Aphale、T.V.R.L.Phani Kumar Dadi、Pratap Kumar Nanda、Pradip kumar Pandey 和 Mayuri Shinde,Amazon Web Services

Summary

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

该模式提供以下优势:

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

  • 自动轮换 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 环境变量。

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

该模式使用 Terraform 部署 AWS Lambda 函数、 EventBridge 亚马逊规则和 IAM 角色。 EventBridge 规则定期运行并调用 Lambda 函数,该函数根据用户访问密钥的创建时间列出所有用户访问密钥。如果之前的密钥存在时间超过您定义的轮换周期(例如,45 天),其他 Lambda 函数会创建新访问密钥 ID 和秘密访问密钥,并使用 Amazon Simple Notification Service(Amazon SNS)和 Amazon Simple Email 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 Simple Storage Service(Amazon S3)存储桶

  • 所需的 IAM 策略

架构

在 AWS Organizations 中集中管理 IAM 访问密钥的架构

下图说明了以下内容:

  1. 一条 EventBridge 规则每 24 小时调用一次 account-inventory Lambda 函数。

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

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

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

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

  6. IAM-access-key-auto-rotation Lambda 函数根据访问密钥的配置来验证其已用时间。如果 IAM 访问密钥使用期限未超过您定义的轮换周期,则 Lambda 函数将不采取进一步的行动。

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

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

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

  10. Notification Lambda 函数在 S3 存储桶中查询电子邮件模板,并使用相关活动元数据动态地生成电子邮件。

  11. Notification Lambda 函数调用 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 函数以及电子邮件模板的 S3 存储桶的 AWS 区域。

  • 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. 从 Amazon 管理控制台登录部署账户。

  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-inventory Lambda 任务在列出账户时失败,并显示 AccessDenied

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

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

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

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

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

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

相关资源