AWS IAM: least-privilege without going insane
A pragmatic guide to AWS IAM least-privilege — policies, boundaries, and how to migrate from "AdministratorAccess" safely.
Least-privilege on AWS is easy to preach and painful to implement. The mistake most teams make is trying to hand-write policies from a blank page. Do this instead.
The three-tier approach
- Managed policies for humans. Use AWS-managed policies (
ReadOnlyAccess,PowerUserAccess, service-specific admin likeAmazonEC2FullAccess) as the baseline. - Custom policies for automation. CI roles, Terraform roles, Lambda roles — these should be tightly scoped to specific resources.
- Permission boundaries for delegation. When teams create their own roles, boundaries cap what those roles can ever do.
Discover what a role actually needs
# Turn on IAM Access Analyzer, then let the role run for 90 days
aws accessanalyzer start-policy-generation \
--policy-generation-details principalArn=arn:aws:iam::123:role/ci-deploy
Access Analyzer will generate a minimum-viable policy based on actual CloudTrail activity. This is 10× better than guessing.
A least-privilege deploy role — real example
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::acme-artifacts/prod/*"
},
{
"Effect": "Allow",
"Action": "ecs:UpdateService",
"Resource": "arn:aws:ecs:eu-west-1:123:service/prod/*",
"Condition": {
"StringEquals": { "ecs:cluster": "arn:aws:ecs:eu-west-1:123:cluster/prod" }
}
}
]
}
Guardrails that scale
- SCP (Service Control Policies) at the org level — deny actions no account should ever use (like
iam:CreateUseroutside break-glass). - Permission boundaries — cap the maximum a role can have, even if a developer attaches AdministratorAccess to it.
- Session tags — restrict what a federated user can do based on their SSO group.
Migrating from wide-open
- Turn on CloudTrail + Access Analyzer everywhere.
- For each role with
AdministratorAccess: run 30–90 days, then let Access Analyzer generate a real policy. - Attach the new policy alongside, monitor for a week, then remove admin.
- Repeat.
Least-privilege isn't a project you finish — it's a discipline you keep. Automate the discovery step or it will never happen.