IAM roles
After this you can answer: What is the difference between a task role and a task execution role?
Picture it
Section titled “Picture it”flowchart TB ECS["ECS agent"] -->|"uses"| EX["api execution role"] EX --> E1["pull image; send logs"] EX --> E2["read 3 secrets"] CODE["api container"] -->|"uses credentials for"| TR["api task role"] TR --> T1["SNS publish; DynamoDB Query"] TR --> T2["S3 prefixes; ECS Exec channels"]How it works
Section titled “How it works”- Trust policy: who may assume the role. Both api roles trust only
ecs-tasks.amazonaws.com, and only whenaws:SourceAccountis our account. That stops another account’s ECS from using them. - Permission policy: what the role may do. Each statement names actions and resources, for
example
sns:Publishon one topic ARN. - Assuming gives short-lived credentials. ECS provides task-role credentials through a container endpoint; the SDK finds them. Execution-role credentials stay with the agent.
- Two roles, separate permissions. The execution role supports startup and logs. The task role permits app AWS calls. It cannot call Secrets Manager, but the code can read injected secret values.
In MiniTickets
Section titled “In MiniTickets”All three roles are made in infra/src/compute/iam.ts → createIamRoles and
infra/src/compute/web-iam.ts → createWebIamRole:
| Role | Used by | May do |
|---|---|---|
minitickets-dev-api-execution-role | ECS, api and migration tasks | ECR pull, log writes, read 3 secrets with entry on; 2 otherwise |
minitickets-dev-api-task-role | the api code | publish to booking-events, query the tickets table, some S3 prefixes, ECS Exec |
minitickets-dev-web-execution-role | ECS, web tasks | ECR pull, log writes, read only the revalidate secret |
The web task has no task role: the Next.js code calls no AWS API.
The task role’s exact statements, generated from the code:
Who may assume API task role: API task definition
What it may do:
| On | Actions | Policy | Why only this |
|---|---|---|---|
| Booking-events SNS topic | sns:Publish | identity send-jobs createIamRoles | The outbox relay publishes booking events. The api cannot read either queue: SNS delivers to them with the queues' own policies. |
| Tickets table | dynamodb:Query | identity ReadTickets createIamRoles | My tickets is one Query on the userId partition. No Scan, and no writes: only the tickets Lambda writes tickets. |
| Ticket assets buckettickets/* only | s3:GetObject | identity ReadTicketPngs createIamRoles | A presigned ticket GET works with the signer's permissions, so the api role must be allowed to read the ticket PNG it signs. |
| Ticket assets bucketposters/* and poster-uploads/* only | s3:GetObject | identity ReadPosters createIamRoles | The api reads staged uploads to check them before publishing, and reads poster objects. This separate statement grants no ticket writes. |
| Ticket assets bucketposters/* and poster-uploads/* only | s3:PutObjectif s3:x-amz-server-side-encryption = AES256 | identity WritePosters createIamRoles | The browser's presigned poster PUT and the copy to posters/ run with this role. It can never overwrite tickets/. |
| API ECS serviceResource * (these actions cannot be limited to one resource) | ssmmessages:CreateControlChannelssmmessages:CreateDataChannelssmmessages:OpenControlChannelssmmessages:OpenDataChannel | identity ecs-exec createIamRoles | ECS Exec opens a debug shell inside the api task, which can reach RDS and Valkey from inside the VPC. |
See it in AWS
Section titled “See it in AWS”IAM → Roles → minitickets-dev-api-task-role → Permissions tab, then Trust relationships.
aws iam list-role-policies --role-name minitickets-dev-api-task-role
Break it
Section titled “Break it”| Symptom | Cause | Where to look |
|---|---|---|
| Tasks stop: AccessDeniedException on GetSecretValue | Execution role does not list that secret | Stopped reason; read-secrets policy |
| Bookings work, no email; “outbox delivery failed” | Task role lost sns:Publish | send-jobs policy |
| First deploy of a new role fails once, retry works | IAM is eventually consistent | CD log at that time |
Say it in an interview
Section titled “Say it in an interview”Follow-ups
Section titled “Follow-ups”Why does the web task have its own execution role?
If it shared the api’s role, one wrong line in the web task definition could hand it the database password. Its own role may read only the revalidate secret, whatever the task definition asks for.
What is the confused deputy problem?
A trusted service is tricked into using its power for the wrong customer. The aws:SourceAccount
condition makes ECS assume our roles only when it acts for our account.
What is the trade-off of AmazonECSTaskExecutionRolePolicy?
Its ECR pull and log-write actions have Resource *, not our repository or log-group ARNs.
Other authorization rules still apply. It is maintained by AWS, but wider than our needs;
see the managed policy JSON.
Advanced: Every statement of the execution role
The execution role also sends logs after startup; its credentials are not exposed to containers. ECS supplies separate task-role credentials through its container endpoint, without the app calling STS. See AWS execution roles and task roles.
Who may assume API task execution role: API task definition, Migration task definition
What it may do:
| On | Actions | Policy | Why only this |
|---|---|---|---|
| ECR repositories, CloudWatch log groupsResource *; one AWS managed statement covers image pulls and log writes | ecr:GetAuthorizationTokenecr:BatchCheckLayerAvailabilityecr:GetDownloadUrlForLayerecr:BatchGetImagelogs:CreateLogStreamlogs:PutLogEvents | identity AmazonECSTaskExecutionRolePolicy (AWS managed, Resource *) createIamRoles | ECS pulls the image before startup, then the awslogs driver writes the container's output. The AWS managed statement applies to all repositories and log groups, not only ours. |
| RDS master password secret, Redis URL secret, Revalidate secretexactly these secret ARNs, never *; the revalidate secret only with entry on | secretsmanager:GetSecretValue | identity read-secrets createIamRoles | ECS puts DB_USER, DB_PASSWORD, REDIS_URL and REVALIDATE_SECRET into the container at start. No kms:Decrypt is needed: the secrets use the AWS managed key aws/secretsmanager. |
Checkpoint
Section titled “Checkpoint”Answer these without scrolling up. If one feels hard, reread that section.
- What do a trust policy and a permission policy each say?
- Which role pulls the image, and when?
- Why can the api read its injected database password, but not call Secrets Manager?
- What does the
aws:SourceAccountcondition protect against? - Why does the web task have no task role?
Redraw it from memory: ECS using the execution role (image, secrets, logs) and the container using task-role credentials (SNS, DynamoDB, S3, ECS Exec)
Try this: on the map, select the API task role and open the Permissions tab: what can it touch, and what can it NOT touch?
Read this book online: https://book.theversehub.in/