Recently (2-29-2016) the Center for Internet Security (CIS) came out with security benchmarks for Amazon Web Services (AWS) Foundations. I created a shell script that basically glues together all of the CIS tests so gathering the data for analysis can be easy. I condensed several of the tests, and fixed some errors that I encountered. This was tested on my own AMI (RHEL 7). There is obviously a lot of room for improvement, however, this is much better than typing commands again and again.
The script needs to be run from a server with AWS CLI installed (http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html).
#Usage # #./AWS_CIS_Script_v_1_0.sh > AWS_Output.txt # printf "####################DATA-GATHERING######################" echo -e "\n\nGathering Data on Instances...\n" aws ec2 describe-instances echo -e "\n\nGathering Data on Alarms...\n" aws cloudwatch describe-alarms echo -e "\n\nGenerating an IAM Credential Report...\n" aws iam generate-credential-report printf "#############IDENTITY AND ACCESS MANAGEMENT#############" echo -e "\n\nCIS 1.1: Avoid the use of the 'root' account...NIST Control(s): AC-2, AC-6\n" aws iam get-credential-report --query 'Content' --output text | base64 -d | cut -d, -f1,5,11,16 | grep -B1 '<root_account>' echo -e "\n\nCIS 1.2: Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password...NIST Control(s): IA-2\n" aws iam get-credential-report --query 'Content' --output text | base64 -d | cut -d, -f1,4,8 echo -e "\n\nCIS 1.3: Ensure credentials unused for 90 days or greater are disabled...NIST Control(s): AC-2(3)\n" aws iam get-credential-report --query 'Content' --output text | base64 -d | cut -d, -f1,4,9,11,14,16 echo -e "\n\nCIS 1.4: Ensure access keys are rotated every 90 days or less...NIST Control(s): SC-12\n" aws iam get-credential-report --query 'Content' --output text | base64 -d | cut -d, -f1,9,10,11,14,15,16 echo -e "\n\nCIS 1.5-1.11: Ensure IAM password policy meets organizational standards...NIST Control(s): IA-5, IA-5(1)\n" aws iam get-account-password-policy echo -e "\n\nCIS 1.12: Ensure no root account access key exists...NIST Control(s): AC-6" aws iam get-credential-report --query 'Content' --output text | base64 -d | cut -d, -f1,9,14 | grep -B1 '<root_account>' echo -e "\n\nCIS 1.13: Ensure hardware MFA is enabled for the 'root' account...NIST Control(s): IA-2, IA-2(1), IA-2(8), IA-5(11), CM-6" aws iam get-account-summary | grep "AccountMFAEnabled" #CIS 1.14 is not scored... echo -e "\n\nCIS 1.15: Ensure IAM policies are attached only to groups or roles...NIST Control(s): AC-2(7), AC-3, AC-6\n" for i in $(aws iam list-users --query 'Users[*].UserName' --output text); do echo $i && aws iam list-attached-user-policies --user-name $i & aws iam list-user-policies --user-name $i; done printf "#######################LOGGING########################" echo -e "\n\nCIS 2.1-2.2: Ensure CloudTrail is enabled in all regions and log file validation is enabled...NIST Control(s) AU-2, AU-3, AU-6, AU-12\n" aws cloudtrail describe-trails | grep '"Name"\|IsMultiRegionTrail\|LogFileValidationEnabled' echo -e "\n\nCIS 2.3: Ensure the S3 bucket CloudTrail logs to is not publicly accessible...NIST Control(s) AU-9\n" for i in $(aws cloudtrail describe-trails --query 'trailList[*].S3BucketName' | awk -F "\"" '{print $2}'); do aws s3api get-bucket-acl --bucket $i --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' && echo "" && aws s3api get-bucket-acl --bucket $i --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/Authenticated Users`]' && echo "" && aws s3api get-bucket-policy --bucket $i; done echo -e "\n\nCIS 2.4: Ensure CloudTrail trails are integrated with CloudWatch Logs...NIST Control(s):\n" for i in $(aws cloudtrail describe-trails | grep \"Name\": | awk -F "\"" '{ print $4}'); do aws cloudtrail get-trail-status --name $i; done #CIS 2.5 is a manual check...It can probably be scripted but the config service is not free so I didn't experiment... echo -e "\n\nCIS 2.6: Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket...NIST Control(s): AU2, AU-6\n" for i in $(aws cloudtrail describe-trails --query 'trailList[*].S3BucketName' | awk -F "\"" '{print $2}'); do aws s3api get-bucket-logging --bucket $i; done echo -e "\n\nCIS 2.7: Ensure CloudTrail logs are encrypted at rest using KMS CMKs...NIST Control(s): AU-9\n" aws cloudtrail describe-trails | grep '"Name"\|KmsKeyId' echo -e "\n\nCIS 2.8: Ensure rotation for customer created CMKs is enabled...NIST Control(s): \n" for i in $(aws kms list-keys | grep KeyId | awk -F "\"" '{print $4}'); do aws kms get-key-rotation-status --key-id $i; done printf "######################MONITORING#######################" echo -e "\n\nCIS 3.1-3.15: Ensure log metric filters and alarms exist...NIST Control(s):\n" for i in $(aws cloudtrail describe-trails | grep CloudWatchLogsLogGroupArn | awk -F ":" '{print $8}'); do aws logs describe-metric-filters --log-group-name $i | grep '"metricName"\|filterPattern'; done for i in $(aws cloudwatch describe-alarms | grep arn | awk -F "\"" '{print $2}' | grep arn); do aws sns list-subscriptions-by-topic --topic-arn $i; done #CIS 3.16 is not scored... printf "######################NETWORKING#######################" echo -e "\n\nCIS 4.1,4.2,and 4.4: Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 or 3389, and the default security group restricts all traffic...NIST Control(s):\n" aws ec2 describe-security-groups echo -e "\n\nCIS 4.3: Ensure VPC Flow Logging is Enabled in all Applicable Regions...NIST Control(s):\n" aws ec2 describe-flow-logs
This work CIS AWS Benchmark Script, is a derivative of CIS Amazon Web Services Foundations v.1.0.0 – 02-29-2016 by The Center for Internet Security, used under https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode. CIS AWS Benchmark Script is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License, by Jake Miller.