Tools · Cloud security · 03 / 24
Least privilege in AWS with IAM Access Analyzer: unused access and generated policies
Use Access Analyzer to find resources shared outside your account, flag unused roles and permissions, and generate a policy from real CloudTrail activity.
Three features in one service
External access analysis finds resources such as S3 buckets, KMS keys, IAM roles, and Lambda functions whose resource policies grant access to principals outside your account or organization. Unused access analysis lists roles, access keys, and passwords not used recently, and permissions granted but never exercised. Policy generation reads CloudTrail and drafts a policy containing only the actions a role actually used.
Together they answer “who outside can reach this” and “what does this role really need”.
Create analyzers
Create an external access analyzer with zone of trust set to the account or the organization, and an unused access analyzer with a tracking period such as 90 days. Findings appear in the console and through the CLI. Unused access analysis is a paid feature billed per monitored role and user, so check pricing for large accounts.
Archive rules let you mark intended sharing, such as a bucket shared with a partner account, so findings stay meaningful.
aws accessanalyzer create-analyzer --analyzer-name org-external --type ORGANIZATION
aws accessanalyzer create-analyzer --analyzer-name unused-90d --type ACCOUNT_UNUSED_ACCESS \
--configuration '{"unusedAccess":{"unusedAccessAge":90}}'
aws accessanalyzer list-findings-v2 --analyzer-arn <arn> --query 'findings[].{type:findingType,resource:resource,status:status}'Lab: tighten a role from real use
Attach the AWS managed ReadOnlyAccess policy to a sandbox role, use it for a day with a script that only reads one S3 bucket and describes EC2 instances, then start policy generation for that role over the CloudTrail trail. The generated draft lists s3:GetObject, s3:ListBucket, and ec2:DescribeInstances instead of thousands of read actions.
Review the draft, scope resources to specific ARNs, attach it, and detach ReadOnlyAccess. Run the script again to confirm it still works.
aws accessanalyzer start-policy-generation \
--policy-generation-details principalArn=arn:aws:iam::111122223333:role/report-script \
--cloud-trail-details '{"trails":[{"cloudTrailArn":"arn:aws:cloudtrail:us-east-1:111122223333:trail/org-trail","allRegions":true}],"accessRole":"arn:aws:iam::111122223333:role/AccessAnalyzerTrailRole","startTime":"2026-11-01T00:00:00Z"}'
aws accessanalyzer get-generated-policy --job-id <job-id>Make it a habit
Review external access findings weekly and unused access monthly. Delete roles and keys unused for 90 days after confirming with owners.
Use policy validation (aws accessanalyzer validate-policy) in CI so new policies are checked for errors and overly broad statements before deployment.
Diagram
What each Access Analyzer feature answers
Use all three.
- External access
Which resources can principals outside the trust zone reach?
- Unused access
Which roles, keys, and permissions are idle?
- Policy generation
What did this role actually use, according to CloudTrail?
- Policy validation
Is this new policy broad or malformed?
Check yourself
1. Which feature drafts a policy from a role’s real activity?
2. What does an external access finding indicate?
3. How do you stop expected sharing from cluttering findings?