aws_04_inactive_iam_users.py
Stale IAM accounts are a persistent problem in every organisation that has been running AWS for more than two years. An employee leaves. IT removes their AD account but nobody touches IAM. A contractor finishes. Their access key stays active in a script nobody runs any more. Six months later that account still has the same permissions it had when it was actively used — and nobody is watching it. Stale accounts are a favoured target for attackers because they are unlikely to trigger alerts when accessed.
An ISO 27001 surveillance audit requires evidence of a quarterly access review for cloud environments. You run this script across four accounts. One account returns three inactive users: an ex-employee whose console access was never revoked, a service account with access keys that have not been used in 412 days, and a contractor account created for a project that completed eight months ago. The script output becomes the access review evidence — username, last activity date, days inactive, and recommended disposition.
aws_04_inactive_iam_users.py enumerates all IAM users, checks each for a console login profile, and evaluates the most recent activity across console logins and access keys. Users whose last activity was more than 90 days ago (configurable via --days) and users who have never been used are listed as inactive findings. Users with no login mechanism at all are excluded. The script sorts results by days inactive, longest first.
Regulation coverage: NIST CSF PR.AC-1 | SOX ITGC AC-04 | PCI DSS 8.8 | ISO 27001 A.9.2.6 | FFIEC CAT | DORA Art.9
Prerequisites: pip install boto3 · iam:ListUsers · iam:GetLoginProfile · iam:ListAccessKeys · iam:GetAccessKeyLastUsed · sts:GetCallerIdentity
# Install dependency $ pip install boto3 # Run with default credentials $ python3 aws_04_inactive_iam_users.py # Named profile $ python3 aws_04_inactive_iam_users.py --profile my-audit-role # Custom inactivity threshold (e.g. 60 days for PCI) $ python3 aws_04_inactive_iam_users.py --days 60 # Save JSON evidence $ python3 aws_04_inactive_iam_users.py --profile my-audit-role --save
Scope 8 total IAM users evaluated ✓ RESULT: PASS Finding All 8 IAM users with active login mechanisms have been active within the last 90 days. No inactive accounts found. Raw: {"total_users": 8, "inactive_count": 0}
Scope 8 total IAM users evaluated ✗ RESULT: FAIL Risk Rating HIGH Inactive user detail ────────────────────────────────────────────────────────────── Username Last activity Days Status ────────────────────────────────────────────────────────────── svc-reporting 2025-07-10T08:22:00Z 236 INACTIVE john.doe 2025-09-01T14:05:00Z 183 INACTIVE deploy-legacy NEVER 412 NEVER_USED Finding 3 IAM users inactive for more than 90 days or never used. Stale accounts retain original permissions and are valid attack targets. Remediation Disable or delete all 3 inactive users. Confirm no service dependency before deleting. Document disposition.
Regulation map
| Framework | Control / Clause | Obligation |
|---|---|---|
| NIST CSF 2.0 | PR.AC-1 | Credentials for departed users and inactive accounts must be revoked in a timely manner. |
| SOX ITGC | AC-04 | Periodic user access reviews must identify and remove stale accounts with access to financial systems. |
| PCI DSS v4.0 | 8.8 | Accounts of terminated users must be removed or disabled within a defined timeframe. Inactive accounts must be reviewed quarterly. |
| ISO 27001:2022 | A.9.2.6 | Formal access removal procedures must ensure accounts are disabled when employment or contract ends. |
| FFIEC CAT | Baseline — IAM | Timely revocation of user access for separated employees and contractors is a baseline requirement. |
| DORA (EU) | Article 9 | ICT access rights must be reviewed at regular intervals and revoked when no longer required. |
Feedback welcome: Corrections, ideas, and requests — grcguy@rtapulse.com.
Request an addition