了解了解如何将 gMSA 用于适用于 Amazon ECS 的 EC2 Windows 容器 - Amazon Elastic Container Service

了解了解如何将 gMSA 用于适用于 Amazon ECS 的 EC2 Windows 容器

Amazon ECS 通过组 Managed Service Account (gMSA )的特殊服务账户支持 Windows 容器的 Active Directory 身份验证。

基于 Windows 的网络应用程序(例如 .NET 应用程序)通常使用 Active Directory 来促进用户和服务之间的身份验证和授权管理。开发人员通常将其应用程序设计为与 Active Directory 集成,并为此在加入域的服务器上运行。由于 Windows 容器无法加入域,因此必须将 Windows 容器配置为使用 gMSA 运行。

使用 gMSA 运行的 Windows 容器依赖于其主机 Amazon EC2 实例从 Active Directory 域控制器检索 gMSA 凭据并将其提供给容器实例。有关详细信息,请参阅为 Windows 容器创建 gMSA

注意

Fargate 上的 Windows 容器不支持此功能。

注意事项

为 Windows 容器使用 gMSA 时,应考虑以下因素:

  • 为容器实例使用经 Amazon ECS 优化的 Windows Server 2016 Full AMI 时,容器主机名必须与凭证规范文件中定义的 gMSA 账户名相同。要为容器指定主机名,请使用 hostname 容器定义参数。有关更多信息,请参阅 Network settings (网络设置)

  • 您可以在无域 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 上为 Windows 容器使用 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 账户。有关详细信息,请参阅为 Windows 容器创建 gMSA

  • 您选择使用无域 gMSA,或托管 Amazon ECS 任务的 Amazon ECS Windows 容器实例必须是加入到 Active Directory 的,并且是有权访问 gMSA 账户的 Active Directory 安全组的成员。

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

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

    • 如果您使用无域 gMSA 作为初始凭证,则 Amazon EC2 实例角色需要 AWS Secrets Manager 的 IAM 权限。

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

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

在 Amazon ECS 上为 Windows 容器设置 gMSA

要在 Amazon ECS 上为 Windows 容器设置 gMSA,您可以按照包括配置先决条件 通过 AWS CLI 将 Amazon ECS Windows 容器与无域 gMSA 结合使用 在内的完整教程进行操作。

以下各节将详细介绍 CredSpec 配置。

示例 CredSpec

Amazon ECS 使用一个凭证规范文件,该文件包含用于将 gMSA 账户上下文传播到 Windows 容器的 gMSA 元数据。您可以生成凭证规范文件并在任务定义的 credentialSpec 字段中引用该文件。凭证规范文件不包含任何密钥。

下面是一个示例凭证规范文件:

{ "CmsPlugins": [ "ActiveDirectory" ], "DomainJoinConfig": { "Sid": "S-1-5-21-2554468230-2647958158-2204241789", "MachineAccountName": "WebApp01", "Guid": "8665abd4-e947-4dd0-9a51-f8254943c90b", "DnsTreeName": "contoso.com", "DnsName": "contoso.com", "NetBiosName": "contoso" }, "ActiveDirectoryConfig": { "GroupManagedServiceAccounts": [ { "Name": "WebApp01", "Scope": "contoso.com" } ] } }

无域 gMSA 设置

建议使用无域 gMSA,而不是将容器实例加入到单个域中。通过使用无域 gMSA,容器实例不会加入该域,实例上的其他应用程序无法使用凭证访问该域,并且加入不同域的任务可以在同一个实例上运行。

  1. 在将 CredSpec 上传到其中一个存储选项之前,请在 Secrets Manager 或 SSM Parameter Store 中使用密钥的 ARN 向 CredSpec 添加信息。有关更多信息,请参阅 Microsoft Learn 网站上的非加入域的容器主机应用场景的其他凭证规范配置

    无域 gMSA 凭证格式

    以下是 Active Directory 的无域 gMSA 凭证的 JSON 格式。将凭证存储在 Secrets Manager 或 SSM Parameter Store 中。

    { "username":"WebApp01", "password":"Test123!", "domainName":"contoso.com" }
  2. 将以下信息添加到 ActiveDirectoryConfig 内的 CredSpec 文件。将 ARN 替换为 Secrets Manager 或 SSM Parameter Store 中的密钥。

    请注意,PluginGUID 值必须与以下示例代码段中的 GUID 相匹配,并且是必填项。

    "HostAccountConfig": { "PortableCcgVersion": "1", "PluginGUID": "{859E1386-BDB4-49E8-85C7-3070B13920E1}", "PluginInput": "{\"credentialArn\": \"arn:aws:secretsmanager:aws-region:111122223333:secret:gmsa-plugin-input\"}" }

    您也可以使用以下格式的 ARN 在 SSM Parameter Store 中使用密钥:\"arn:aws:ssm:aws-region:111122223333:parameter/gmsa-plugin-input\"

  3. CredSpec 文件修改后,应类似于以下示例:

    { "CmsPlugins": [ "ActiveDirectory" ], "DomainJoinConfig": { "Sid": "S-1-5-21-4066351383-705263209-1606769140", "MachineAccountName": "WebApp01", "Guid": "ac822f13-583e-49f7-aa7b-284f9a8c97b6", "DnsTreeName": "contoso", "DnsName": "contoso", "NetBiosName": "contoso" }, "ActiveDirectoryConfig": { "GroupManagedServiceAccounts": [ { "Name": "WebApp01", "Scope": "contoso" }, { "Name": "WebApp01", "Scope": "contoso" } ], "HostAccountConfig": { "PortableCcgVersion": "1", "PluginGUID": "{859E1386-BDB4-49E8-85C7-3070B13920E1}", "PluginInput": "{\"credentialArn\": \"arn:aws:secretsmanager:aws-region:111122223333:secret:gmsa-plugin-input\"}" } } }

在任务定义中引用凭证规范文件

Amazon ECS 支持使用以下方法在任务定义的 credentialSpecs 字段中引用文件路径。对于这些选项中的每一个,您可以提供 credentialspec:domainlesscredentialspec:,具体取决于您是将容器实例加入单个域还是使用无域 gMSA。

Amazon S3 存储桶

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

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

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

{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor", "Effect": "Allow", "Action": [ "s3:Get*", "s3:List*" ], "Resource": [ "arn:aws:s3:::{bucket_name}", "arn:aws:s3:::{bucket_name}/{object}" ] } ] }

SSM Parameter Store 参数

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

{ "family": "", "executionRoleArn": "", "containerDefinitions": [ { "name": "", ... "credentialSpecs": [ "credentialspecdomainless:arn:aws:ssm: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:region:111122223333:parameter/parameter_name" ] } ] }

本地文件

使用本地文件中的凭证规范详细信息,在任务定义的 credentialSpecs 字段中引用文件路径。引用的文件路径必须相对于 C:\ProgramData\Docker\CredentialSpecs 目录,并使用反斜杠('\')作为文件路径分隔符。

{ "family": "", "executionRoleArn": "", "containerDefinitions": [ { "name": "", ... "credentialSpecs": [ "credentialspec:file://CredentialSpecDir\CredentialSpecFile.json" ], ... } ], ... }