将 gMSA 用于 Amazon ECS 上的 EC2 Linux 容器 - Amazon Elastic Container Service

将 gMSA 用于 Amazon ECS 上的 EC2 Linux 容器

Amazon ECS 通过称为组托管服务账户(gMSA)的特殊服务账户支持 EC2 上的 Linux 容器的 Active Directory 身份验证。

基于 Linux 的网络应用程序(例如 .NET Core 应用程序)可以使用 Active Directory 来促进用户和服务之间的身份验证和授权管理。通过设计与 Active Directory 集成并在加入域的服务器上运行的应用程序,您可以使用此功能。但是,由于 Linux 容器无法加入域,因此您需要配置一个 Linux 容器来使用 gMSA 运行。

使用 gMSA 运行的 Linux 容器依赖于在容器主机 Amazon EC2 实例上运行的 credentials-fetcher 进程守护程序。也就是说,进程守护程序从 Active Directory 域控制器检索 gMSA 凭证,然后将这些凭证传输到容器实例。有关服务账户的更多信息,请参阅 Microsoft Learn 网站上的为 Windows 容器创建 gMSAs

注意事项

在将 gMSA 用于 Linux 容器之前,请注意以下各项:

  • 如果您的容器在 EC2 上运行,则可以将 gMSA 用于 Windows 容器和 Linux 容器。有关如何在 Fargate 上使用 gMSA Linux 容器的信息,请参阅 将 gMSA 用于 Fargate 上的 Linux 容器

  • 您可能需要一台已加入域的 Windows 计算机才能完成先决条件。例如,您可能需要一台已加入域的 Windows 计算机才能使用 PowerShell 在 Active Directory 中创建 gMSA。RSAT Active Director PowerShell 工具仅适用于 Windows。有关更多信息,请参阅安装 Active Directory 管理工具

  • 您可以在无域 gMSA将每个实例加入单个域之间进行选择。通过使用无域 gMSA,容器实例不会加入该域,实例上的其他应用程序无法使用凭证访问该域,并且加入不同域的任务可以在同一个实例上运行。

    然后,选择数据存储用于 CredSpec,以及无域 gMSA 的 Active Directory 用户凭证(可选)。

    Amazon ECS 使用 Active Directory 凭证规范文件(CredSpec)。该文件包含用于将 gMSA 账户上下文传播到容器的 gMSA 元数据。您可以生成 CredSpec 文件,然后将其存储在下表中的一个 CredSpec 存储选项中,该存储选项特定于容器实例的操作系统。要使用无域方法,CredSpec 文件中的可选部分可以在下表中的其中一个 domainless user credentials 存储选项中指定凭证,这些凭证特定于容器实例的操作系统。

    存储位置 Linux Windows
    Amazon Simple Storage Service CredSpec CredSpec
    AWS Secrets Manager 无域用户凭证 无域用户凭证
    Amazon EC2 Systems Manager Parameter Store CredSpec CredSpec,无域用户凭证
    本地文件 不适用 CredSpec

先决条件

在 Amazon ECS 上为 Linux 容器使用 gMSA 之前,请确保完成以下操作:

  • 您可以使用您希望容器访问的资源设置 Active Directory 域。Amazon ECS 支持以下设置:

    • AWS Directory Service Active Directory。AWS Directory Service 是托管在 Amazon EC2 上的 AWS 托管式 Active Directory。有关更多信息,请参阅 AWS Directory Service 管理指南中的 AWS 托管 Microsoft AD 入门

    • 本地 Active Directory。您必须确保 Amazon ECS Linux 容器实例可以加入域。有关更多信息,请参阅 AWS Direct Connect

  • 您在 Active Directory 中有现有的 gMSA 账户。有关更多信息,请参阅 将 gMSA 用于 Amazon ECS 上的 EC2 Linux 容器

  • 您已在 Amazon ECS Linux 容器实例上安装并正在运行 credentials-fetcher 进程守护程序。您还向 credentials-fetcher 进程守护程序添加了一组初始凭证,以便通过 Active Directory 进行身份验证。

    注意

    credentials-fetcher 进程守护程序仅适用于 Amazon Linux 2023 和 Fedora 37 及更高版本。该进程守护程序不适用于 Amazon Linux 2。有关更多信息,请参阅 GitHub 上的 aws/credentials-fetcher

  • 您可以为 credentials-fetcher 进程守护程序设置凭证,以便通过 Active Directory 进行身份验证。凭证必须是有权访问 gMSA 账户的 Active Directory 安全组的成员。决定是要将实例加入域,还是要使用无域 gMSA。 里面有多个选项。

  • 您已添加所需的 IAM 权限。所需的权限取决于您为初始凭证和存储凭证规范选择的方法:

    • 如果您使用无域 gMSA 作为初始凭证,则任务执行角色需要 AWS Secrets Manager 的 IAM 权限。

    • 如果您将凭证规范存储在 SSM Parameter Store 中,则任务执行角色需要获得 Amazon EC2 Systems Manager Parameter Store 的 IAM 权限。

    • 如果您将凭证规范存储在 Amazon S3 中,则任务执行角色需要 Amazon Simple Storage Service 的 IAM 权限。

