AWS¶
iam-zero scans AWS IAM roles using CloudTrail management events and IAM Access Advisor.
Authentication¶
Uses the standard boto3 credential chain:
- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN) - Shared credential file (
~/.aws/credentials) - IAM role (EC2, ECS, EKS)
You can specify a profile with --profile:
iam-zero scan aws --role arn:aws:iam::123456789012:role/my-role --profile my-profile
Required Permissions¶
Your caller identity needs:
| Permission | Why |
|---|---|
cloudtrail:LookupEvents |
Read CloudTrail events |
iam:GenerateServiceLastAccessedDetails |
Start Access Advisor analysis |
iam:GetServiceLastAccessedDetails |
Get Access Advisor results |
iam:GetRole |
Read role details |
iam:ListAttachedRolePolicies |
List managed policies |
iam:GetPolicy |
Read policy details |
iam:GetPolicyVersion |
Read policy content |
iam:ListRolePolicies |
List inline policies |
iam:GetRolePolicy |
Read inline policy content |
How AWS Scanning Works¶
- Fetch CloudTrail events — paginates
LookupEventsbyUsername(extracted from role ARN) over N days - Get IAM policies — reads both managed and inline policies via
get_role_policies(), extracts all allowed actions with wildcard expansion - Access Advisor — calls
GenerateServiceLastAccessedDetailswith 60s polling timeout, protects actions whose service had recent activity - Compute unused —
compute_unused()returns actions in policy not in CloudTrail; wildcards always flagged;protect_active_services()splits protected vs truly unused - Claude analysis — sends current vs used vs unused to
claude-sonnet-4-20250514for structured JSON assessment - Generate policy —
generate_minimal_policy()keeps used + safe-to-keep actions, maps to original resources, addsIamZeroReviewUnmappedActionsSid for orphans
Listing Roles¶
Use --all-roles to scan every IAM role in the account. Roles under the /aws-service-role/ path are automatically skipped.
iam-zero scan aws --all-roles
Limitations¶
- CloudTrail
LookupEventsrecords management events only. Data-plane calls (S3GetObject, DynamoDBGetItem, etc.) never appear. Access Advisor helps fill this gap at the service level. - Lookup is per-region. Use
--regionfor each region the role operates in. - 90-day max retention.
--daysbeyond 90 won't return more data.