AWS Security Checklist: 40 Controls for Hardening Your AWS Account
A comprehensive 40-control checklist covering IAM, networking, data protection, and monitoring to harden any AWS account against modern threats.
The CIS AWS Foundations Benchmark is the industry-standard baseline for AWS security, but at over 80 pages it can be daunting to operationalize. This checklist distills it — plus additional controls from the AWS Well-Architected Security Pillar and NIST SP 800-53 — into 40 concrete, actionable items organized by domain. Each item includes the relevant CLI command or configuration snippet.
Identity and Access Management
1. Enable MFA on the Root Account
The root account must have a hardware MFA device (YubiKey or equivalent). Virtual MFA is acceptable but hardware is preferred.
# Verify root MFA status
aws iam get-account-summary --query 'SummaryMap.AccountMFAEnabled'
# 1 = enabled, 0 = not enabled
2. Delete Root Account Access Keys
Root access keys cannot be restricted and grant unlimited API access. Delete them.
aws iam list-access-keys --user-name root 2>/dev/null || echo "No root access keys (expected)"
3. Set Account Password Policy
Enforce complexity, minimum length of 14 characters, and password rotation:
aws iam update-account-password-policy \
--minimum-password-length 14 \
--require-symbols \
--require-numbers \
--require-uppercase-characters \
--require-lowercase-characters \
--allow-users-to-change-password \
--max-password-age 90 \
--password-reuse-prevention 24
4. Enforce MFA for All IAM Users
Attach a policy to all users or the AllUsers group that denies all actions except MFA enrollment when MFA is absent. See the DenyWithoutMFA policy pattern in the misconfigurations guide.
5. No Access Keys for Root
This is separate from #2 — periodically re-verify. Automate with a Config rule:
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "root-access-key-check",
"Source": {"Owner": "AWS", "SourceIdentifier": "IAM_ROOT_ACCESS_KEY_CHECK"}
}'
6. Use IAM Roles for EC2 Instances (Not Access Keys)
Never place access keys on EC2 instances. Attach instance profiles with least-privilege roles instead. Audit for keys on instances:
# Check if any instances have access keys embedded in user data
aws ec2 describe-instances \
--query 'Reservations[].Instances[].{ID:InstanceId,UserData:UserData}' | \
grep -i "AKIA"
7. Apply Permission Boundaries to Developer Roles
Permission boundaries cap the maximum effective permissions, preventing privilege escalation even if a role's policies are accidentally broadened.
8. Enable IAM Access Analyzer
Access Analyzer identifies resources shared outside your account or organization:
aws accessanalyzer create-analyzer \
--analyzer-name org-analyzer \
--type ORGANIZATION
9. Use SCPs to Enforce Guardrails
If using AWS Organizations, apply Service Control Policies to deny dangerous actions at the OU level. Example: deny disabling CloudTrail:
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyCloudTrailDisable",
"Effect": "Deny",
"Action": [
"cloudtrail:DeleteTrail",
"cloudtrail:StopLogging",
"cloudtrail:UpdateTrail"
],
"Resource": "*"
}]
}
10. Rotate Access Keys Regularly
Keys older than 90 days should be rotated. Audit:
aws iam generate-credential-report
aws iam get-credential-report --query 'Content' --output text | base64 -d | \
awk -F, 'NR>1 && $9 != "N/A" && $9 < "'$(date -d '-90 days' +%Y-%m-%d)'" {print $1, $9}'
Networking
11. Enable VPC Flow Logs
Flow logs capture metadata about network traffic and are essential for incident response:
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-12345 \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flowlogs
12. No Security Groups Open to 0.0.0.0/0 on Admin Ports
Ports 22, 3389, 5432, 3306, 6379, 27017 must not be reachable from 0.0.0.0/0. Use Systems Manager Session Manager for SSH/RDP instead.
13. Delete the Default VPC
# For each region, delete internet gateway, subnets, then VPC
VPC_ID=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true \
--query 'Vpcs[0].VpcId' --output text)
IGW_ID=$(aws ec2 describe-internet-gateways \
--filters Name=attachment.vpc-id,Values=$VPC_ID \
--query 'InternetGateways[0].InternetGatewayId' --output text)
aws ec2 detach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID
aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID
# Then delete subnets and VPC
14. Use Private Subnets for Compute
EC2 instances, ECS tasks, and Lambda functions should run in private subnets with no direct route to the internet gateway. Use NAT gateways for outbound-only internet access.
15. Enable AWS Network Firewall for Egress Filtering
For workloads requiring internet access, deploy Network Firewall with domain-based filtering to block connections to known malicious hosts and restrict egress to known-good destinations.
16. Use VPC Endpoints for AWS Services
Route S3, DynamoDB, SSM, and Secrets Manager traffic through VPC endpoints to keep it off the public internet:
aws ec2 create-vpc-endpoint \
--vpc-id vpc-12345 \
--service-name com.amazonaws.us-east-1.secretsmanager \
--vpc-endpoint-type Interface \
--subnet-ids subnet-private1 subnet-private2 \
--security-group-ids sg-endpoint
Data Protection
17. Enable S3 Block Public Access at Account Level
aws s3control put-public-access-block \
--account-id $(aws sts get-caller-identity --query Account --output text) \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
18. Enable S3 Versioning and MFA Delete on Critical Buckets
Versioning protects against accidental or malicious deletion. MFA Delete requires MFA for permanent deletion:
aws s3api put-bucket-versioning \
--bucket critical-data-bucket \
--versioning-configuration MFADelete=Enabled,Status=Enabled \
--mfa "arn:aws:iam::123456789012:mfa/root-account-mfa-device 123456"
19. Enable Default Encryption on All S3 Buckets
Use SSE-KMS with customer-managed keys so you control key rotation and access.
20. Enable EBS Encryption by Default
aws ec2 enable-ebs-encryption-by-default
aws ec2 get-ebs-encryption-by-default
21. Encrypt RDS Instances
Enable encryption at creation. For existing unencrypted databases, create a snapshot, copy it with encryption enabled, and restore.
22. Rotate KMS Keys Annually
Enable automatic key rotation for all customer-managed KMS keys:
aws kms enable-key-rotation --key-id <KEY_ID>
23. Store Secrets in Secrets Manager, Not Environment Variables
Audit Lambda functions and ECS task definitions for secrets in environment variables:
aws lambda list-functions --query 'Functions[].FunctionName' --output text | \
xargs -I{} aws lambda get-function-configuration --function-name {} \
--query 'Environment.Variables'
24. Enable S3 Access Logging
Log requests to critical buckets to a separate logging bucket:
aws s3api put-bucket-logging \
--bucket my-important-bucket \
--bucket-logging-status '{
"LoggingEnabled": {
"TargetBucket": "my-access-logs-bucket",
"TargetPrefix": "my-important-bucket/"
}
}'
Monitoring and Detection
25. Enable CloudTrail Multi-Region Trail
A single multi-region trail with log file validation enabled and logs sent to a locked S3 bucket in a separate security account.
26. Enable AWS Config
Config records configuration changes to resources and evaluates compliance against rules:
aws configservice put-configuration-recorder \
--configuration-recorder name=default,roleARN=arn:aws:iam::123456789012:role/ConfigRole \
--recording-group allSupported=true,includeGlobalResourceTypes=true
27. Enable GuardDuty in All Regions
GuardDuty uses ML and threat intelligence to detect anomalous activity. Enable it across all regions and for all accounts in your organization:
aws guardduty create-detector --enable \
--data-sources '{"S3Logs":{"Enable":true},"EKSAuditLogs":{"Enable":true},"MalwareProtection":{"ScanEc2InstanceWithFindings":{"EbsVolumes":{"Enable":true}}}}'
28. Enable Security Hub
Security Hub aggregates findings from GuardDuty, Inspector, Macie, and third-party tools, and runs CIS and AWS Foundational Security Best Practice checks:
aws securityhub enable-security-hub \
--enable-default-standards
29. Enable Amazon Macie
Macie uses ML to discover and protect sensitive data (PII, credentials) in S3:
aws macie2 enable-macie
aws macie2 create-classification-job \
--job-type SCHEDULED \
--name "Daily S3 Scan" \
--schedule-frequency '{"dailySchedule":{}}' \
--s3-job-definition '{"bucketDefinitions":[{"accountId":"123456789012","buckets":["my-bucket"]}]}'
30. Create CloudWatch Metric Filters for Critical Events
Alert on root login, MFA disable, CloudTrail changes, and security group modifications:
# Root login alarm
aws cloudwatch put-metric-alarm \
--alarm-name RootAccountLogin \
--metric-name RootAccountLoginCount \
--namespace CloudTrailMetrics \
--statistic Sum \
--period 300 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--alarm-actions arn:aws:sns:us-east-1:123456789012:SecurityAlerts
31. Enable CloudTrail Insights
CloudTrail Insights detects unusual write API call volumes that may indicate an ongoing attack or misconfiguration:
aws cloudtrail put-insight-selectors \
--trail-name my-trail \
--insight-selectors '[{"InsightType":"ApiCallRateInsight"},{"InsightType":"ApiErrorRateInsight"}]'
32. Enable Inspector for Vulnerability Scanning
AWS Inspector continuously scans EC2 instances, ECR container images, and Lambda functions for vulnerabilities:
aws inspector2 enable --resource-types EC2 ECR LAMBDA
Incident Response Readiness
33. Create a Dedicated Security Account
In AWS Organizations, designate a separate security account as the delegated administrator for GuardDuty, Security Hub, Macie, and CloudTrail. This account cannot be modified by workload account operators.
34. Enable S3 Object Lock on CloudTrail Bucket
Prevent log tampering with WORM (Write Once Read Many) protection:
aws s3api put-object-lock-configuration \
--bucket cloudtrail-logs-bucket \
--object-lock-configuration '{
"ObjectLockEnabled": "Enabled",
"Rule": {
"DefaultRetention": {
"Mode": "COMPLIANCE",
"Years": 7
}
}
}'
35. Create Runbooks for Common GuardDuty Findings
Document response procedures for UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B, CryptoCurrency:EC2/BitcoinTool.B!DNS, and Recon:IAMUser/MaliciousIPCaller. Store runbooks in a location accessible even if your primary account is compromised.
36. Enable AWS Backup with Cross-Region Replication
Critical data should have automated backups in a separate region and account to survive ransomware or accidental deletion.
37. Use AWS Systems Manager Parameter Store / Secrets Manager for Rotation
Configure automatic rotation for all database credentials and API keys stored in Secrets Manager.
38. Tag All Resources
Consistent tagging enables cost attribution, security scoping, and automated policy enforcement. Enforce tagging with Config rules or Tag Policies in Organizations:
{
"tags": {
"Environment": {"tag_value": {"@@assign": ["production", "staging", "development"]}},
"Owner": {}
}
}
39. Enable Trusted Advisor Security Checks
Trusted Advisor identifies open security group rules, public S3 buckets, and IAM users without MFA. Business and Enterprise support tiers expose all checks via API.
40. Automate Compliance Scanning with Prowler
Prowler is an open-source tool that runs over 300 checks against CIS, PCI-DSS, HIPAA, GDPR, NIST, and SOC2 frameworks:
docker run --rm -it \
-e AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY \
-e AWS_SESSION_TOKEN \
toniblyx/prowler:latest \
-M csv -o /output \
--compliance cis_level2_aws
Run Prowler weekly or integrate it into your CI/CD pipeline to catch drift before it becomes a breach.
Prioritization
If you're starting from scratch, prioritize in this order:
- Root MFA (#1) and delete root access keys (#2)
- CloudTrail multi-region trail (#25) and GuardDuty (#27)
- S3 Block Public Access (#17) and EBS encryption by default (#20)
- MFA enforcement for all IAM users (#4)
- Security Hub with CIS benchmark (#28)
Items 1-5 take less than an hour to implement and eliminate the majority of risk from opportunistic attackers. The remaining 35 controls harden your environment against more sophisticated threats and ensure compliance readiness.