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

  1. 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.

  2. 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).

  3. 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.

  4. 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.

Next steps

Continue to