Join our Newsletter — 33% off our NHI Course
Home› Guides› How to find unused AWS IAM roles and…
Guide Non-Human Identity (NHI)

How to find unused AWS IAM roles and access keys: Find them, disable them, then delete safely

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 28 October 2026 10 min read
On this page

Unused IAM roles and access keys are standing permissions that nobody is watching, and AWS accounts tend to collect them faster than teams remove them. Each one is a credential or trust relationship that an attacker can use without creating anything new. This runbook shows how to find unused roles and keys with the tools AWS already provides: the credential report, RoleLastUsed, last accessed information and IAM Access Analyzer unused access findings. It then covers how to disable them first, delete them in the order IAM requires, and recover when something turns out to be in use. It is for cloud security and platform engineers running periodic clean-ups in single accounts or across an AWS Organization. For background on why long-term keys are risky, see the AWS Access Keys Security Guide.

Key takeaways

  • Start with the free, read-only sources. The credential report covers access keys for every IAM user; aws iam get-role returns RoleLastUsed for each role.
  • Use Access Analyzer at scale. An unused access analyzer (type ACCOUNT_UNUSED_ACCESS or ORGANIZATION_UNUSED_ACCESS) reports unused roles, access keys, passwords and permissions against a tracking period of 1 to 365 days. It is a paid feature.
  • Know the tracking limits. Role last activity covers the trailing 400 days; data can lag up to four hours in the console; resource-based policies are not covered by last accessed information.
  • Disable before delete. Deactivate keys and neutralise roles first. Deletion of a role needs its instance profiles and policies removed, and nothing undoes it.
  • Exclude service-linked roles. They are deleted through the owning service, not by your clean-up script.

When you need this

  • Periodic hygiene: quarterly or monthly review of IAM principals, often required by an audit control such as NIST SP 800-53 AC-2(3) Disable Accounts.
  • After an incident or a provider breach: compromised long-term keys with broad permissions are a recurring cause of AWS account takeover. In the Amazon AWS crypto-mining campaign, attackers used compromised IAM access keys with admin-like privileges, and AWS's advice afterwards was to replace long-term keys with temporary credentials.
  • Before a migration: moving workloads to roles, federation or a new account structure is easier when dead principals are gone first.
  • When Access Analyzer findings pile up: AWS recommends aiming for zero active findings, so that any new finding signals a recent change.

Before you start

SourceWhat it tells youPermission or costLimit to know
Credential reportPer user: access_key_1_active, access_key_1_last_rotated, access_key_1_last_used_date, service and Region, and the same for key 2iam:GenerateCredentialReport, iam:GetCredentialReport; freeNew report at most every four hours; only the first two keys per user
get-access-key-last-usedLast use date, service and Region for one keyFreeNever-used keys return a null date and N/A
get-role RoleLastUsedLastUsedDate and Region of last role activityFreeTrailing 400 days; an empty RoleLastUsed means unused in that period
Last accessed informationWhich allowed services a principal used and wheniam:GenerateServiceLastAccessedDetails, iam:GetServiceLastAccessedDetails; freeIdentity-based policies only; includes denied attempts; iam:PassRole not tracked
Access Analyzer unused accessFindings: unused role, unused access key, unused password, unused permissionCharged per IAM role and user analysed per monthOne analyzer per account per Region; findings do not vary by Region

Run discovery from a dedicated read-only role rather than an administrator session, and keep the write steps (deactivate, neutralise, delete) behind a separate role that needs approval. Last accessed reports are visible only to the principal that generated them, and with temporary role credentials they must be generated and retrieved in the same session, so script the generate and get calls together. Export the full role definition (trust policy, inline and attached policies, tags) for every candidate before any change; this export is your only rollback for a deleted role.

Agree the threshold and the owner contact route first. Ninety days is a common starting point; choose longer for roles used by annual or disaster recovery processes. The NHI Dormancy Detection guide covers threshold choice across platforms.

Step-by-step

