An IAM user is a long-lived identity with permanent credentials. A group is a container that carries policies and applies them to its members.
Both are foundational to understanding IAM, and current AWS guidance is that you should not create users for people. That tension is worth resolving up front, because most material on this topic predates the recommendation.
A user has an ARN, optionally a console password, and optionally up to two access keys:
aws iam create-user --user-name ci-legacy-uploader
aws iam create-access-key --user-name ci-legacy-uploader{
"AccessKey": {
"AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"Status": "Active"
}
}The secret is shown exactly once. There is no way to retrieve it again. Losing it means creating a new key and deleting the old one.
Those credentials remain valid until someone deletes them. They do not expire, they work from anywhere in the world, and they are trivially copied. That is the entire problem.
A group holds policies; users in it inherit them. Groups have no credentials and cannot be assumed.
aws iam create-group --group-name developers
aws iam attach-group-policy \
--group-name developers \
--policy-arn arn:aws:iam::aws:policy/PowerUserAccess
aws iam add-user-to-group --user-name alice --group-name developersAttach policies to groups, never directly to users. Per-user policies produce an estate where nobody can answer "what can this person do" without inspecting each account individually, and where offboarding means finding every attachment.
A user can belong to up to ten groups, and permissions are the union of all of them.
Groups cannot be nested, there is no group-within-a-group, which is one of several reasons Identity Center exists.
| IAM user | Identity Center | |
|---|---|---|
| Credentials | Permanent | Temporary, expiring |
| Offboarding | Delete in every account | Disable once centrally |
| MFA | Per user, easy to skip | Enforced centrally |
| Multi-account | A user per account | One identity, many accounts |
| Access keys | Long-lived, leak-prone | None issued |
The failure mode with IAM users is not theoretical. Access keys end up in Git repositories, in CI configuration, in Slack messages, on former employees' laptops, and in Docker images. Public scanners find exposed AWS keys within minutes.
IAM Identity Center removes the category entirely: people sign in with corporate credentials and receive a temporary role session.
aws configure ssoA small number of genuine cases remain:
Treat each as a liability with a named owner and a review date. Everything else, EC2, Lambda, ECS, EKS, CI pipelines, should use a role.
If you must have keys, manage them properly.
aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 -d | column -t -s,The report lists every user with MFA status, key age, and when each key was last used. Two things to act on:
Keys unused for 90 days should be deleted, not rotated. An unused key is pure risk with no benefit.
Rotation uses the two-key allowance:
# 1. Create a second key
aws iam create-access-key --user-name ci-legacy-uploader
# 2. Deploy it everywhere, verify
# 3. Deactivate the old one. Reversible
aws iam update-access-key --user-name ci-legacy-uploader \
--access-key-id AKIAOLD --status Inactive
# 4. After a settling period, delete it
aws iam delete-access-key --user-name ci-legacy-uploader --access-key-id AKIAOLDDeactivating before deleting is the part people skip, and it is what turns a botched rotation from an outage into a one-command revert.
aws iam list-users --query 'Users[].UserName' --output text | \
xargs -n1 -I{} sh -c 'echo -n "{}: "; aws iam list-mfa-devices --user-name {} --query "length(MFADevices)"'Enforce it with a policy condition rather than trusting people to enable it. Denying everything except MFA management when aws:MultiFactorAuthPresent is false is the standard pattern.
aws configure sso.Step 6 matters. Deactivate rather than delete first, so anything you missed fails visibly and reversibly rather than permanently.
| Task | Command |
|---|---|
| Create a user | aws iam create-user --user-name <n> |
| Create a group | aws iam create-group --group-name <n> |
| Add to a group | aws iam add-user-to-group --user-name <u> --group-name <g> |
| Attach a policy to a group | aws iam attach-group-policy --group-name <g> --policy-arn <arn> |
| Credential report | aws iam generate-credential-report then get-credential-report |
| List a user's keys | aws iam list-access-keys --user-name <n> |
| Deactivate a key | aws iam update-access-key --user-name <n> --access-key-id <id> --status Inactive |
| Check MFA | aws iam list-mfa-devices --user-name <n> |
| Configure SSO instead | aws configure sso |
<MCQExercise exercise={{ id: 'aws-iamug-group-policies', title: 'Policies on users or groups', description: 'Why is attaching policies to groups rather than directly to individual users considered best practice?', options: [ { id: 'a', text: 'Permissions become reviewable and consistent in one place, and removing someone from a group revokes everything at once' }, { id: 'b', text: 'Group policies are evaluated faster than user policies by IAM' }, { id: 'c', text: 'Users cannot have policies attached directly' }, { id: 'd', text: 'Group policies bypass service control policy restrictions' }, ], correctId: 'a', explanation: 'With per-user policies, answering "what can this person do" means inspecting every attachment on every user, and offboarding means finding all of them. Group-based permissions make the intended access model explicit and reviewable, and membership changes apply instantly. It is the same reasoning behind role-based access control generally.', wrongExplanations: { b: 'Policy evaluation performance is identical and is never a consideration. The benefit is entirely organisational.', c: 'Users can have policies attached directly, both managed and inline. Doing so is discouraged rather than impossible.', d: 'Nothing bypasses a service control policy. SCPs set a ceiling that no identity policy of any kind can exceed.', }, }} />
<MCQExercise exercise={{ id: 'aws-iamug-rotation', title: 'Rotating a key safely', description: 'What is the correct sequence for rotating an IAM access key that is in active use?', options: [ { id: 'a', text: 'Create a second key, deploy it, deactivate the old one, verify nothing broke, then delete it' }, { id: 'b', text: 'Delete the old key, then create a new one and deploy it quickly' }, { id: 'c', text: 'Create a new key and delete the old one in the same command to avoid a window with two active keys' }, { id: 'd', text: 'Rotate the user's console password, which regenerates the access key automatically' }, ], correctId: 'a', explanation: 'IAM allows two active keys per user precisely to make zero-downtime rotation possible. Deactivating rather than deleting at step three is the important detail: if something you missed was still using the old key, reactivating it is one command, whereas a deleted key is gone and the secret is unrecoverable.', wrongExplanations: { b: 'Deleting first guarantees an outage for anything using the key, and leaves no way back since the old secret cannot be recovered.', c: 'The overlap window is the whole point of the two-key allowance, not something to avoid. Without it, rotation always causes downtime.', d: 'Console passwords and access keys are entirely separate credentials. Changing one has no effect on the other.', }, }} />
A user is a long-lived identity with permanent credentials. A password and possibly access keys that remain valid until deleted. A role has no permanent credentials; it is assumed temporarily by a person, a service or another account, issuing credentials that expire automatically, typically within an hour. Roles are safer because there is no lasting secret, and they are what EC2 instances, Lambda functions, ECS tasks and CI pipelines should use.
No. The secret is displayed exactly once, at creation, and AWS does not store it in retrievable form. Create a new access key, deploy it wherever the old one was used, then deactivate and finally delete the old key. Since a user may hold two active keys, this can be done without downtime. If the lost key is no longer needed anywhere, simply delete it.
Frequently enough that a leaked key has limited value: 90 days is a common policy. But rotation is a mitigation for a problem better solved by removal: a key unused for 90 days should be deleted rather than rotated, and workloads should use roles so there is no key at all. Generate a credential report regularly to find both stale keys and users without MFA. Rotation matters most for the small number of keys that genuinely cannot be eliminated.
No. A group cannot contain another group, so hierarchies such as "all engineers" containing "backend engineers" are not possible in IAM. You would attach overlapping policies or add users to multiple groups instead. A user can belong to up to ten groups and receives the union of their permissions. This limitation is one of several reasons IAM Identity Center exists, since its permission sets and directory groups model organisational structure far better.
Enable Identity Center in the management account, connect an identity source such as Entra ID, Okta or Google Workspace, then create permission sets and assign groups to accounts. Have people reconfigure their CLI with aws configure sso. Before deleting anything, deactivate the old access keys and watch CloudTrail for authentication failures, that surfaces any automation still using them in a way you can reverse with a single command. Delete the users only once the account has been quiet for a while.
Understand IAM roles and policies: trust vs permission policies, assuming roles with STS, managed vs inline policies, boundaries and AssumeRole errors.
Harden IAM: replace IAM users with Identity Center, drop long-lived CI keys, lock down root, reach least privilege from usage data and set boundaries.
Learn how EC2 works: instance families and sizing, pricing models, EBS vs instance store, IMDSv2, Session Manager instead of SSH, and stop vs terminate.