You can inject AWS Secrets Manager values into ECS task containers by using the secrets parameter in your task definition. This parameter allows you to map secrets stored in Secrets Manager to environment variables within your container.
Here’s how it works:
1. Create a Secret in AWS Secrets Manager
First, you need to have a secret stored in AWS Secrets Manager. If you don’t have one, you can create it through the AWS Management Console or using the AWS CLI.
For example, to create a secret named my-database-credentials with a JSON payload:
aws secretsmanager create-secret \
--name my-database-credentials \
--secret-string '{"username": "admin", "password": "supersecretpassword123"}'
2. Update Your ECS Task Definition
Next, you’ll modify your ECS task definition to reference the secret. This is done within the containerDefinitions section, using the secrets parameter.
Here’s an example of a task definition snippet:
{
"containerDefinitions": [
{
"name": "my-application-container",
"image": "my-docker-repo/my-application:latest",
"environment": [
{
"name": "DB_USERNAME",
"value": "admin" // This can be a hardcoded value if the secret only contains the password
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-database-credentials:password::"
}
],
"portMappings": [
{
"containerPort": 80,
"hostPort": 80
}
]
}
]
}
Explanation of the secrets parameter:
name: This is the name of the environment variable that will be created inside your container. In the example above, it’sDB_PASSWORD.valueFrom: This is the ARN (Amazon Resource Name) of the secret in Secrets Manager. The formatarn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>:<key>is important.<region>: The AWS region where your secret is stored (e.g.,us-east-1).<account-id>: Your AWS account ID.<secret-name>: The name of your secret (e.g.,my-database-credentials).<key>: This part is crucial for extracting specific values from a JSON secret.- If your secret is a plain text string, you can omit the key part (e.g.,
arn:aws:secretsmanager:us-east-1:123456789012:secret:my-plain-text-secret). - If your secret is a JSON object, you specify the key within the JSON that you want to extract. For example,
passwordin{"username": "admin", "password": "supersecretpassword123"}. The::at the end signifies that you want the plain text value of that key.
- If your secret is a plain text string, you can omit the key part (e.g.,
Important Considerations:
-
IAM Permissions: The ECS task execution role needs permission to access AWS Secrets Manager. You’ll need to add a policy that grants
secretsmanager:GetSecretValuepermission for the specific secret(s) your task needs.{ "Version": "2012-01-01", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": [ "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-database-credentials" ] } ] } -
Secret Rotation: For sensitive information like database credentials, configure secret rotation in AWS Secrets Manager. This automates the process of updating your secrets.
-
Plaintext vs. JSON Secrets: You can store either a plain text string (e.g., an API key) or a JSON object (e.g., database credentials) in Secrets Manager. The
valueFromARN format adapts to both. -
Environment Variables vs. Mounts: While environment variables are common, for very large secrets or binary data, you might consider mounting secrets as files into your container using the
volumesandmountPointsparameters in your task definition, in conjunction with Secrets Manager. This is a more advanced pattern.
By using the secrets parameter, you avoid hardcoding sensitive information directly into your container images or task definitions, enhancing your application’s security posture.
When you successfully inject your secrets, the next challenge will be managing the lifecycle of these secrets, especially with features like rotation.