Skip to main content
emnode
Compliance Medium severity

AWS Security Hub · IAM

IAM.3: Long-lived access keys have not been rotated

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub IAM.3 check?

IAM.3 fails when an active IAM access key has not been rotated within 90 days. The control reads each user's key creation date from the credential report and flags any long-lived key past that age.

Why does IAM.3 matter?

A leaked access key is weaponised in minutes: security researchers who plant dummy keys in public GitHub repositories have measured the median time from a key going public to the first malicious API call at under four minutes (some honeypot studies see it inside a minute). The longer a key lives, the more places it has been copied into and the wider its blast radius. Regular rotation caps the window any single exposed secret stays useful.

How do I fix IAM.3?

  1. Pull the credential report and identify keys older than 90 days.
  2. Mint a second key, roll it out to every consumer, then deactivate (don't yet delete) the old one.
  3. Once nothing breaks, delete the deactivated key.
  4. Where you can, retire long-lived keys entirely in favour of instance roles, IAM Roles Anywhere, or OIDC federation for CI/CD.

Remediation script · bash

# Stop the irreversible clock first: cancel any scheduled deletion, then re-enable.
for k in $(aws kms list-keys --query 'Keys[].KeyId' --output text); do
  state=$(aws kms describe-key --key-id "$k" \
    --query 'KeyMetadata.KeyState' --output text)
  if [ "$state" = "PendingDeletion" ]; then
    aws kms cancel-key-deletion --key-id "$k"
    aws kms enable-key --key-id "$k"   # cancel leaves it Disabled
    echo "$k: deletion cancelled and re-enabled"
  fi
done

# Turn rotation on for eligible customer-managed symmetric keys.
for k in $(aws kms list-keys --query 'Keys[].KeyId' --output text); do
  read -r mgr spec <<<"$(aws kms describe-key --key-id "$k" \
    --query 'KeyMetadata.[KeyManager,KeySpec]' --output text)"
  if [ "$mgr" = "CUSTOMER" ] && [ "$spec" = "SYMMETRIC_DEFAULT" ]; then
    aws kms enable-key-rotation --key-id "$k"
  fi
done

Full walkthrough (console steps, edge cases and verification) in the lesson Manage KMS encryption keys.

Is IAM.3 a false positive?

The check only evaluates *active* keys (the access-keys-rotated Config rule ignores inactive ones), so a key you've deactivated, or one that was created but never activated, won't be flagged no matter how old it is. There's otherwise no benign reason for an active key to be older than 90 days, so genuine misfires are rare. A handful of legitimate keys belong to identities that genuinely can't take an instance role or federation: a long-running on-prem batch job, a third-party SaaS integration, or a partner account where you can't dictate the auth method. The fix is still rotation, not suppression: cut a new key, swap it in, and deactivate the old one, since a deactivated key drops out of scope and the finding clears. If a specific user truly must hold a long-lived key and you've accepted that risk in writing, suppress that finding for the named ARN rather than disabling the control account-wide, so a second un-rotated key elsewhere still pages you.

Part of the learning path Lock down access
  • IAM.1 A policy grants full "*" administrative privileges
  • IAM.2 Policies attached directly to users do not scale or audit cleanly
  • IAM.4 The root user still has long-lived access keys
  • IAM.5 Console users without MFA are one phish from compromise
  • IAM.6 The root user is not protected by hardware MFA
  • IAM.7 The IAM password policy is too weak
  • IAM.8 Unused IAM keys and passwords are waiting to be leaked
  • IAM.9 The root user can sign in without MFA
  • IAM.10 IAM user password policies should be strong (PCI DSS)
  • IAM.19 MFA should be enabled for all IAM users
  • IAM.21 Wildcard permissions grant far more access than intended
  • IAM.22 IAM credentials unused for 45 days should be removed