A read-only security scanner for AWS environments. It audits an account for common misconfigurations and produces a structured report without making any changes. Safe to run in production accounts.
The scanner checks S3 buckets, IAM roles and users, EC2 security groups, and untagged resources. Every finding includes the affected resource, the misconfiguration, and a suggested remediation.
S3
- Buckets with public access enabled
- Buckets without server-side encryption
- Buckets without versioning
- Buckets without access logging
IAM
- Roles with wildcard actions or resources in their policies
- Users with console access but no MFA enabled
- Access keys older than 90 days
- Users with more than one active access key
- Roles that have not been used in 90 days
EC2 and VPC
- Security groups with inbound rules open to 0.0.0.0/0
- Security groups with inbound rules open to ::/0
- EC2 instances not enforcing IMDSv2
- EC2 instances with a public IP in a non-public subnet
RDS
- Instances that are publicly accessible
- Instances without encryption at rest
- Instances without automated backups
Tagging
- Any resource missing required tags (configurable)
The scanner uses only read-only IAM permissions. It calls Describe, List, and Get APIs — never Create, Update, or Delete. This makes it safe to run against any account, including production, without risk of accidental changes.
All findings are written to a JSON report and optionally printed to the console as a formatted table. The JSON output is structured so it can be ingested by Security Hub or any SIEM.
The scanner is designed to run both locally and as a scheduled Lambda function.
- Python 3.10+
- AWS credentials with the
SecurityAuditmanaged policy attached (read-only) - boto3
git clone https://github.com/OueSan/aws-cloud-asset-scanner
cd aws-cloud-asset-scanner
pip install -r requirements.txt
# Run all checks
python -m scanner --region us-east-1 --output report.json
# Run specific checks only
python -m scanner --checks s3,iam --region us-east-1
# Run and print results to console as a table
python -m scanner --region us-east-1 --print-tableThe minimum permissions needed to run the scanner:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketAcl",
"s3:GetBucketEncryption",
"s3:GetBucketLogging",
"s3:GetBucketPublicAccessBlock",
"s3:GetBucketVersioning",
"s3:ListAllMyBuckets",
"iam:GenerateCredentialReport",
"iam:GetCredentialReport",
"iam:GetAccountPasswordPolicy",
"iam:ListRoles",
"iam:ListRolePolicies",
"iam:GetRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:ListUsers",
"iam:ListAccessKeys",
"iam:GetAccessKeyLastUsed",
"iam:ListMFADevices",
"ec2:DescribeSecurityGroups",
"ec2:DescribeInstances",
"rds:DescribeDBInstances",
"tag:GetResources"
],
"Resource": "*"
}
]
}Alternatively, attach arn:aws:iam::aws:policy/SecurityAudit which covers all of these and more.
.
├── scanner/
│ ├── __main__.py # Entry point and CLI argument parsing
│ ├── runner.py # Orchestrates all checks and produces the report
│ ├── checks/
│ │ ├── s3.py # S3 bucket checks
│ │ ├── iam.py # IAM role and user checks
│ │ ├── ec2.py # EC2 and security group checks
│ │ ├── rds.py # RDS instance checks
│ │ └── tagging.py # Resource tagging checks
│ └── reports/
│ └── formatter.py # Formats findings as JSON and console table
├── tests/
│ ├── test_s3.py
│ ├── test_iam.py
│ └── test_ec2.py
├── docs/
│ └── findings-reference.md
└── requirements.txt
AWS Cloud Asset Scanner — us-east-1
=====================================
Account: 123456789012
Scan time: 2024-01-15 09:32:14 UTC
Checks run: s3, iam, ec2, rds, tagging
FINDINGS (12 total — 3 HIGH, 6 MEDIUM, 3 LOW)
[HIGH] s3/public-access-enabled
Resource: my-app-bucket
Detail: Block public access is not fully enabled.
Fix: Enable all four block public access settings.
[HIGH] iam/mfa-not-enabled
Resource: iam-user: deploy-user
Detail: IAM user has console access but no MFA device enrolled.
Fix: Enroll an MFA device or remove console access if not needed.
[MEDIUM] ec2/open-security-group
Resource: sg-0abc123def (web-server-sg)
Detail: Inbound rule allows all traffic from 0.0.0.0/0 on port 22.
Fix: Restrict SSH to specific IP ranges or use SSM Session Manager.
... 9 more findings
Writing the IAM checks was the most interesting part because IAM policies can be attached in multiple ways — inline policies, managed policies attached directly, and managed policies attached via groups. The scanner has to enumerate all three paths to get a complete picture of what permissions a user or role actually has.
The credential report was also useful to learn about. IAM generates a CSV file that contains information about all users in the account including password last used, MFA status, and access key ages. Generating and downloading the report is more efficient than calling individual APIs per user for basic compliance checks.