How to audit IAM user permissions
Topic: Accounts access
Summary
Audit effective permissions for an IAM user: list attached and group policies, simulate actions with the IAM policy simulator, and use last-used for access keys. Use this to verify least privilege and before revoking or changing access.
Intent: How-to
Quick answer
- List direct and group-based permissions with list-attached-user-policies, list-groups-for-user, and list-attached-group-policies; include permission boundaries if set.
- Use the IAM policy simulator (console or simulate-principal-policy) to test which actions are allowed or denied for the user.
- Check access key last-used with get-access-key-last-used and CloudTrail to see what the user actually did; remove unused keys and narrow over-permissive policies.
Prerequisites
Steps
-
List all policies effective for the user
List attached user policies and list groups for the user; for each group list attached group policies; note any permission boundary on the user; collect policy ARNs and versions.
-
Resolve and inspect policy documents
For each managed policy, get the default version with get-policy and get-policy-version; compute effective allow/deny for the actions you care about; account for permission boundaries (cap the maximum grant).
-
Simulate and verify with policy simulator
In IAM → Policy simulator, select the user and run simulations for critical actions (e.g. s3:DeleteBucket, iam:CreateUser); or use simulate-principal-policy via CLI to batch test.
-
Check key usage and CloudTrail
Use get-access-key-last-used for each key; query CloudTrail for the user's principal ID to see recent API calls; identify unused keys and over-used permissions for cleanup.
Summary
You will audit an IAM user’s effective permissions by listing direct and group policies, resolving policy documents, simulating actions, and checking key last-used and CloudTrail. Use this to enforce least privilege, prepare for revoke, or satisfy compliance reviews.
Prerequisites
- IAM permissions to read IAM entities and policies (e.g. iam:GetUser, iam:ListAttachedUserPolicies, iam:GetPolicy, iam:GetPolicyVersion) and optionally CloudTrail read.
- The IAM user name (or ARN) you are auditing.
Steps
Step 1: List all policies effective for the user
USER=audit-target-user
aws iam list-attached-user-policies --user-name "$USER"
aws iam list-groups-for-user --user-name "$USER"
For each group, list attached policies:
aws iam list-attached-group-policies --group-name GROUP_NAME
Get the user’s permission boundary (if any):
aws iam get-user --user-name "$USER" --query 'User.PermissionsBoundary'
Note every policy ARN; the effective permission set is the union of allowed actions from these policies, minus any Deny, capped by the permission boundary.
Step 2: Resolve and inspect policy documents
For each policy ARN:
aws iam get-policy --policy-arn arn:aws:iam::123456789012:policy/MyPolicy --query 'Policy.DefaultVersionId'
aws iam get-policy-version --policy-arn arn:aws:iam::123456789012:policy/MyPolicy --version-id v1
Review the policy document for Action, Resource, and Condition. If the user has a permission boundary, fetch that policy too; the effective maximum permission is the intersection of boundary and attached policies.
Step 3: Simulate and verify with policy simulator
Console: IAM → Policy simulator. Select Users → your user, then add the actions to test (e.g. s3:DeleteBucket, iam:CreateUser). Run the simulation and note Allowed or Denied and the reason.
CLI:
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/audit-target-user \
--action-names s3:DeleteBucket iam:CreateUser
Use this to verify least privilege: sensitive actions should be Denied unless required.
Step 4: Check key usage and CloudTrail
aws iam list-access-keys --user-name "$USER"
aws iam get-access-key-last-used --access-key-id AKIA...
In CloudTrail (or CloudTrail Lake), filter by userIdentity.principalId or the user ARN and time range to see which APIs were actually called. Correlate with the policy list to find unused permissions or over-privileged users.
Verification
- You have a full list of attached and group policies and the user’s permission boundary.
- Policy simulator results match expectations for critical actions; over-permissive results are documented and reduced.
- Access key last-used and CloudTrail show actual usage; unused keys or unused permissions are flagged for removal.
Troubleshooting
Simulator says Denied but user says it works — Check for resource-based policies (e.g. S3 bucket policy) that grant the user access; simulator only evaluates identity-based policies. Include the resource ARN in the simulation if the tool supports it.
Permission boundary not obvious — get-user returns PermissionsBoundary; if present, that policy limits the maximum permission regardless of attached policies. Fetch and review that policy document.
Too many policies to review manually — Use IAM Access Analyzer (if enabled) or script get-policy/get-policy-version for each ARN and aggregate Action/Resource; then simulate a curated list of high-risk actions.