How to find and remove unused IAM users

Topic: Accounts access

Summary

Identify IAM users that have not signed in or used access keys recently using last-used timestamps and CloudTrail, then safely remove or deactivate them. Use this to reduce attack surface and meet compliance; avoid removing users that own critical resources.

Intent: How-to

Quick answer

  • Use get-user (password last used) and get-access-key-last-used for each user and key to find users with no recent console or API activity.
  • Cross-check CloudTrail for the user's principal ID over the last 90 days to confirm no activity; account for password and key last-used being updated only on use.
  • Remove access keys and login profile, then delete the user after confirming no resource ownership (e.g. S3 bucket owner); or deactivate and tag for later deletion.

Prerequisites

Steps

  1. List users and password last used

    List all IAM users and get password last used (and access key last used per key); filter for users with no password last used or last used older than your threshold (e.g. 90 days).

  2. Cross-check with CloudTrail

    Query CloudTrail (or CloudTrail Lake) for events where userIdentity.principalId or userIdentity.userName matches the user, over the last 90 days; if no events, user is a candidate for removal.

  3. Check resource ownership and dependencies

    Ensure the user does not own resources (e.g. S3 bucket owner, EC2 resource tags); transfer or reassign ownership if needed; check for inline policies or group membership that might be referenced elsewhere.

  4. Revoke and delete or deactivate

    Delete all access keys and the login profile (see revoke guide); optionally detach policies and remove from groups; delete the user or leave deactivated with a tag for deletion after retention.

Summary

You will find unused IAM users using password and access key last-used data and CloudTrail, verify they do not own critical resources, then revoke access and delete or deactivate them. Use this for periodic cleanup and to reduce unused credentials.

Prerequisites

  • IAM permissions to list users, get user details, list and get access key last used (iam:ListUsers, iam:GetUser, iam:ListAccessKeys, iam:GetAccessKeyLastUsed), and optionally CloudTrail read.
  • A defined threshold for “unused” (e.g. no activity in 90 days).

Steps

Step 1: List users and password last used

aws iam list-users --query 'Users[].[UserName,CreateDate]' --output table

For each user, get password last used (only set when the user has signed in to the console):

aws iam get-user --user-name USERNAME --query 'User.PasswordLastUsed'

For each user’s access keys, get last used:

aws iam list-access-keys --user-name USERNAME
aws iam get-access-key-last-used --access-key-id AKIA...

Build a list of users with no PasswordLastUsed (or very old) and no access key last used (or all keys older than your threshold). Note: PasswordLastUsed is updated only when the user signs in to the console; access key last used is updated when the key is used for an API call.

Step 2: Cross-check with CloudTrail

In CloudTrail (or CloudTrail Lake), run a query for the last 90 days (or your threshold) filtered by:

  • userIdentity.type = IAMUser
  • userIdentity.userName = the candidate user name (or userIdentity.principalId)

If there are no events, the user has had no API or console activity in that window. This confirms they are unused; password/key last-used can be delayed or missing for some edge cases.

Step 3: Check resource ownership and dependencies

  • S3: List buckets and check ownership; if the user is the bucket owner, transfer ownership or update ACLs before deleting the user.
  • Other resources: Check tags and resource policies that reference the user ARN; reassign or remove references.
  • Inline policies / groups: List inline policies and groups for the user; removing the user from groups and deleting the user will drop these; ensure no automation assumes the user exists.

Step 4: Revoke and delete or deactivate

  1. Follow How to revoke an IAM user immediately: delete all access keys and the login profile.
  2. Detach all managed policies and remove the user from all groups (required before delete-user).
  3. Delete any inline policies: aws iam delete-user-policy --user-name USERNAME --policy-name POLICYNAME
  4. Delete the user: aws iam delete-user --user-name USERNAME

If you must retain the user for audit, leave the user but with no keys and no login profile, and tag the user (e.g. pending-deletion) for deletion after your retention period.

Verification

  • Unused users are identified from last-used and CloudTrail; no active use in the last 90 days.
  • Revoked users have no access keys and no login profile; deleted users no longer appear in list-users.
  • No resources are left orphaned or failing due to the removed user ARN.

Troubleshooting

PasswordLastUsed is null — The user may have never signed in to the console or only uses access keys; rely on access key last-used and CloudTrail for those users.

Delete user fails: entity in use — A resource (e.g. S3 bucket owner, inline policy name) still references the user. Fix the dependency (transfer bucket, delete inline policy) and retry.

Uncertain if user is used by automation — Search code and config for the user name or access key ID; check CloudTrail for the key ID. If in doubt, deactivate (remove keys and login profile) and monitor before deleting.

Next steps

Continue to