A policy document has to live somewhere. IAM gives you three places, and the choice is about reuse.
Three kinds
| Kind | Who owns it | Reusable | ARN looks like |
|---|---|---|---|
| AWS managed | AWS, maintained for you | yes, across accounts | arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess |
| customer managed | your account | yes, across users, groups and roles | arn:aws:iam::123456789012:policy/ReportsRead |
| inline | embedded in one user, group or role | no | none |
AWS managed policies cover common jobs: ReadOnlyAccess, AmazonS3FullAccess, AmazonSSMManagedInstanceCore. They are broad and convenient; AWS updates them when services add operations. Customer managed policies are yours, written for your resources, and attachable anywhere. Inline policies live inside one identity and vanish with it. They are for the rare permission that genuinely belongs to exactly one thing.
aws iam list-policies --scope AWS --query "Policies[?starts_with(PolicyName, 'AmazonS3')].PolicyName"
aws iam list-policies --scope LocalAttaching
aws iam attach-group-policy --group-name developers --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
aws iam attach-user-policy --user-name dana --policy-arn arn:aws:iam::123456789012:policy/ReportsRead
aws iam put-user-policy --user-name dana --policy-name BudgetView --policy-document file://budget-view.jsonattach-*-policy links a managed policy by ARN. put-*-policy writes an inline document under a name. Each has a detach or delete twin, and a list-attached-*-policies or list-*-policies to read back.
Effective permissions
A user's permissions are the union of every policy attached to the user, plus every policy attached to each group the user belongs to. IAM gathers them all and evaluates them together; the next lesson explains the order. So the working pattern is: attach managed policies to groups, put people in groups, and reach for direct user attachments only for exceptions.
aws iam list-attached-user-policies --user-name dana
aws iam list-user-policies --user-name dana
aws iam list-groups-for-user --user-name dana --query "Groups[].GroupName"Three commands, three sources. When a user can do something you did not expect, one of these shows where it came from.