Long-lived AWS access keys in CI are still one of the most common breach patterns. Prefer OIDC federation from GitHub Actions, GitLab, or Azure DevOps into short-lived roles.
Scope deploy roles per environment and service. Avoid AdministratorAccess “just for Terraform.” Use permission boundaries and explicit resource ARNs where practical.
Separate plan and apply roles if your process needs human approval. Log assume-role events and alert on unusual principals.
Least privilege is not a one-time IAM review—it is part of how every pipeline is designed.
Add permission boundaries so new roles cannot escalate beyond a ceiling.
Require MFA or break-glass for human privilege elevation; keep automation on short-lived tokens.
Review unused roles quarterly—pipelines change and permissions rarely shrink without a process.
Key takeaways
- CI/CD roles should deploy specific stacks—not AdministratorAccess.
- Prefer OIDC federation from GitHub/GitLab over long-lived access keys.
- Separate plan/apply and environment roles to limit blast radius.
FAQ
How do we start shrinking CI permissions?
Capture what the pipeline actually uses via access advisor or CloudTrail, then replace wildcards with resource-scoped actions and conditions.
Should each repo have its own deploy role?
Usually yes for production. Shared mega-roles turn every repository compromise into an estate-wide incident.