AWS for DevOps — IAM Access Analyzer
13.3 — IAM Access Analyzer
IAM Access Analyzer identifies resources that are shared with external entities — other accounts, public access, or cross-account roles. It answers: “What in my account is accessible from outside?”
Real-World Analogy
IAM Access Analyzer is like a home security audit. An inspector walks through your house checking every door and window: “This back door is unlocked (public S3 bucket), this window faces the neighbor’s yard (cross-account access), this safe has a simple combination (weak IAM policy).” You get a report of everything that needs fixing.
Supported Resource Types
| Resource | What It Checks |
|---|---|
| S3 Buckets | Public access, cross-account policies |
| IAM Roles | Trust policies allowing external access |
| KMS Keys | Key policies granting external access |
| Lambda Functions | Resource policies allowing external invocation |
| SQS Queues | Queue policies allowing external access |
| Secrets Manager | Resource policies for cross-account access |
Creating an Analyzer
# Create an analyzer for the account
$ aws accessanalyzer create-analyzer \
--analyzer-name account-analyzer \
--type ACCOUNT
{
"arn": "arn:aws:access-analyzer:ap-south-1:123456789012:analyzer/account-analyzer"
}
# For organization-wide analysis
$ aws accessanalyzer create-analyzer \
--analyzer-name org-analyzer \
--type ORGANIZATION
Viewing Findings
# List all findings
$ aws accessanalyzer list-findings \
--analyzer-arn arn:aws:access-analyzer:ap-south-1:123456789012:analyzer/account-analyzer
{
"findings": [
{
"id": "finding-123",
"resourceType": "AWS::S3::Bucket",
"resource": "arn:aws:s3:::my-public-bucket",
"principal": {"AWS": "*"},
"action": ["s3:GetObject"],
"condition": {},
"status": "ACTIVE",
"isPublic": true
},
{
"id": "finding-456",
"resourceType": "AWS::IAM::Role",
"resource": "arn:aws:iam::123456789012:role/cross-account-role",
"principal": {"AWS": "987654321098"},
"action": ["sts:AssumeRole"],
"status": "ACTIVE",
"isPublic": false
}
]
}
Policy Validation
Access Analyzer can also validate IAM policies before you deploy them:
# Validate a policy
$ aws accessanalyzer validate-policy \
--policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}]
}' \
--policy-type IDENTITY_POLICY
{
"findings": [
{
"findingType": "WARNING",
"issueCode": "PASS_ROLE_WITH_STAR_IN_RESOURCE",
"learnMoreLink": "https://docs.aws.amazon.com/...",
"message": "Using wildcards (*) in the resource for iam:PassRole can be overly permissive..."
}
]
}
Policy Generation
Generate least-privilege policies based on actual CloudTrail activity:
# Start policy generation based on last 90 days of activity
$ aws accessanalyzer start-policy-generation \
--policy-generation-details '{
"principalArn": "arn:aws:iam::123456789012:role/my-app-role"
}'
{
"jobId": "job-abc123"
}
# Get the generated policy
$ aws accessanalyzer get-generated-policy --job-id job-abc123
Common Mistakes
| Mistake | Why It Hurts | Fix |
|---|---|---|
| Not creating an analyzer | No visibility into external access | Create one in every region |
| Ignoring findings | Public resources stay public | Triage findings weekly |
| Not validating policies | Overly permissive policies deployed | Validate in CI/CD pipeline |
| Account-level only | Miss org-wide risks | Use ORGANIZATION type analyzer |
Quick Reference
| Task | Command |
|---|---|
| Create analyzer | aws accessanalyzer create-analyzer --analyzer-name NAME --type ACCOUNT |
| List findings | aws accessanalyzer list-findings --analyzer-arn ARN |
| Validate policy | aws accessanalyzer validate-policy --policy-document '...' --policy-type IDENTITY_POLICY |
| Generate policy | aws accessanalyzer start-policy-generation --policy-generation-details '...' |
| Archive finding | aws accessanalyzer update-findings --analyzer-arn ARN --ids '["ID"]' --status ARCHIVED |
Next → KMS Encryption