Steps 1 to 4 are read-only. Steps 5 and 6 change access but are reversible. Step 7 is destructive.

  1. Find unused access keys from the credential report.
    aws iam generate-credential-report
    aws iam get-credential-report --query Content --output text | base64 --decode > credential-report.csv
    Flag rows where access_key_1_active or access_key_2_active is TRUE and the matching last_used_date is N/A or older than your threshold. Check additional_credentials_info and run aws iam list-access-keys for users the report does not fully cover.
  2. Find unused roles. List roles, then read RoleLastUsed for each.
    aws iam list-roles --query "Roles[].RoleName" --output text
    aws iam get-role --role-name <role-name> --query "Role.RoleLastUsed"
    Separate service-linked roles, which show "(Service-linked role)" in the Trusted entities column of the console, and leave them to their owning service.
  3. Turn on an unused access analyzer for continuous findings. In the IAM console choose Access analyzer > Analyzer settings > Create analyzer, then Principal analysis - Unused access, set the tracking period and choose Current account or Current organization. The CLI equivalent takes --type ACCOUNT_UNUSED_ACCESS and a configuration with unusedAccessAge:
    aws accessanalyzer create-analyzer --analyzer-name unused-access \
      --type ACCOUNT_UNUSED_ACCESS \
      --configuration '{"unusedAccess":{"unusedAccessAge":90}}'
    Organization analyzers are created from the management or delegated administrator account. You can exclude accounts (organisation analyzers only) or principals by tag, which suits sandboxes and break-glass roles.
  4. Enrich and confirm with owners. For each candidate, record the trust policy, attached and inline policies, tags and the creating team. Check that no running EC2 instance uses the role or its instance profile, as AWS warns that deleting it can break applications on those instances. Use last accessed information to see whether a role used any allowed service recently:
    aws iam generate-service-last-accessed-details --arn arn:aws:iam::<account-id>:role/<role-name>
    aws iam get-service-last-accessed-details --job-id <JobId>
    Remember that last accessed reports only services allowed by the role's identity-based policies, while RoleLastUsed includes any attempt, so the two can differ.
  5. Deactivate unused access keys (reversible).
    aws iam update-access-key --user-name <user-name> --access-key-id <KEY_ID> --status Inactive
  6. Neutralise unused roles (reversible). AWS documents that a role you do not want to delete can be disabled by changing its policies and revoking current sessions. A practical pattern is to attach an explicit deny-all inline policy, tag the role with the date and ticket, and use the console's revoke active sessions option for the role. Keep it in this state for a full business cycle.
  7. Delete (destructive). For keys: aws iam delete-access-key --user-name <user-name> --access-key-id <KEY_ID>, then consider whether the IAM user itself is still needed. For roles, the CLI requires each dependency to be removed first:
    aws iam list-instance-profiles-for-role --role-name <role-name>
    aws iam remove-role-from-instance-profile --instance-profile-name <profile> --role-name <role-name>
    aws iam list-role-policies --role-name <role-name>
    aws iam delete-role-policy --role-name <role-name> --policy-name <policy-name>
    aws iam list-attached-role-policies --role-name <role-name>
    aws iam detach-role-policy --role-name <role-name> --policy-arn <policy-arn>
    aws iam delete-role --role-name <role-name>
    Unlike the console, the CLI does not delete the instance profile with the role; run aws iam delete-instance-profile if it is no longer needed.

Verify it worked

  • Keys: a new credential report (after the four hour window) shows the key inactive or gone.
  • Roles: aws iam get-role returns NoSuchEntity for deleted roles; neutralised roles show the deny policy and tag.
  • Findings: the matching Access Analyzer unused access findings move to Resolved on the next analysis. Archive findings you accept, with an archive rule for expected patterns, so active findings trend to zero.
  • No breakage: CloudTrail and CloudWatch show no rise in access denied errors from the principals you changed during the waiting period.

Rollback and common errors

SituationFix
A job fails after key deactivationupdate-access-key --status Active, record the real usage, and plan a move to a role
A neutralised role is neededRemove the deny-all inline policy; sessions must be re-established by the caller
A role was deleted but is neededNo restore exists. Recreate it from infrastructure as code or your pre-change export of the trust policy, policies and tags; role ARNs referenced in resource policies must be re-added because the new role has a new unique ID
DeleteConflict on delete-roleAn instance profile, inline policy or attached policy is still present; complete the earlier steps
Role looks unused but is used yearlyAnnual, audit and disaster recovery roles fall outside short thresholds; tag and exclude them from the analyzer instead
Service-linked role flaggedDo not delete with IAM; follow the owning service's documented method

Hardening afterwards

  • Keep the analyzer running: continuous unused access findings turn a quarterly project into a weekly queue. Route new findings to the owning team.
  • Replace long-term keys: move remaining IAM user keys to roles, OIDC federation or IAM Roles Anywhere. For keys that must stay, follow How to rotate an AWS IAM access key without downtime.
  • Tag ownership at creation: require owner and purpose tags on roles and users through infrastructure as code checks, so step 4 is a lookup, not an investigation.
  • Trim permissions on roles you keep: unused permission findings and last accessed data show services a role never calls; remove them.
  • Feed the inventory: reconcile deletions with your NHI inventory. See NHI Inventory Reconciliation.

Small account or large organisation

A single account with a few dozen roles can rely on the credential report and get-role in a short script at no cost. An AWS Organization with hundreds of accounts should use an organisation-level unused access analyzer from a delegated administrator account, exclude sandbox OUs by account ID, and work the findings centrally; the per-principal charge is usually far below the effort of scripting every account.

Metrics

MetricDirection
Active unused access findings (roles and keys)Towards zero
Active access keys unused beyond thresholdZero
Roles without owner tagsFalling
IAM users with long-term keysFalling each quarter
Rollbacks after neutralisingLow and explained

Framework mapping

FrameworkReferenceRelevance
NIST SP 800-53 Rev 5AC-2(3) Disable Accounts; AC-6 Least PrivilegeDisable inactive principals; remove unused permissions
NIST CSF 2.0PR.AA-01, PR.AA-05Manage service credentials; review access permissions
MITRE ATT&CKT1078.004 Cloud AccountsFewer dormant principals for valid account abuse
CIS Controls v8.15.3 Disable Dormant AccountsSame intent applied to IAM users and roles

Practitioner checklist

  • Generate the credential report and flag active keys unused beyond the threshold.
  • Read RoleLastUsed for every role and set service-linked roles aside.
  • Create an unused access analyzer with an explicit tracking period and exclusions.
  • Confirm owners and check for EC2 instance profile use before any change.
  • Deactivate keys and neutralise roles before deleting anything.
  • Delete roles in the documented order and remove orphaned instance profiles.
  • Archive accepted findings with a reason and keep active findings near zero.

Standards and references

Related NHI Mgmt Group resources: AWS Access Keys Security Guide · How to rotate an AWS IAM access key without downtime · NHI Dormancy Detection · Cloud Access Key Leak Playbook

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 28 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org