Mechanism per workload
| Workload | Identity mechanism |
|---|---|
| EC2 instance | Instance profile (IAM role) via IMDSv2 |
| ECS task | Task role (app) + task execution role (agent: pulls images, writes logs) |
| Lambda | Execution role |
| EKS pod | EKS Pod Identity (preferred for new setups) or IRSA |
| On-premises server / other cloud | IAM Roles Anywhere (X.509 certificates) or a workload-specific federation |
| CI/CD pipelines | OIDC federation (GitHub Actions, GitLab, Azure DevOps, etc.) |
| Human users | IAM Identity Center (not part of workload identity) |
If something uses an IAM user access key, it's almost always replaceable by one of these.
EKS Pod Identity vs IRSA
| EKS Pod Identity | IRSA | |
|---|---|---|
| Setup | Pod Identity Agent add-on + association (cluster, namespace, service account → role) | OIDC provider per cluster + role trust policy per cluster |
| Trust policy | Same trust (pods.eks.amazonaws.com) across clusters | Per-cluster OIDC issuer in each trust policy |
| Session tags | Automatically adds cluster/namespace/service account tags (useful for ABAC) | No automatic tags |
| Where it works | EKS (check support for Fargate / special cases) | EKS and self-managed clusters with OIDC |
aws eks create-pod-identity-association --cluster-name prod-eks --namespace orders \
--service-account orders-api --role-arn arn:aws:iam::123456789012:role/orders-api-pod
IAM Roles Anywhere for servers outside AWS
- A trust anchor (your private CA or AWS Private CA) and a profile mapping to roles.
- Servers present X.509 certificates and use the credential helper to get temporary credentials.
- Certificate lifecycle (issuance, renewal, revocation via CRL) becomes the key operational task.
Scope permissions well
| Technique | Use |
|---|---|
| One role per workload (not per team or account) | Small blast radius; clear audit trail |
| Resource ARNs and conditions | aws:SourceVpce, aws:ResourceTag, s3:prefix |
| ABAC with session tags | Pod Identity tags, e.g. allow access to secrets tagged with the same namespace |
| Permission boundaries | Let teams create roles without exceeding a ceiling |
| IAM Access Analyzer | Generate least-privilege policies from CloudTrail activity; find unused permissions |
Guardrails
- SCP denying
iam:CreateAccessKeyexcept for a small, approved set (with exceptions process). - IMDSv2 required (SCP + declarative policy) so instance credentials aren't exposed via SSRF.
- Alerts on new access keys and on roles with trust policies allowing external accounts.
- Regular review of roles unused for 90 days (last accessed info).
Migration from access keys
- Inventory keys: credential report, last used service and date.
- For each, identify the workload and its mechanism from the table above.
- Deploy the role; switch the workload; watch CloudTrail for the key's last use.
- Deactivate, wait, then delete the key.
Tip
Don't reuse the ECS task execution role as the task role. The execution role needs ECR and logs permissions for the agent; the application should only get what the application needs.
Checklist
- Mechanism chosen per workload type
- Pod Identity (or IRSA) standardised for EKS
- Roles Anywhere design for non-AWS servers, with certificate lifecycle
- One role per workload, least privilege, Access Analyzer review
- SCPs on access key creation and IMDSv2
- Remaining access keys migrated and deleted