AWS ECS Task Credentials: IAM Roles, Metadata Endpoints, and Secure Application Access
Learn how ECS task roles provide temporary AWS credentials to containers, how task and execution roles differ, how SDKs retrieve credentials, and how to configure and troubleshoot access securely.
AWS ECS task credentials let application containers call AWS services without storing long-lived access keys in images, task definitions, or environment variables. ECS associates an IAM task role with a running task and makes temporary security credentials available through a container credential endpoint.
This lesson explains the difference between task and execution roles, how SDKs discover credentials, how ECS on EC2 differs from Fargate, and how to design, verify, and troubleshoot least-privilege access.
Prerequisites and core terms
You should understand IAM policies and roles, ECS clusters, services, tasks, task definitions, containers, Docker basics, ARNs, AWS Regions, and the AWS SDK credential provider chain.
Temporary security credentials are short-lived credentials containing an access key ID, secret access key, session token, and expiration time. AWS Security Token Service (STS) issues and represents credentials for assumed roles.
A credential provider chain is the ordered set of sources an AWS SDK or tool checks when looking for credentials. Modern SDKs can select ECS task credentials automatically when the container credential environment is correctly configured.
Why ECS tasks need their own credentials
An ECS task is a unit of deployment that can contain one or more containers. The task role gives application code in those containers an AWS identity. This identity is separate from the identity used by ECS components to start and manage the task.
On ECS on EC2, the container instance has an EC2 instance profile. That profile is intended for the ECS agent and host operations, not for arbitrary application code. If a container can obtain the host instance-profile credentials, it may gain permissions intended for every workload on that host.
On Fargate, AWS operates the underlying compute infrastructure, but the application still needs a task role for AWS API calls. Fargate's infrastructure isolation does not make a broad task role safe.
- Automatic rotation: credentials expire and ECS supplies refreshed credentials, reducing manual key rotation work.
- Scoped permissions: each workload can receive only the API actions and resources it needs.
- Per-task identity: CloudTrail and other audit systems can attribute calls to an assumed task role.
- Reduced secret sprawl: keys do not need to be embedded in images, committed to source control, or copied into task definitions.
Do not normally pass AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY containing long-lived IAM user keys into a task. An exceptional use case should be documented, reviewed, and protected with a safer alternative whenever possible.
Task role versus task execution role
| Characteristic | Task role | Task execution role |
|---|---|---|
| Setting | taskRoleArn | executionRoleArn |
| Primary user | Application code inside task containers | ECS-related components and supported AWS integrations |
| Typical permissions | Read S3 objects, write DynamoDB records, call application AWS APIs, or retrieve secrets at runtime | Pull private images, publish logs, and retrieve secrets injected during task startup |
| Automatically shared? | Available to application containers in the task through the task credential endpoint | Not automatically available as application permissions |
| Security goal | Least-privilege runtime access for the workload | Least-privilege startup and managed-operation access |
The task role authorizes AWS API requests made by application code. The execution role authorizes ECS and related services to perform operations such as retrieving an image from a private registry, sending container logs, and obtaining specified secrets during startup.
How ECS delivers task credentials
- You create an IAM role whose trust policy allows the ECS tasks service principal to assume it.
- You reference the role ARN in
taskRoleArnin the task definition. - ECS starts a task from a registered task definition revision.
- ECS makes a local container credential endpoint available and supplies the endpoint location through the container environment.
- The AWS SDK or CLI requests temporary credentials from that endpoint when it needs to sign an AWS API request.
- ECS refreshes the credentials before expiration, and a supported SDK refreshes its provider when necessary.
For ECS on EC2, the ECS container agent participates in task credential delivery. For Fargate, the platform provides the managed implementation. Exact endpoint behavior can vary by launch type, operating system, ECS agent or platform version, and networking mode.
SDKs commonly discover the endpoint through these environment variables:
AWS_CONTAINER_CREDENTIALS_RELATIVE_URIidentifies an ECS credential path relative to the link-local credential host.AWS_CONTAINER_CREDENTIALS_FULL_URIprovides a complete URI for a container credential provider endpoint.
The response conceptually contains an access key ID, secret access key, session token, expiration, and role context. Treat the response as secret material. Do not print it to logs, tickets, crash reports, or debugging output.
EC2 and Fargate behavior
| Environment | Who operates the underlying host | Why task-role isolation matters | Key configuration considerations |
|---|---|---|---|
| ECS on EC2 | You operate the EC2 container instances and their instance profiles | A compromised or misconfigured container might otherwise reach host credentials | Review instance-profile permissions, agent version, credential endpoint access, proxy settings, and bridge, host, or awsvpc networking |
| AWS Fargate | AWS operates the underlying infrastructure | The task role still defines application API permissions and should remain narrowly scoped | Review Fargate platform version, task definition, networking, security groups, and endpoint behavior |
With bridge networking, containers use Docker networking and host-level routing considerations. Host networking gives a container a closer relationship to the host network and requires careful isolation review. With awsvpc, the task receives its own elastic network interface and security-group context, which improves network separation but does not replace IAM controls.
On EC2, use task roles rather than relying on the instance profile. Keep the instance profile limited to ECS host operations, and follow the security guidance for preventing containers from reaching unintended instance metadata or credential paths.
Configure an ECS task role
1. Create a trust policy
The role trust policy states who may assume the role. An ECS task role normally trusts the ecs-tasks.amazonaws.com service principal.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "ecs-tasks.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
2. Attach a least-privilege permissions policy
Grant only the actions and resources required by the application. Use resource ARNs, conditions, Regions, encryption constraints, and service-specific resource policies where supported.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadApplicationPrefix",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example-data-bucket/app/input/*"
},
{
"Sid": "ListOnlyApplicationPrefix",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example-data-bucket",
"Condition": {
"StringLike": {
"s3:prefix": ["app/input/*"]
}
}
}
]
}
The exact actions must match application behavior. If the application only reads known object keys, it may not need s3:ListBucket. A DynamoDB writer might need dynamodb:PutItem on one table ARN and no permission to scan or administer the table.
| Application need | Example AWS actions | Resource scope | Additional considerations |
|---|---|---|---|
| Read one S3 prefix | s3:GetObject; possibly s3:ListBucket | Object prefix and one bucket ARN | Use an s3:prefix condition for listing; account for bucket policies and encryption |
| Write DynamoDB records | dynamodb:PutItem, possibly dynamodb:UpdateItem | One table ARN | Check table, index, VPC endpoint, SCP, and resource-policy restrictions |
| Read one secret | secretsmanager:GetSecretValue | One secret ARN | Add narrowly scoped kms:Decrypt when a customer-managed KMS key is used |
| Read one parameter | ssm:GetParameter | One parameter ARN | Check KMS permissions for encrypted parameters |
3. Reference both roles in the task definition
{
"family": "orders-worker",
"taskRoleArn": "arn:aws:iam::123456789012:role/orders-task-role",
"executionRoleArn": "arn:aws:iam::123456789012:role/orders-execution-role",
"networkMode": "awsvpc",
"containerDefinitions": [
{
"name": "worker",
"image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/orders:2026-08",
"essential": true
}
]
}
Register a new revision after changing the task role. Update the ECS service or run a task using that revision. Existing tasks do not automatically change identity merely because a role policy or task definition was edited.
4. Example CLI workflow
aws iam create-role \
--role-name orders-task-role \
--assume-role-policy-document file://ecs-tasks-trust.json
aws iam put-role-policy \
--role-name orders-task-role \
--policy-name orders-runtime-access \
--policy-document file://orders-runtime-policy.json
aws ecs register-task-definition \
--cli-input-json file://orders-task-definition.json
aws ecs describe-task-definition \
--task-definition orders-worker
aws ecs describe-tasks \
--cluster production \
--tasks TASK_ID
For reusable policies, an approved customer-managed policy can be attached with aws iam attach-role-policy. Verify the role ARN and the task definition revision shown by describe-task-definition and describe-tasks.
Use the default SDK credential chain
The preferred integration is to create an SDK client without passing access keys. The SDK selects ECS task credentials through its default provider chain.
import boto3
from botocore.exceptions import ClientError
s3 = boto3.client("s3")
try:
response = s3.get_object(
Bucket="example-data-bucket",
Key="app/input/job.json"
)
body = response["Body"].read()
except ClientError as error:
code = error.response.get("Error", {}).get("Code")
if code in ("AccessDenied", "AllAccessDisabled"):
raise RuntimeError("Task role is not authorized for this object") from error
raise
Do not construct the client with static keys. In long-running applications, reuse the SDK client and its refresh-capable credential provider. Do not extract credentials into application variables and cache the raw fields yourself.
The AWS CLI can also use task credentials inside a container when no higher-precedence static source overrides the default chain:
aws sts get-caller-identity
A successful result commonly has an assumed-role ARN resembling arn:aws:sts::123456789012:assumed-role/orders-task-role/session-name. The exact session name varies.
Directly inspecting the credential endpoint can help diagnose endpoint or provider problems, but it is not the normal application integration pattern. Perform such inspection only in an authorized debugging context and never record the returned credential material.
Credential sources and precedence in containers
| Credential source | Typical use | Risk or caveat | Recommended practice |
|---|---|---|---|
| Static environment variables | Legacy configuration or controlled tests | May expose long-lived keys through task definitions, process inspection, logs, or dumps | Do not use for normal ECS workloads |
| Mounted shared credentials file | Local development or specialized tooling | Can override task identity and may contain user credentials | Keep out of production tasks unless explicitly required |
| Instance-profile credentials | EC2 host operations | May grant host-level permissions to a container if isolation or provider behavior is wrong | Use a task role and restrict host permissions |
| ECS container credentials | Normal application access in ECS | Unavailable outside ECS and dependent on task configuration and endpoint connectivity | Use the SDK default provider chain |
| Local developer credentials | Running the same code on a workstation | Not the identity used by a deployed task | Use a separate development role or profile with equivalent, limited permissions |
Application-specific configuration can change provider precedence. Invalid static variables or a credentials file can cause the SDK to ignore the intended ECS provider. Test the effective caller identity rather than assuming the task role is active.
Secrets and configuration
Task credentials are not the same as application secrets. A database password, OAuth client secret, and external API token are secret values; the task role is an AWS identity that can authorize access to AWS APIs.
One pattern is runtime retrieval: grant the task role permission to read one Secrets Manager secret or Systems Manager Parameter Store parameter, then retrieve it with the SDK during startup or on demand. If a customer-managed KMS key encrypts the value, the task role may also need a narrowly scoped kms:Decrypt permission, and the key policy must permit the role.
Another pattern is ECS startup-time secret injection. ECS obtains specified secret values while starting the task; this commonly depends on the execution role. That is different from application code calling Secrets Manager or Parameter Store at runtime.
- Environment-variable injection is convenient but can expose values through process inspection, diagnostics, crash dumps, or accidental logging.
- SDK retrieval keeps values out of the task definition and can support on-demand refresh, but requires runtime AWS connectivity and careful caching.
- Whichever pattern you use, never log secret values or place them in image layers, source code, shell history, or debugging tickets.
Security design and threat model
- Prefer one role per workload, or per group with a genuinely shared permission boundary, rather than one broad role for all tasks.
- Restrict actions, resource ARNs, Regions, encryption keys, and request conditions.
- Use S3 bucket policies, KMS key policies, Secrets Manager resource policies, DynamoDB resource controls, and VPC endpoint policies where applicable.
- Remember that permissions boundaries and AWS Organizations service control policies can limit a role even when its identity policy allows an action.
- Keep application permissions out of the EC2 container-instance role unless the host itself requires them.
- Protect endpoint responses, environment variables, logs, shell history, crash dumps, and outbound proxy logs from credential disclosure.
- Multiple containers in one task normally share the task role permission boundary. If a sidecar needs materially different AWS access, place it in a separate task when practical.
- Task roles authorize AWS API calls; they do not replace image scanning, network controls, secret handling, container isolation, or application-level authorization.
CloudTrail records can help attribute AWS API calls to assumed task roles. Combine CloudTrail with service logs, ECS task details, IAM policy simulation, and resource-policy review when investigating access.
Verification workflow
- Inspect the registered task definition and confirm
taskRoleArnis the intended role. - Inspect the running task and confirm it uses the expected revision.
- Run
aws sts get-caller-identityinside the container, or use an equivalent SDK STS call. - Compare the returned assumed-role identity with the intended task role.
- Use CloudTrail to verify the role responsible for a real service call.
- Use IAM policy simulation and service logs to examine denied actions.
Common failures and fixes
| Symptom | Likely cause | How to verify | Remediation |
|---|---|---|---|
AccessDenied from S3, DynamoDB, or another service | Missing action, wrong ARN, dependent permission, explicit deny, boundary, SCP, endpoint policy, or resource policy | Check the running task role, exact request ARN, policy simulation, CloudTrail, and related KMS permissions | Update the narrowest applicable identity or resource policy, deploy a new revision if needed, and retest |
| No credentials found | No taskRoleArn, old revision, incompatible SDK, invalid static override, or local execution outside ECS | Describe the task and inspect provider configuration and credential-related environment variables | Attach a valid task role, redeploy, remove inappropriate overrides, and use the default provider chain |
| Logs work but application calls fail | Permissions were granted only to the execution role | Compare execution-role and task-role policies | Put runtime permissions on the task role and retain startup permissions on the execution role |
| Expired-token errors after earlier success | Raw temporary credentials were cached without refresh | Review credential caching and SDK version | Use a supported refresh-capable SDK provider and do not persist raw fields |
| Credential endpoint cannot be reached | Networking, proxy handling, endpoint variables, agent, or platform problem | Check task networking, proxy exclusions, endpoint variables, agent/platform health, and logs | Correct connectivity and provider configuration; avoid exposing the endpoint outside its authorized task context |
| Unexpected EC2 instance-profile identity | Incorrect provider behavior, static override, networking exposure, or insufficient task isolation | Run STS identity verification and review EC2 networking, agent settings, and instance-profile permissions | Correct task-role use, reduce instance-profile permissions, and apply ECS isolation guidance |
| Encrypted secret cannot be retrieved | Secret read is allowed but KMS decrypt or key policy is missing | Check secret ARN, KMS key ARN and policy, account, and Region | Grant narrowly scoped secret-read and decrypt permissions and update the relevant resource policy |
Practical design examples
One S3 prefix
Give the task role s3:GetObject only for arn:aws:s3:::example-data-bucket/app/input/*. Add s3:ListBucket on the bucket only if the application lists objects, and constrain that action with an s3:prefix condition. Create the S3 client without explicit credentials.
DynamoDB writer
Grant only the write operations required by the application, such as dynamodb:PutItem, on the target table ARN. If the call is denied, verify the table ARN, dependent operations, VPC endpoint policy, SCP, permissions boundary, and any resource restrictions.
Runtime secret retrieval
Grant the task role access to one Secrets Manager secret or Parameter Store parameter. Add KMS decrypt only for the required customer-managed key. Keep the value out of the task definition and retrieve it with an SDK provider when the application starts or needs the value.
Separate application and execution permissions
The execution role may pull a private image and publish logs. The task role may write application records. Giving the execution role the record-writing permission does not authorize application code, because ECS uses the roles for different actors and purposes.
Multiple containers in one task
Containers in one task normally receive access governed by the same task role. A sidecar that can call AWS APIs therefore increases the exposure of that role. Use separate tasks when containers require materially different permissions.
Key takeaways
taskRoleArnsupplies the identity used by application code;executionRoleArnsupports ECS startup and managed operations.- Use temporary ECS task credentials through the SDK default provider chain instead of hard-coded keys.
- Design each task role with least privilege and verify the effective identity with STS.
- On EC2, prevent applications from falling back to host instance-profile credentials.
- Credential refresh, endpoint connectivity, policy evaluation, and task-definition revisions are common troubleshooting areas.
For related credential configuration concepts, see AWS credentials, AWS configuration, and EC2 security credentials.