Using gMSA for EC2 Linux containers on Amazon ECS
Amazon ECS supports Active Directory authentication for Linux containers on EC2 through a special kind of service account called a group Managed Service Account (gMSA).
Linux based network applications, such as .NET Core applications, can use Active Directory to facilitate authentication and authorization management between users and services. You can use this feature by designing applications that integrate with Active Directory and run on domain-joined servers. But, because Linux containers can't be domain-joined, you need to configure a Linux container to run with gMSA.
A Linux container that runs with gMSA relies on the credentials-fetcher
daemon that runs on
the container's host Amazon EC2 instance. That is, the daemon retrieves the gMSA credentials
from the Active Directory domain controller and then transfers these credentials to the
container instance. For more information about service accounts, see Create gMSAs for Windows containers
Considerations
Consider the following before you use gMSA for Linux containers:
-
If your containers run on EC2, you can use gMSA for Windows containers and Linux containers. For information about how to use gMSA for Linux container on Fargate, see Using gMSA for Linux containers on Fargate.
-
You might need a Windows computer that's joined to the domain to complete the prerequisites. For example, you might need a Windows computer that's joined to the domain to create the gMSA in Active Directory with PowerShell. The RSAT Active Director PowerShell tools are only available for Windows. For more information, see Installing the Active Directory administration tools.
-
You chose between domainless gMSA and joining each instance to a single domain. By using domainless gMSA, the container instance isn't joined to the domain, other applications on the instance can't use the credentials to access the domain, and tasks that join different domains can run on the same instance.
Then, choose the data storage for the CredSpec and optionally, for the Active Directory user credentials for domainless gMSA.
Amazon ECS uses an Active Directory credential specification file (CredSpec). This file contains the gMSA metadata that's used to propagate the gMSA account context to the container. You generate the CredSpec file and then store it in one of the CredSpec storage options in the following table, specific to the Operating System of the container instances. To use the domainless method, an optional section in the CredSpec file can specify credentials in one of the domainless user credentials storage options in the following table, specific to the Operating System of the container instances.
Storage location Linux Windows Amazon Simple Storage Service CredSpec CredSpec Amazon Secrets Manager domainless user credentials domainless user credentials Amazon EC2 Systems Manager Parameter Store CredSpec CredSpec, domainless user credentials Local file N/A CredSpec
Prerequisites
Before you use the gMSA for Linux containers feature with Amazon ECS, make sure to complete the following:
-
You set up an Active Directory domain with the resources that you want your containers to access. Amazon ECS supports the following setups:
-
An Amazon Directory Service Active Directory. Amazon Directory Service is an Amazon managed Active Directory that's hosted on Amazon EC2. For more information, see Getting Started with Amazon Managed Microsoft AD in the Amazon Directory Service Administration Guide.
-
An on-premises Active Directory. You must ensure that the Amazon ECS Linux container instance can join the domain. For more information, see Amazon Direct Connect.
-
-
You have an existing gMSA account in the Active Directory. For more information, see Using gMSA for EC2 Linux containers on Amazon ECS.
-
You installed and are running the
credentials-fetcher
daemon on an Amazon ECS Linux container instance. You also added an initial set of credentials to thecredentials-fetcher
daemon to authenticate with the Active Directory.Note
The
credentials-fetcher
daemon is only available for Amazon Linux 2023 and Fedora 37 and later. The daemon isn't available for Amazon Linux 2. For more information, see aws/credentials-fetcheron GitHub. -
You set up the credentials for the
credentials-fetcher
daemon to authenticate with the Active Directory. The credentials must be a member of the Active Directory security group that has access to the gMSA account. There are multiple options in Decide if you want to join the instances to the domain, or use domainless gMSA.. -
You added the required IAM permissions. The permissions that are required depend on the methods that you choose for the initial credentials and for storing the credential specification:
-
If you use domainless gMSA for initial credentials, IAM permissions for Amazon Secrets Manager are required on the task execution role.
-
If you store the credential specification in SSM Parameter Store, IAM permissions for Amazon EC2 Systems Manager Parameter Store are required on the task execution role.
-
If you store the credential specification in Amazon S3, IAM permissions for Amazon Simple Storage Service are required on the task execution role.
-
Setting up gMSA-capable Linux Containers on Amazon ECS
Prepare the infrastructure
The following steps are considerations and setup that are performed once. After you complete these steps, you can automate creating container instances to reuse this configuration.
Decide how the initial credentials are provided and configure the EC2 user data in a
reusable EC2 launch template to install the credentials-fetcher
daemon.
-
Decide if you want to join the instances to the domain, or use domainless gMSA.
-
Join EC2 instances to the Active Directory domain
-
Join the instances by user data
Add the steps to join the Active Directory domain to your EC2 user data in an EC2 launch template. Multiple Amazon EC2 Auto Scaling groups can use the same launch template.
You can use these steps Joining an Active Directory or FreeIPA domain
in the Fedora Docs.
-
-
Make an Active Directory user for domainless gMSA
The
credentials-fetcher
daemon has a feature that's called domainless gMSA. This feature requires a domain, but the EC2 instance doesn't need to be joined to the domain. By using domainless gMSA, the container instance isn't joined to the domain, other applications on the instance can't use the credentials to access the domain, and tasks that join different domains can run on the same instance. Instead, you provide the name of a secret in Amazon Secrets Manager in the CredSpec file. The secret must contain a username, password, and the domain to log in to.This feature is supported and can be used with Linux and Windows containers.
This feature is similar to the gMSA support for non-domain-joined container hosts feature. For more information about the Windows feature, see gMSA architecture and improvements
on the Microsoft Learn website. -
Make a user in your Active Directory domain. The user in Active Directory must have permission to access the gMSA service accounts that you use in the tasks.
-
Create a secret in Amazon Secrets Manager, after you made the user in Active Directory. For more information, see Create an Amazon Secrets Manager secret.
-
Enter the user's username, password, and the domain into JSON key-value pairs called
username
,password
anddomainName
, respectively.{"username":"
username
","password":"passw0rd
", "domainName":"example.com"} -
Add configuration to the CredSpec file for the service account. The additional
HostAccountConfig
contains the Amazon Resource Name (ARN) of the secret in Secrets Manager.On Windows, the
PluginGUID
must match the GUID in the following example snippet. On Linux, thePluginGUID
is ignored. ReplaceMySecret
with example with the Amazon Resource Name (ARN) of your secret."ActiveDirectoryConfig": { "HostAccountConfig": { "PortableCcgVersion": "1", "PluginGUID": "{859E1386-BDB4-49E8-85C7-3070B13920E1}", "PluginInput": { "CredentialArn": "
arn:aws:secretsmanager:
" } }aws-region
:111122223333:secret:MySecret -
The domainless gMSA feature needs additional permissions in the task execution role. Follow the step (Optional) domainless gMSA secret.
-
-
-
Configure instances and install
credentials-fetcher
daemonYou can install the
credentials-fetcher
daemon with a user data script in your EC2 Launch Template. The following examples demonstrate two types of user data,cloud-config
YAML or bash script. These examples are for Amazon Linux 2023 (AL2023). ReplaceMyCluster
with the name of the Amazon ECS cluster that you want these instances to join.-
cloud-config
YAMLContent-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 script
If you're more comfortable with bash scripts and have multiple variables to write to
/etc/ecs/ecs.config
, use the followingheredoc
format. This format writes everything between the lines beginning with cat andEOF
to the configuration file.#!/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
There are optional configuration variables for the
credentials-fetcher
daemon that you can set in/etc/ecs/ecs.config
. We recommend that you set the variables in the user data in the YAML block orheredoc
similar to the previous examples. Doing so prevents issues with partial configuration that can happen with editing a file multiple times. For more information about the ECS agent configuration, see Amazon ECS Container Agenton GitHub. -
Optionally, you can use the variable
CREDENTIALS_FETCHER_HOST
if you change thecredentials-fetcher
daemon configuration to move the socket to another location.
-
Setting up permissions and secrets
Do the following steps once for each application and each task definition. We recommend that you use the best practice of granting the least privilege and narrow the permissions used in the policy. This way, each task can only read the secrets that it needs.
-
(Optional) domainless gMSA secret
If you use the domainless method where the instance isn't joined to the domain, follow this step.
You must add the following permissions as an inline policy to the task execution IAM role. Doing so gives the
credentials-fetcher
daemon access to the Secrets Manager secret. Replace theMySecret
example with the Amazon Resource Name (ARN) of your secret in theResource
list.{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": [ "
arn:aws:ssm:
" ] } ] }aws-region
:111122223333:secret:MySecretNote
If you use your own KMS key to encrypt your secret, you must add the necessary permissions to this role and add this role to the Amazon KMS key policy.
-
Decide if you're using SSM Parameter Store or S3 to store the CredSpec
Amazon ECS supports the following ways to reference the file path in the
credentialSpecs
field of the task definition.If you join the instances to a single domain, use the prefix
credentialspec:
at the start of the ARN in the string. If you use domainless gMSA, then usecredentialspecdomainless:
.For more information about the CredSpec, see Credential specification file.
-
Amazon S3 Bucket
Add the credential spec to an Amazon S3 bucket. Then, reference the Amazon Resource Name (ARN) of the Amazon S3 bucket in the
credentialSpecs
field of the task definition.{ "family": "", "executionRoleArn": "", "containerDefinitions": [ { "name": "", ... "credentialSpecs": [ "credentialspecdomainless:arn:aws:s3:::
${BucketName}/${ObjectName}
" ], ... } ], ... }To give your tasks access to the S3 bucket, add the following permissions as an inline policy to the Amazon ECS task execution IAM role.
{ "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 parameter
Add the credential spec to an SSM Parameter Store parameter. Then, reference the Amazon Resource Name (ARN) of the SSM Parameter Store parameter in the
credentialSpecs
field of the task definition.{ "family": "", "executionRoleArn": "", "containerDefinitions": [ { "name": "", ... "credentialSpecs": [ "credentialspecdomainless:arn:aws:ssm:
aws-region
:111122223333
:parameter/parameter_name
" ], ... } ], ... }To give your tasks access to the SSM Parameter Store parameter, add the following permissions as an inline policy to the Amazon ECS task execution IAM role.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:GetParameters" ], "Resource": [ "arn:aws:ssm:
aws-region
:111122223333
:parameter/parameter_name
" ] } ] }
-
Credential specification file
Amazon ECS uses an Active Directory credential specification file
(CredSpec). This file contains the gMSA metadata that's
used to propagate the gMSA account context to the Linux container. You
generate the CredSpec and reference it in the credentialSpecs
field in
your task definition. The CredSpec file doesn't contain any secrets.
The following is an example CredSpec file.
{
"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
"
}
}
}
}
Creating a CredSpec
You create a CredSpec by using the CredSpec PowerShell module
on a Windows computer that's joined to the domain. Follow the steps
in Create a credential spec