From 5541bb170efa39979e7ff7e8f80ea47fe89ad132 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 13 Sep 2016 00:01:11 -0400 Subject: [PATCH] First functional version --- prowler.sh | 806 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 652 insertions(+), 154 deletions(-) diff --git a/prowler.sh b/prowler.sh index 80a7bb66..3b6de272 100755 --- a/prowler.sh +++ b/prowler.sh @@ -26,7 +26,7 @@ # set -vx # Exits if any error is found -set -e +#set -e # Colors NORMAL="" @@ -87,6 +87,67 @@ while getopts "hp:r:" OPTION; do esac done +# Functions to manage dates depending on OS +if [[ "$OSTYPE" == "linux-gnu" ]]; then + # function to compare in days, usage how_older_from_today date + # date format %Y-%m-%d + how_older_from_today() + { + DATE_TO_COMPARE=$1 + TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s) + DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s) + DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) + echo $DAYS_SINCE + } + # function to convert from timestamp to date, usage timestamp_to_date timestamp + # output date format %Y-%m-%d + timestamp_to_date() + { + # remove fractions of a second + TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") + OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d') + echo $OUTPUT_DATE + } +elif [[ "$OSTYPE" == "darwin"* ]]; then + # BSD/OSX coommands compatibility + how_older_from_today() + { + DATE_TO_COMPARE=$1 + TODAY_IN_DAYS=$(date +%s) + DATE_FROM_IN_DAYS=$(date -jf %Y-%m-%d $DATE_TO_COMPARE +%s) + DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) + echo $DAYS_SINCE + } + timestamp_to_date() + { + # remove fractions of a second + TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") + OUTPUT_DATE=$(date -r $TIMESTAMP_TO_CONVERT +'%Y-%m-%d') + echo $OUTPUT_DATE + } + +elif [[ "$OSTYPE" == "cygwin" ]]; then + # POSIX compatibility layer and Linux environment emulation for Windows + how_older_from_today() + { + DATE_TO_COMPARE=$1 + TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s) + DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s) + DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) + echo $DAYS_SINCE + } + timestamp_to_date() + { + # remove fractions of a second + TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") + OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d') + echo $OUTPUT_DATE + } +else + echo "Unknown Operating System" + exit +fi + if (($# == 0)); then PROFILE=$DEFULT_AWS_PROFILE REGION=$DEFAULT_AWS_REGION @@ -123,191 +184,628 @@ fi #cat ~/.aws/credentials -TITLE1="$BLUE 1 Identity and Access Management$NORMAL" -TITLE11="$BLUE 1.1$NORMAL Avoid the use of the root account (Scored). Last time root account was used - (password last used, access_key_1_last_used, access_key_2_last_used): " -TITLE12="$BLUE 1.2$NORMAL Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" -TITLE13="$BLUE 1.3$NORMAL Ensure credentials unused for 90 days or greater are disabled (Scored)" -TITLE14="$BLUE 1.4$NORMAL Ensure access keys are rotated every 90 days or less (Scored)" -TITLE15="$BLUE 1.5$NORMAL Ensure IAM password policy requires at least one uppercase letter (Scored)" -TITLE16="$BLUE 1.6$NORMAL Ensure IAM password policy require at least one lowercase letter (Scored)" -TITLE17="$BLUE 1.7$NORMAL Ensure IAM password policy require at least one symbol (Scored)" -TITLE18="$BLUE 1.8$NORMAL Ensure IAM password policy require at least one number (Scored)" -TITLE19="$BLUE 1.9$NORMAL Ensure IAM password policy requires minimum length of 14 or greater (Scored)" -TITLE110="$BLUE 1.10$NORMAL Ensure IAM password policy prevents password reuse (Scored)" -TITLE111="$BLUE 1.11$NORMAL Ensure IAM password policy expires passwords within 90 days or less (Scored)" -TITLE112="$BLUE 1.12$NORMAL Ensure no root account access key exists (Scored)" -TITLE113="$BLUE 1.13$NORMAL Ensure hardware MFA is enabled for the root account (Scored)" -TITLE114="$BLUE 1.14$NORMAL Ensure security questions are registered in the AWS account (Not Scored)" -TITLE115="$BLUE 1.15$NORMAL Ensure IAM policies are attached only to groups or roles (Scored)" -TITLE2="$BLUE 2 Logging$NORMAL" -TITLE21="$BLUE 2.1$NORMAL Ensure CloudTrail is enabled in all regions (Scored)" -TITLE22="$BLUE 2.2$NORMAL Ensure CloudTrail log file validation is enabled (Scored)" -TITLE23="$BLUE 2.3$NORMAL Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" -TITLE24="$BLUE 2.4$NORMAL Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" -TITLE25="$BLUE 2.5$NORMAL Ensure AWS Config is enabled in all regions (Scored)" -TITLE26="$BLUE 2.6$NORMAL Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" -TITLE27="$BLUE 2.7$NORMAL Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" -TITLE28="$BLUE 2.8$NORMAL Ensure rotation for customer created CMKs is enabled (Scored)" -TITLE3="$BLUE 3 Monitoring" -TITLE31="$BLUE 3.1$NORMAL Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" -TITLE32="$BLUE 3.2$NORMAL Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" -TITLE33="$BLUE 3.3$NORMAL Ensure a log metric filter and alarm exist for usage of root account (Scored)" -TITLE34="$BLUE 3.4$NORMAL Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" -TITLE35="$BLUE 3.5$NORMAL Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" -TITLE36="$BLUE 3.6$NORMAL Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" -TITLE37="$BLUE 3.7$NORMAL Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" -TITLE38="$BLUE 3.8$NORMAL Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" -TITLE39="$BLUE 3.9$NORMAL Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" -TITLE310="$BLUE 3.10$NORMAL Ensure a log metric filter and alarm exist for security group changes (Scored)" -TITLE311="$BLUE 3.11$NORMAL Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" -TITLE312="$BLUE 3.12$NORMAL Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" -TITLE313="$BLUE 3.13$NORMAL Ensure a log metric filter and alarm exist for route table changes (Scored)" -TITLE314="$BLUE 3.14$NORMAL Ensure a log metric filter and alarm exist for VPC changes (Scored)" -TITLE315="$BLUE 3.15$NORMAL Ensure security contact information is registered (Scored)" -TITLE316="$BLUE 3.16$NORMAL Ensure appropriate subscribers to each SNS topic (Not Scored)" -TITLE4="$BLUE 4 Networking$NORMAL" -TITLE41="$BLUE 4.1$NORMAL Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" -TITLE42="$BLUE 4.2$NORMAL Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" -TITLE43="$BLUE 4.3$NORMAL Ensure VPC Flow Logging is Enabled in all Applicable Regions (Scored)" -TITLE44="$BLUE 4.4$NORMAL Ensure the default security group restricts all traffic (Scored)" +prowlerBanner() { +echo -e "$CYAN _" +echo -e " _ __ _ __ _____ _| | ___ _ __" +echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|" +echo -e " | |_) | | | (_) \ V V /| | __/ |" +echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|" +echo -e " |_|$NORMAL$BLUE CIS based AWS Account Hardening Tool$NORMAL\n" +} # Get whoami in AWS, who is the user running this shell script getWhoami() { - echo -e '\n This report is being generated using credentials below:\n' - echo -e "\n AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS Region: $NOTICE[$REGION]$NORMAL\n" + echo -e "\nThis report is being generated using credentials below:\n" + echo -e "AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS Region: $NOTICE[$REGION]$NORMAL\n" $AWSCLI sts get-caller-identity --output table --profile $PROFILE --region $REGION } + +prowlerBanner +echo -e "\nDate: $NOTICE$(date)$NORMAL" getWhoami -echo -e "\nColors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK CORRECT (RECOMMENDED VALUE)$NORMAL, $BAD CRITICAL (FIX REQUIRED)$NORMAL \n" +echo -e "\nColors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD CRITICAL (FIX REQUIRED)$NORMAL \n" # Generate Credential Report genCredReport() { echo -en '\nGenerating Credential Report...' while STATE=$($AWSCLI iam generate-credential-report --output text --query 'State' --profile $PROFILE --region $REGION) test "$STATE" = "STARTED" - #test "$STATE" = "COMPLETE" do sleep 1 echo -n '.' done - echo -en " $STATE!" + echo -en " COMPLETE!" } genCredReport +# Save report to a file, deletion at finish. ACB stands for AWS CIS Benchmark +TEMP_REPORT_FILE=/tmp/.acb +$AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION | base64 -D > $TEMP_REPORT_FILE + +# Get a list of all available AWS Regions REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ --output text \ --profile $PROFILE \ --region $REGION) +TITLE1="$BLUE 1 Identity and Access Management *********************************$NORMAL" +echo -e "\n\n$TITLE1 " -# 1 Identity and Access Management check commands -COMMAND11=$($AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION| base64 -D | grep '' | cut -d, -f5,11,16) -# COMMAND12=$($AWSCLI iam generate-credential-report --profile $PROFILE --region $REGION; $AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION| base64 -D | cut -d, -f1,4,8) -# COMMAND13=$($AWSCLI iam generate-credential-report --profile $PROFILE --region $REGION; $AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION| base64 -D) # checked by Security Monkey -# COMMAND14=$($AWSCLI iam generate-credential-report --profile $PROFILE --region $REGION; $AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION| base64 -D) # checked by Security Monkey -# COMMAND15=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION| grep RequireUppercaseCharacters) # must be true -# COMMAND16=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION| grep RequireLowercaseCharacters) # must be true -# COMMAND17=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION| grep RequireSymbols) # must be true -# COMMAND18=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION| grep RequireNumbers) # must be true -# COMMAND19=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION| grep MinimumPasswordLength) # must be 14 -# COMMAND110=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION| grep PasswordReusePrevention) # must be 24 -# COMMAND111=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION| grep MaxPasswordAge) # must be 90 -# COMMAND112=$($AWSCLI iam generate-credential-report --profile $PROFILE --region $REGION; $AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION| base64 -D) # ensure the access_key_1_active and access_key_2_active fields are set to FALSE. -# COMMAND113=$($AWSCLI iam get-account-summary --profile $PROFILE --region $REGION| grep AccountMFAEnabled) # must be 1 -# Review 14, no command available -# COMMAND114=$(for i in $($AWSCLI iam list-users --query 'Users[*].UserName' --output text --profile $PROFILE --region $REGION); do echo $i;$AWSCLI iam list-attached-user-policies --user-name $i --profile $PROFILE --region $REGION; $AWSCLI iam list-user-policies --user-name $i --profile $PROFILE --region $REGION; done) -# COMMAND115=$($AWSCLI iam generate-credential-report --profile $PROFILE --region $REGION; $AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION| base64 -D | grep root_account | awk -F, '{ print $1"\t" $9"\t" $14 }') # both must be false +# 1.1 +TITLE11="$BLUE 1.1$NORMAL Avoid the use of the root account (Scored). Last time root account was used + (password last used, access_key_1_last_used, access_key_2_last_used): " + COMMAND11=$(cat $TEMP_REPORT_FILE| grep '' | cut -d, -f5,11,16) + echo -e "\n$TITLE11 $NOTICE $COMMAND11 $NORMAL" -echo -e "\n $TITLE1" -echo -e "\n $TITLE11 $NOTICE $COMMAND11 $NORMAL" +# 1.2 +TITLE12="$BLUE 1.2$NORMAL Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" + # List users with password enabled + COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED=$(cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$4 }' |grep true | awk '{ print $1 }') + COMMAND12=$( + for i in $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED; do + cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$8 }' |grep $i| grep false | awk '{ print $1 }'|tr '\n' ' '; + done) -# 2 Logging check commands -# COMMAND21=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION| grep IsMultiRegionTrail) # must be true -# COMMAND22=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION| grep LogFileValidationEnabled) # must be true -# COMMAND23=$($AWSCLI s3api get-bucket-acl --bucket $(aws cloudtrail describe-trails --query 'trailList[*].S3BucketName' --profile $PROFILE --region $REGION --output text --profile $PROFILE --region $REGION) --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' --profile $PROFILE --region $REGION # must be empty -# $AWSCLI s3api get-bucket-acl --bucket $(aws cloudtrail describe-trails --query 'trailList[*].S3BucketName' --profile $PROFILE --region $REGION --output text) --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/Authenticated Users`]' --profile $PROFILE --region $REGION # must be empty -# $AWSCLI s3api get-bucket-policy --bucket usm-cloudtrail--1066738384 --profile $PROFILE --region $REGION) # must be empty or not policy" -# COMMAND24=$(for i in $($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].Name' --output text); do aws cloudtrail get-trail-status --name $i --profile $PROFILE --region $REGION | grep LatestcloudwatchLogdDeliveryTime; done) # it must be set to ~one day old -# COMMAND25=$(aws configservice get-status --profile $PROFILE --region $REGION) # must be set -# COMMAND26=$(for i in $($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --profile $PROFILE --region $REGION --output text); do aws s3api get-bucket-logging --bucket $i --profile $PROFILE --region $REGION; done) # must be enabled -# COMMAND27=$(for i in $($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].Name' --output text); do aws cloudtrail describe-trails --profile $PROFILE --region $REGION; done |grep KmsKeyId) # it can NOT be empty -# COMMAND28=$(for i in $($AWSCLI kms list-keys --query 'Keys[*].KeyId' --output text --profile $PROFILE --region $REGION); do echo $i; aws kms get-key-rotation-status --key-id $i --profile $PROFILE --region $REGION; done) # must be true + echo -e "\n$TITLE12" + if [[ $COMMAND12 ]]; then + echo " List of users with Password enabled but MFA disabled: $RED $COMMAND12 $NORMAL" + else + echo " $OK CORRECT! No users found with Password enabled and MFA disabled $NORMAL" + fi +# 1.3 +TITLE13="$BLUE 1.3$NORMAL Ensure credentials unused for 90 days or greater are disabled (Scored)" + COMMAND13=$( + for i in $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED; do + cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$5 }' |grep $i| grep false | awk '{ print $1 }'|tr '\n' ' '; + done) + # list of users that have used password + USERS_PASSWORD_USED=$($AWSCLI iam list-users --query "Users[?PasswordLastUsed].UserName" --output text --profile $PROFILE --region $REGION) + + echo -e "\n$TITLE13 " + # look for users with a password last used more or equal to 90 days + echo -e " User list: " + for i in $USERS_PASSWORD_USED; do + DATEUSED=$($AWSCLI iam list-users --query "Users[?UserName=='$i'].PasswordLastUsed" --output text --profile $PROFILE --region $REGION | cut -d'T' -f1) + HOWOLDER=$(how_older_from_today $DATEUSED) + if [ $HOWOLDER -gt "90" ];then + echo " $RED $i $NORMAL" + else + echo " $OK OK $NORMAL" + fi + done + +# 1.4 +TITLE14="$BLUE 1.4$NORMAL Ensure access keys are rotated every 90 days or less (Scored)" # also checked by Security Monkey +LIST_OF_USERS_WITH_ACCESS_KEY1=$(cat $TEMP_REPORT_FILE| awk -F, '{ print $1, $9 }' |grep "\ true" | awk '{ print $1 }') +LIST_OF_USERS_WITH_ACCESS_KEY2=$(cat $TEMP_REPORT_FILE| awk -F, '{ print $1, $14 }' |grep "\ true" | awk '{ print $1 }') + echo -e "\n$TITLE14 " + echo -e " Users with access key 1 older than 90 days: " + for user in $LIST_OF_USERS_WITH_ACCESS_KEY1; do + # check access key 1 + DATEROTATED1=$(cat $TEMP_REPORT_FILE | grep $user| awk -F, '{ print $10 }' | grep -v "N/A" | awk -F"T" '{ print $1 }') + HOWOLDER=$(how_older_from_today $DATEROTATED1) + + if [ $HOWOLDER -gt "90" ];then + echo -e " $RED $user $NORMAL" + fi + done + + echo -e " Users with access key 2 older than 90 days: " + for user in $LIST_OF_USERS_WITH_ACCESS_KEY2; do + # check access key 2 + DATEROTATED2=$(cat $TEMP_REPORT_FILE | grep $user| awk -F, '{ print $10 }' | grep -v "N/A" | awk -F"T" '{ print $1 }') + HOWOLDER=$(how_older_from_today $DATEROTATED2) + if [ $HOWOLDER -gt "90" ];then + echo -e " $RED $user $NORMAL" + fi + done + +# 1.5 +TITLE15="$BLUE 1.5$NORMAL Ensure IAM password policy requires at least one uppercase letter (Scored)" +COMMAND15=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --query 'PasswordPolicy.RequireUppercaseCharacters') # must be true + echo -e "\n$TITLE15 " + if [ $COMMAND15 == "True" ];then + echo -e " $OK OK $NORMAL" + else + echo -e " $RED FALSE $NORMAL" + fi + +# 1.6 +TITLE16="$BLUE 1.6$NORMAL Ensure IAM password policy require at least one lowercase letter (Scored)" +COMMAND16=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --query 'PasswordPolicy.RequireLowercaseCharacters') # must be true + echo -e "\n$TITLE16 " + if [ $COMMAND16 == "True" ];then + echo -e " $OK OK $NORMAL" + else + echo -e " $RED FALSE $NORMAL" + fi + +# 1.7 +TITLE17="$BLUE 1.7$NORMAL Ensure IAM password policy require at least one symbol (Scored)" +COMMAND17=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --query 'PasswordPolicy.RequireSymbols') # must be true + echo -e "\n$TITLE17 " + if [ $COMMAND17 == "True" ];then + echo -e " $OK OK $NORMAL" + else + echo -e " $RED FALSE $NORMAL" + fi + +# 1.8 +TITLE18="$BLUE 1.8$NORMAL Ensure IAM password policy require at least one number (Scored)" +COMMAND18=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --query 'PasswordPolicy.RequireNumbers') # must be true + echo -e "\n$TITLE18 " + if [ $COMMAND18 == "True" ];then + echo -e " $OK OK $NORMAL" + else + echo -e " $RED FALSE $NORMAL" + fi + +# 1.9 +TITLE19="$BLUE 1.9$NORMAL Ensure IAM password policy requires minimum length of 14 or greater (Scored)" +COMMAND19=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --query 'PasswordPolicy.MinimumPasswordLength') + echo -e "\n$TITLE19 " + if [ $COMMAND19 -gt "13" ];then + echo -e " $OK OK $NORMAL" + else + echo -e " $RED FALSE $NORMAL" + fi + +# 1.10 +TITLE110="$BLUE 1.10$NORMAL Ensure IAM password policy prevents password reuse (Scored)" +COMMAND110=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' | grep PasswordReusePrevention | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g') + echo -e "\n$TITLE110 " + if [[ $COMMAND110 ]];then + if [[ $COMMAND110 -gt "23" ]];then + echo -e " $OK OK $NORMAL" + fi + else + echo -e " $RED FALSE $NORMAL" + fi + +# 1.11 +TITLE111="$BLUE 1.11$NORMAL Ensure IAM password policy expires passwords within 90 days or less (Scored)" +COMMAND111=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g') + echo -e "\n$TITLE111 " + if [[ $COMMAND111 ]];then + if [ $COMMAND111 == "90" ];then + echo -e " $OK OK $NORMAL" + fi + else + echo -e " $RED FALSE $NORMAL" + fi + +# 1.12 +TITLE112="$BLUE 1.12$NORMAL Ensure no root account access key exists (Scored)" +# ensure the access_key_1_active and access_key_2_active fields are set to FALSE. +ROOTKEY1=$(cat $TEMP_REPORT_FILE |grep root_account|awk -F, '{ print $9 }') +ROOTKEY2=$(cat $TEMP_REPORT_FILE |grep root_account|awk -F, '{ print $14 }') + echo -e "\n$TITLE112 " + if [ $ROOTKEY1 == false ];then + echo -e " $OK OK $NORMAL No access key 1 found " + else + echo -e " $RED Found access key 1 $NORMAL" + fi + if [ $ROOTKEY2 == false ];then + echo -e " $OK OK $NORMAL No access key 2 found " + else + echo -e " $RED Found access key 2 $NORMAL" + fi + +# 1.13 +TITLE113="$BLUE 1.13$NORMAL Ensure hardware MFA is enabled for the root account (Scored)" +COMMAND113=$($AWSCLI iam list-virtual-mfa-devices --profile $PROFILE --region $REGION --query 'VirtualMFADevices[*].User.Arn' --output text | awk -F":" '{ print $6 }'|tr '\n' ' ') +echo -e "\n$TITLE113" + if [ $COMMAND113 ]; then + echo " $OK OK $NORMAL" + else + echo " $RED WARNING, MFA is not ENABLED for root account $NORMAL" + fi + +# 1.14 +TITLE114="$BLUE 1.14$NORMAL Ensure security questions are registered in the AWS account (Not Scored)" +# No command available +echo -e "\n$TITLE114" +echo -e " $NOTICE No command available for check 1.14" +echo -e " Login to the AWS Console as root, click on the Account " +echo -e " Name -> My Account -> Configure Security Challenge Questions $NORMAL" + +# 1.15 +TITLE115="$BLUE 1.15$NORMAL Ensure IAM policies are attached only to groups or roles (Scored)" +echo -e "\n$TITLE115" +LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text --profile $PROFILE --region $REGION) +echo -e " Users with policy attached to them instead to groups: (it may take few seconds...) " + for user in $LIST_USERS;do + USER_POLICY=$($AWSCLI iam list-attached-user-policies --output text --profile $PROFILE --region $REGION --user-name $user) + if [[ $USER_POLICY ]]; then + echo -e " $RED $user $NORMAL" + fi + done + +TITLE2="$BLUE 2 Logging ********************************************************$NORMAL" +echo -e "\n\n$TITLE2 " + +TITLE21="$BLUE 2.1$NORMAL Ensure CloudTrail is enabled in all regions (Scored)" +echo -e "\n$TITLE21" +COMMAND21=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].IsMultiRegionTrail' --output text) + if [[ $COMMAND21 ]];then + if [ $COMMAND21 == "True" ];then + echo -e " $OK OK $NORMAL" + fi + else + echo -e " $RED FALSE $NORMAL" + fi + +TITLE22="$BLUE 2.2$NORMAL Ensure CloudTrail log file validation is enabled (Scored)" +echo -e "\n$TITLE22" +COMMAND22=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].LogFileValidationEnabled' --output text +) + if [[ $COMMAND22 ]];then + if [ $COMMAND22 == "True" ];then + echo -e " $OK OK $NORMAL" + fi + else + echo -e " $RED FALSE $NORMAL" + fi + +TITLE23="$BLUE 2.3$NORMAL Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" +echo -e "\n$TITLE23" + +CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text --profile $PROFILE --region $REGION) + if [[ $CLOUDTRAILBUCKET ]];then + CLOUDTRAILBUCKET_HASALLPERMISIONS=$($AWSCLI s3api get-bucket-acl --bucket $CLOUDTRAILBUCKET --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' --profile $PROFILE --region $REGION --output text) + # aws s3api get-bucket-policy --bucket $CLOUDTRAILBUCKET --profile $PROFILE --region $REGION --output text + if [[ $CLOUDTRAILBUCKET_HASALLPERMISIONS ]];then + echo -e " $RED WARNING, check your CloudTrail bucket ACL and Policy!$NORMAL" + else + echo -e " $OK OK $NORMAL" + fi + else + echo -e " $RED WARNING, CloudTrail bucket doesn't exist!$NORMAL" + fi + +TITLE24="$BLUE 2.4$NORMAL Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" +echo -e "\n$TITLE24" + +LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].Name' --output text) +if [[ $LIST_OF_TRAILS ]];then + for trail in $LIST_OF_TRAILS;do + LATESTDELIVERY_TIMESTAMP=$($AWSCLI cloudtrail get-trail-status --name $trail --profile $PROFILE --region $REGION --query 'LatestCloudWatchLogsDeliveryTime') + LATESTDELIVERY_DATE=$(timestamp_to_date $LATESTDELIVERY_TIMESTAMP) + HOWOLDER=$(how_older_from_today $LATESTDELIVERY_DATE) + if [ $HOWOLDER -gt "1" ];then + echo -e " $RED $trail is not logging in the last 24h $NORMAL" + else + echo -e " $OK $trail has been logging during the last 24h $NORMAL" + fi + done +else + echo -e " $RED WARNING, No CloudTrail trails found!$NORMAL" +fi + +TITLE25="$BLUE 2.5$NORMAL Ensure AWS Config is enabled in all regions (Scored)" +echo -e "\n$TITLE25" +for regx in $REGIONS; do + CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice get-status --profile $PROFILE --region $regx | grep recorder) + if [[ $CHECK_AWSCONFIG_STATUS ]];then + echo -e " $OK Region $regx has AWS Config $CHECK_AWSCONFIG_STATUS $NORMAL" + else + echo -e " $RED WARNING, Region $regx has AWS Config disabled or not configured$NORMAL" + fi +done + +TITLE26="$BLUE 2.6$NORMAL Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" +echo -e "\n$TITLE26" +CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text --profile $PROFILE --region $REGION) + if [[ $CLOUDTRAILBUCKET ]];then + CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $CLOUDTRAILBUCKET --profile $PROFILE --region $REGION --query 'LoggingEnabled.TargetBucket' --output text|grep -v None) + if [[ $CLOUDTRAILBUCKET_LOGENABLED ]];then + echo -e " $OK OK $NORMAL" + else + echo -e " $RED WARNING, access logging is not enabled in your CloudTrail S3 bucket!$NORMAL" + fi + else + echo -e " $RED WARNING, CloudTrail bucket doesn't exist!$NORMAL" + fi + +TITLE27="$BLUE 2.7$NORMAL Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" +echo -e "\n$TITLE27" +CLOUDTRAILNAME=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].Name' --output text --profile $PROFILE --region $REGION) + if [[ $CLOUDTRAILNAME ]];then + CLOUDTRAILENC_ENABLED=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --trail $CLOUDTRAILNAME --query 'trailList[*].KmsKeyId' --output text) + if [[ $CLOUDTRAILENC_ENABLED ]];then + echo -e " $OK OK $NORMAL" + else + echo -e " $RED WARNING, encryption is not enabled in your CloudTrail trail, KMS key not found!$NORMAL" + fi + else + echo -e " $RED WARNING, CloudTrail bucket doesn't exist!$NORMAL" + fi + +TITLE28="$BLUE 2.8$NORMAL Ensure rotation for customer created CMKs is enabled (Scored)" +echo -e "\n$TITLE28" +for regx in $REGIONS; do + CHECK_KMS_KEYLIST=$($AWSCLI kms list-keys --profile $PROFILE --region $regx --output text --query 'Keys[*].KeyId') + if [[ $CHECK_KMS_KEYLIST ]];then + for key in $CHECK_KMS_KEYLIST; do + CHECK_KMS_KEY_ROTATION=$($AWSCLI kms get-key-rotation-status --key-id $key --profile $PROFILE --region $regx --output text) + if [ $CHECK_KMS_KEY_ROTATION == "True" ];then + echo -e " $OK OK $NORMAL, Key $key in Region $regx is set correctly" + else + echo -e " $RED WARNING, Key $key in Region $regx is not set to rotate!$NORMAL" + fi + done + else + echo -e " $NOTICE Region $regx doesn't have encryption keys $NORMAL" + fi +done + +TITLE3="$BLUE 3 Monitoring *****************************************************" +echo -e "\n\n$TITLE3 " # 3 Monitoring check commands / Mostly covered by SecurityMonkey -#COMMAND31=$AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION | take group ARN | aws logs describe-metric-filters --log-group-name "" -COMMAND32= -COMMAND33= -COMMAND34= -COMMAND35= -COMMAND36= -COMMAND37= -COMMAND38= -COMMAND39= -COMMAND310= -COMMAND311= -COMMAND312= -COMMAND313= -COMMAND314= -COMMAND315= -COMMAND316= -# 4 Networking check commands -# COMMAND41= THIS MAY HELP: aws ec2 describe-security-groups --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" --query "SecurityGroups[].[GroupId, GroupName]" --profile $PROFILE --region $REGION -# COMMAND42= same above for here -# COMMAND43= Ensure VPC Flow Logging is Enabled in all Applicable Regions +TITLE31="$BLUE 3.1$NORMAL Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" +echo -e "\n$TITLE31 " +CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }') +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep AccessDenied) + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters for Access Denied enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE32="$BLUE 3.2$NORMAL Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" +echo -e "\n$TITLE32 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'userIdentity.sessionContext.attributes.mfaAuthenticated.*true') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters for sign-in Console without MFA enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE33="$BLUE 3.3$NORMAL Ensure a log metric filter and alarm exist for usage of root account (Scored)" +echo -e "\n$TITLE33 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'Root.*AwsServiceEvent') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters for usage of root account enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE34="$BLUE 3.4$NORMAL Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" +echo -e "\n$TITLE34 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'DeleteGroupPolicy.*DeleteRolePolicy.*DeleteUserPolicy.*PutGroupPolicy.*PutRolePolicy.*PutUserPolicy.*CreatePolicy.*DeletePolicy.*CreatePolicyVersion.*DeletePolicyVersion.*AttachRolePolicy.*DetachRolePolicy.*AttachUserPolicy.*DetachUserPolicy.*AttachGroupPolicy.*DetachGroupPolicy') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters for IAM policy changes enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE35="$BLUE 3.5$NORMAL Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" +echo -e "\n$TITLE35 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'CreateTrail.*UpdateTrail.*DeleteTrail.*StartLogging.*StopLogging') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters for CloudTrail configuration changes enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE36="$BLUE 3.6$NORMAL Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" +echo -e "\n$TITLE36 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'ConsoleLogin.*Failed') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters for usage of root account enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE37="$BLUE 3.7$NORMAL Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" +echo -e "\n$TITLE37 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'kms.amazonaws.com.*DisableKey.*ScheduleKeyDeletion') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE38="$BLUE 3.8$NORMAL Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" +echo -e "\n$TITLE38 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 's3.amazonaws.com.*PutBucketAcl.*PutBucketPolicy.*PutBucketCors.*PutBucketLifecycle.*PutBucketReplication.*DeleteBucketPolicy.*DeleteBucketCors.*DeleteBucketLifecycle.*DeleteBucketReplication') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE39="$BLUE 3.9$NORMAL Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" +echo -e "\n$TITLE39 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'config.amazonaws.com.*StopConfigurationRecorder.*DeleteDeliveryChannel.*PutDeliveryChannel.*PutConfigurationRecorder') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE310="$BLUE 3.10$NORMAL Ensure a log metric filter and alarm exist for security group changes (Scored)" +echo -e "\n$TITLE310 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'AuthorizeSecurityGroupIngress.*AuthorizeSecurityGroupEgress.*RevokeSecurityGroupIngress.*RevokeSecurityGroupEgress.*CreateSecurityGroup.*DeleteSecurityGroup') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE311="$BLUE 3.11$NORMAL Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" +echo -e "\n$TITLE311 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'CreateNetworkAcl.*CreateNetworkAclEntry.*DeleteNetworkAcl.*DeleteNetworkAclEntry.*ReplaceNetworkAclEntry.*ReplaceNetworkAclAssociation') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE312="$BLUE 3.12$NORMAL Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" +echo -e "\n$TITLE312 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'CreateCustomerGateway.*DeleteCustomerGateway.*AttachInternetGateway.*CreateInternetGateway.*DeleteInternetGateway.*DetachInternetGateway') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE313="$BLUE 3.13$NORMAL Ensure a log metric filter and alarm exist for route table changes (Scored)" +echo -e "\n$TITLE313 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'CreateRoute.*CreateRouteTable.*ReplaceRoute.*ReplaceRouteTableAssociation.*DeleteRouteTable.*DeleteRoute.*DisassociateRouteTable') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE314="$BLUE 3.14$NORMAL Ensure a log metric filter and alarm exist for VPC changes (Scored)" +echo -e "\n$TITLE314 " +if [[ $CLOUDWATCH_GROUP ]];then + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name CloudTrail/CloudWatchGroup --profile $PROFILE --region $REGION --query 'trailList' | grep -E 'CreateVpc.*DeleteVpc.*ModifyVpcAttribute.*AcceptVpcPeeringConnection.*CreateVpcPeeringConnection.*DeleteVpcPeeringConnection.*RejectVpcPeeringConnection.*AttachClassicLinkVpc.*DetachClassicLinkVpc.*DisableVpcClassicLink.*EnableVpcClassicLink') + if [[ $METRICFILTER_SET ]];then + echo -e " $OK OK, CloudWatch group found, and metric filters enabled$NORMAL" + else + echo -e " $RED WARNING, CloudWatch group found, but no metric filters or alarms associated$NORMAL" + fi +else + echo -e " $RED WARNING, No CloudWatch group found, no metric filters or alarms associated$NORMAL" +fi + +TITLE315="$BLUE 3.15$NORMAL Ensure security contact information is registered (Scored)" +# No command available +echo -e "\n$TITLE315 " +echo -e " $NOTICE No command available for check 3.15" +echo -e " Login to the AWS Console, click on My Account " +echo -e " Go to Alternate Contacts -> make sure Security section is filled $NORMAL" + +TITLE316="$BLUE 3.16$NORMAL Ensure appropriate subscribers to each SNS topic (Not Scored)" +echo -e "\n$TITLE316 " +for regx in $REGIONS; do + TOPICS_LIST=$($AWSCLI sns list-topics --profile $PROFILE --region $regx --output text --query 'Topics[*].TopicArn') + if [[ $TOPICS_LIST ]];then + for topic in $TOPICS_LIST; do + CHECK_TOPIC_LIST=$($AWSCLI sns list-subscriptions-by-topic --topic-arn $topic --profile $PROFILE --region $regx --query 'Subscriptions[*].{Endpoint:Endpoint,Protocol:Protocol}' --output text) + if [[ $CHECK_TOPIC_LIST ]]; then + TOPIC_SHORT=$(echo $topic | awk -F: '{ print $7 }') + echo -e " $NOTICE Region $regx with Topic $TOPIC_SHORT: $NORMAL " + echo -e " $NOTICE - Suscription: $CHECK_TOPIC_LIST $NORMAL" + else + echo -e " $RED WARNING, No suscription found in Region $regx and Topic $topic $NORMAL" + fi + done + else + echo -e " $NOTICE Region $regx doesn't have topics $NORMAL" + fi +done + +TITLE4="$BLUE 4 Networking **************************************************$NORMAL" +echo -e "\n\n$TITLE4 " + +TITLE41="$BLUE 4.1$NORMAL Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" +echo -e "\n$TITLE41 " +for regx in $REGIONS; do + SG_LIST=$($AWSCLI ec2 describe-security-groups --filters "Name=ip-permission.to-port,Values=22" --query 'SecurityGroups[?length(IpPermissions[?ToPort==`22` && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupName: GroupName}' --profile $PROFILE --region $regx --output text) + if [[ $SG_LIST ]];then + for SG in $SG_LIST;do + echo -e " $RED Found Security Group: $SG open to 0.0.0.0/0 in Region $regx $NORMAL " + done + else + echo -e " $OK OK, No Security Groups found in $regx with port 22 TCP open to 0.0.0.0/0 $NORMAL " + fi +done + +TITLE42="$BLUE 4.2$NORMAL Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" +echo -e "\n$TITLE42 " +for regx in $REGIONS; do + SG_LIST=$($AWSCLI ec2 describe-security-groups --filters "Name=ip-permission.to-port,Values=3389" --query 'SecurityGroups[?length(IpPermissions[?ToPort==`3389` && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupName: GroupName}' --profile $PROFILE --region $regx --output text) + if [[ $SG_LIST ]];then + for SG in $SG_LIST;do + echo -e " $RED Found Security Group: $SG open to 0.0.0.0/0 in Region $regx $NORMAL " + done + else + echo -e " $OK OK, No Security Groups found in $regx with port 3389 TCP open to 0.0.0.0/0 $NORMAL " + fi +done + +TITLE43="$BLUE 4.3$NORMAL Ensure VPC Flow Logging is Enabled in all Applicable Regions (Scored)" +echo -e "\n$TITLE43 " +for regx in $REGIONS; do + CHECK_FL=$($AWSCLI ec2 describe-flow-logs --profile $PROFILE --region $regx --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].LogGroupName' --output text) + if [[ $CHECK_FL ]];then + for FL in $CHECK_FL;do + echo -e " $OK OK, VPCFlowLog is enabled for LogGroupName: $FL in Region $regx $NORMAL " + done + else + echo -e " $RED WARNING, no VPCFlowLog has been found in Region $regx $NORMAL " + fi +done + +TITLE44="$BLUE 4.4$NORMAL Ensure the default security group restricts all traffic (Scored)" +echo -e "\n$TITLE44 " #COMMAND44= Ensure the default security group restricts all traffic - -# Report result -echo -e "\n$TITLE1\n " -echo -e "$TITLE11 " -echo -e "$TITLE12 " -echo -e "$TITLE13 " -echo -e "$TITLE14 " -echo -e "$TITLE15 " -echo -e "$TITLE16 " -echo -e "$TITLE17 " -echo -e "$TITLE18 " -echo -e "$TITLE19 " -echo -e "$TITLE110 " -echo -e "$TITLE111 " -echo -e "$TITLE112 " -echo -e "$TITLE113 " -echo -e "$TITLE114 " -echo -e "$TITLE115 " -echo -e "\n$TITLE2\n " -echo -e "$TITLE21 " -echo -e "$TITLE22 " -echo -e "$TITLE23 " -echo -e "$TITLE24 " -echo -e "$TITLE25 " -echo -e "$TITLE26 " -echo -e "$TITLE27 " -echo -e "$TITLE28 " -echo -e "\n$TITLE3\n " -echo -e "$TITLE31 " -echo -e "$TITLE32 " -echo -e "$TITLE33 " -echo -e "$TITLE34 " -echo -e "$TITLE35 " -echo -e "$TITLE36 " -echo -e "$TITLE37 " -echo -e "$TITLE38 " -echo -e "$TITLE39 " -echo -e "$TITLE310 " -echo -e "$TITLE311 " -echo -e "$TITLE312 " -echo -e "$TITLE313 " -echo -e "$TITLE314 " -echo -e "$TITLE315 " -echo -e "$TITLE316 " -echo -e "\n$TITLE4\n " -echo -e "$TITLE41 " -echo -e "$TITLE42 " -echo -e "$TITLE43 " -echo -e "$TITLE44 " +#aws ec2 describe-security-groups --filters Name=group-name,Values='default' --profile internalmg --region us-east-1 # Final -echo -e "\nFor more information and reference: https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf" +echo -e "\n$BLUE - For more information and reference:$NORMAL" +echo -e " $NOTICE https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf$NORMAL" + +# Delete temp file +rm -fr $TEMP_REPORT_FILE