IAM user vs IAM role: what's the difference, and which should you use?
Updated · 4 min read
Both are identities in IAM, and you give both permissions with the same kind of policy. The difference is how you prove you're them:
- An IAM user is a permanent identity with long-term credentials: a console password, and up to two access keys (IDs starting
AKIA) that keep working until someone deactivates or deletes them. - An IAM role has no credentials of its own. A person, a service or another account assumes it and gets temporary credentials (IDs starting
ASIA, plus a session token) that expire, after an hour by default. Who may assume it is set by the role's trust policy.
A leaked access key works until someone notices. Leaked role credentials stop working on their own. That's why AWS's own advice is to use roles wherever they can work.
Which to use
- People, including you: IAM Identity Center. Everyone signs in through one portal and gets role sessions behind the scenes; AWS's IAM best practices ask for exactly this, federated sign-in with temporary credentials, for human users.
- Code on an EC2 server: a role, attached to the server as an instance profile. The AWS SDKs pick up its credentials automatically.
- A Lambda function: its execution role. Every function has one.
- GitHub Actions or another CI system: a role that trusts the CI provider's OpenID Connect (OIDC) identity, so no keys are stored in the CI settings.
- Another AWS account, or a third-party tool: a role in your account that trusts theirs, usually with an external ID.
- Servers outside AWS: IAM Roles Anywhere hands out temporary credentials in exchange for an X.509 certificate.
- Something that only accepts an access key, like some WordPress plugins or third-party clients: an IAM user with an access key, as a last resort. Give it only the permissions it needs.
A role is two policies
A role's trust policy says who may assume it. This one lets the Lambda service use it on a function's behalf:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}Its permissions policies say what the session may do, exactly like a user's. Paste either kind into the IAM policy explainer to read it in plain English. If assuming a role fails, here's how to find out which side said no.
Groups are neither: a group is just a way to attach the same policies to several users. It can't sign in, and you can't name one in a trust policy or a bucket policy.
Which one are you right now?
aws sts get-caller-identityarn:aws:iam::111122223333:user/aliceis an IAM user, so you're using long-term keys.arn:aws:sts::111122223333:assumed-role/deploy/aliceis a role session. If you signed in through IAM Identity Center, the role's name starts withAWSReservedSSO_.
In the console, the account menu at the top right shows the same, and Switch role there lets an IAM user assume a role. A session lasts from 15 minutes up to the role's maximum session duration (one to 12 hours, set on the role), except that a role assumed from another role's session is capped at one hour.
Find old access keys
Long-lived keys are the ones worth hunting down. IAM → Credential report → Download report gives a spreadsheet of every user, with password and access key status and when each key was last used. With the AWS CLI:
aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 --decode | cut -d, -f1,9,10,11,14,15,16That prints each user, then for each of their two possible keys whether it's active, when it was created and when it was last used. If the second command says the report isn't ready, wait a few seconds and run it again. For a key nobody seems to use, deactivate it first and delete it once nothing has broken for a while:
aws iam update-access-key --user-name alice --access-key-id AKIAIOSFODNN7EXAMPLE --status Inactive
aws iam delete-access-key --user-name alice --access-key-id AKIAIOSFODNN7EXAMPLEOr in Cloud GUI
Cloud GUI connects to your AWS account through a role you create from its template, never with access keys. The role trusts Cloud GUI's account only with your connection's own external ID, and every session carries the email of the person using it, so each one shows up by name in your CloudTrail. Sessions last 15 minutes and nothing long-lived is stored. Editing (Pro) uses a second, separate role that you choose to add, limited to the buckets and functions you pick. Delete a role's CloudFormation stack and that access ends. How access works lists every permission and the whole template, and Cloud GUI's own trust policy is one of the samples in the IAM policy explainer.