在 Amazon ECS 上设置支持 gMSA 的 Linux 容器

准备基础设施

以下步骤是仅执行一次的注意事项和设置。完成这些步骤后,您可以自动创建容器实例,以重复使用此配置。

决定如何提供初始凭证,并在可重复使用的 EC2 启动模板中配置 EC2 用户数据以安装 credentials-fetcher 进程守护程序。

  1. 决定是要将实例加入域,还是要使用无域 gMSA。
    • 将 EC2 实例加入 Active Directory 域

      • 按用户数据加入实例

        在 EC2 启动模板中,将加入 Active Directory 域的步骤添加到 EC2 用户数据中。多个 Amazon EC2 Auto Scaling 组可以使用同一个启动模板。

        您可以使用 Fedora 文档中的这些步骤加入 Active Directory 或 FreeIPA 域

    • 为无域 gMSA 创建 Active Directory 用户

      credentials-fetcher 进程守护程序有一个称为无域 gMSA 的功能。此功能需要域,但是无需 EC2 实例加入该域。通过使用无域 gMSA,容器实例不会加入该域,实例上的其他应用程序无法使用凭证访问该域,并且加入不同域的任务可以在同一个实例上运行。相反,您可以在 CredSpec 文件中的 AWS Secrets Manager 中提供密钥的名称。密钥必须包含用户名、密码和要登录到的域。

      该功能受支持,并且可以与 Linux 和 Windows 容器结合使用。

      此功能与该 gMSA support for non-domain-joined container hosts 功能类似。有关 Windows 功能的更多信息,请参阅 Microsoft Learn 网站上的 gMSA 架构和改进

      1. 在 Active Directory 域中创建用户。Active Directory 中的用户必须具有访问您在任务中使用的 gMSA 服务账户的权限。

      2. 在 Active Directory 中创建用户后,请在 AWS Secrets Manager 中创建密钥。有关更多信息,请参阅创建一个 AWS Secrets Manager 密钥

      3. 将用户的用户名、密码和域分别输入名为 usernamepassworddomainName 的 JSON 键值对。

        {"username":"username","password":"passw0rd", "domainName":"example.com"}
      4. 向 CredSpec 文件中添加服务账户的配置。其他 HostAccountConfig 中包含 Secrets Manager 密钥的 Amazon 资源名称(ARN)。

        在 Windows 上,PluginGUID 必须与以下示例代码段中的 GUID 相匹配。在 Linux 上,PluginGUID 会被忽略。将 MySecret 示例替换为密钥的 Amazon 资源名称(ARN)。

        "ActiveDirectoryConfig": { "HostAccountConfig": { "PortableCcgVersion": "1", "PluginGUID": "{859E1386-BDB4-49E8-85C7-3070B13920E1}", "PluginInput": { "CredentialArn": "arn:aws:secretsmanager:aws-region:111122223333:secret:MySecret" } }
      5. 无域 gMSA 功能需要任务执行角色中的额外权限。执行步骤 (可选)无域 gMSA 密钥

  2. 配置实例并安装 credentials-fetcher 进程守护程序

    您可以在 EC2 启动模板中使用用户数据脚本安装 credentials-fetcher 进程守护程序。以下示例演示了两种类型的用户数据,cloud-config YAML 或 bash 脚本。这些示例适用于 Amazon Linux 2023(AL2023)。将 MyCluster 替换为要让这些实例加入的 Amazon ECS 集群的名称。

    • cloud-config YAML
      Content-Type: text/cloud-config package_reboot_if_required: true packages: # prerequisites - dotnet - realmd - oddjob - oddjob-mkhomedir - sssd - adcli - krb5-workstation - samba-common-tools # https://github.com/aws/credentials-fetcher gMSA credentials management for containers - credentials-fetcher write_files: # configure the ECS Agent to join your cluster. # replace MyCluster with the name of your cluster. - path: /etc/ecs/ecs.config owner: root:root permissions: '0644' content: | ECS_CLUSTER=MyCluster ECS_GMSA_SUPPORTED=true runcmd: # start the credentials-fetcher daemon and if it succeeded, make it start after every reboot - "systemctl start credentials-fetcher" - "systemctl is-active credentials-fetcher && systemctl enable credentials-fetcher"
    • bash 脚本

      如果您更熟悉 bash 脚本并且有多个变量要写入 /etc/ecs/ecs.config,请使用以下 heredoc 格式。此格式会将以 catEOF 开头的行之间的所有内容写入到配置文件。

      #!/usr/bin/env bash set -euxo pipefail # prerequisites timeout 30 dnf install -y dotnet realmd oddjob oddjob-mkhomedir sssd adcli krb5-workstation samba-common-tools # install https://github.com/aws/credentials-fetcher gMSA credentials management for containers timeout 30 dnf install -y credentials-fetcher # start credentials-fetcher systemctl start credentials-fetcher systemctl is-active credentials-fetcher && systemctl enable credentials-fetcher cat <<'EOF' >> /etc/ecs/ecs.config ECS_CLUSTER=MyCluster ECS_GMSA_SUPPORTED=true EOF

    您可以在 /etc/ecs/ecs.config 中设置的 credentials-fetcher 进程守护程序有一些可选的配置变量。建议您在 YAML 块中或类似于前面的示例的 heredoc 中设置用户数据中的变量。这样,在多次编辑文件时,可以防止可能出现的部分配置问题。有关 ECS 代理配置的更多信息,请参阅 GitHub 上的 Amazon ECS 容器代理

    • 或者,如果您更改 credentials-fetcher 进程守护程序配置以将套接字移到其他位置,则可以使用变量 CREDENTIALS_FETCHER_HOST

设置权限和密钥

针对每个应用程序和每个任务定义,执行一次以下步骤。建议您使用以下最佳实践:授予最低权限和限制策略中使用的权限。这样,每个任务只能读取它需要的密钥。

  1. (可选)无域 gMSA 密钥

    如果您使用实例未加入域的无域方法,请按照此步骤操作。

    您还必须将以下权限作为内联策略添加到任务执行 IAM 角色。这样做可以让 credentials-fetcher 进程守护程序访问 Secrets Manager 密钥。将 MySecret 示例替换为 Resource 列表中的密钥的 Amazon 资源名称(ARN)。

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": [ "arn:aws:ssm:aws-region:111122223333:secret:MySecret" ] } ] }
    注意

    如果您使用自己的 KMS 密钥来加密您的密钥,则必须向该角色添加必要的权限并将此角色添加到 AWS KMS 密钥政策中。

  2. 决定是使用 SSM Parameter Store 还是 S3 来存储 CredSpec

    Amazon ECS 支持使用以下方法在任务定义的 credentialSpecs 字段中引用文件路径。

    如果您将实例加入单个域,请使用字符串中 ARN 开头的前缀 credentialspec:。如果您使用无域 gMSA,则使用 credentialspecdomainless:

    有关 CredSpec 的更多信息,请参阅 凭证规范文件

    • Amazon S3 存储桶

      将凭证规范添加到 Amazon S3 存储桶。然后在任务定义的 credentialSpecs 字段中引用 Amazon S3 存储桶的 Amazon 资源名称(ARN)。

      { "family": "", "executionRoleArn": "", "containerDefinitions": [ { "name": "", ... "credentialSpecs": [ "credentialspecdomainless:arn:aws:s3:::${BucketName}/${ObjectName}" ], ... } ], ... }

      为了让您的任务可以访问 S3 存储桶,请将以下权限作为内联策略添加到 Amazon ECS 任务执行 IAM 角色中。

      { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor", "Effect": "Allow", "Action": [ "s3:Get*", "s3:List*" ], "Resource": [ "arn:aws:s3:::amzn-s3-demo-bucket", "arn:aws:s3:::amzn-s3-demo-bucket/{object}" ] } ] }
    • SSM Parameter Store 参数

      将凭证规范添加到 SSM Parameter Store 参数中。然后在任务定义的 credentialSpecs 字段中引用 SSM Parameter Store 参数的 Amazon 资源名称(ARN)。

      { "family": "", "executionRoleArn": "", "containerDefinitions": [ { "name": "", ... "credentialSpecs": [ "credentialspecdomainless:arn:aws:ssm:aws-region:111122223333:parameter/parameter_name" ], ... } ], ... }

      为了让您的任务可以访问 SSM Parameter Store 参数,请将以下权限作为内联策略添加到 Amazon ECS 任务执行 IAM 角色。

      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:GetParameters" ], "Resource": [ "arn:aws:ssm:aws-region:111122223333:parameter/parameter_name" ] } ] }

凭证规范文件

Amazon ECS 使用 Active Directory 凭证规范文件(CredSpec)。该文件包含用于将 gMSA 账户上下文传播到 Linux 容器的 gMSA 元数据。您可以生成 CredSpec 并在任务定义的 credentialSpecs 字段中引用该文件。CredSpec 文件不包含任何机密。

下面是一个 CredSpec 示例文件。

{ "CmsPlugins": [ "ActiveDirectory" ], "DomainJoinConfig": { "Sid": "S-1-5-21-2554468230-2647958158-2204241789", "MachineAccountName": "WebApp01", "Guid": "8665abd4-e947-4dd0-9a51-f8254943c90b", "DnsTreeName": "example.com", "DnsName": "example.com", "NetBiosName": "example" }, "ActiveDirectoryConfig": { "GroupManagedServiceAccounts": [ { "Name": "WebApp01", "Scope": "example.com" } ], "HostAccountConfig": { "PortableCcgVersion": "1", "PluginGUID": "{859E1386-BDB4-49E8-85C7-3070B13920E1}", "PluginInput": { "CredentialArn": "arn:aws:secretsmanager:aws-region:111122223333:secret:MySecret" } } } }
创建CredSpec

您可以通过在已加入域的 Windows 计算机上使用 CredSpec PowerShell 模块来创建 CredSpec。按照 Microsoft Learn 网站上的创建凭证规范中的步骤进行操作。