From 4901561fec82994d9484ca7de8e2be530de7d579 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 19 Mar 2018 14:54:05 -0400 Subject: [PATCH 01/41] tests v2 --- include/check11 | 12 + include/group1 | 8 + prowler2 | 625 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 645 insertions(+) create mode 100644 include/check11 create mode 100644 include/group1 create mode 100755 prowler2 diff --git a/include/check11 b/include/check11 new file mode 100644 index 0000000000..39e051a110 --- /dev/null +++ b/include/check11 @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +CHECK_ID[check11]="1.1,1.01" +CHECK_TITLE[check11]="Avoid the use of the root account (Scored)." +CHECK_SCORED[check11]="SCORED" +check11() { + # "Avoid the use of the root account (Scored)." + COMMAND11=$(cat $TEMP_REPORT_FILE| grep '' | cut -d, -f5,11,16 | sed 's/,/\ /g') + textTitle "$CHECK_ID" "$CHECK_TITLE" "SCORED" "LEVEL1" + textNotice "Root account last accessed (password key_1 key_2): $COMMAND11" +} +CHECK_ALTERNATE[check101]="check11" diff --git a/include/group1 b/include/group1 new file mode 100644 index 0000000000..f77f5ae513 --- /dev/null +++ b/include/group1 @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +GROUP_ID[1]="group1" +GROUP_NUMBER[1]="1.0" +GROUP_TITLE[1]="Identity and Access Management" +GROUP_RUN_BY_DEFAULT[1]="Y" +GROUP_CHECKS[1]="check11" +textTitle "$GROUP_NUMBER" "$GROUP_TITLE" diff --git a/prowler2 b/prowler2 new file mode 100755 index 0000000000..d7338f4bfa --- /dev/null +++ b/prowler2 @@ -0,0 +1,625 @@ +#!/usr/bin/env bash + +# Prowler is a tool that provides automate auditing and hardening guidance of an AWS account. +# It is based on AWS-CLI commands. It follows guidelines present in the CIS Amazon +# Web Services Foundations Benchmark at: +# https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf + +# This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 +# International Public License. The link to the license terms can be found at +# https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode +# +# Author: Toni de la Fuente - @ToniBlyx - https://blyx.com/contact + +# Prowler - Iron Maiden +# +# Walking through the city, looking oh so pretty +# I've just got to find my way +# See the ladies flashing +# All there legs and lashes +# I've just got to find my way... + +OPTRED="" +OPTNORMAL="" + +# Set the defaults for these getopts variables +REGION="us-east-1" +FILTERREGION="" +MAXITEMS=100 +MONOCHROME=0 +MODE="text" +SEP=',' +KEEPCREDREPORT=0 +EXITCODE=0 + +# Command usage menu +usage(){ + echo " +USAGE: + `basename $0` -p -r [ -h ] + + Options: + -p specify your AWS profile to use (i.e.: default) + -r specify an AWS region to direct API requests to + (i.e.: us-east-1), all regions are checked anyway + -c specify a check number or group from the AWS CIS benchmark + (i.e.: "check11" for check 1.1, "check3" for entire section 3, "level1" for CIS Level 1 Profile Definitions or "forensics-ready") + -f specify an AWS region to run checks against + (i.e.: us-west-1) + -m specify the maximum number of items to return for long-running requests (default: 100) + -M output mode: text (defalut), mono, csv (separator is ","; data is on stdout; progress on stderr) + -k keep the credential report + -n show check numbers to sort easier + (i.e.: 1.01 instead of 1.1) + -l list all available checks only (does not perform any check) + -e exclude extras + -h this help + " + exit +} + +while getopts ":hlkp:r:c:f:m:M:en" OPTION; do + case $OPTION in + h ) + usage + EXITCODE=1 + exit $EXITCODE + ;; + l ) + PRINTCHECKSONLY=1 + ;; + k ) + KEEPCREDREPORT=1 + ;; + p ) + PROFILE=$OPTARG + ;; + r ) + REGION=$OPTARG + ;; + c ) + CHECKNUMBER=$OPTARG + ;; + f ) + FILTERREGION=$OPTARG + ;; + m ) + MAXITEMS=$OPTARG + ;; + M ) + MODE=$OPTARG + ;; + n ) + NUMERAL=1 + ;; + e ) + EXTRAS=1 + ;; + : ) + echo "" + echo "$OPTRED ERROR!$OPTNORMAL -$OPTARG requires an argument" + usage + EXITCODE=1 + exit $EXITCODE + ;; + ? ) + echo "" + echo "$OPTRED ERROR!$OPTNORMAL Invalid option" + usage + EXITCODE=1 + exit $EXITCODE + ;; + esac +done + +if [[ $MODE != "mono" && $MODE != "text" && $MODE != "csv" ]]; then + echo "" + echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, or csv." + usage + EXITCODE=1 + exit $EXITCODE +fi + +if [[ "$MODE" == "mono" || "$MODE" == "csv" ]]; then + MONOCHROME=1 +fi + +if [[ $MONOCHROME -eq 1 ]]; then + # Colors + NORMAL='' + WARNING='' # Bad (red) + SECTION='' # Section (yellow) + NOTICE='' # Notice (yellow) + OK='' # Ok (green) + BAD='' # Bad (red) + CYAN='' + BLUE='' + BROWN='' + DARKGRAY='' + GRAY='' + GREEN='' + MAGENTA='' + PURPLE='' + RED='' + YELLOW='' + WHITE='' +else + # Colors + # NOTE: Your editor may NOT show the 0x1b / escape character left of the '[' + NORMAL="" + WARNING="" # Bad (red) + SECTION="" # Section (yellow) + NOTICE="" # Notice (yellow) + OK="" # Ok (green) + BAD="" # Bad (red) + CYAN="" + BLUE="" + BROWN="" + DARKGRAY="" + GRAY="" + GREEN="" + MAGENTA="" + PURPLE="" + RED="" + YELLOW="" + WHITE="" +fi + +SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) + +# Functions to manage dates depending on OS +if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then + TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) + # 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 + } + decode_report() + { + base64 -d + } +elif [[ "$OSTYPE" == "darwin"* ]]; then + # BSD/OSX commands compatibility + TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX) + 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 + } + decode_report() + { + base64 -D + } +elif [[ "$OSTYPE" == "cygwin" ]]; then + # POSIX compatibility layer and Linux environment emulation for Windows + TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) + 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 + } + decode_report() + { + base64 -d + } +else + echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin" + echo "Found: $OSTYPE" + EXITCODE=1 + exit $EXITCODE +fi + +# It checks -p optoin first and use it as profile, if not -p provided then +# check environment variables and if not, it checks and loads credentials from +# instance profile (metadata server) if runs in an EC2 instance + +if [[ $PROFILE ]]; then + PROFILE_OPT="--profile $PROFILE" +else + # if Prowler runs insinde an AWS instance with IAM instance profile attached + INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) + if [[ $INSTANCE_PROFILE ]]; then + AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g') + AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') + AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') + fi + if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then + PROFILE="ENV" + PROFILE_OPT="" + else + PROFILE="default" + PROFILE_OPT="--profile $PROFILE" + fi +fi + +# AWS-CLI variables +AWSCLI=$(which aws) +if [ -z "${AWSCLI}" ]; then + echo -e "\n$RED ERROR!$NORMAL AWS-CLI (aws command) not found. Make sure it is installed correctly and in your \$PATH\n" + EXITCODE=1 + exit $EXITCODE +fi + +TITLE_ID="" +TITLE_TEXT="CALLER ERROR - UNSET TITLE" + +## Output formatting functions +textOK(){ + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $OK OK! $NORMAL $1" + fi +} + +textNotice(){ + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $NOTICE INFO! $1 $NORMAL" + fi +} + +textWarn(){ + EXITCODE=3 + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $BAD WARNING! $1 $NORMAL" + fi +} + +textTitle(){ + TITLE_ID=$1 + if [[ $NUMERAL ]]; then + TITLE_ID=$(echo $TITLE_ID | cut -d, -f2) + else + TITLE_ID=$(echo $TITLE_ID | cut -d, -f1) + fi + + TITLE_TEXT=$2 + + case "$3" in + 0|No|NOT_SCORED) + ITEM_SCORED="Not Scored" + ;; + 1|Yes|SCORED) + ITEM_SCORED="Scored" + ;; + *) + ITEM_SCORED="Unspecified" + ;; + esac + + case "$4" in + LEVEL1) ITEM_LEVEL="Level 1";; + LEVEL2) ITEM_LEVEL="Level 2";; + EXTRA) ITEM_LEVEL="Extra";; + SUPPORT) ITEM_LEVEL="Support";; + *) ITEM_LEVEL="Unspecified or Invalid";; + esac + + if [[ "$MODE" == "csv" ]]; then + >&2 echo "$TITLE_ID $TITLE_TEXT" + else + if [[ "$ITEM_SCORED" == "Scored" ]]; then + echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT" + else + echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" + fi + fi +} + +printCsvHeader() { + >&2 echo "" + >&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM" + echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES" +} + +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" + echo -e "$YELLOW Date: $(date)" +} + +# Get whoami in AWS, who is the user running this shell script +getWhoami(){ + ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"') + if [[ "$MODE" == "csv" ]]; then + CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn") + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + EXITCODE=2 + exit $EXITCODE + fi + CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') + printCsvHeader + textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT" + textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" + else + echo "" + echo "This report is being generated using credentials below:" + echo "" + echo -e "AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n" + if [[ $MONOCHROME -eq 1 ]]; then + echo "Caller Identity:" + $AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn" + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi + echo "" + else + echo "Caller Identity:" + $AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo variable $PROFILE_OPT + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + EXITCODE=2 + exit $EXITCODE + fi + echo "" + fi + fi +} + +printColorsCode(){ + if [[ $MONOCHROME -eq 0 ]]; then + echo -e "\nColors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL \n" + fi +} + +# Generate Credential Report +genCredReport() { + textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT" + until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do + sleep 1 + done +} + +# Save report to a file, decode it, deletion at finish and after every single check +saveReport(){ + $AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE + if [[ $KEEPCREDREPORT -eq 1 ]]; then + textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT" + textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE" + fi +} + +# Delete temporary report file +cleanTemp(){ + if [[ $KEEPCREDREPORT -ne 1 ]]; then + rm -fr $TEMP_REPORT_FILE + fi +} + +# Delete the temporary report file if we get interrupted/terminated +trap cleanTemp EXIT + +# Get a list of all available AWS Regions +REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ + --output text \ + $PROFILE_OPT \ + --region $REGION \ + --region-names $FILTERREGION) + +infoReferenceLong(){ + # Report review note: + echo -e "" + echo -e "For more information on the Prowler, feedback and issue reporting:" + echo -e "https://github.com/Alfresco/prowler" + echo -e "" + echo -e "For more information on the CIS benchmark:" + echo -e "https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf" + +} + +callCheck(){ + if [[ $CHECKNUMBER ]];then + case "$CHECKNUMBER" in + check11|check101 ) execute_check check11;; + * ) + textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n"; + esac + cleanTemp + exit $EXITCODE + fi +} + +# List only check tittles + +if [[ $PRINTCHECKSONLY == "1" ]]; then + prowlerBanner + show_all_titles + exit $EXITCODE +fi + +# Data Structures +# +# Groups +# ------ +# GROUP_NAME[X] = "groupname" +# GROUP_TITLE[X] = "Logging *****" +# GROUP_RUN_BY_DEFAULT[X] = "Y" // Whether this group is run by default +# GROUP_CHECKS[X] = "check11,check12" // etc. etc. +# +# Checks & Extras +# --------------- +# CHECK_TITLE[checkname] = "Title checkname" +# CHECK_ID[checkname] = '1.1,1.01' +# CHECK_SCORED[checkname] = 'SCORED' or 'NOT_SCORED' +# checkname() { +# // code of the function. The function should be named checkname +# } +# +# Check alternate names +# CHECK_ALTERNATE[alternatename] = "checkname" +# CHECK_ALTERNATE["check101"] = "check11" + +# # For group of checks arrays +# declare -a GROUP_NAME +# declare -a GROUP_TITLE +# declare -a GROUP_RUN_BY_DEFAULT +# declare -a GROUP_CHECKS +# +# # For checks +# declare -a CHECK_TITLE +# declare -a CHECK_ID +# declare -a CHECK_SCORED +# declare -a CHECK_ALTERNATE + +# Include all of the groups of checks inside include folder +for group in $(ls include/group*); do + . "$group" +done + +# Include all of the checks inside include folder +# this includes also extra check since they are "check_extraNN" +for checks in $(ls include/check*); do + . "$checks" +done + +# Function to show the title of the check +show_check_title() { + # This would just call textTitle + textTitle "${CHECK_ID[$1]} ${CHECK_TITLE[$1]} ${CHECK_SCORED[$1]}" +} + +# Function to show the title of a group, by numeric id +show_group_title() { + # This would also just call textTitle in the real prowler + textTitle ${GROUP_NUMBER[$1]} - ${GROUP_TITLE[$1]} +} + +# Function to execute the check +execute_check() { + # See if this is an alternate name for a check + # for example, we might have been passed 1.01 which is another name for 1.1 + if [ ${CHECK_ALTERNATE[$1]} ];then + show_check_title ${CHECK_ALTERNATE[$1]} + ${CHECK_ALTERNATE[$1]} + else + show_check_title $1 + $1 + fi +} + +# Function to execute all checks in a group +execute_group() { + show_group_title $1 + # run the checks in the group + IFS=',' read -ra CHECKS <<< ${GROUP_CHECKS[$1]} + for i in "${CHECKS[@]}"; do + execute_check $i + done +} + +# Function to execute group by name +execute_group_by_name() { + for i in ${#GROUP_NAME[@]}; do + if [ "${GROUP_NAME[$i]}" == "$1" ]; then + execute_group $i + fi + done +} + +# Function to execute all checks in all groups +execute_all() { + for i in ${#GROUP_TITLE[@]}; do + execute_group $i + done +} + +# Function to show the titles of everything +show_all_titles() { + for i in ${#GROUP_TITLE[@]}; do + show_group_title $i + # Display the title of the checks + IFS=',' read -ra CHECKS <<< ${GROUP_CHECKS[$i]} + for j in "${CHECKS[@]}"; do + show_check_title $j + done + done +} + +### All functions defined above ... run the workflow + +if [[ $MODE != "csv" ]]; then + prowlerBanner + printColorsCode +fi +getWhoami +genCredReport +saveReport +callCheck + +execute_all + + +if [[ ! $EXTRAS ]]; then + textTitle "7" "$TITLE7" "NOT_SCORED" "SUPPORT" + execute_group 7 +fi + +cleanTemp +exit $EXITCODE From 6a4127dc405d8db115c8e1c8a6d608a00e0320a8 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 19 Mar 2018 14:55:25 -0400 Subject: [PATCH 02/41] tests v2 --- .../prowler-policy-additions.json | 0 Dockerfile => util/Dockerfile | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename prowler-policy-additions.json => iam/prowler-policy-additions.json (100%) rename Dockerfile => util/Dockerfile (100%) diff --git a/prowler-policy-additions.json b/iam/prowler-policy-additions.json similarity index 100% rename from prowler-policy-additions.json rename to iam/prowler-policy-additions.json diff --git a/Dockerfile b/util/Dockerfile similarity index 100% rename from Dockerfile rename to util/Dockerfile From 2f761f62a674c97c26dc4956b6b32eacc0fef08e Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 20 Mar 2018 10:56:37 -0400 Subject: [PATCH 03/41] new folder structure --- {include => checks}/check11 | 5 +- {include => groups}/group1 | 3 +- include/colors | 0 prowler2 | 111 +++++------------------------------- 4 files changed, 19 insertions(+), 100 deletions(-) rename {include => checks}/check11 (88%) rename {include => groups}/group1 (66%) create mode 100644 include/colors diff --git a/include/check11 b/checks/check11 similarity index 88% rename from include/check11 rename to checks/check11 index 39e051a110..adc5400a4b 100644 --- a/include/check11 +++ b/checks/check11 @@ -3,10 +3,11 @@ CHECK_ID[check11]="1.1,1.01" CHECK_TITLE[check11]="Avoid the use of the root account (Scored)." CHECK_SCORED[check11]="SCORED" +CHECK_TYPE[check11]="LEVEL1" +CHECK_ALTERNATE[check101]="check11" + check11() { # "Avoid the use of the root account (Scored)." COMMAND11=$(cat $TEMP_REPORT_FILE| grep '' | cut -d, -f5,11,16 | sed 's/,/\ /g') - textTitle "$CHECK_ID" "$CHECK_TITLE" "SCORED" "LEVEL1" textNotice "Root account last accessed (password key_1 key_2): $COMMAND11" } -CHECK_ALTERNATE[check101]="check11" diff --git a/include/group1 b/groups/group1 similarity index 66% rename from include/group1 rename to groups/group1 index f77f5ae513..1663ceeb82 100644 --- a/include/group1 +++ b/groups/group1 @@ -3,6 +3,5 @@ GROUP_ID[1]="group1" GROUP_NUMBER[1]="1.0" GROUP_TITLE[1]="Identity and Access Management" -GROUP_RUN_BY_DEFAULT[1]="Y" +GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called GROUP_CHECKS[1]="check11" -textTitle "$GROUP_NUMBER" "$GROUP_TITLE" diff --git a/include/colors b/include/colors new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler2 b/prowler2 index d7338f4bfa..c75439d096 100755 --- a/prowler2 +++ b/prowler2 @@ -112,58 +112,7 @@ while getopts ":hlkp:r:c:f:m:M:en" OPTION; do esac done -if [[ $MODE != "mono" && $MODE != "text" && $MODE != "csv" ]]; then - echo "" - echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, or csv." - usage - EXITCODE=1 - exit $EXITCODE -fi - -if [[ "$MODE" == "mono" || "$MODE" == "csv" ]]; then - MONOCHROME=1 -fi - -if [[ $MONOCHROME -eq 1 ]]; then - # Colors - NORMAL='' - WARNING='' # Bad (red) - SECTION='' # Section (yellow) - NOTICE='' # Notice (yellow) - OK='' # Ok (green) - BAD='' # Bad (red) - CYAN='' - BLUE='' - BROWN='' - DARKGRAY='' - GRAY='' - GREEN='' - MAGENTA='' - PURPLE='' - RED='' - YELLOW='' - WHITE='' -else - # Colors - # NOTE: Your editor may NOT show the 0x1b / escape character left of the '[' - NORMAL="" - WARNING="" # Bad (red) - SECTION="" # Section (yellow) - NOTICE="" # Notice (yellow) - OK="" # Ok (green) - BAD="" # Bad (red) - CYAN="" - BLUE="" - BROWN="" - DARKGRAY="" - GRAY="" - GREEN="" - MAGENTA="" - PURPLE="" - RED="" - YELLOW="" - WHITE="" -fi +. include/colors SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) @@ -494,61 +443,29 @@ if [[ $PRINTCHECKSONLY == "1" ]]; then exit $EXITCODE fi -# Data Structures -# -# Groups -# ------ -# GROUP_NAME[X] = "groupname" -# GROUP_TITLE[X] = "Logging *****" -# GROUP_RUN_BY_DEFAULT[X] = "Y" // Whether this group is run by default -# GROUP_CHECKS[X] = "check11,check12" // etc. etc. -# -# Checks & Extras -# --------------- -# CHECK_TITLE[checkname] = "Title checkname" -# CHECK_ID[checkname] = '1.1,1.01' -# CHECK_SCORED[checkname] = 'SCORED' or 'NOT_SCORED' -# checkname() { -# // code of the function. The function should be named checkname -# } -# -# Check alternate names -# CHECK_ALTERNATE[alternatename] = "checkname" -# CHECK_ALTERNATE["check101"] = "check11" - -# # For group of checks arrays -# declare -a GROUP_NAME -# declare -a GROUP_TITLE -# declare -a GROUP_RUN_BY_DEFAULT -# declare -a GROUP_CHECKS -# -# # For checks -# declare -a CHECK_TITLE -# declare -a CHECK_ID -# declare -a CHECK_SCORED -# declare -a CHECK_ALTERNATE - # Include all of the groups of checks inside include folder -for group in $(ls include/group*); do +for group in $(ls groups/group*); do . "$group" done # Include all of the checks inside include folder # this includes also extra check since they are "check_extraNN" -for checks in $(ls include/check*); do +for checks in $(ls checks/check*); do . "$checks" done # Function to show the title of the check show_check_title() { # This would just call textTitle - textTitle "${CHECK_ID[$1]} ${CHECK_TITLE[$1]} ${CHECK_SCORED[$1]}" + textTitle "${CHECK_ID[$1]}" "${CHECK_TITLE[$1]}" "${CHECK_SCORED[$1]}" "${CHECK_TYPE[$1]}" } # Function to show the title of a group, by numeric id show_group_title() { # This would also just call textTitle in the real prowler - textTitle ${GROUP_NUMBER[$1]} - ${GROUP_TITLE[$1]} + if [[ "$MODE" != "csv" ]]; then + textTitle "${GROUP_NUMBER[$1]}" "${GROUP_TITLE[$1]}" "NOT_SCORED" "SUPPORT" + fi } # Function to execute the check @@ -586,7 +503,9 @@ execute_group_by_name() { # Function to execute all checks in all groups execute_all() { for i in ${#GROUP_TITLE[@]}; do - execute_group $i + if [ "${GROUP_RUN_BY_DEFAULT[$i]}" == "Y" ]; then + execute_group $i + fi done } @@ -613,13 +532,13 @@ genCredReport saveReport callCheck -execute_all +show_all_titles -if [[ ! $EXTRAS ]]; then - textTitle "7" "$TITLE7" "NOT_SCORED" "SUPPORT" - execute_group 7 -fi +# if [[ ! $EXTRAS ]]; then +# textTitle "7" "$TITLE7" "NOT_SCORED" "SUPPORT" +# execute_group 7 +# fi cleanTemp exit $EXITCODE From a21bff31a5931f5149d132c9637f1f1420bf2152 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 20 Mar 2018 22:59:34 -0400 Subject: [PATCH 04/41] create check files --- checks/check | 0 checks/check11 | 2 +- checks/check110 | 0 checks/check111 | 0 checks/check112 | 0 checks/check113 | 0 checks/check114 | 0 checks/check115 | 0 checks/check116 | 0 checks/check117 | 0 checks/check118 | 0 checks/check119 | 0 checks/check12 | 25 +++ checks/check120 | 0 checks/check121 | 0 checks/check122 | 0 checks/check123 | 0 checks/check124 | 0 checks/check13 | 0 checks/check14 | 0 checks/check15 | 0 checks/check16 | 0 checks/check17 | 0 checks/check18 | 0 checks/check19 | 0 checks/check21 | 0 checks/check22 | 0 checks/check23 | 0 checks/check24 | 0 checks/check25 | 0 checks/check26 | 0 checks/check27 | 0 checks/check28 | 0 checks/check31 | 0 checks/check310 | 0 checks/check311 | 0 checks/check312 | 0 checks/check313 | 0 checks/check314 | 0 checks/check315 | 0 checks/check32 | 0 checks/check33 | 0 checks/check34 | 0 checks/check35 | 0 checks/check36 | 0 checks/check37 | 0 checks/check38 | 0 checks/check39 | 0 checks/check41 | 0 checks/check42 | 0 checks/check43 | 0 checks/check44 | 0 checks/check45 | 0 checks/check_extra71 | 0 checks/check_extra710 | 0 checks/check_extra711 | 0 checks/check_extra712 | 0 checks/check_extra713 | 0 checks/check_extra714 | 0 checks/check_extra715 | 0 checks/check_extra716 | 0 checks/check_extra717 | 0 checks/check_extra718 | 0 checks/check_extra719 | 0 checks/check_extra72 | 0 checks/check_extra720 | 0 checks/check_extra721 | 0 checks/check_extra722 | 0 checks/check_extra723 | 0 checks/check_extra73 | 0 checks/check_extra74 | 0 checks/check_extra75 | 0 checks/check_extra76 | 0 checks/check_extra77 | 0 checks/check_extra78 | 0 checks/check_extra79 | 0 checks/list | 166 ++++++++++++++++++ checks/lista | 79 +++++++++ groups/group1 | 6 +- groups/group2 | 0 groups/group3 | 0 groups/group4 | 0 groups/group_cislevel1 | 0 groups/group_cislevel2 | 0 groups/group_extras | 0 groups/group_forensics | 0 include/aws_profile_loader | 22 +++ include/awscli_detector | 7 + include/banner | 19 +++ include/colors | 58 +++++++ include/credentials_report | 26 +++ include/csv_header | 5 + include/os_detector | 76 +++++++++ include/outputs | 81 +++++++++ include/whoami | 44 +++++ prowler => prowler1 | 0 prowler2 | 334 +++---------------------------------- 97 files changed, 635 insertions(+), 315 deletions(-) create mode 100644 checks/check create mode 100644 checks/check110 create mode 100644 checks/check111 create mode 100644 checks/check112 create mode 100644 checks/check113 create mode 100644 checks/check114 create mode 100644 checks/check115 create mode 100644 checks/check116 create mode 100644 checks/check117 create mode 100644 checks/check118 create mode 100644 checks/check119 create mode 100644 checks/check12 create mode 100644 checks/check120 create mode 100644 checks/check121 create mode 100644 checks/check122 create mode 100644 checks/check123 create mode 100644 checks/check124 create mode 100644 checks/check13 create mode 100644 checks/check14 create mode 100644 checks/check15 create mode 100644 checks/check16 create mode 100644 checks/check17 create mode 100644 checks/check18 create mode 100644 checks/check19 create mode 100644 checks/check21 create mode 100644 checks/check22 create mode 100644 checks/check23 create mode 100644 checks/check24 create mode 100644 checks/check25 create mode 100644 checks/check26 create mode 100644 checks/check27 create mode 100644 checks/check28 create mode 100644 checks/check31 create mode 100644 checks/check310 create mode 100644 checks/check311 create mode 100644 checks/check312 create mode 100644 checks/check313 create mode 100644 checks/check314 create mode 100644 checks/check315 create mode 100644 checks/check32 create mode 100644 checks/check33 create mode 100644 checks/check34 create mode 100644 checks/check35 create mode 100644 checks/check36 create mode 100644 checks/check37 create mode 100644 checks/check38 create mode 100644 checks/check39 create mode 100644 checks/check41 create mode 100644 checks/check42 create mode 100644 checks/check43 create mode 100644 checks/check44 create mode 100644 checks/check45 create mode 100644 checks/check_extra71 create mode 100644 checks/check_extra710 create mode 100644 checks/check_extra711 create mode 100644 checks/check_extra712 create mode 100644 checks/check_extra713 create mode 100644 checks/check_extra714 create mode 100644 checks/check_extra715 create mode 100644 checks/check_extra716 create mode 100644 checks/check_extra717 create mode 100644 checks/check_extra718 create mode 100644 checks/check_extra719 create mode 100644 checks/check_extra72 create mode 100644 checks/check_extra720 create mode 100644 checks/check_extra721 create mode 100644 checks/check_extra722 create mode 100644 checks/check_extra723 create mode 100644 checks/check_extra73 create mode 100644 checks/check_extra74 create mode 100644 checks/check_extra75 create mode 100644 checks/check_extra76 create mode 100644 checks/check_extra77 create mode 100644 checks/check_extra78 create mode 100644 checks/check_extra79 create mode 100644 checks/list create mode 100644 checks/lista create mode 100644 groups/group2 create mode 100644 groups/group3 create mode 100644 groups/group4 create mode 100644 groups/group_cislevel1 create mode 100644 groups/group_cislevel2 create mode 100644 groups/group_extras create mode 100644 groups/group_forensics create mode 100644 include/aws_profile_loader create mode 100644 include/awscli_detector create mode 100644 include/banner create mode 100644 include/credentials_report create mode 100644 include/csv_header create mode 100644 include/os_detector create mode 100644 include/outputs create mode 100644 include/whoami rename prowler => prowler1 (100%) diff --git a/checks/check b/checks/check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check11 b/checks/check11 index adc5400a4b..457faed155 100644 --- a/checks/check11 +++ b/checks/check11 @@ -1,7 +1,7 @@ #!/usr/bin/env bash CHECK_ID[check11]="1.1,1.01" -CHECK_TITLE[check11]="Avoid the use of the root account (Scored)." +CHECK_TITLE[check11]="Avoid the use of the root account (Scored)" CHECK_SCORED[check11]="SCORED" CHECK_TYPE[check11]="LEVEL1" CHECK_ALTERNATE[check101]="check11" diff --git a/checks/check110 b/checks/check110 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check111 b/checks/check111 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check112 b/checks/check112 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check113 b/checks/check113 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check114 b/checks/check114 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check115 b/checks/check115 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check116 b/checks/check116 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check117 b/checks/check117 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check118 b/checks/check118 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check119 b/checks/check119 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check12 b/checks/check12 new file mode 100644 index 0000000000..76d1dddcf7 --- /dev/null +++ b/checks/check12 @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +CHECK_ID[check12]="1.2,1.02" +CHECK_TITLE[check12]="Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" +CHECK_SCORED[check12]="SCORED" +CHECK_TYPE[check12]="LEVEL1" +CHECK_ALTERNATE[check102]="check12" + +check12(){ + # "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 }' + done) + textTitle "$ID12" "$TITLE12" "SCORED" "LEVEL1" + if [[ $COMMAND12 ]]; then + for u in $COMMAND12; do + textWarn "User $u has Password enabled but MFA disabled" + done + else + textOK "No users found with Password enabled and MFA disabled" + fi +} diff --git a/checks/check120 b/checks/check120 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check121 b/checks/check121 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check122 b/checks/check122 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check123 b/checks/check123 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check124 b/checks/check124 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check13 b/checks/check13 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check14 b/checks/check14 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check15 b/checks/check15 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check16 b/checks/check16 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check17 b/checks/check17 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check18 b/checks/check18 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check19 b/checks/check19 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check21 b/checks/check21 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check22 b/checks/check22 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check23 b/checks/check23 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check24 b/checks/check24 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check25 b/checks/check25 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check26 b/checks/check26 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check27 b/checks/check27 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check28 b/checks/check28 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check31 b/checks/check31 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check310 b/checks/check310 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check311 b/checks/check311 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check312 b/checks/check312 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check313 b/checks/check313 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check314 b/checks/check314 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check315 b/checks/check315 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check32 b/checks/check32 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check33 b/checks/check33 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check34 b/checks/check34 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check35 b/checks/check35 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check36 b/checks/check36 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check37 b/checks/check37 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check38 b/checks/check38 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check39 b/checks/check39 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check41 b/checks/check41 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check42 b/checks/check42 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check43 b/checks/check43 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check44 b/checks/check44 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check45 b/checks/check45 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra71 b/checks/check_extra71 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra710 b/checks/check_extra710 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra711 b/checks/check_extra711 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra712 b/checks/check_extra712 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra713 b/checks/check_extra713 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra714 b/checks/check_extra714 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra715 b/checks/check_extra715 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra716 b/checks/check_extra716 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra717 b/checks/check_extra717 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra718 b/checks/check_extra718 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra719 b/checks/check_extra719 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra72 b/checks/check_extra72 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra720 b/checks/check_extra720 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra721 b/checks/check_extra721 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra722 b/checks/check_extra722 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra723 b/checks/check_extra723 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra73 b/checks/check_extra73 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra74 b/checks/check_extra74 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra75 b/checks/check_extra75 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra76 b/checks/check_extra76 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra77 b/checks/check_extra77 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra78 b/checks/check_extra78 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/check_extra79 b/checks/check_extra79 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/checks/list b/checks/list new file mode 100644 index 0000000000..bb66eca356 --- /dev/null +++ b/checks/list @@ -0,0 +1,166 @@ + _ + _ __ _ __ _____ _| | ___ _ __ + | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__| + | |_) | | | (_) \ V V /| | __/ | + | .__/|_| \___/ \_/\_/ |_|\___|_| + |_| CIS based AWS Account Hardening Tool + + Date: Tue Mar 20 21:50:38 EDT 2018 + + 1 Identity and Access Management **************************************** + + 1.1 Avoid the use of the root account (Scored). + + 1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) + + 1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) + + 1.4 Ensure access keys are rotated every 90 days or less (Scored) + + 1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) + + 1.6 Ensure IAM password policy require at least one lowercase letter (Scored) + + 1.7 Ensure IAM password policy require at least one symbol (Scored) + + 1.8 Ensure IAM password policy require at least one number (Scored) + + 1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) + + 1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) + + 1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) + + 1.12 Ensure no root account access key exists (Scored) + + 1.13 Ensure MFA is enabled for the root account (Scored) + + 1.14 Ensure hardware MFA is enabled for the root account (Scored) + + 1.15 Ensure security questions are registered in the AWS account (Not Scored) + + 1.16 Ensure IAM policies are attached only to groups or roles (Scored) + + 1.17 Enable detailed billing (Scored) + + 1.18 Ensure IAM Master and IAM Manager roles are active (Scored) + + 1.19 Maintain current contact details (Scored) + + 1.20 Ensure security contact information is registered (Scored) + + 1.21 Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) + + 1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) + + 1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) + + 1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) + + 2 Logging *************************************************************** + + 2.1 Ensure CloudTrail is enabled in all regions (Scored) + + 2.2 Ensure CloudTrail log file validation is enabled (Scored) + + 2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) + + 2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) + + 2.5 Ensure AWS Config is enabled in all regions (Scored) + + 2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) + + 2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) + + 2.8 Ensure rotation for customer created CMKs is enabled (Scored) + + 3 Monitoring ************************************************************ + + 3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) + + 3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) + + 3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) + + 3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) + + 3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) + + 3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) + + 3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) + + 3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) + + 3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) + + 3.10 Ensure a log metric filter and alarm exist for security group changes (Scored) + + 3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) + + 3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) + + 3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) + + 3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) + + 3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) + + 4 Networking ************************************************************ + + 4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) + + 4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) + + 4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) + + 4.4 Ensure the default security group of every VPC restricts all traffic (Scored) + + 4.5 Ensure routing tables for VPC peering are "least access" (Not Scored) + + 7 Extras **************************************************************** + + 7.1 Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark) + + 7.2 Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark) + + 7.3 Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark) + + 7.4 Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark) + + 7.5 Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark) + + 7.6 Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark) + + 7.7 Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark) + + 7.8 Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark) + + 7.9 Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark) + + 7.10 Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark) + + 7.11 Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark) + + 7.12 Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) + + 7.13 Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) + + 7.14 Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.15 Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.16 Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark) + + 7.17 Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.18 Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.19 Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) + + 7.20 Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) + + 7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) diff --git a/checks/lista b/checks/lista new file mode 100644 index 0000000000..c31d8bc726 --- /dev/null +++ b/checks/lista @@ -0,0 +1,79 @@ +check1 +check11 +check12 +check13 +check14 +check15 +check16 +check17 +check18 +check19 +check110 +check111 +check112 +check113 +check114 +check115 +check116 +check117 +check118 +check119 +check120 +check121 +check122 +check123 +check124 +check2 +check21 +check22 +check23 +check24 +check25 +check26 +check27 +check28 +check3 +check31 +check32 +check33 +check34 +check35 +check36 +check37 +check38 +check39 +check310 +check311 +check312 +check313 +check314 +check315 +check4 +check41 +check42 +check43 +check44 +check45 +check7 +check71 +check72 +check73 +check74 +check75 +check76 +check77 +check78 +check79 +check710 +check711 +check712 +check713 +check714 +check715 +check716 +check717 +check718 +check719 +check720 +check721 +check722 diff --git a/groups/group1 b/groups/group1 index 1663ceeb82..c82504e033 100644 --- a/groups/group1 +++ b/groups/group1 @@ -2,6 +2,6 @@ GROUP_ID[1]="group1" GROUP_NUMBER[1]="1.0" -GROUP_TITLE[1]="Identity and Access Management" -GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called -GROUP_CHECKS[1]="check11" +GROUP_TITLE[1]="Identity and Access Management ****************************************" +GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called +GROUP_CHECKS[1]="check11,check12" diff --git a/groups/group2 b/groups/group2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/groups/group3 b/groups/group3 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/groups/group4 b/groups/group4 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/groups/group_cislevel1 b/groups/group_cislevel1 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/groups/group_cislevel2 b/groups/group_cislevel2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/groups/group_extras b/groups/group_extras new file mode 100644 index 0000000000..e69de29bb2 diff --git a/groups/group_forensics b/groups/group_forensics new file mode 100644 index 0000000000..e69de29bb2 diff --git a/include/aws_profile_loader b/include/aws_profile_loader new file mode 100644 index 0000000000..4e7ea2a357 --- /dev/null +++ b/include/aws_profile_loader @@ -0,0 +1,22 @@ +# It checks -p optoin first and use it as profile, if not -p provided then +# check environment variables and if not, it checks and loads credentials from +# instance profile (metadata server) if runs in an EC2 instance + +if [[ $PROFILE ]]; then + PROFILE_OPT="--profile $PROFILE" +else + # if Prowler runs insinde an AWS instance with IAM instance profile attached + INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) + if [[ $INSTANCE_PROFILE ]]; then + AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g') + AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') + AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') + fi + if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then + PROFILE="ENV" + PROFILE_OPT="" + else + PROFILE="default" + PROFILE_OPT="--profile $PROFILE" + fi +fi diff --git a/include/awscli_detector b/include/awscli_detector new file mode 100644 index 0000000000..6794be3523 --- /dev/null +++ b/include/awscli_detector @@ -0,0 +1,7 @@ +# AWS-CLI detector variable +AWSCLI=$(which aws) +if [ -z "${AWSCLI}" ]; then + echo -e "\n$RED ERROR!$NORMAL AWS-CLI (aws command) not found. Make sure it is installed correctly and in your \$PATH\n" + EXITCODE=1 + exit $EXITCODE +fi diff --git a/include/banner b/include/banner new file mode 100644 index 0000000000..19c1638682 --- /dev/null +++ b/include/banner @@ -0,0 +1,19 @@ +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" + echo -e "$YELLOW Date: $(date)" +} + +infoReferenceLong(){ + # Report review note: + echo -e "" + echo -e "For more information on the Prowler, feedback and issue reporting:" + echo -e "https://github.com/toniblyx/prowler" + echo -e "" + echo -e "For more information on the CIS benchmark:" + echo -e "https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf" +} diff --git a/include/colors b/include/colors index e69de29bb2..31fc2cd918 100644 --- a/include/colors +++ b/include/colors @@ -0,0 +1,58 @@ +if [[ $MODE != "mono" && $MODE != "text" && $MODE != "csv" ]]; then + echo "" + echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, or csv." + usage + EXITCODE=1 + exit $EXITCODE +fi + +if [[ "$MODE" == "mono" || "$MODE" == "csv" ]]; then + MONOCHROME=1 +fi + +if [[ $MONOCHROME -eq 1 ]]; then + # Colors + NORMAL='' + WARNING='' # Bad (red) + SECTION='' # Section (yellow) + NOTICE='' # Notice (yellow) + OK='' # Ok (green) + BAD='' # Bad (red) + CYAN='' + BLUE='' + BROWN='' + DARKGRAY='' + GRAY='' + GREEN='' + MAGENTA='' + PURPLE='' + RED='' + YELLOW='' + WHITE='' +else + # Colors + # NOTE: Your editor may NOT show the 0x1b / escape character left of the '[' + NORMAL="" + WARNING="" # Bad (red) + SECTION="" # Section (yellow) + NOTICE="" # Notice (yellow) + OK="" # Ok (green) + BAD="" # Bad (red) + CYAN="" + BLUE="" + BROWN="" + DARKGRAY="" + GRAY="" + GREEN="" + MAGENTA="" + PURPLE="" + RED="" + YELLOW="" + WHITE="" +fi + +printColorsCode(){ + if [[ $MONOCHROME -eq 0 ]]; then + echo -e "\n$NORMAL Colors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL" + fi +} diff --git a/include/credentials_report b/include/credentials_report new file mode 100644 index 0000000000..d958a76853 --- /dev/null +++ b/include/credentials_report @@ -0,0 +1,26 @@ +# Generate Credential Report +genCredReport() { + textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT" + until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do + sleep 1 + done +} + +# Save report to a file, decode it, deletion at finish and after every single check +saveReport(){ + $AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE + if [[ $KEEPCREDREPORT -eq 1 ]]; then + textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT" + textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE" + fi +} + +# Delete temporary report file +cleanTemp(){ + if [[ $KEEPCREDREPORT -ne 1 ]]; then + rm -fr $TEMP_REPORT_FILE + fi +} + +# Delete the temporary report file if we get interrupted/terminated +trap cleanTemp EXIT diff --git a/include/csv_header b/include/csv_header new file mode 100644 index 0000000000..bad90f37a8 --- /dev/null +++ b/include/csv_header @@ -0,0 +1,5 @@ +printCsvHeader() { + >&2 echo "" + >&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM" + echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES" +} diff --git a/include/os_detector b/include/os_detector new file mode 100644 index 0000000000..d36c07ce59 --- /dev/null +++ b/include/os_detector @@ -0,0 +1,76 @@ +# Functions to manage dates depending on OS +if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then + TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) + # 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 + } + decode_report() + { + base64 -d + } +elif [[ "$OSTYPE" == "darwin"* ]]; then + # BSD/OSX commands compatibility + TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX) + 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 + } + decode_report() + { + base64 -D + } +elif [[ "$OSTYPE" == "cygwin" ]]; then + # POSIX compatibility layer and Linux environment emulation for Windows + TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) + 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 + } + decode_report() + { + base64 -d + } +else + echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin" + echo "Found: $OSTYPE" + EXITCODE=1 + exit $EXITCODE +fi diff --git a/include/outputs b/include/outputs new file mode 100644 index 0000000000..42ad7336a1 --- /dev/null +++ b/include/outputs @@ -0,0 +1,81 @@ +## Output formatting functions +textOK(){ + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $OK OK! $NORMAL $1" + fi +} + +textNotice(){ + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $NOTICE INFO! $1 $NORMAL" + fi +} + +textWarn(){ + EXITCODE=3 + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $BAD WARNING! $1 $NORMAL" + fi +} + +textTitle(){ + TITLE_ID=$1 + if [[ $NUMERAL ]]; then + TITLE_ID=$(echo $TITLE_ID | cut -d, -f2) + else + TITLE_ID=$(echo $TITLE_ID | cut -d, -f1) + fi + + TITLE_TEXT=$2 + + case "$3" in + 0|No|NOT_SCORED) + ITEM_SCORED="Not Scored" + ;; + 1|Yes|SCORED) + ITEM_SCORED="Scored" + ;; + *) + ITEM_SCORED="Unspecified" + ;; + esac + + case "$4" in + LEVEL1) ITEM_LEVEL="Level 1";; + LEVEL2) ITEM_LEVEL="Level 2";; + EXTRA) ITEM_LEVEL="Extra";; + SUPPORT) ITEM_LEVEL="Support";; + *) ITEM_LEVEL="Unspecified or Invalid";; + esac + + if [[ "$MODE" == "csv" ]]; then + >&2 echo "$TITLE_ID $TITLE_TEXT" + else + if [[ "$ITEM_SCORED" == "Scored" ]]; then + echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT" + else + echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" + fi + fi +} diff --git a/include/whoami b/include/whoami new file mode 100644 index 0000000000..4a6f391389 --- /dev/null +++ b/include/whoami @@ -0,0 +1,44 @@ +# Get whoami in AWS, who is the user running this shell script +getWhoami(){ + ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"') + if [[ "$MODE" == "csv" ]]; then + CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn") + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + EXITCODE=2 + exit $EXITCODE + fi + CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') + printCsvHeader + textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT" + textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" + else + echo "" + echo -e " This report is being generated using credentials below:\n" + echo -e " AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n" + if [[ $MONOCHROME -eq 1 ]]; then + echo -e " Caller Identity:" + $AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn" + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi + else + echo -e " Caller Identity:" + $AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo variable $PROFILE_OPT + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + EXITCODE=2 + exit $EXITCODE + fi + echo "" + fi + fi +} diff --git a/prowler b/prowler1 similarity index 100% rename from prowler rename to prowler1 diff --git a/prowler2 b/prowler2 index c75439d096..388730311a 100755 --- a/prowler2 +++ b/prowler2 @@ -31,12 +31,15 @@ MODE="text" SEP=',' KEEPCREDREPORT=0 EXITCODE=0 +SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) +TITLE_ID="" +TITLE_TEXT="CALLER ERROR - UNSET TITLE" # Command usage menu usage(){ echo " USAGE: - `basename $0` -p -r [ -h ] + `basename $0` [ -p -r -h ] Options: -p specify your AWS profile to use (i.e.: default) @@ -53,12 +56,13 @@ USAGE: (i.e.: 1.01 instead of 1.1) -l list all available checks only (does not perform any check) -e exclude extras + -b do not print Prowler banner -h this help " exit } -while getopts ":hlkp:r:c:f:m:M:en" OPTION; do +while getopts ":hlkp:r:c:f:m:M:enb" OPTION; do case $OPTION in h ) usage @@ -92,6 +96,9 @@ while getopts ":hlkp:r:c:f:m:M:en" OPTION; do n ) NUMERAL=1 ;; + b ) + NOBANNER="true" + ;; e ) EXTRAS=1 ;; @@ -113,297 +120,14 @@ while getopts ":hlkp:r:c:f:m:M:en" OPTION; do done . include/colors - -SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) - -# Functions to manage dates depending on OS -if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then - TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) - # 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 - } - decode_report() - { - base64 -d - } -elif [[ "$OSTYPE" == "darwin"* ]]; then - # BSD/OSX commands compatibility - TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX) - 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 - } - decode_report() - { - base64 -D - } -elif [[ "$OSTYPE" == "cygwin" ]]; then - # POSIX compatibility layer and Linux environment emulation for Windows - TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) - 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 - } - decode_report() - { - base64 -d - } -else - echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin" - echo "Found: $OSTYPE" - EXITCODE=1 - exit $EXITCODE -fi - -# It checks -p optoin first and use it as profile, if not -p provided then -# check environment variables and if not, it checks and loads credentials from -# instance profile (metadata server) if runs in an EC2 instance - -if [[ $PROFILE ]]; then - PROFILE_OPT="--profile $PROFILE" -else - # if Prowler runs insinde an AWS instance with IAM instance profile attached - INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) - if [[ $INSTANCE_PROFILE ]]; then - AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g') - AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') - AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') - fi - if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then - PROFILE="ENV" - PROFILE_OPT="" - else - PROFILE="default" - PROFILE_OPT="--profile $PROFILE" - fi -fi - -# AWS-CLI variables -AWSCLI=$(which aws) -if [ -z "${AWSCLI}" ]; then - echo -e "\n$RED ERROR!$NORMAL AWS-CLI (aws command) not found. Make sure it is installed correctly and in your \$PATH\n" - EXITCODE=1 - exit $EXITCODE -fi - -TITLE_ID="" -TITLE_TEXT="CALLER ERROR - UNSET TITLE" - -## Output formatting functions -textOK(){ - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $OK OK! $NORMAL $1" - fi -} - -textNotice(){ - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $NOTICE INFO! $1 $NORMAL" - fi -} - -textWarn(){ - EXITCODE=3 - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $BAD WARNING! $1 $NORMAL" - fi -} - -textTitle(){ - TITLE_ID=$1 - if [[ $NUMERAL ]]; then - TITLE_ID=$(echo $TITLE_ID | cut -d, -f2) - else - TITLE_ID=$(echo $TITLE_ID | cut -d, -f1) - fi - - TITLE_TEXT=$2 - - case "$3" in - 0|No|NOT_SCORED) - ITEM_SCORED="Not Scored" - ;; - 1|Yes|SCORED) - ITEM_SCORED="Scored" - ;; - *) - ITEM_SCORED="Unspecified" - ;; - esac - - case "$4" in - LEVEL1) ITEM_LEVEL="Level 1";; - LEVEL2) ITEM_LEVEL="Level 2";; - EXTRA) ITEM_LEVEL="Extra";; - SUPPORT) ITEM_LEVEL="Support";; - *) ITEM_LEVEL="Unspecified or Invalid";; - esac - - if [[ "$MODE" == "csv" ]]; then - >&2 echo "$TITLE_ID $TITLE_TEXT" - else - if [[ "$ITEM_SCORED" == "Scored" ]]; then - echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT" - else - echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" - fi - fi -} - -printCsvHeader() { - >&2 echo "" - >&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM" - echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES" -} - -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" - echo -e "$YELLOW Date: $(date)" -} - -# Get whoami in AWS, who is the user running this shell script -getWhoami(){ - ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"') - if [[ "$MODE" == "csv" ]]; then - CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn") - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - EXITCODE=2 - exit $EXITCODE - fi - CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') - printCsvHeader - textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT" - textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" - else - echo "" - echo "This report is being generated using credentials below:" - echo "" - echo -e "AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n" - if [[ $MONOCHROME -eq 1 ]]; then - echo "Caller Identity:" - $AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn" - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - exit 2 - fi - echo "" - else - echo "Caller Identity:" - $AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo variable $PROFILE_OPT - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - EXITCODE=2 - exit $EXITCODE - fi - echo "" - fi - fi -} - -printColorsCode(){ - if [[ $MONOCHROME -eq 0 ]]; then - echo -e "\nColors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL \n" - fi -} - -# Generate Credential Report -genCredReport() { - textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT" - until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do - sleep 1 - done -} - -# Save report to a file, decode it, deletion at finish and after every single check -saveReport(){ - $AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE - if [[ $KEEPCREDREPORT -eq 1 ]]; then - textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT" - textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE" - fi -} - -# Delete temporary report file -cleanTemp(){ - if [[ $KEEPCREDREPORT -ne 1 ]]; then - rm -fr $TEMP_REPORT_FILE - fi -} - -# Delete the temporary report file if we get interrupted/terminated -trap cleanTemp EXIT +. include/os_detector +. include/aws_profile_loader +. include/awscli_detector +. include/outputs +. include/csv_header +. include/banner +. include/whoami +. include/credentials_report # Get a list of all available AWS Regions REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ @@ -412,17 +136,6 @@ REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ --region $REGION \ --region-names $FILTERREGION) -infoReferenceLong(){ - # Report review note: - echo -e "" - echo -e "For more information on the Prowler, feedback and issue reporting:" - echo -e "https://github.com/Alfresco/prowler" - echo -e "" - echo -e "For more information on the CIS benchmark:" - echo -e "https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf" - -} - callCheck(){ if [[ $CHECKNUMBER ]];then case "$CHECKNUMBER" in @@ -436,20 +149,19 @@ callCheck(){ } # List only check tittles - if [[ $PRINTCHECKSONLY == "1" ]]; then prowlerBanner show_all_titles exit $EXITCODE fi -# Include all of the groups of checks inside include folder +# Load all of the groups of checks inside groups folder named as "group*" for group in $(ls groups/group*); do . "$group" done -# Include all of the checks inside include folder -# this includes also extra check since they are "check_extraNN" +# Load all of the checks inside checks folder named as "check*" +# this includes also extra checks since they are "check_extraNN" for checks in $(ls checks/check*); do . "$checks" done @@ -462,7 +174,7 @@ show_check_title() { # Function to show the title of a group, by numeric id show_group_title() { - # This would also just call textTitle in the real prowler + # when csv mode is used, no group tittle is shown if [[ "$MODE" != "csv" ]]; then textTitle "${GROUP_NUMBER[$1]}" "${GROUP_TITLE[$1]}" "NOT_SCORED" "SUPPORT" fi @@ -523,7 +235,7 @@ show_all_titles() { ### All functions defined above ... run the workflow -if [[ $MODE != "csv" ]]; then +if [[ $MODE != "csv" || $NOBANNER != "true" ]]; then prowlerBanner printColorsCode fi @@ -532,7 +244,7 @@ genCredReport saveReport callCheck -show_all_titles +execute_all # if [[ ! $EXTRAS ]]; then From a98fdf76797bea484ffe2ba2b8cdb332dcf234ad Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 20 Mar 2018 23:08:35 -0400 Subject: [PATCH 05/41] create check files --- checks/check12 | 3 +-- prowler2 | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/checks/check12 b/checks/check12 index 76d1dddcf7..2c520084d1 100644 --- a/checks/check12 +++ b/checks/check12 @@ -10,8 +10,7 @@ check12(){ # "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 + 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 }' done) textTitle "$ID12" "$TITLE12" "SCORED" "LEVEL1" diff --git a/prowler2 b/prowler2 index 388730311a..cbd9024117 100755 --- a/prowler2 +++ b/prowler2 @@ -140,6 +140,7 @@ callCheck(){ if [[ $CHECKNUMBER ]];then case "$CHECKNUMBER" in check11|check101 ) execute_check check11;; + check12|check102 ) execute_check check12;; * ) textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n"; esac @@ -242,7 +243,8 @@ fi getWhoami genCredReport saveReport -callCheck + +#callCheck execute_all From a2806ad86bbad2bc7ebec24e5a06e221f3d539ad Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Fri, 23 Mar 2018 10:05:20 -0400 Subject: [PATCH 06/41] populated checks --- checks/check11 | 21 ++++++------ checks/check110 | 20 +++++++++++ checks/check111 | 18 ++++++++++ checks/check112 | 23 +++++++++++++ checks/check113 | 16 +++++++++ checks/check114 | 21 ++++++++++++ checks/check115 | 13 ++++++++ checks/check116 | 22 ++++++++++++ checks/check117 | 13 ++++++++ checks/check118 | 31 +++++++++++++++++ checks/check119 | 13 ++++++++ checks/check12 | 15 ++++----- checks/check120 | 13 ++++++++ checks/check121 | 12 +++++++ checks/check122 | 27 +++++++++++++++ checks/check123 | 31 +++++++++++++++++ checks/check124 | 31 +++++++++++++++++ checks/check13 | 34 +++++++++++++++++++ checks/check14 | 50 ++++++++++++++++++++++++++++ checks/check15 | 16 +++++++++ checks/check16 | 16 +++++++++ checks/check17 | 16 +++++++++ checks/check18 | 16 +++++++++ checks/check19 | 16 +++++++++ checks/check21 | 23 +++++++++++++ checks/check22 | 23 +++++++++++++ checks/check23 | 23 +++++++++++++ checks/check24 | 31 +++++++++++++++++ checks/check25 | 18 ++++++++++ checks/check26 | 23 +++++++++++++ checks/check27 | 23 +++++++++++++ checks/check28 | 32 ++++++++++++++++++ checks/check31 | 54 ++++++++++++++++++++++++++++++ checks/check310 | 30 +++++++++++++++++ checks/check311 | 30 +++++++++++++++++ checks/check312 | 30 +++++++++++++++++ checks/check313 | 30 +++++++++++++++++ checks/check314 | 30 +++++++++++++++++ checks/check315 | 42 +++++++++++++++++++++++ checks/check32 | 30 +++++++++++++++++ checks/check33 | 30 +++++++++++++++++ checks/check34 | 30 +++++++++++++++++ checks/check35 | 30 +++++++++++++++++ checks/check36 | 30 +++++++++++++++++ checks/check37 | 30 +++++++++++++++++ checks/check38 | 30 +++++++++++++++++ checks/check39 | 30 +++++++++++++++++ checks/check41 | 20 +++++++++++ checks/check42 | 20 +++++++++++ checks/check43 | 20 +++++++++++ checks/check44 | 18 ++++++++++ checks/check45 | 25 ++++++++++++++ checks/check_extra71 | 37 +++++++++++++++++++++ checks/check_extra710 | 23 +++++++++++++ checks/check_extra711 | 23 +++++++++++++ checks/check_extra712 | 18 ++++++++++ checks/check_extra713 | 25 ++++++++++++++ checks/check_extra714 | 25 ++++++++++++++ checks/check_extra715 | 31 +++++++++++++++++ checks/check_extra716 | 33 ++++++++++++++++++ checks/check_extra717 | 39 ++++++++++++++++++++++ checks/check_extra718 | 23 +++++++++++++ checks/check_extra719 | 23 +++++++++++++ checks/check_extra72 | 22 ++++++++++++ checks/check_extra720 | 46 +++++++++++++++++++++++++ checks/check_extra721 | 26 +++++++++++++++ checks/check_extra722 | 33 ++++++++++++++++++ checks/check_extra723 | 40 ++++++++++++++++++++++ checks/check_extra73 | 46 +++++++++++++++++++++++++ checks/check_extra74 | 22 ++++++++++++ checks/check_extra75 | 22 ++++++++++++ checks/check_extra76 | 21 ++++++++++++ checks/check_extra77 | 26 +++++++++++++++ checks/check_extra78 | 23 +++++++++++++ checks/check_extra79 | 26 +++++++++++++++ checks/{check => check_sample} | 0 checks/lista | 52 +++++++++++++---------------- groups/group1 | 7 ---- groups/group1_iam | 5 +++ groups/group2 | 0 groups/group2_logging | 5 +++ groups/group3 | 0 groups/group3_monitoring | 5 +++ groups/group4 | 0 groups/group4_networking | 5 +++ groups/group5_cislevel1 | 5 +++ groups/group6_cislevel2 | 5 +++ groups/group7_extras | 5 +++ groups/group8_forensics | 5 +++ groups/groupN_sample | 5 +++ groups/group_cislevel1 | 0 groups/group_cislevel2 | 0 groups/group_extras | 0 groups/group_forensics | 0 include/banner | 4 +-- include/colors | 2 +- lll | 2 ++ prowler2 | 61 +++++++++++++++++++++------------- 98 files changed, 2034 insertions(+), 81 deletions(-) rename checks/{check => check_sample} (100%) delete mode 100644 groups/group1 create mode 100644 groups/group1_iam delete mode 100644 groups/group2 create mode 100644 groups/group2_logging delete mode 100644 groups/group3 create mode 100644 groups/group3_monitoring delete mode 100644 groups/group4 create mode 100644 groups/group4_networking create mode 100644 groups/group5_cislevel1 create mode 100644 groups/group6_cislevel2 create mode 100644 groups/group7_extras create mode 100644 groups/group8_forensics create mode 100644 groups/groupN_sample delete mode 100644 groups/group_cislevel1 delete mode 100644 groups/group_cislevel2 delete mode 100644 groups/group_extras delete mode 100644 groups/group_forensics create mode 100644 lll diff --git a/checks/check11 b/checks/check11 index 457faed155..deee3ed521 100644 --- a/checks/check11 +++ b/checks/check11 @@ -1,13 +1,12 @@ -#!/usr/bin/env bash +CHECK_ID_check11="1.1,1.01" +CHECK_TITLE_check11="Avoid the use of the root account (Scored)" +CHECK_SCORED_check11="SCORED" +CHECK_TYPE_check11="LEVEL1" +CHECK_ALTERNATE_check101="check11" -CHECK_ID[check11]="1.1,1.01" -CHECK_TITLE[check11]="Avoid the use of the root account (Scored)" -CHECK_SCORED[check11]="SCORED" -CHECK_TYPE[check11]="LEVEL1" -CHECK_ALTERNATE[check101]="check11" - -check11() { - # "Avoid the use of the root account (Scored)." - COMMAND11=$(cat $TEMP_REPORT_FILE| grep '' | cut -d, -f5,11,16 | sed 's/,/\ /g') - textNotice "Root account last accessed (password key_1 key_2): $COMMAND11" +check11(){ + # "Avoid the use of the root account (Scored)." + COMMAND11=$(cat $TEMP_REPORT_FILE| grep '' | cut -d, -f5,11,16 | sed 's/,/\ /g') + textTitle "$ID11" "$TITLE11" "SCORED" "LEVEL1" + textNotice "Root account last accessed (password key_1 key_2): $COMMAND11" } diff --git a/checks/check110 b/checks/check110 index e69de29bb2..3de5513a25 100644 --- a/checks/check110 +++ b/checks/check110 @@ -0,0 +1,20 @@ +CHECK_ID_check110="" +CHECK_TITLE_check110="" +CHECK_SCORED_check110="" +CHECK_TYPE_check110="" +CHECK_ALTERNATE_check110="check110" + +check110(){ + # "Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" + COMMAND110=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' --output text 2> /dev/null) + textTitle "$ID110" "$TITLE110" "SCORED" "LEVEL1" + if [[ $COMMAND110 ]];then + if [[ $COMMAND110 -gt "23" ]];then + textOK "Password Policy limits reuse" + else + textWarn "Password Policy has weak reuse requirement (lower than 24)" + fi + else + textWarn "Password Policy missing reuse requirement" + fi +} diff --git a/checks/check111 b/checks/check111 index e69de29bb2..8348e4b4be 100644 --- a/checks/check111 +++ b/checks/check111 @@ -0,0 +1,18 @@ +CHECK_ID_check111="" +CHECK_TITLE_check111="" +CHECK_SCORED_check111="" +CHECK_TYPE_check111="" +CHECK_ALTERNATE_check111="check111" + +check111(){ + # "Ensure IAM password policy expires passwords within 90 days or less (Scored)" + COMMAND111=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g' 2> /dev/null) + textTitle "$ID111" "$TITLE111" "SCORED" "LEVEL1" + if [[ $COMMAND111 ]];then + if [ "$COMMAND111" == "90" ];then + textOK "Password Policy includes expiration" + fi + else + textWarn "Password expiration not set or set greater than 90 days " + fi +} diff --git a/checks/check112 b/checks/check112 index e69de29bb2..c1e85c3f03 100644 --- a/checks/check112 +++ b/checks/check112 @@ -0,0 +1,23 @@ +CHECK_ID_check112="" +CHECK_TITLE_check112="" +CHECK_SCORED_check112="" +CHECK_TYPE_check112="" +CHECK_ALTERNATE_check112="check112" + +check112(){ + # "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 }') + textTitle "$ID112" "$TITLE112" "SCORED" "LEVEL1" + if [ "$ROOTKEY1" == "false" ];then + textOK "No access key 1 found for root" + else + textWarn "Found access key 1 for root " + fi + if [ "$ROOTKEY2" == "false" ];then + textOK "No access key 2 found for root" + else + textWarn "Found access key 2 for root " + fi +} diff --git a/checks/check113 b/checks/check113 index e69de29bb2..839857858d 100644 --- a/checks/check113 +++ b/checks/check113 @@ -0,0 +1,16 @@ +CHECK_ID_check113="" +CHECK_TITLE_check113="" +CHECK_SCORED_check113="" +CHECK_TYPE_check113="" +CHECK_ALTERNATE_check113="check113" + +check113(){ + # "Ensure MFA is enabled for the root account (Scored)" + COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') + textTitle "$ID113" "$TITLE113" "SCORED" "LEVEL1" + if [ "$COMMAND113" == "1" ]; then + textOK "Virtual MFA is enabled for root" + else + textWarn "MFA is not ENABLED for root account " + fi +} diff --git a/checks/check114 b/checks/check114 index e69de29bb2..8fae9dcbfb 100644 --- a/checks/check114 +++ b/checks/check114 @@ -0,0 +1,21 @@ +CHECK_ID_check114="" +CHECK_TITLE_check114="" +CHECK_SCORED_check114="" +CHECK_TYPE_check114="" +CHECK_ALTERNATE_check114="check114" + +check114(){ + # "Ensure hardware MFA is enabled for the root account (Scored)" + COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') + textTitle "$ID114" "$TITLE114" "SCORED" "LEVEL1" + if [ "$COMMAND113" == "1" ]; then + COMMAND114=$($AWSCLI iam list-virtual-mfa-devices $PROFILE_OPT --region $REGION --output text --assignment-status Assigned --query 'VirtualMFADevices[*].[SerialNumber]' | grep '^arn:aws:iam::[0-9]\{12\}:mfa/root-account-mfa-device$') + if [[ "$COMMAND114" ]]; then + textWarn "Only Virtual MFA is enabled for root" + else + textOK "Hardware MFA is enabled for root " + fi + else + textWarn "MFA is not ENABLED for root account " + fi +} diff --git a/checks/check115 b/checks/check115 index e69de29bb2..9512805771 100644 --- a/checks/check115 +++ b/checks/check115 @@ -0,0 +1,13 @@ +CHECK_ID_check115="" +CHECK_TITLE_check115="" +CHECK_SCORED_check115="" +CHECK_TYPE_check115="" +CHECK_ALTERNATE_check115="check115" + +check115(){ + # "Ensure security questions are registered in the AWS account (Not Scored)" + textTitle "$ID115" "$TITLE115" "NOT_SCORED" "LEVEL2" + textNotice "No command available for check 1.15 " + textNotice "Login to the AWS Console as root & click on the Account " + textNotice "Name -> My Account -> Configure Security Challenge Questions " +} diff --git a/checks/check116 b/checks/check116 index e69de29bb2..5df186fc6f 100644 --- a/checks/check116 +++ b/checks/check116 @@ -0,0 +1,22 @@ +CHECK_ID_check116="" +CHECK_TITLE_check116="" +CHECK_SCORED_check116="" +CHECK_TYPE_check116="" +CHECK_ALTERNATE_check116="check116" + +check116(){ + # "Ensure IAM policies are attached only to groups or roles (Scored)" + textTitle "$ID116" "$TITLE116" "SCORED" "LEVEL1" + LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION) + C116_NUM_USERS=0 + for user in $LIST_USERS;do + USER_POLICY=$($AWSCLI iam list-attached-user-policies --output text $PROFILE_OPT --region $REGION --user-name $user) + if [[ $USER_POLICY ]]; then + textWarn "$user has policy directly attached " + C116_NUM_USERS=$(expr $C116_NUM_USERS + 1) + fi + done + if [[ $C116_NUM_USERS -eq 0 ]]; then + textOK "No policies attached to users." + fi +} diff --git a/checks/check117 b/checks/check117 index e69de29bb2..4badfe9af9 100644 --- a/checks/check117 +++ b/checks/check117 @@ -0,0 +1,13 @@ +CHECK_ID_check117="" +CHECK_TITLE_check117="" +CHECK_SCORED_check117="" +CHECK_TYPE_check117="" +CHECK_ALTERNATE_check117="check117" + +check117(){ + # "Enable detailed billing (Scored)" + # No command available + textTitle "$ID117" "$TITLE117" "SCORED" "LEVEL1" + textNotice "No command available for check 1.17 " + textNotice "See section 1.17 on the CIS Benchmark guide for details " +} diff --git a/checks/check118 b/checks/check118 index e69de29bb2..d81bb6adc3 100644 --- a/checks/check118 +++ b/checks/check118 @@ -0,0 +1,31 @@ +CHECK_ID_check118="" +CHECK_TITLE_check118="" +CHECK_SCORED_check118="" +CHECK_TYPE_check118="" +CHECK_ALTERNATE_check118="check118" + +check118(){ + # "Ensure IAM Master and IAM Manager roles are active (Scored)" + textTitle "$ID118" "$TITLE118" "SCORED" "LEVEL1" + FINDMASTERANDMANAGER=$($AWSCLI iam list-roles $PROFILE_OPT --region $REGION --query "Roles[*].{RoleName:RoleName}" --output text | grep -E 'Master|Manager'| tr ' +' ' ') + if [[ $FINDMASTERANDMANAGER ]];then + textNotice "Found next roles as possible IAM Master and IAM Manager candidates: " + textNotice "$FINDMASTERANDMANAGER " + textNotice "run the commands below to check their policies with section 1.18 in the guide..." + for role in $FINDMASTERANDMANAGER;do + # find inline policies in found roles + INLINEPOLICIES=$($AWSCLI iam list-role-policies --role-name $role $PROFILE_OPT --region $REGION --query "PolicyNames[*]" --output text) + for policy in $INLINEPOLICIES;do + textNotice "INLINE: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json" + done + # find attached policies in found roles + ATTACHEDPOLICIES=$($AWSCLI iam list-attached-role-policies --role-name $role $PROFILE_OPT --region $REGION --query "AttachedPolicies[*]" --output text) + for policy in $ATTACHEDPOLICIES;do + textNotice "ATTACHED: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json" + done + done + else + textWarn "IAM Master and IAM Manager roles not found" + fi +} diff --git a/checks/check119 b/checks/check119 index e69de29bb2..c1095b3df2 100644 --- a/checks/check119 +++ b/checks/check119 @@ -0,0 +1,13 @@ +CHECK_ID_check119="" +CHECK_TITLE_check119="" +CHECK_SCORED_check119="" +CHECK_TYPE_check119="" +CHECK_ALTERNATE_check119="check119" + +check119(){ + # "Maintain current contact details (Scored)" + # No command available + textTitle "$ID119" "$TITLE119" "SCORED" "LEVEL1" + textNotice "No command available for check 1.19 " + textNotice "See section 1.19 on the CIS Benchmark guide for details " +} diff --git a/checks/check12 b/checks/check12 index 2c520084d1..638e29d94c 100644 --- a/checks/check12 +++ b/checks/check12 @@ -1,16 +1,15 @@ -#!/usr/bin/env bash - -CHECK_ID[check12]="1.2,1.02" -CHECK_TITLE[check12]="Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" -CHECK_SCORED[check12]="SCORED" -CHECK_TYPE[check12]="LEVEL1" -CHECK_ALTERNATE[check102]="check12" +CHECK_ID_check12="1.2,1.02" +CHECK_TITLE_check12="Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" +CHECK_SCORED_check12="SCORED" +CHECK_TYPE_check12="LEVEL1" +CHECK_ALTERNATE_check102="check12" check12(){ # "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 + 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 }' done) textTitle "$ID12" "$TITLE12" "SCORED" "LEVEL1" diff --git a/checks/check120 b/checks/check120 index e69de29bb2..d319f64d33 100644 --- a/checks/check120 +++ b/checks/check120 @@ -0,0 +1,13 @@ +CHECK_ID_check120="" +CHECK_TITLE_check120="" +CHECK_SCORED_check120="" +CHECK_TYPE_check120="" +CHECK_ALTERNATE_check120="check120" + +check120(){ + # "Ensure security contact information is registered (Scored)" + # No command available + textTitle "$ID120" "$TITLE120" "SCORED" "LEVEL1" + textNotice "No command available for check 1.20 " + textNotice "See section 1.20 on the CIS Benchmark guide for details " +} diff --git a/checks/check121 b/checks/check121 index e69de29bb2..fc0f048f00 100644 --- a/checks/check121 +++ b/checks/check121 @@ -0,0 +1,12 @@ +CHECK_ID_check121="" +CHECK_TITLE_check121="" +CHECK_SCORED_check121="" +CHECK_TYPE_check121="" +CHECK_ALTERNATE_check121="check121" + +check121(){ + # "Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" + textTitle "$ID121" "$TITLE121" "NOT_SCORED" "LEVEL2" + textNotice "No command available for check 1.21 " + textNotice "See section 1.21 on the CIS Benchmark guide for details " +} diff --git a/checks/check122 b/checks/check122 index e69de29bb2..aa5117c493 100644 --- a/checks/check122 +++ b/checks/check122 @@ -0,0 +1,27 @@ +CHECK_ID_check122="" +CHECK_TITLE_check122="" +CHECK_SCORED_check122="" +CHECK_TYPE_check122="" +CHECK_ALTERNATE_check122="check122" + +check122(){ + # "Ensure a support role has been created to manage incidents with AWS Support (Scored)" + textTitle "$ID122" "$TITLE122" "SCORED" "LEVEL1" + SUPPORTPOLICYARN=$($AWSCLI iam list-policies --query "Policies[?PolicyName == 'AWSSupportAccess'].Arn" $PROFILE_OPT --region $REGION --output text) + if [[ $SUPPORTPOLICYARN ]];then + for policyarn in $SUPPORTPOLICYARN;do + POLICYUSERS=$($AWSCLI iam list-entities-for-policy --policy-arn $SUPPORTPOLICYARN $PROFILE_OPT --region $REGION --output json) + if [[ $POLICYUSERS ]];then + textOK "Support Policy attached to $policyarn" + for user in $(echo "$POLICYUSERS" | grep UserName | cut -d'"' -f4) ; do + textNotice "User $user has support access via $policyarn" + done + # textNotice "Make sure your team can create a Support case with AWS " + else + textWarn "Support Policy not applied to any Group / User / Role " + fi + done + else + textWarn "No Support Policy found" + fi +} diff --git a/checks/check123 b/checks/check123 index e69de29bb2..b46248964d 100644 --- a/checks/check123 +++ b/checks/check123 @@ -0,0 +1,31 @@ +CHECK_ID_check123="" +CHECK_TITLE_check123="" +CHECK_SCORED_check123="" +CHECK_TYPE_check123="" +CHECK_ALTERNATE_check123="check123" + +check123(){ + # "Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" + textTitle "$ID123" "$TITLE123" "NOT_SCORED" "LEVEL1" + LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION) + # List of USERS with KEY1 last_used_date as N/A + LIST_USERS_KEY1_NA=$(for user in $LIST_USERS; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$11 }'|grep N/A |awk '{ print $1 }'; done) + LIST_USERS_KEY1_ACTIVE=$(for user in $LIST_USERS_KEY1_NA; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$9 }'|grep "true$"|awk '{ print $1 }'|sed 's/[[:blank:]]+/,/g' ; done) + if [[ $LIST_USERS_KEY1_ACTIVE ]]; then + for user in $LIST_USERS_KEY1_ACTIVE; do + textNotice "$user has never used Access Key 1" + done + else + textOK "No users found with Access Key 1 never used" + fi + # List of USERS with KEY2 last_used_date as N/A + LIST_USERS_KEY2_NA=$(for user in $LIST_USERS; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$16 }'|grep N/A |awk '{ print $1 }' ; done) + LIST_USERS_KEY2_ACTIVE=$(for user in $LIST_USERS_KEY2_NA; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$14 }'|grep "true$" |awk '{ print $1 }' ; done) + if [[ $LIST_USERS_KEY2_ACTIVE ]]; then + for user in $LIST_USERS_KEY2_ACTIVE; do + textNotice "$user has never used Access Key 2" + done + else + textOK "No users found with Access Key 2 never used" + fi +} diff --git a/checks/check124 b/checks/check124 index e69de29bb2..d5635f20dc 100644 --- a/checks/check124 +++ b/checks/check124 @@ -0,0 +1,31 @@ +CHECK_ID_check124="" +CHECK_TITLE_check124="" +CHECK_SCORED_check124="" +CHECK_TYPE_check124="" +CHECK_ALTERNATE_check124="check124" + +check124(){ + # "Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" + textTitle "$ID124" "$TITLE124" "SCORED" "LEVEL1" + LIST_CUSTOM_POLICIES=$($AWSCLI iam list-policies --output text $PROFILE_OPT --region $REGION|grep 'arn:aws:iam::[0-9]\{12\}:'|awk '{ print $2 }') + if [[ $LIST_CUSTOM_POLICIES ]]; then + textNotice "Looking for custom policies: (skipping default policies - it may take few seconds...)" + for policy in $LIST_CUSTOM_POLICIES; do + POLICY_VERSION=$($AWSCLI iam list-policies $PROFILE_OPT --region $REGION --query 'Policies[*].[Arn,DefaultVersionId]' --output text |awk "\$1 == \"$policy\" { print \$2 }") + POLICY_WITH_FULL=$($AWSCLI iam get-policy-version --output text --policy-arn $policy --version-id $POLICY_VERSION --query "PolicyVersion.Document.Statement[?Effect == 'Allow' && contains(Resource, '*') && contains (Action, '*')]" $PROFILE_OPT --region $REGION) + if [[ $POLICY_WITH_FULL ]]; then + POLICIES_ALLOW_LIST="$POLICIES_ALLOW_LIST $policy" + fi + done + if [[ $POLICIES_ALLOW_LIST ]]; then + textNotice "List of custom policies: " + for policy in $POLICIES_ALLOW_LIST; do + textNotice "Policy $policy allows \"*:*\"" + done + else + textOK "No custom policy found that allow full \"*:*\" administrative privileges" + fi + else + textOK "No custom policies found" + fi +} diff --git a/checks/check13 b/checks/check13 index e69de29bb2..a981b900c0 100644 --- a/checks/check13 +++ b/checks/check13 @@ -0,0 +1,34 @@ +CHECK_ID_check13="" +CHECK_TITLE_check13="" +CHECK_SCORED_check13="" +CHECK_TYPE_check13="" +CHECK_ALTERNATE_check13="check13" + +check13(){ + # "Ensure credentials unused for 90 days or greater are disabled (Scored)" + textTitle "$ID13" "$TITLE13" "SCORED" "LEVEL1" + COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED=$(cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$4 }' |grep true | awk '{ print $1 }') + if [[ $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED ]]; then + COMMAND13=$( + for i in $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED; do + cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$5 }' |grep $i| awk '{ print $1 }'|tr ' +' ' '; + done) + # list of users that have used password + USERS_PASSWORD_USED=$($AWSCLI iam list-users --query "Users[?PasswordLastUsed].UserName" --output text $PROFILE_OPT --region $REGION) + if [[ $USERS_PASSWORD_USED ]]; then + # look for users with a password last used more or equal to 90 days + for i in $USERS_PASSWORD_USED; do + DATEUSED=$($AWSCLI iam list-users --query "Users[?UserName=='$i'].PasswordLastUsed" --output text $PROFILE_OPT --region $REGION | cut -d'T' -f1) + HOWOLDER=$(how_older_from_today $DATEUSED) + if [ $HOWOLDER -gt "90" ];then + textWarn "User \"$i\" has not logged in during the last 90 days " + else + textOK "User \"$i\" found with credentials used in the last 90 days" + fi + done + fi + else + textOK "No users found with password enabled" + fi +} diff --git a/checks/check14 b/checks/check14 index e69de29bb2..129b69f713 100644 --- a/checks/check14 +++ b/checks/check14 @@ -0,0 +1,50 @@ +CHECK_ID_check14="" +CHECK_TITLE_check14="" +CHECK_SCORED_check14="" +CHECK_TYPE_check14="" +CHECK_ALTERNATE_check14="check14" + +check14(){ + # "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 }') + textTitle "$ID14" "$TITLE14" "SCORED" "LEVEL1" + C14_NUM_USERS1=0 + C14_NUM_USERS2=0 + if [[ $LIST_OF_USERS_WITH_ACCESS_KEY1 ]]; then + # textWarn "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 -v user_creation_time | 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 + textWarn " $user has not rotated access key1 in over 90 days " + C14_NUM_USERS1=$(expr $C14_NUM_USERS1 + 1) + fi + done + if [[ $C14_NUM_USERS1 -eq 0 ]]; then + textOK "No users with access key 1 older than 90 days." + fi + else + textOK "No users with access key 1." + fi + + if [[ $LIST_OF_USERS_WITH_ACCESS_KEY2 ]]; then + # textWarn "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 -v user_creation_time | 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 + textWarn " $user has not rotated access key2. " + C14_NUM_USERS2=$(expr $C14_NUM_USERS2 + 1) + fi + done + if [[ $C14_NUM_USERS2 -eq 0 ]]; then + textOK "No users with access key 2 older than 90 days." + fi + else + textOK "No users with access key 2." + fi +} diff --git a/checks/check15 b/checks/check15 index e69de29bb2..9ef12a6bfc 100644 --- a/checks/check15 +++ b/checks/check15 @@ -0,0 +1,16 @@ +CHECK_ID_check15="" +CHECK_TITLE_check15="" +CHECK_SCORED_check15="" +CHECK_TYPE_check15="" +CHECK_ALTERNATE_check15="check15" + +check15(){ + # "Ensure IAM password policy requires at least one uppercase letter (Scored)" + COMMAND15=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireUppercaseCharacters' 2> /dev/null) # must be true + textTitle "$ID15" "$TITLE15" "SCORED" "LEVEL1" + if [[ "$COMMAND15" == "true" ]];then + textOK "Password Policy requires upper case" + else + textWarn "Password Policy missing upper-case requirement" + fi +} diff --git a/checks/check16 b/checks/check16 index e69de29bb2..5562a6ea3d 100644 --- a/checks/check16 +++ b/checks/check16 @@ -0,0 +1,16 @@ +CHECK_ID_check16="" +CHECK_TITLE_check16="" +CHECK_SCORED_check16="" +CHECK_TYPE_check16="" +CHECK_ALTERNATE_check16="check16" + +check16(){ + # "Ensure IAM password policy require at least one lowercase letter (Scored)" + COMMAND16=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireLowercaseCharacters' 2> /dev/null) # must be true + textTitle "$ID16" "$TITLE16" "SCORED" "LEVEL1" + if [[ "$COMMAND16" == "true" ]];then + textOK "Password Policy requires lower case" + else + textWarn "Password Policy missing lower-case requirement" + fi +} diff --git a/checks/check17 b/checks/check17 index e69de29bb2..97162b446a 100644 --- a/checks/check17 +++ b/checks/check17 @@ -0,0 +1,16 @@ +CHECK_ID_check17="" +CHECK_TITLE_check17="" +CHECK_SCORED_check17="" +CHECK_TYPE_check17="" +CHECK_ALTERNATE_check17="check17" + +check17(){ + # "Ensure IAM password policy require at least one symbol (Scored)" + COMMAND17=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireSymbols' 2> /dev/null) # must be true + textTitle "$ID17" "$TITLE17" "SCORED" "LEVEL1" + if [[ "$COMMAND17" == "true" ]];then + textOK "Password Policy requires symbol" + else + textWarn "Password Policy missing symbol requirement" + fi +} diff --git a/checks/check18 b/checks/check18 index e69de29bb2..48bf56e0f9 100644 --- a/checks/check18 +++ b/checks/check18 @@ -0,0 +1,16 @@ +CHECK_ID_check18="" +CHECK_TITLE_check18="" +CHECK_SCORED_check18="" +CHECK_TYPE_check18="" +CHECK_ALTERNATE_check18="check18" + +check18(){ + # "Ensure IAM password policy require at least one number (Scored)" + COMMAND18=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireNumbers' 2> /dev/null) # must be true + textTitle "$ID18" "$TITLE18" "SCORED" "LEVEL1" + if [[ "$COMMAND18" == "true" ]];then + textOK "Password Policy requires number" + else + textWarn "Password Policy missing number requirement" + fi +} diff --git a/checks/check19 b/checks/check19 index e69de29bb2..f4e5647110 100644 --- a/checks/check19 +++ b/checks/check19 @@ -0,0 +1,16 @@ +CHECK_ID_check19="" +CHECK_TITLE_check19="" +CHECK_SCORED_check19="" +CHECK_TYPE_check19="" +CHECK_ALTERNATE_check19="check19" + +check19(){ + # "Ensure IAM password policy requires minimum length of 14 or greater (Scored)" + COMMAND19=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.MinimumPasswordLength' 2> /dev/null) + textTitle "$ID19" "$TITLE19" "SCORED" "LEVEL1" + if [[ $COMMAND19 -gt "13" ]];then + textOK "Password Policy requires more than 13 characters" + else + textWarn "Password Policy missing or weak length requirement" + fi +} diff --git a/checks/check21 b/checks/check21 index e69de29bb2..627b738b35 100644 --- a/checks/check21 +++ b/checks/check21 @@ -0,0 +1,23 @@ +CHECK_ID_check21="" +CHECK_TITLE_check21="" +CHECK_SCORED_check21="" +CHECK_TYPE_check21="" +CHECK_ALTERNATE_check21="check21" + +check21(){ + # "Ensure CloudTrail is enabled in all regions (Scored)" + textTitle "$ID21" "$TITLE21" "SCORED" "LEVEL1" + LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].Name' --output text) + if [[ $LIST_OF_TRAILS ]];then + for trail in $LIST_OF_TRAILS;do + MULTIREGION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].IsMultiRegionTrail' --output text --trail-name-list $trail) + if [[ "$MULTIREGION_TRAIL_STATUS" == 'False' ]];then + textWarn "$trail trail in $REGION is not enabled in multi region mode" + else + textOK "$trail trail in $REGION is enabled for all regions" + fi + done + else + textWarn "No CloudTrail trails found!" + fi +} diff --git a/checks/check22 b/checks/check22 index e69de29bb2..55a9c9b6c9 100644 --- a/checks/check22 +++ b/checks/check22 @@ -0,0 +1,23 @@ +CHECK_ID_check22="" +CHECK_TITLE_check22="" +CHECK_SCORED_check22="" +CHECK_TYPE_check22="" +CHECK_ALTERNATE_check22="check22" + +check22(){ + # "Ensure CloudTrail log file validation is enabled (Scored)" + textTitle "$ID22" "$TITLE22" "SCORED" "LEVEL2" + LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].Name' --output text) + if [[ $LIST_OF_TRAILS ]];then + for trail in $LIST_OF_TRAILS;do + LOGFILEVALIDATION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].LogFileValidationEnabled' --output text --trail-name-list $trail) + if [[ "$LOGFILEVALIDATION_TRAIL_STATUS" == 'False' ]];then + textWarn "$trail trail in $REGION has not log file validation enabled" + else + textOK "$trail trail in $REGION has log file validation enabled" + fi + done + else + textWarn "No CloudTrail trails found!" + fi +} diff --git a/checks/check23 b/checks/check23 index e69de29bb2..b06dbc0555 100644 --- a/checks/check23 +++ b/checks/check23 @@ -0,0 +1,23 @@ +CHECK_ID_check23="" +CHECK_TITLE_check23="" +CHECK_SCORED_check23="" +CHECK_TYPE_check23="" +CHECK_ALTERNATE_check23="check23" + +check23(){ + # "Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" + textTitle "$ID23" "$TITLE23" "SCORED" "LEVEL1" + CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text $PROFILE_OPT --region $REGION) + if [[ $CLOUDTRAILBUCKET ]];then + for bucket in $CLOUDTRAILBUCKET;do + CLOUDTRAILBUCKET_HASALLPERMISIONS=$($AWSCLI s3api get-bucket-acl --bucket $bucket --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' $PROFILE_OPT --region $REGION --output text) + if [[ $CLOUDTRAILBUCKET_HASALLPERMISIONS ]];then + textWarn "check your $bucket CloudTrail bucket ACL and Policy!" + else + textOK "Bucket $bucket is set correctly" + fi + done + else + textWarn "No CloudTrail bucket found!" + fi +} diff --git a/checks/check24 b/checks/check24 index e69de29bb2..95f22f792c 100644 --- a/checks/check24 +++ b/checks/check24 @@ -0,0 +1,31 @@ +CHECK_ID_check24="" +CHECK_TITLE_check24="" +CHECK_SCORED_check24="" +CHECK_TYPE_check24="" +CHECK_ALTERNATE_check24="check24" + +check24(){ + # "Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" + textTitle "$ID24" "$TITLE24" "SCORED" "LEVEL1" + TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion}' --output text | tr " " ',') + if [[ $TRAILS_AND_REGIONS ]];then + for reg_trail in $TRAILS_AND_REGIONS;do + trail=$(echo $reg_trail | cut -d',' -f2) + TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) + LATESTDELIVERY_TIMESTAMP=$($AWSCLI cloudtrail get-trail-status --name $trail $PROFILE_OPT --region $TRAIL_REGION --query 'LatestCloudWatchLogsDeliveryTime' --output text|grep -v None) + if [[ ! $LATESTDELIVERY_TIMESTAMP ]];then + textWarn "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" + else + LATESTDELIVERY_DATE=$(timestamp_to_date $LATESTDELIVERY_TIMESTAMP) + HOWOLDER=$(how_older_from_today $LATESTDELIVERY_DATE) + if [ $HOWOLDER -gt "1" ];then + textWarn "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" + else + textOK "$trail trail has been logging during the last 24h (it is in $TRAIL_REGION)" + fi + fi + done + else + textWarn "No CloudTrail trails found!" + fi +} diff --git a/checks/check25 b/checks/check25 index e69de29bb2..b6c9cff5d8 100644 --- a/checks/check25 +++ b/checks/check25 @@ -0,0 +1,18 @@ +CHECK_ID_check25="" +CHECK_TITLE_check25="" +CHECK_SCORED_check25="" +CHECK_TYPE_check25="" +CHECK_ALTERNATE_check25="check25" + +check25(){ + # "Ensure AWS Config is enabled in all regions (Scored)" + textTitle "$ID25" "$TITLE25" "SCORED" "LEVEL1" + for regx in $REGIONS; do + CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice get-status $PROFILE_OPT --region $regx --output json| grep "recorder: ON") + if [[ $CHECK_AWSCONFIG_STATUS ]];then + textOK "Region $regx has AWS Config recorder: ON" "$regx" + else + textWarn "Region $regx has AWS Config disabled or not configured" "$regx" + fi + done +} diff --git a/checks/check26 b/checks/check26 index e69de29bb2..7158da6174 100644 --- a/checks/check26 +++ b/checks/check26 @@ -0,0 +1,23 @@ +CHECK_ID_check26="" +CHECK_TITLE_check26="" +CHECK_SCORED_check26="" +CHECK_TYPE_check26="" +CHECK_ALTERNATE_check26="check26" + +check26(){ + # "Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" + textTitle "$ID26" "$TITLE26" "SCORED" "LEVEL1" + CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text $PROFILE_OPT --region $REGION) + if [[ $CLOUDTRAILBUCKET ]];then + for bucket in $CLOUDTRAILBUCKET;do + CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --region $REGION --query 'LoggingEnabled.TargetBucket' --output text|grep -v None) + if [[ $CLOUDTRAILBUCKET_LOGENABLED ]];then + textOK "Bucket access logging enabled in $bucket" + else + textWarn "access logging is not enabled in $bucket CloudTrail S3 bucket!" + fi + done + else + textWarn "CloudTrail bucket not found!" + fi +} diff --git a/checks/check27 b/checks/check27 index e69de29bb2..0106ad70dc 100644 --- a/checks/check27 +++ b/checks/check27 @@ -0,0 +1,23 @@ +CHECK_ID_check27="" +CHECK_TITLE_check27="" +CHECK_SCORED_check27="" +CHECK_TYPE_check27="" +CHECK_ALTERNATE_check27="check27" + +check27(){ + # "Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" + textTitle "$ID27" "$TITLE27" "SCORED" "LEVEL2" + CLOUDTRAILNAME=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].Name' --output text $PROFILE_OPT --region $REGION) + if [[ $CLOUDTRAILNAME ]];then + for trail in $CLOUDTRAILNAME;do + CLOUDTRAILENC_ENABLED=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --trail $trail --query 'trailList[*].KmsKeyId' --output text) + if [[ $CLOUDTRAILENC_ENABLED ]];then + textOK "KMS key found for $trail" + else + textWarn "encryption is not enabled in your CloudTrail trail $trail (KMS key not found)!" + fi + done + else + textWarn "CloudTrail bucket doesn't exist!" + fi +} diff --git a/checks/check28 b/checks/check28 index e69de29bb2..56cd89a2e5 100644 --- a/checks/check28 +++ b/checks/check28 @@ -0,0 +1,32 @@ +CHECK_ID_check28="" +CHECK_TITLE_check28="" +CHECK_SCORED_check28="" +CHECK_TYPE_check28="" +CHECK_ALTERNATE_check28="check28" + +check28(){ + # "Ensure rotation for customer created CMKs is enabled (Scored)" + textTitle "$ID28" "$TITLE28" "SCORED" "LEVEL2" + for regx in $REGIONS; do + CHECK_KMS_KEYLIST=$($AWSCLI kms list-keys $PROFILE_OPT --region $regx --output text --query 'Keys[*].KeyId') + if [[ $CHECK_KMS_KEYLIST ]];then + CHECK_KMS_KEYLIST_NO_DEFAULT=$(for key in $CHECK_KMS_KEYLIST ; do $AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --output text --query 'KeyMetadata.[KeyId, KeyManager]'|grep -v 'AWS'|awk '{ print $1 }'; done) + for key in $CHECK_KMS_KEYLIST_NO_DEFAULT; do + CHECK_KMS_KEY_TYPE=$($AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --query 'KeyMetadata.Origin' | sed 's/["]//g') + if [[ "$CHECK_KMS_KEY_TYPE" == "EXTERNAL" ]];then + textOK "Key $key in Region $regx Customer Uploaded Key Material." "$regx" + else + CHECK_KMS_KEY_ROTATION=$($AWSCLI kms get-key-rotation-status --key-id $key $PROFILE_OPT --region $regx --output text) + if [[ "$CHECK_KMS_KEY_ROTATION" == "True" ]];then + textOK "Key $key in Region $regx is set correctly" + else + textWarn "Key $key in Region $regx is not set to rotate!!!" "$regx" + fi + fi + done + + else + textNotice "Region $regx doesn't have encryption keys" "$regx" + fi + done +} diff --git a/checks/check31 b/checks/check31 index e69de29bb2..59ae384b0b 100644 --- a/checks/check31 +++ b/checks/check31 @@ -0,0 +1,54 @@ +CHECK_ID_check31="" +CHECK_TITLE_check31="" +CHECK_SCORED_check31="" +CHECK_TYPE_check31="" +CHECK_ALTERNATE_check31="check31" + +check31(){ + # "Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" + textTitle "$ID31" "$TITLE31" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text| tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | grep $group | awk -F: '{ print $4 }') + #METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | awk '/UnauthorizedOperation/ || /AccessDenied/ {print $3}') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --output text | grep METRICFILTERS | awk 'BEGIN {IGNORECASE=1}; /UnauthorizedOperation/ || /AccessDenied/ {print $3};') + if [[ $METRICFILTER_SET ]];then + for metric in $METRICFILTER_SET; do + metric_name=$($AWSCLI logs describe-metric-filters $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --log-group-name $group --filter-name-prefix $metric --output text --query 'metricFilters[0].metricTransformations[0].metricName') + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[?MetricName==`'$metric_name'`]' --output text) + if [[ $HAS_ALARM_ASSOCIATED ]];then + CHECK31OK="$CHECK31OK $group:$metric" + else + CHECK31WARN="$CHECK31WARN $group:$metric" + fi + done + else + CHECK31WARN="$CHECK31WARN $group" + fi + done + + if [[ $CHECK31OK ]]; then + for group in $CHECK31OK; do + metric=${group#*:} + group=${group%:*} + textOK "CloudWatch group $group found with metric filter $metric and alarms set for Unauthorized Operation and Access Denied" + done + fi + if [[ $CHECK31WARN ]]; then + for group in $CHECK31WARN; do + case $group in + *:*) metric=${group#*:} + group=${group%:*} + textWarn "CloudWatch group $group found with metric filter $metric but no alarms associated" + ;; + *) textWarn "CloudWatch group $group found but no metric filters or alarms associated" + esac + done + fi + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check310 b/checks/check310 index e69de29bb2..9860acdcf4 100644 --- a/checks/check310 +++ b/checks/check310 @@ -0,0 +1,30 @@ +CHECK_ID_check310="" +CHECK_TITLE_check310="" +CHECK_SCORED_check310="" +CHECK_TYPE_check310="" +CHECK_ALTERNATE_check310="check310" + +check310(){ + # "Ensure a log metric filter and alarm exist for security group changes (Scored)" + textTitle "$ID310" "$TITLE310" "SCORED" "LEVEL2" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'AuthorizeSecurityGroupIngress.*AuthorizeSecurityGroupEgress.*RevokeSecurityGroupIngress.*RevokeSecurityGroupEgress.*CreateSecurityGroup.*DeleteSecurityGroup') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /SecurityGroup/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for security group changes" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check311 b/checks/check311 index e69de29bb2..d097c8b4a6 100644 --- a/checks/check311 +++ b/checks/check311 @@ -0,0 +1,30 @@ +CHECK_ID_check311="" +CHECK_TITLE_check311="" +CHECK_SCORED_check311="" +CHECK_TYPE_check311="" +CHECK_ALTERNATE_check311="check311" + +check311(){ + # "Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" + textTitle "$ID311" "$TITLE311" "SCORED" "LEVEL2" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateNetworkAcl.*CreateNetworkAclEntry.*DeleteNetworkAcl.*DeleteNetworkAclEntry.*ReplaceNetworkAclEntry.*ReplaceNetworkAclAssociation') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /NetworkAcl/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for changes to NACLs" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check312 b/checks/check312 index e69de29bb2..70a0aa9f29 100644 --- a/checks/check312 +++ b/checks/check312 @@ -0,0 +1,30 @@ +CHECK_ID_check312="" +CHECK_TITLE_check312="" +CHECK_SCORED_check312="" +CHECK_TYPE_check312="" +CHECK_ALTERNATE_check312="check312" + +check312(){ + # "Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" + textTitle "$ID312" "$TITLE312" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateCustomerGateway.*DeleteCustomerGateway.*AttachInternetGateway.*CreateInternetGateway.*DeleteInternetGateway.*DetachInternetGateway') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /InternetGateway/ || /CustomerGateway/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for changes to network gateways" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check313 b/checks/check313 index e69de29bb2..7e293c3546 100644 --- a/checks/check313 +++ b/checks/check313 @@ -0,0 +1,30 @@ +CHECK_ID_check313="" +CHECK_TITLE_check313="" +CHECK_SCORED_check313="" +CHECK_TYPE_check313="" +CHECK_ALTERNATE_check313="check313" + +check313(){ + # "Ensure a log metric filter and alarm exist for route table changes (Scored)" + textTitle "$ID313" "$TITLE313" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateRoute.*CreateRouteTable.*ReplaceRoute.*ReplaceRouteTableAssociation.*DeleteRouteTable.*DeleteRoute.*DisassociateRouteTable') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /Route/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for route table changes" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check314 b/checks/check314 index e69de29bb2..437452d65c 100644 --- a/checks/check314 +++ b/checks/check314 @@ -0,0 +1,30 @@ +CHECK_ID_check314="" +CHECK_TITLE_check314="" +CHECK_SCORED_check314="" +CHECK_TYPE_check314="" +CHECK_ALTERNATE_check314="check314" + +check314(){ + # "Ensure a log metric filter and alarm exist for VPC changes (Scored)" + textTitle "$ID314" "$TITLE314" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateVpc.*DeleteVpc.*ModifyVpcAttribute.*AcceptVpcPeeringConnection.*CreateVpcPeeringConnection.*DeleteVpcPeeringConnection.*RejectVpcPeeringConnection.*AttachClassicLinkVpc.*DetachClassicLinkVpc.*DisableVpcClassicLink.*EnableVpcClassicLink') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /VPC/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for VPC changes" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check315 b/checks/check315 index e69de29bb2..df71f78652 100644 --- a/checks/check315 +++ b/checks/check315 @@ -0,0 +1,42 @@ +CHECK_ID_check315="" +CHECK_TITLE_check315="" +CHECK_SCORED_check315="" +CHECK_TYPE_check315="" +CHECK_ALTERNATE_check315="check315" + +check315(){ + # "Ensure appropriate subscribers to each SNS topic (Not Scored)" + textTitle "$ID315" "$TITLE315" "NOT_SCORED" "LEVEL1" + CAN_SNS_LIST_SUBS=1 + for regx in $REGIONS; do + TOPICS_LIST=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --output text --query 'Topics[*].TopicArn') + ntopics=$(echo $TOPICS_LIST | wc -w ) + if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then + textNotice "Region $regx has $ntopics topics" "$regx" + for topic in $TOPICS_LIST; do + TOPIC_SHORT=$(echo $topic | awk -F: '{ print $6 }') + CHECK_TOPIC_LIST=$($AWSCLI sns list-subscriptions-by-topic --topic-arn $topic $PROFILE_OPT --region $regx --query 'Subscriptions[*].{Endpoint:Endpoint,Protocol:Protocol}' --output text --max-items $MAXITEMS 2> /dev/null) + if [[ $? -eq 255 ]]; then + # Permission error + export CAN_SNS_LIST_SUBS=0 + ntopics=$(echo $TOPICS_LIST | wc -w ) + textNotice "Region $regx / $ntopics Topics / Subscriptions NO_PERMISSION" "$regx" + break; + fi + if [[ "Z" != "Z${CHECK_TOPIC_LIST}" ]]; then + printf '%s +' "$CHECK_TOPIC_LIST" | while IFS= read -r dest ; do + textNotice "Region $regx / Topic $TOPIC_SHORT / Subscription $dest" "$regx" + done + else + textWarn "Region $regx / Topic $TOPIC_SHORT / Subscription NONE" "$regx" + fi + done + elif [[ $CAN_SNS_LIST_SUBS -eq 0 ]]; then + textNotice "Region $regx has $ntopics topics - unable to list subscribers" "$regx" + # break + else + textOK "Region $regx has 0 topics" "$regx" + fi + done +} diff --git a/checks/check32 b/checks/check32 index e69de29bb2..68e42787e2 100644 --- a/checks/check32 +++ b/checks/check32 @@ -0,0 +1,30 @@ +CHECK_ID_check32="" +CHECK_TITLE_check32="" +CHECK_SCORED_check32="" +CHECK_TYPE_check32="" +CHECK_ALTERNATE_check32="check32" + +check32(){ + # "Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" + textTitle "$ID32" "$TITLE32" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' |grep filterPattern|grep MFAUsed| awk '/ConsoleLogin/ && (/additionalEventData.MFAUsed.*\!=.*\"Yes/) {print $1}') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /ConsoleLogin/ || /MFAUsed/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms set for sign-in Console without MFA enabled" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check33 b/checks/check33 index e69de29bb2..6e6362e25a 100644 --- a/checks/check33 +++ b/checks/check33 @@ -0,0 +1,30 @@ +CHECK_ID_check33="" +CHECK_TITLE_check33="" +CHECK_SCORED_check33="" +CHECK_TYPE_check33="" +CHECK_ALTERNATE_check33="check33" + +check33(){ + # "Ensure a log metric filter and alarm exist for usage of root account (Scored)" + textTitle "$ID33" "$TITLE33" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION |grep -E 'userIdentity.*Root.*AwsServiceEvent') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | tr '[:upper:]' '[:lower:]'| grep -Ei 'userIdentity|Root|AwsServiceEvent') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms set for usage of root account" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check34 b/checks/check34 index e69de29bb2..e84790c78c 100644 --- a/checks/check34 +++ b/checks/check34 @@ -0,0 +1,30 @@ +CHECK_ID_check34="" +CHECK_TITLE_check34="" +CHECK_SCORED_check34="" +CHECK_TYPE_check34="" +CHECK_ALTERNATE_check34="check34" + +check34(){ + # "Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" + textTitle "$ID34" "$TITLE34" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'DeleteGroupPolicy.*DeleteRolePolicy.*DeleteUserPolicy.*PutGroupPolicy.*PutRolePolicy.*PutUserPolicy.*CreatePolicy.*DeletePolicy.*CreatePolicyVersion.*DeletePolicyVersion.*AttachRolePolicy.*DetachRolePolicy.*AttachUserPolicy.*DetachUserPolicy.*AttachGroupPolicy.*DetachGroupPolicy') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /DeletePolicy/ || /DeletePolicies/ || /Policies/ || /Policy/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for IAM policy changes" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check35 b/checks/check35 index e69de29bb2..0d93635ab2 100644 --- a/checks/check35 +++ b/checks/check35 @@ -0,0 +1,30 @@ +CHECK_ID_check35="" +CHECK_TITLE_check35="" +CHECK_SCORED_check35="" +CHECK_TYPE_check35="" +CHECK_ALTERNATE_check35="check35" + +check35(){ + # "Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" + textTitle "$ID35" "$TITLE35" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateTrail.*UpdateTrail.*DeleteTrail.*StartLogging.*StopLogging') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /TrailChange/ || /Trails/ || /CreateTrail/ || /UpdateTrail/ || /DeleteTrail/ || /StartLogging/ || /StopLogging/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for CloudTrail configuration changes" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check36 b/checks/check36 index e69de29bb2..62f31c7505 100644 --- a/checks/check36 +++ b/checks/check36 @@ -0,0 +1,30 @@ +CHECK_ID_check36="" +CHECK_TITLE_check36="" +CHECK_SCORED_check36="" +CHECK_TYPE_check36="" +CHECK_ALTERNATE_check36="check36" + +check36(){ + # "Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" + textTitle "$ID36" "$TITLE36" "SCORED" "LEVEL2" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'ConsoleLogin.*Failed') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /FailedLogin/ || /ConsoleLogin/ || /Failed/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for AWS Management Console authentication failures" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check37 b/checks/check37 index e69de29bb2..6809b5d0dd 100644 --- a/checks/check37 +++ b/checks/check37 @@ -0,0 +1,30 @@ +CHECK_ID_check37="" +CHECK_TITLE_check37="" +CHECK_SCORED_check37="" +CHECK_TYPE_check37="" +CHECK_ALTERNATE_check37="check37" + +check37(){ + # "Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" + textTitle "$ID37" "$TITLE37" "SCORED" "LEVEL2" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'kms.amazonaws.com.*DisableKey.*ScheduleKeyDeletion') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /DisableKey/ || /ScheduleKeyDeletion/ || /kms/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for changes of customer created CMKs" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check38 b/checks/check38 index e69de29bb2..e51edccfd0 100644 --- a/checks/check38 +++ b/checks/check38 @@ -0,0 +1,30 @@ +CHECK_ID_check38="" +CHECK_TITLE_check38="" +CHECK_SCORED_check38="" +CHECK_TYPE_check38="" +CHECK_ALTERNATE_check38="check38" + +check38(){ + # "Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" + textTitle "$ID38" "$TITLE38" "SCORED" "LEVEL1" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 's3.amazonaws.com.*PutBucketAcl.*PutBucketPolicy.*PutBucketCors.*PutBucketLifecycle.*PutBucketReplication.*DeleteBucketPolicy.*DeleteBucketCors.*DeleteBucketLifecycle.*DeleteBucketReplication') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /S3/ || /BucketPolicy/ || /BucketPolicies/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for S3 bucket policy changes" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check39 b/checks/check39 index e69de29bb2..7a66fceb84 100644 --- a/checks/check39 +++ b/checks/check39 @@ -0,0 +1,30 @@ +CHECK_ID_check39="" +CHECK_TITLE_check39="" +CHECK_SCORED_check39="" +CHECK_TYPE_check39="" +CHECK_ALTERNATE_check39="check39" + +check39(){ + # "Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" + textTitle "$ID39" "$TITLE39" "SCORED" "LEVEL2" + CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' +' | awk -F: '{ print $7 }') + if [[ $CLOUDWATCH_GROUP ]];then + for group in $CLOUDWATCH_GROUP; do + CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') + METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'config.amazonaws.com.*StopConfigurationRecorder.*DeleteDeliveryChannel.*PutDeliveryChannel.*PutConfigurationRecorder') + if [[ $METRICFILTER_SET ]];then + HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /config/ || /ConfigurationRecorder/ || /DeliveryChannel/;') + if [[ $HAS_ALARM_ASSOCIATED ]];then + textOK "CloudWatch group $group found with metric filters and alarms for AWS Config configuration changes" + else + textWarn "CloudWatch group $group found with metric filters but no alarms associated" + fi + else + textWarn "CloudWatch group $group found but no metric filters or alarms associated" + fi + done + else + textWarn "No CloudWatch group found for CloudTrail events" + fi +} diff --git a/checks/check41 b/checks/check41 index e69de29bb2..0e63eb4d09 100644 --- a/checks/check41 +++ b/checks/check41 @@ -0,0 +1,20 @@ +CHECK_ID_check41="" +CHECK_TITLE_check41="" +CHECK_SCORED_check41="" +CHECK_TYPE_check41="" +CHECK_ALTERNATE_check41="check41" + +check41(){ + # "Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" + textTitle "$ID41" "$TITLE41" "SCORED" "LEVEL1" + for regx in $REGIONS; do + SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`22` && ToPort>=`22`)) && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text) + if [[ $SG_LIST ]];then + for SG in $SG_LIST;do + textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" + done + else + textOK "No Security Groups found in $regx with port 22 TCP open to 0.0.0.0/0" "$regx" + fi + done +} diff --git a/checks/check42 b/checks/check42 index e69de29bb2..7334c30492 100644 --- a/checks/check42 +++ b/checks/check42 @@ -0,0 +1,20 @@ +CHECK_ID_check42="" +CHECK_TITLE_check42="" +CHECK_SCORED_check42="" +CHECK_TYPE_check42="" +CHECK_ALTERNATE_check42="check42" + +check42(){ + # "Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" + textTitle "$ID42" "$TITLE42" "SCORED" "LEVEL1" + for regx in $REGIONS; do + SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`3389` && ToPort>=`3389`)) && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text) + if [[ $SG_LIST ]];then + for SG in $SG_LIST;do + textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" + done + else + textOK "No Security Groups found in $regx with port 3389 TCP open to 0.0.0.0/0" "$regx" + fi + done +} diff --git a/checks/check43 b/checks/check43 index e69de29bb2..627eca2b80 100644 --- a/checks/check43 +++ b/checks/check43 @@ -0,0 +1,20 @@ +CHECK_ID_check43="" +CHECK_TITLE_check43="" +CHECK_SCORED_check43="" +CHECK_TYPE_check43="" +CHECK_ALTERNATE_check43="check43" + +check43(){ + # "Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" + textTitle "$ID43" "$TITLE43" "SCORED" "LEVEL2" + for regx in $REGIONS; do + CHECK_FL=$($AWSCLI ec2 describe-flow-logs $PROFILE_OPT --region $regx --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].LogGroupName' --output text) + if [[ $CHECK_FL ]];then + for FL in $CHECK_FL;do + textOK "VPCFlowLog is enabled for LogGroupName: $FL in Region $regx" "$regx" + done + else + textWarn "No VPCFlowLog has been found in Region $regx" "$regx" + fi + done +} diff --git a/checks/check44 b/checks/check44 index e69de29bb2..afdbbfcb89 100644 --- a/checks/check44 +++ b/checks/check44 @@ -0,0 +1,18 @@ +CHECK_ID_check44="" +CHECK_TITLE_check44="" +CHECK_SCORED_check44="" +CHECK_TYPE_check44="" +CHECK_ALTERNATE_check44="check44" + +check44(){ + # "Ensure the default security group of every VPC restricts all traffic (Scored)" + textTitle "$ID44" "$TITLE44" "SCORED" "LEVEL2" + for regx in $REGIONS; do + CHECK_SGDEFAULT=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters Name=group-name,Values='default' --query 'SecurityGroups[*].{IpPermissions:IpPermissions,IpPermissionsEgress:IpPermissionsEgress,GroupId:GroupId}' --output text |grep 0.0.0.0) + if [[ $CHECK_SGDEFAULT ]];then + textWarn "Default Security Groups found that allow 0.0.0.0 IN or OUT traffic in Region $regx" "$regx" + else + textOK "No Default Security Groups open to 0.0.0.0 found in Region $regx" "$regx" + fi + done +} diff --git a/checks/check45 b/checks/check45 index e69de29bb2..ac8764d052 100644 --- a/checks/check45 +++ b/checks/check45 @@ -0,0 +1,25 @@ +CHECK_ID_check45="" +CHECK_TITLE_check45="" +CHECK_SCORED_check45="" +CHECK_TYPE_check45="" +CHECK_ALTERNATE_check45="check45" + +check45(){ + # "Ensure routing tables for VPC peering are \"least access\" (Not Scored)" + textTitle "$ID45" "$TITLE45" "NOT_SCORED" "LEVEL2" + textNotice "Looking for VPC peering in all regions... " + for regx in $REGIONS; do + LIST_OF_VPCS_PEERING_CONNECTIONS=$($AWSCLI ec2 describe-vpc-peering-connections --output text $PROFILE_OPT --region $regx --query 'VpcPeeringConnections[*].VpcPeeringConnectionId') + if [[ $LIST_OF_VPCS_PEERING_CONNECTIONS ]];then + textNotice "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS - review routing tables" "$regx" + #LIST_OF_VPCS=$($AWSCLI ec2 describe-vpcs $PROFILE_OPT --region $regx --query 'Vpcs[*].VpcId' --output text) + #aws ec2 describe-route-tables --filter "Name=vpc-id,Values=vpc-0213e864" --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" $PROFILE_OPT --region $regx + # for vpc in $LIST_OF_VPCS; do + # VPCS_WITH_PEERING=$($AWSCLI ec2 describe-route-tables --filter "Name=vpc-id,Values=$vpc" $PROFILE_OPT --region $regx --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" |grep GatewayId|grep pcx-) + # done + #echo $VPCS_WITH_PEERING + else + textOK "$regx: No VPC peering found" "$regx" + fi + done +} diff --git a/checks/check_extra71 b/checks/check_extra71 index e69de29bb2..b757559887 100644 --- a/checks/check_extra71 +++ b/checks/check_extra71 @@ -0,0 +1,37 @@ +CHECK_ID_check_extra71="" +CHECK_TITLE_check_extra71="" +CHECK_SCORED_check_extra71="" +CHECK_TYPE_check_extra71="" +CHECK_ALTERNATE_check_extra71="check_extra71" + +extra71(){ + # "Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID71" "$TITLE71" "NOT_SCORED" "EXTRA" + + ADMIN_GROUPS='' + AWS_GROUPS=$($AWSCLI $PROFILE_OPT iam list-groups --output text --query 'Groups[].GroupName') + for grp in $AWS_GROUPS; do + # aws --profile onlinetraining iam list-attached-group-policies --group-name Administrators --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess' + # list-attached-group-policies + CHECK_ADMIN_GROUP=$($AWSCLI $PROFILE_OPT iam list-attached-group-policies --group-name $grp --output json --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess') + if [[ $CHECK_ADMIN_GROUP ]]; then + ADMIN_GROUPS="$ADMIN_GROUPS $grp" + textNotice "$grp group provides administrative access" + ADMIN_USERS=$($AWSCLI $PROFILE_OPT iam get-group --group-name $grp --output json --query 'Users[].UserName' | grep '"' | cut -d'"' -f2 ) + for auser in $ADMIN_USERS; do + # users in group are Administrators + # users + # check for user MFA device in credential report + USER_MFA_ENABLED=$( cat $TEMP_REPORT_FILE | grep "^$auser," | cut -d',' -f8) + if [[ "true" == $USER_MFA_ENABLED ]]; then + textOK "$auser / MFA Enabled / admin via group $grp" + else + textWarn "$auser / MFA DISABLED / admin via group $grp" + fi + done + else + textNotice "$grp group provides non-administrative access" + fi + done + # set +x +} diff --git a/checks/check_extra710 b/checks/check_extra710 index e69de29bb2..1f7cb26e02 100644 --- a/checks/check_extra710 +++ b/checks/check_extra710 @@ -0,0 +1,23 @@ +CHECK_ID_check_extra710="" +CHECK_TITLE_check_extra710="" +CHECK_SCORED_check_extra710="" +CHECK_TYPE_check_extra710="" +CHECK_ALTERNATE_check_extra710="check_extra710" + +extra710(){ + # "Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID710" "$TITLE710" "NOT_SCORED" "EXTRA" + textNotice "Looking for instances in all regions... " + for regx in $REGIONS; do + LIST_OF_PUBLIC_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]' --output text) + if [[ $LIST_OF_PUBLIC_INSTANCES ]];then + while read -r instance;do + INSTANCE_ID=$(echo $instance | awk '{ print $1; }') + PUBLIC_IP=$(echo $instance | awk '{ print $2; }') + textWarn "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx" + done <<< "$LIST_OF_PUBLIC_INSTANCES" + else + textOK "$regx: no Internet Facing EC2 Instances found" "$regx" + fi + done +} diff --git a/checks/check_extra711 b/checks/check_extra711 index e69de29bb2..b2a0c8e405 100644 --- a/checks/check_extra711 +++ b/checks/check_extra711 @@ -0,0 +1,23 @@ +CHECK_ID_check_extra711="" +CHECK_TITLE_check_extra711="" +CHECK_SCORED_check_extra711="" +CHECK_TYPE_check_extra711="" +CHECK_ALTERNATE_check_extra711="check_extra711" + +extra711(){ + # "Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID711" "$TITLE711" "NOT_SCORED" "EXTRA" + textNotice "Looking for Reshift clusters in all regions... " + for regx in $REGIONS; do + LIST_OF_PUBLIC_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[?PubliclyAccessible == `true`].[ClusterIdentifier,Endpoint.Address]' --output text) + if [[ $LIST_OF_PUBLIC_REDSHIFT_CLUSTERS ]];then + while read -r cluster;do + CLUSTER_ID=$(echo $cluster | awk '{ print $1; }') + CLUSTER_ENDPOINT=$(echo $cluster | awk '{ print $2; }') + textWarn "$regx: Cluster: $CLUSTER_ID at Endpoint: $CLUSTER_ENDPOINT is publicly accessible!" "$regx" + done <<< "$LIST_OF_PUBLIC_REDSHIFT_CLUSTERS" + else + textOK "$regx: no Publicly Accessible Redshift Clusters found" "$regx" + fi + done +} diff --git a/checks/check_extra712 b/checks/check_extra712 index e69de29bb2..3515484c56 100644 --- a/checks/check_extra712 +++ b/checks/check_extra712 @@ -0,0 +1,18 @@ +CHECK_ID_check_extra712="" +CHECK_TITLE_check_extra712="" +CHECK_SCORED_check_extra712="" +CHECK_TYPE_check_extra712="" +CHECK_ALTERNATE_check_extra712="check_extra712" + +extra712(){ + # "Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID712" "$TITLE712" "NOT_SCORED" "EXTRA" + textNotice "No API commands available to check if Macie is enabled," + textNotice "just looking if IAM Macie related permissions exist. " + MACIE_IAM_ROLES_CREATED=$($AWSCLI iam list-roles $PROFILE_OPT --query 'Roles[*].Arn'|grep AWSMacieServiceCustomer|wc -l) + if [[ $MACIE_IAM_ROLES_CREATED -eq 2 ]];then + textOK "Macie related IAM roles exist, so it might be enabled. Check it out manually." + else + textWarn "No Macie related IAM roles found. It is most likely not to be enabled" + fi +} diff --git a/checks/check_extra713 b/checks/check_extra713 index e69de29bb2..a64cd24f3a 100644 --- a/checks/check_extra713 +++ b/checks/check_extra713 @@ -0,0 +1,25 @@ +CHECK_ID_check_extra713="" +CHECK_TITLE_check_extra713="" +CHECK_SCORED_check_extra713="" +CHECK_TYPE_check_extra713="" +CHECK_ALTERNATE_check_extra713="check_extra713" + +extra713(){ + # "Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID713" "$TITLE713" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + LIST_OF_GUARDDUTY_DETECTORS=$($AWSCLI guardduty list-detectors $PROFILE_OPT --region $regx --output text |cut -f2) + if [[ $LIST_OF_GUARDDUTY_DETECTORS ]];then + while read -r detector;do + DETECTOR_ENABLED=$($AWSCLI guardduty get-detector --detector-id $detector $PROFILE_OPT --region $regx --output text| cut -f3|grep ENABLED) + if [[ $DETECTOR_ENABLED ]]; then + textOK "$regx: GuardDuty detector $detector enabled" "$regx" + else + textWarn "$regx: GuardDuty detector $detector configured but suspended" "$regx" + fi + done <<< "$LIST_OF_GUARDDUTY_DETECTORS" + else + textWarn "$regx: GuardDuty detector not configured!" "$regx" + fi + done +} diff --git a/checks/check_extra714 b/checks/check_extra714 index e69de29bb2..5fab1be2f2 100644 --- a/checks/check_extra714 +++ b/checks/check_extra714 @@ -0,0 +1,25 @@ +CHECK_ID_check_extra714="" +CHECK_TITLE_check_extra714="" +CHECK_SCORED_check_extra714="" +CHECK_TYPE_check_extra714="" +CHECK_ALTERNATE_check_extra714="check_extra714" + +extra714(){ + # "Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID714" "$TITLE714" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + LIST_OF_DISTRIBUTIONS=$($AWSCLI cloudfront list-distributions $PROFILE_OPT --region $regx --query 'DistributionList.Items[].Id' --output text |grep -v "^None") + if [[ $LIST_OF_DISTRIBUTIONS ]]; then + for cdn in $LIST_OF_DISTRIBUTIONS;do + CDN_LOG_ENABLED=$($AWSCLI cloudfront get-distribution $PROFILE_OPT --region $regx --id "$cdn" --query 'Distribution.DistributionConfig.Logging.Enabled' | grep true) + if [[ $CDN_LOG_ENABLED ]];then + textOK "$regx: CDN $cdn logging enabled" "$regx" + else + textWarn "$regx: CDN $cdn logging disabled!" "$regx" + fi + done + else + textNotice "$regx: No CDN configured" "$regx" + fi + done +} diff --git a/checks/check_extra715 b/checks/check_extra715 index e69de29bb2..503d7c2c41 100644 --- a/checks/check_extra715 +++ b/checks/check_extra715 @@ -0,0 +1,31 @@ +CHECK_ID_check_extra715="" +CHECK_TITLE_check_extra715="" +CHECK_SCORED_check_extra715="" +CHECK_TYPE_check_extra715="" +CHECK_ALTERNATE_check_extra715="check_extra715" + +extra715(){ + # "Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID715" "$TITLE715" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text) + if [[ $LIST_OF_DOMAINS ]]; then + for domain in $LIST_OF_DOMAINS;do + SEARCH_SLOWLOG_ENABLED=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.LogPublishingOptions.Options.SEARCH_SLOW_LOGS.Enabled --output text |grep -v ^None|grep -v ^False) + if [[ $SEARCH_SLOWLOG_ENABLED ]];then + textOK "$regx: ElasticSearch Service domain $domain SEARCH_SLOW_LOGS enabled" "$regx" + else + textWarn "$regx: ElasticSearch Service domain $domain SEARCH_SLOW_LOGS disabled!" "$regx" + fi + INDEX_SLOWLOG_ENABLED=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.LogPublishingOptions.Options.INDEX_SLOW_LOGS.Enabled --output text |grep -v ^None|grep -v ^False) + if [[ $INDEX_SLOWLOG_ENABLED ]];then + textOK "$regx: ElasticSearch Service domain $domain INDEX_SLOW_LOGS enabled" "$regx" + else + textWarn "$regx: ElasticSearch Service domain $domain INDEX_SLOW_LOGS disabled!" "$regx" + fi + done + else + textNotice "$regx: No Elasticsearch Service domain found" "$regx" + fi + done +} diff --git a/checks/check_extra716 b/checks/check_extra716 index e69de29bb2..7749af1d3d 100644 --- a/checks/check_extra716 +++ b/checks/check_extra716 @@ -0,0 +1,33 @@ +CHECK_ID_check_extra716="" +CHECK_TITLE_check_extra716="" +CHECK_SCORED_check_extra716="" +CHECK_TYPE_check_extra716="" +CHECK_ALTERNATE_check_extra716="check_extra716" + +extra716(){ + # "Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID716" "$TITLE716" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text) + if [[ $LIST_OF_DOMAINS ]]; then + for domain in $LIST_OF_DOMAINS;do + CHECK_IF_MEMBER_OF_VPC=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.VPCOptions.Options.VPCId --output text|grep -v ^None) + if [[ ! $CHECK_IF_MEMBER_OF_VPC ]];then + TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.policy.XXXXXXXXXX) + $AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.AccessPolicies.Options --output text > $TEMP_POLICY_FILE 2> /dev/null + # check if the policy has Principal as * + CHECK_ES_DOMAIN_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep \"Principal|grep \*) + if [[ $CHECK_ES_DOMAIN_ALLUSERS_POLICY ]];then + textWarn "$regx: $domain policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" + else + textOK "$regx: $domain is not open" "$regx" + fi + else + textOK "$regx: $domain is in a VPC" "$regx" + fi + done + fi + textNotice "$regx: No Elasticsearch Service domain found" "$regx" + rm -fr $TEMP_POLICY_FILE + done +} diff --git a/checks/check_extra717 b/checks/check_extra717 index e69de29bb2..7dac48b5e6 100644 --- a/checks/check_extra717 +++ b/checks/check_extra717 @@ -0,0 +1,39 @@ +CHECK_ID_check_extra717="" +CHECK_TITLE_check_extra717="" +CHECK_SCORED_check_extra717="" +CHECK_TYPE_check_extra717="" +CHECK_ALTERNATE_check_extra717="check_extra717" + +extra717(){ + # "Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID717" "$TITLE717" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text|xargs -n1) + LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text|xargs -n1) + if [[ $LIST_OF_ELBS || $LIST_OF_ELBSV2 ]]; then + if [[ $LIST_OF_ELBS ]]; then + for elb in $LIST_OF_ELBS; do + CHECK_ELBS_LOG_ENABLED=$($AWSCLI elb describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-name $elb --query 'LoadBalancerAttributes.AccessLog.Enabled'|grep "^true") + if [[ $CHECK_ELBS_LOG_ENABLED ]]; then + textOK "$regx: $elb has access logs to S3 configured" "$regx" + else + textWarn "$regx: $elb has not configured access logs" "$regx" + fi + done + fi + if [[ $LIST_OF_ELBSV2 ]]; then + for elbarn in $LIST_OF_ELBSV2; do + CHECK_ELBSV2_LOG_ENABLED=$($AWSCLI elbv2 describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-arn $elbarn --query Attributes[*] --output text|grep "^access_logs.s3.enabled"|cut -f2|grep true) + ELBV2_NAME=$(echo $elbarn|cut -d\/ -f3) + if [[ $CHECK_ELBSV2_LOG_ENABLED ]]; then + textOK "$regx: $ELBV2_NAME has access logs to S3 configured" "$regx" + else + textWarn "$regx: $ELBV2_NAME has not configured access logs" "$regx" + fi + done + fi + else + textNotice "$regx: No ELBs found" "$regx" + fi + done +} diff --git a/checks/check_extra718 b/checks/check_extra718 index e69de29bb2..6d3108b628 100644 --- a/checks/check_extra718 +++ b/checks/check_extra718 @@ -0,0 +1,23 @@ +CHECK_ID_check_extra718="" +CHECK_TITLE_check_extra718="" +CHECK_SCORED_check_extra718="" +CHECK_TYPE_check_extra718="" +CHECK_ALTERNATE_check_extra718="check_extra718" + +extra718(){ + # "Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID718" "$TITLE718" "NOT_SCORED" "EXTRA" + LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --query Buckets[*].Name --output text|xargs -n1) + if [[ $LIST_OF_BUCKETS ]]; then + for bucket in $LIST_OF_BUCKETS;do + BUCKET_SERVER_LOG_ENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --query [LoggingEnabled] --output text|grep -v "^None$") + if [[ $BUCKET_SERVER_LOG_ENABLED ]];then + textOK "Bucket $bucket has server access logging enabled" + else + textWarn "Bucket $bucket has server access logging disabled!" + fi + done + else + textNotice "No S3 Buckets found" + fi +} diff --git a/checks/check_extra719 b/checks/check_extra719 index e69de29bb2..d260f66fae 100644 --- a/checks/check_extra719 +++ b/checks/check_extra719 @@ -0,0 +1,23 @@ +CHECK_ID_check_extra719="" +CHECK_TITLE_check_extra719="" +CHECK_SCORED_check_extra719="" +CHECK_TYPE_check_extra719="" +CHECK_ALTERNATE_check_extra719="check_extra719" + +extra719(){ + # "Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID719" "$TITLE719" "NOT_SCORED" "EXTRA" + LIST_OF_HOSTED_ZONES=$($AWSCLI route53 list-hosted-zones $PROFILE_OPT --query HostedZones[*].Id --output text|xargs -n1) + if [[ $LIST_OF_HOSTED_ZONES ]]; then + for hostedzoneid in $LIST_OF_HOSTED_ZONES;do + HOSTED_ZONE_QUERY_LOG_ENABLED=$($AWSCLI route53 list-query-logging-configs --hosted-zone-id $hostedzoneid $PROFILE_OPT --query QueryLoggingConfigs[*].CloudWatchLogsLogGroupArn --output text|cut -d: -f7) + if [[ $HOSTED_ZONE_QUERY_LOG_ENABLED ]];then + textOK "Route53 hosted zone Id $hostedzoneid has query logging enabled in Log Group $HOSTED_ZONE_QUERY_LOG_ENABLED" + else + textWarn "Route53 hosted zone Id $hostedzoneid has query logging disabled!" + fi + done + else + textNotice "No Route53 hosted zones found" + fi +} diff --git a/checks/check_extra72 b/checks/check_extra72 index e69de29bb2..86fd88f299 100644 --- a/checks/check_extra72 +++ b/checks/check_extra72 @@ -0,0 +1,22 @@ +CHECK_ID_check_extra72="" +CHECK_TITLE_check_extra72="" +CHECK_SCORED_check_extra72="" +CHECK_TYPE_check_extra72="" +CHECK_ALTERNATE_check_extra72="check_extra72" + +extra72(){ + # "Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID72" "$TITLE72" "NOT_SCORED" "EXTRA" + textNotice "Looking for EBS Snapshots in all regions... " + for regx in $REGIONS; do + LIST_OF_EBS_SNAPSHOTS=$($AWSCLI ec2 describe-snapshots $PROFILE_OPT --region $regx --owner-ids $ACCOUNT_NUM --output text --query 'Snapshots[*].{ID:SnapshotId}' --max-items $MAXITEMS | grep -v None 2> /dev/null) + for snapshot in $LIST_OF_EBS_SNAPSHOTS; do + SNAPSHOT_IS_PUBLIC=$($AWSCLI ec2 describe-snapshot-attribute $PROFILE_OPT --region $regx --output text --snapshot-id $snapshot --attribute createVolumePermission --query "CreateVolumePermissions[?Group=='all']") + if [[ $SNAPSHOT_IS_PUBLIC ]];then + textWarn "$regx: $snapshot is currently Public!" "$regx" + else + textOK "$regx: $snapshot is not Public" "$regx" + fi + done + done +} diff --git a/checks/check_extra720 b/checks/check_extra720 index e69de29bb2..975d6f92c0 100644 --- a/checks/check_extra720 +++ b/checks/check_extra720 @@ -0,0 +1,46 @@ +CHECK_ID_check_extra720="" +CHECK_TITLE_check_extra720="" +CHECK_SCORED_check_extra720="" +CHECK_TYPE_check_extra720="" +CHECK_ALTERNATE_check_extra720="check_extra720" + +extra720(){ + # "Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID720" "$TITLE720" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text) + if [[ $LIST_OF_FUNCTIONS ]]; then + for lambdafunction in $LIST_OF_FUNCTIONS;do + LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query trailList[?HomeRegion==\`$regx\`].Name --output text) + if [[ $LIST_OF_TRAILS ]]; then + for trail in $LIST_OF_TRAILS; do + FUNCTION_ENABLED_IN_TRAIL=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $regx --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") + if [[ $FUNCTION_ENABLED_IN_TRAIL ]]; then + textOK "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" + else + textWarn "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" + fi + done + # LIST_OF_MULTIREGION_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\`].Name" --output text) + # if [[ $LIST_OF_MULTIREGION_TRAILS ]]; then + # for trail in $LIST_OF_MULTIREGION_TRAILS; do + # REGION_OF_TRAIL=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\` && Name == \`$trail\` ].HomeRegion" --output text) + # FUNCTION_ENABLED_IN_THIS_REGION=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $REGION_OF_TRAIL --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") + # if [[ $FUNCTION_ENABLED_IN_THIS_REGION ]]; then + # textOK "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" + # else + # textWarn "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" + # fi + # done + # else + # textWarn "$regx: Lambda function $lambdafunction is not being recorded!" "$regx" + # fi + else + textWarn "$regx: Lambda function $lambdafunction is not being recorded no CloudTrail found!" "$regx" + fi + done + else + textNotice "$regx: No Lambda functions found" "$regx" + fi + done +} diff --git a/checks/check_extra721 b/checks/check_extra721 index e69de29bb2..2a5f5f4f1f 100644 --- a/checks/check_extra721 +++ b/checks/check_extra721 @@ -0,0 +1,26 @@ +CHECK_ID_check_extra721="" +CHECK_TITLE_check_extra721="" +CHECK_SCORED_check_extra721="" +CHECK_TYPE_check_extra721="" +CHECK_ALTERNATE_check_extra721="check_extra721" + +extra721(){ + # "Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID721" "$TITLE721" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + LIST_OF_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*].ClusterIdentifier' --output text) + if [[ $LIST_OF_REDSHIFT_CLUSTERS ]]; then + for redshiftcluster in $LIST_OF_REDSHIFT_CLUSTERS;do + REDSHIFT_LOG_ENABLED=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query LoggingEnabled --output text | grep True) + if [[ $REDSHIFT_LOG_ENABLED ]];then + REDSHIFT_LOG_ENABLED_BUCKET=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query BucketName --output text) + textOK "$regx: Redshift cluster $redshiftcluster has audit logging enabled to bucket $REDSHIFT_LOG_ENABLED_BUCKET" "$regx" + else + textWarn "$regx: Redshift cluster $redshiftcluster logging disabled!" "$regx" + fi + done + else + textNotice "$regx: No Redshift cluster configured" "$regx" + fi + done +} diff --git a/checks/check_extra722 b/checks/check_extra722 index e69de29bb2..bcd7ab4702 100644 --- a/checks/check_extra722 +++ b/checks/check_extra722 @@ -0,0 +1,33 @@ +CHECK_ID_check_extra722="" +CHECK_TITLE_check_extra722="" +CHECK_SCORED_check_extra722="" +CHECK_TYPE_check_extra722="" +CHECK_ALTERNATE_check_extra722="check_extra722" + +extra722(){ + # "Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID722" "$TITLE722" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + LIST_OF_API_GW=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query items[*].id --output text) + if [[ $LIST_OF_API_GW ]];then + for apigwid in $LIST_OF_API_GW;do + API_GW_NAME=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query "items[?id==\`$apigwid\`].name" --output text) + CHECK_STAGES_NAME=$($AWSCLI apigateway get-stages $PROFILE_OPT --region $regx --rest-api-id $apigwid --query "item[*].stageName" --output text) + if [[ $CHECK_STAGES_NAME ]];then + for stagname in $CHECK_STAGES_NAME;do + CHECK_STAGE_METHOD_LOGGING=$($AWSCLI apigateway get-stages $PROFILE_OPT --region $regx --rest-api-id $apigwid --query "item[?stageName == \`$stagname\` ].methodSettings" --output text|awk '{ print $1" log level "$6}') + if [[ $CHECK_STAGE_METHOD_LOGGING ]];then + textOK "$regx: API Gateway $API_GW_NAME has stage logging enabled for $CHECK_STAGE_METHOD_LOGGING" "$regx" + else + textWarn "$regx: API Gateway $API_GW_NAME logging disabled for stage $stagname!" "$regx" + fi + done + else + textWarn "$regx: No Stage name found for $API_GW_NAME" "$regx" + fi + done + else + textNotice "$regx: No API Gateway found" "$regx" + fi + done +} diff --git a/checks/check_extra723 b/checks/check_extra723 index e69de29bb2..470ce3ad75 100644 --- a/checks/check_extra723 +++ b/checks/check_extra723 @@ -0,0 +1,40 @@ +CHECK_ID_check_extra723="" +CHECK_TITLE_check_extra723="" +CHECK_SCORED_check_extra723="" +CHECK_TYPE_check_extra723="" +CHECK_ALTERNATE_check_extra723="check_extra723" + +extra723(){ + # "Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID723" "$TITLE723" "NOT_SCORED" "EXTRA" + for regx in $REGIONS; do + # RDS snapshots + LIST_OF_RDS_SNAPSHOTS=$($AWSCLI rds describe-db-snapshots $PROFILE_OPT --region $regx --query DBSnapshots[*].DBSnapshotIdentifier --output text) + if [[ $LIST_OF_RDS_SNAPSHOTS ]]; then + for rdssnapshot in $LIST_OF_RDS_SNAPSHOTS;do + SNAPSHOT_IS_PUBLIC=$($AWSCLI rds describe-db-snapshot-attributes $PROFILE_OPT --region $regx --db-snapshot-identifier $rdssnapshot --query DBSnapshotAttributesResult.DBSnapshotAttributes[*] --output text|grep ^ATTRIBUTEVALUES|cut -f2|grep all) + if [[ $SNAPSHOT_IS_PUBLIC ]];then + textWarn "$regx: RDS Snapshot $rdssnapshot is public!" "$regx" + else + textOK "$regx: RDS Snapshot $rdssnapshot is not shared" "$regx" + fi + done + else + textNotice "$regx: No RDS Snapshots found" "$regx" + fi + # RDS cluster snapshots + LIST_OF_RDS_CLUSTER_SNAPSHOTS=$($AWSCLI rds describe-db-cluster-snapshots $PROFILE_OPT --region $regx --query DBClusterSnapshots[*].DBClusterSnapshotIdentifier --output text) + if [[ $LIST_OF_RDS_CLUSTER_SNAPSHOTS ]]; then + for rdsclustersnapshot in $LIST_OF_RDS_CLUSTER_SNAPSHOTS;do + CLUSTER_SNAPSHOT_IS_PUBLIC=$($AWSCLI rds describe-db-cluster-snapshot-attributes $PROFILE_OPT --region $regx --db-cluster-snapshot-identifier $rdsclustersnapshot --query DBClusterSnapshotAttributesResult.DBClusterSnapshotAttributes[*] --output text|grep ^ATTRIBUTEVALUES|cut -f2|grep all) + if [[ $CLUSTER_SNAPSHOT_IS_PUBLIC ]];then + textWarn "$regx: RDS Cluster Snapshot $rdsclustersnapshot is public!" "$regx" + else + textOK "$regx: RDS Cluster Snapshot $rdsclustersnapshot is not shared" "$regx" + fi + done + else + textNotice "$regx: No RDS Cluster Snapshots found" "$regx" + fi + done +} diff --git a/checks/check_extra73 b/checks/check_extra73 index e69de29bb2..273d0813dd 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -0,0 +1,46 @@ +CHECK_ID_check_extra73="" +CHECK_TITLE_check_extra73="" +CHECK_SCORED_check_extra73="" +CHECK_TYPE_check_extra73="" +CHECK_ALTERNATE_check_extra73="check_extra73" + +extra73(){ + # "Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID73" "$TITLE73" "NOT_SCORED" "EXTRA" + textNotice "Looking for open S3 Buckets (ACLs and Policies) in all regions... " + ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' $PROFILE_OPT --region $REGION --output text) + for bucket in $ALL_BUCKETS_LIST; do + BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket $PROFILE_OPT --region $REGION --output text) + if [[ "None" == $BUCKET_LOCATION ]]; then + BUCKET_LOCATION="us-east-1" + fi + if [[ "EU" == $BUCKET_LOCATION ]]; then + BUCKET_LOCATION="eu-west-1" + fi + # check if AllUsers is in the ACL as Grantee + CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE) + CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL) + # check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only + CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE) + CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL) + # to prevent error NoSuchBucketPolicy first clean the output controlling stderr + TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX) + $AWSCLI s3api get-bucket-policy $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null + # check if the S3 policy has Principal as * + CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*) + if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then + if [[ $CHECK_BUCKET_ALLUSERS_ACL ]];then + textWarn "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" + fi + if [[ $CHECK_BUCKET_AUTHUSERS_ACL ]];then + textWarn "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" + fi + if [[ $CHECK_BUCKET_ALLUSERS_POLICY ]];then + textWarn "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" + fi + else + textOK "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" + fi + rm -fr $TEMP_POLICY_FILE + done +} diff --git a/checks/check_extra74 b/checks/check_extra74 index e69de29bb2..c1e527274a 100644 --- a/checks/check_extra74 +++ b/checks/check_extra74 @@ -0,0 +1,22 @@ +CHECK_ID_check_extra74="" +CHECK_TITLE_check_extra74="" +CHECK_SCORED_check_extra74="" +CHECK_TYPE_check_extra74="" +CHECK_ALTERNATE_check_extra74="check_extra74" + +extra74(){ + # "Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID74" "$TITLE74" "NOT_SCORED" "EXTRA" + textNotice "Looking for Security Groups in all regions... " + for regx in $REGIONS; do + LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS) + for SG_ID in $LIST_OF_SECURITYGROUPS; do + SG_NO_INGRESS_FILTER=$($AWSCLI ec2 describe-network-interfaces $PROFILE_OPT --region $regx --filters "Name=group-id,Values=$SG_ID" --query "length(NetworkInterfaces)" --output text) + if [[ $SG_NO_INGRESS_FILTER -ne 0 ]];then + textWarn "$regx: $SG_ID has not ingress filtering and it is being used!" "$regx" + else + textNotice "$regx: $SG_ID has not ingress filtering but it is no being used" "$regx" + fi + done + done +} diff --git a/checks/check_extra75 b/checks/check_extra75 index e69de29bb2..bc5a8a87e9 100644 --- a/checks/check_extra75 +++ b/checks/check_extra75 @@ -0,0 +1,22 @@ +CHECK_ID_check_extra75="" +CHECK_TITLE_check_extra75="" +CHECK_SCORED_check_extra75="" +CHECK_TYPE_check_extra75="" +CHECK_ALTERNATE_check_extra75="check_extra75" + +extra75(){ + # "Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID75" "$TITLE75" "NOT_SCORED" "EXTRA" + textNotice "Looking for Security Groups in all regions... " + for regx in $REGIONS; do + LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS) + for SG_ID in $LIST_OF_SECURITYGROUPS; do + SG_NOT_USED=$($AWSCLI ec2 describe-network-interfaces $PROFILE_OPT --region $regx --filters "Name=group-id,Values=$SG_ID" --query "length(NetworkInterfaces)" --output text) + if [[ $SG_NOT_USED -eq 0 ]];then + textWarn "$regx: $SG_ID is not being used!" "$regx" + else + textOK "$regx: $SG_ID is being used" "$regx" + fi + done + done +} diff --git a/checks/check_extra76 b/checks/check_extra76 index e69de29bb2..bd0ebafc42 100644 --- a/checks/check_extra76 +++ b/checks/check_extra76 @@ -0,0 +1,21 @@ +CHECK_ID_check_extra76="" +CHECK_TITLE_check_extra76="" +CHECK_SCORED_check_extra76="" +CHECK_TYPE_check_extra76="" +CHECK_ALTERNATE_check_extra76="check_extra76" + +extra76(){ + # "Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID76" "$TITLE76" "NOT_SCORED" "EXTRA" + textNotice "Looking for AMIs in all regions... " + for regx in $REGIONS; do + LIST_OF_PUBLIC_AMIS=$($AWSCLI ec2 describe-images --owners self $PROFILE_OPT --region $regx --filters "Name=is-public,Values=true" --query 'Images[*].{ID:ImageId}' --output text) + if [[ $LIST_OF_PUBLIC_AMIS ]];then + for ami in $LIST_OF_PUBLIC_AMIS; do + textWarn "$regx: $ami is currently Public!" "$regx" + done + else + textOK "$regx: No Public AMIs found" "$regx" + fi + done +} diff --git a/checks/check_extra77 b/checks/check_extra77 index e69de29bb2..f90c34ffa5 100644 --- a/checks/check_extra77 +++ b/checks/check_extra77 @@ -0,0 +1,26 @@ +CHECK_ID_check_extra77="" +CHECK_TITLE_check_extra77="" +CHECK_SCORED_check_extra77="" +CHECK_TYPE_check_extra77="" +CHECK_ALTERNATE_check_extra77="check_extra77" + +extra77(){ + # "Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID77" "$TITLE77" "NOT_SCORED" "EXTRA" + textNotice "Looking for ECR repos in all regions... " + for regx in $REGIONS; do + LIST_OF_ECR_REPOS=$($AWSCLI ecr describe-repositories $PROFILE_OPT --region $regx --query 'repositories[*].{Name:repositoryName}' --output text) + for ecr_repo in $LIST_OF_ECR_REPOS; do + TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-ecr-repo.policy.XXXXXXXXXX) + $AWSCLI ecr get-repository-policy --repository-name $ecr_repo $PROFILE_OPT --region $regx --output text > $TEMP_POLICY_FILE 2> /dev/null + # check if the policy has Principal as * + CHECK_ECR_REPO_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep \"Principal|grep \*) + if [[ $CHECK_ECR_REPO_ALLUSERS_POLICY ]];then + textWarn "$regx: $ecr_repo policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" + else + textOK "$regx: $ecr_repo is not open" "$regx" + fi + done + rm -fr $TEMP_POLICY_FILE + done +} diff --git a/checks/check_extra78 b/checks/check_extra78 index e69de29bb2..8baf0f59e4 100644 --- a/checks/check_extra78 +++ b/checks/check_extra78 @@ -0,0 +1,23 @@ +CHECK_ID_check_extra78="" +CHECK_TITLE_check_extra78="" +CHECK_SCORED_check_extra78="" +CHECK_TYPE_check_extra78="" +CHECK_ALTERNATE_check_extra78="check_extra78" + +extra78(){ + # "Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID78" "$TITLE78" "NOT_SCORED" "EXTRA" + textNotice "Looking for RDS instances in all regions... " + for regx in $REGIONS; do + LIST_OF_RDS_PUBLIC_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[?PubliclyAccessible==`true`].[DBInstanceIdentifier,Endpoint.Address]' --output text) + if [[ $LIST_OF_RDS_PUBLIC_INSTANCES ]];then + while read -r rds_instance;do + RDS_NAME=$(echo $rds_instance | awk '{ print $1; }') + RDS_DNSNAME=$(echo $rds_instance | awk '{ print $2; }') + textWarn "$regx: RDS instance: $RDS_NAME at $RDS_DNSNAME is set as Publicly Accessible!" "$regx" + done <<< "$LIST_OF_RDS_PUBLIC_INSTANCES" + else + textOK "$regx: no Publicly Accessible RDS instances found" "$regx" + fi + done +} diff --git a/checks/check_extra79 b/checks/check_extra79 index e69de29bb2..ff24bd2e1a 100644 --- a/checks/check_extra79 +++ b/checks/check_extra79 @@ -0,0 +1,26 @@ +CHECK_ID_check_extra79="" +CHECK_TITLE_check_extra79="" +CHECK_SCORED_check_extra79="" +CHECK_TYPE_check_extra79="" +CHECK_ALTERNATE_check_extra79="check_extra79" + +extra79(){ + # "Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" + textTitle "$ID79" "$TITLE79" "NOT_SCORED" "EXTRA" + textNotice "Looking for Elastic Load Balancers in all regions... " + for regx in $REGIONS; do + LIST_OF_PUBLIC_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text) + LIST_OF_PUBLIC_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text) + LIST_OF_ALL_ELBS=$( echo $LIST_OF_PUBLIC_ELBS; echo $LIST_OF_PUBLIC_ELBSV2) + LIST_OF_ALL_ELBS_PER_LINE=$( echo $LIST_OF_ALL_ELBS| xargs -n2 ) + if [[ $LIST_OF_ALL_ELBS ]];then + while read -r elb;do + ELB_NAME=$(echo $elb | awk '{ print $1; }') + ELB_DNSNAME=$(echo $elb | awk '{ print $2; }') + textWarn "$regx: ELB: $ELB_NAME at DNS: $ELB_DNSNAME is internet-facing!" "$regx" + done <<< "$LIST_OF_ALL_ELBS_PER_LINE" + else + textOK "$regx: no Internet Facing ELBs found" "$regx" + fi + done +} diff --git a/checks/check b/checks/check_sample similarity index 100% rename from checks/check rename to checks/check_sample diff --git a/checks/lista b/checks/lista index c31d8bc726..4640ead066 100644 --- a/checks/lista +++ b/checks/lista @@ -1,6 +1,3 @@ -check1 -check11 -check12 check13 check14 check15 @@ -23,7 +20,6 @@ check121 check122 check123 check124 -check2 check21 check22 check23 @@ -32,7 +28,6 @@ check25 check26 check27 check28 -check3 check31 check32 check33 @@ -48,32 +43,31 @@ check312 check313 check314 check315 -check4 check41 check42 check43 check44 check45 -check7 -check71 -check72 -check73 -check74 -check75 -check76 -check77 -check78 -check79 -check710 -check711 -check712 -check713 -check714 -check715 -check716 -check717 -check718 -check719 -check720 -check721 -check722 +check_extra71 +check_extra72 +check_extra73 +check_extra74 +check_extra75 +check_extra76 +check_extra77 +check_extra78 +check_extra79 +check_extra710 +check_extra711 +check_extra712 +check_extra713 +check_extra714 +check_extra715 +check_extra716 +check_extra717 +check_extra718 +check_extra719 +check_extra720 +check_extra721 +check_extra722 +check_extra723 diff --git a/groups/group1 b/groups/group1 deleted file mode 100644 index c82504e033..0000000000 --- a/groups/group1 +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -GROUP_ID[1]="group1" -GROUP_NUMBER[1]="1.0" -GROUP_TITLE[1]="Identity and Access Management ****************************************" -GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called -GROUP_CHECKS[1]="check11,check12" diff --git a/groups/group1_iam b/groups/group1_iam new file mode 100644 index 0000000000..73a4e6498f --- /dev/null +++ b/groups/group1_iam @@ -0,0 +1,5 @@ +GROUP_ID[1]="group1" +GROUP_NUMBER[1]="1.0" +GROUP_TITLE[1]="Identity and Access Management ****************************************" +GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called +GROUP_CHECKS[1]="check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check114,check115,check116,check117,check118,check119,check120,check121,check122,check123,check124" diff --git a/groups/group2 b/groups/group2 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/groups/group2_logging b/groups/group2_logging new file mode 100644 index 0000000000..c9225cacf0 --- /dev/null +++ b/groups/group2_logging @@ -0,0 +1,5 @@ +GROUP_ID[2]="group2" +GROUP_NUMBER[2]="2.0" +GROUP_TITLE[2]="Logging ***************************************************************" +GROUP_RUN_BY_DEFAULT[2]="Y" # run it when execute_all is called +GROUP_CHECKS[2]="check21,check22,check23,check24,check25,check26,check27,check28" diff --git a/groups/group3 b/groups/group3 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/groups/group3_monitoring b/groups/group3_monitoring new file mode 100644 index 0000000000..c74d4cf137 --- /dev/null +++ b/groups/group3_monitoring @@ -0,0 +1,5 @@ +GROUP_ID[3]="group3" +GROUP_NUMBER[3]="3.0" +GROUP_TITLE[3]="Monitoring ************************************************************" +GROUP_RUN_BY_DEFAULT[3]="Y" # run it when execute_all is called +GROUP_CHECKS[3]="check31,check32,check33,check34,check35,check36,check37,check38,check39,check310,check311,check312,check313,check314,check315" diff --git a/groups/group4 b/groups/group4 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/groups/group4_networking b/groups/group4_networking new file mode 100644 index 0000000000..b5be3299a8 --- /dev/null +++ b/groups/group4_networking @@ -0,0 +1,5 @@ +GROUP_ID[4]="group4" +GROUP_NUMBER[4]="4.0" +GROUP_TITLE[4]="Networking ************************************************************" +GROUP_RUN_BY_DEFAULT[4]="Y" # run it when execute_all is called +GROUP_CHECKS[4]="check41,check42,check43,check44,check45" diff --git a/groups/group5_cislevel1 b/groups/group5_cislevel1 new file mode 100644 index 0000000000..99656963ef --- /dev/null +++ b/groups/group5_cislevel1 @@ -0,0 +1,5 @@ +GROUP_ID[5]="level1" +GROUP_NUMBER[5]="5.0" +GROUP_TITLE[5]="CIS Level 1 **********************************************************" +GROUP_RUN_BY_DEFAULT[5]="N" # run it when execute_all is called +GROUP_CHECKS[5]="check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check115,check116,check117,check118,check119,check120,check122,check123,check124,check21,check23,check24,check25,check26,check31,check32,check33,check34,check35,check38,check312,check313,check314,check315,check41,check42" diff --git a/groups/group6_cislevel2 b/groups/group6_cislevel2 new file mode 100644 index 0000000000..698b926b2c --- /dev/null +++ b/groups/group6_cislevel2 @@ -0,0 +1,5 @@ +GROUP_ID[6]="level2" +GROUP_NUMBER[6]="6.0" +GROUP_TITLE[6]="CIS Level 2 **********************************************************" +GROUP_RUN_BY_DEFAULT[6]="N" # run it when execute_all is called +GROUP_CHECKS[6]="check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check114,check115,check116,check117,check118,check119,check120,check121,check122,check123,check124,check21,check22,check23,check24,check25,check26,check27,check28,check31,check32,check33,check34,check35,check36,check37,check38,check39,check310,check311,check312,check313,check314,check315,check41,check42,check43,check44,check45" diff --git a/groups/group7_extras b/groups/group7_extras new file mode 100644 index 0000000000..1cdd6ebee3 --- /dev/null +++ b/groups/group7_extras @@ -0,0 +1,5 @@ +GROUP_ID[7]="extras" +GROUP_NUMBER[7]="7.0" +GROUP_TITLE[7]="Extras ****************************************************************" +GROUP_RUN_BY_DEFAULT[7]="Y" # run it when execute_all is called +GROUP_CHECKS[7]="extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723" diff --git a/groups/group8_forensics b/groups/group8_forensics new file mode 100644 index 0000000000..c199de7092 --- /dev/null +++ b/groups/group8_forensics @@ -0,0 +1,5 @@ +GROUP_ID[8]="forensics-ready" +GROUP_NUMBER[8]="8.0" +GROUP_TITLE[8]="Forensics Readiness ***************************************************" +GROUP_RUN_BY_DEFAULT[8]="N" # run it when execute_all is called +GROUP_CHECKS[8]="check21,check22,check23,check24,check25,check26,check27,check43,extra712,extra713,extra714,extra715,extra717,extra718,extra719,extra720,extra721,extra722" diff --git a/groups/groupN_sample b/groups/groupN_sample new file mode 100644 index 0000000000..27678c86f7 --- /dev/null +++ b/groups/groupN_sample @@ -0,0 +1,5 @@ +GROUP_ID[9]="my-custom-group" +GROUP_NUMBER[9]="9.0" +GROUP_TITLE[9]="My Custom Group **********************************************" +GROUP_RUN_BY_DEFAULT[9]="N" # run it when execute_all is called +GROUP_CHECKS[9]="checkNN,checkMM" diff --git a/groups/group_cislevel1 b/groups/group_cislevel1 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/groups/group_cislevel2 b/groups/group_cislevel2 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/groups/group_extras b/groups/group_extras deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/groups/group_forensics b/groups/group_forensics deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/include/banner b/include/banner index 19c1638682..2dcfbc9916 100644 --- a/include/banner +++ b/include/banner @@ -3,8 +3,8 @@ prowlerBanner() { echo -e " _ __ _ __ _____ _| | ___ _ __" echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|" echo -e " | |_) | | | (_) \ V V /| | __/ |" - echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|" - echo -e " |_|$NORMAL$BLUE CIS based AWS Account Hardening Tool$NORMAL\n" + echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|v2.0" + echo -e " |_|$NORMAL$BLUE the handy cloud security tool$NORMAL\n" echo -e "$YELLOW Date: $(date)" } diff --git a/include/colors b/include/colors index 31fc2cd918..cd738b86bc 100644 --- a/include/colors +++ b/include/colors @@ -53,6 +53,6 @@ fi printColorsCode(){ if [[ $MONOCHROME -eq 0 ]]; then - echo -e "\n$NORMAL Colors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL" + echo -e "\n$NORMAL Colors code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL" fi } diff --git a/lll b/lll new file mode 100644 index 0000000000..66f5ad2d26 --- /dev/null +++ b/lll @@ -0,0 +1,2 @@ +check11 +check12 diff --git a/prowler2 b/prowler2 index cbd9024117..082c293515 100755 --- a/prowler2 +++ b/prowler2 @@ -97,7 +97,7 @@ while getopts ":hlkp:r:c:f:m:M:enb" OPTION; do NUMERAL=1 ;; b ) - NOBANNER="true" + BANNER=1 ;; e ) EXTRAS=1 @@ -136,18 +136,19 @@ REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ --region $REGION \ --region-names $FILTERREGION) -callCheck(){ - if [[ $CHECKNUMBER ]];then - case "$CHECKNUMBER" in - check11|check101 ) execute_check check11;; - check12|check102 ) execute_check check12;; - * ) - textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n"; - esac - cleanTemp - exit $EXITCODE - fi -} + callCheck(){ + if [[ $CHECKNUMBER ]];then + execute_check $CHECKNUMBER + # case "$CHECKNUMBER" in + # check11|check101 ) execute_check check11;; + # check12|check102 ) execute_check check12;; + # * ) + # textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n"; + # esac + cleanTemp + exit $EXITCODE + fi + } # List only check tittles if [[ $PRINTCHECKSONLY == "1" ]]; then @@ -168,9 +169,14 @@ for checks in $(ls checks/check*); do done # Function to show the title of the check +# using this way instead of arrays to keep bash3 (osx) and bash4(linux) compatibility show_check_title() { # This would just call textTitle - textTitle "${CHECK_ID[$1]}" "${CHECK_TITLE[$1]}" "${CHECK_SCORED[$1]}" "${CHECK_TYPE[$1]}" + local check_id=CHECK_ID_$1 + local check_title=CHECK_TITLE_$1 + local check_scored=CHECK_SCORED_$1 + local check_type=CHECK_TYPE_$1 + textTitle "${!check_id}" "${!check_title}" "${!check_scored}" "${!check_type}" } # Function to show the title of a group, by numeric id @@ -185,12 +191,22 @@ show_group_title() { execute_check() { # See if this is an alternate name for a check # for example, we might have been passed 1.01 which is another name for 1.1 - if [ ${CHECK_ALTERNATE[$1]} ];then - show_check_title ${CHECK_ALTERNATE[$1]} - ${CHECK_ALTERNATE[$1]} + local alternate_name_var=CHECK_ALTERNATE_$1 + local alternate_name=${!alternate_name_var} + + if [ ${alternate_name} ];then + show_check_title ${alternate_name} + ${alternate_name} else - show_check_title $1 - $1 + # Check to see if this is a real check + local check_id_var=CHECK_ID_$1 + local check_id=${!check_id_var} + if [ ${check_id} ]; then + show_check_title $1 + $1 + else + textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n"; + fi fi } @@ -199,8 +215,8 @@ execute_group() { show_group_title $1 # run the checks in the group IFS=',' read -ra CHECKS <<< ${GROUP_CHECKS[$1]} - for i in "${CHECKS[@]}"; do - execute_check $i + for i in ${CHECKS[@]}; do + execute_check $i done } @@ -235,8 +251,7 @@ show_all_titles() { } ### All functions defined above ... run the workflow - -if [[ $MODE != "csv" || $NOBANNER != "true" ]]; then +if [[ $MODE != "csv" ]]; then prowlerBanner printColorsCode fi From da0f26694418b1d9fae2c2b76d08a20a8ddabed6 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Fri, 23 Mar 2018 19:26:10 -0400 Subject: [PATCH 07/41] first semi functional v2 --- checks/check11 | 1 - checks/check110 | 9 +++---- checks/check111 | 9 +++---- checks/check112 | 11 ++++---- checks/check113 | 9 +++---- checks/check114 | 9 +++---- checks/check115 | 9 +++---- checks/check116 | 9 +++---- checks/check117 | 9 +++---- checks/check118 | 9 +++---- checks/check119 | 9 +++---- checks/check12 | 1 - checks/check120 | 9 +++---- checks/check121 | 9 +++---- checks/check122 | 9 +++---- checks/check123 | 11 ++++---- checks/check124 | 9 +++---- checks/check13 | 14 +++++----- checks/check14 | 11 ++++---- checks/check15 | 11 ++++---- checks/check16 | 9 +++---- checks/check17 | 11 ++++---- checks/check18 | 11 ++++---- checks/check19 | 11 ++++---- checks/check21 | 11 ++++---- checks/check22 | 11 ++++---- checks/check23 | 11 ++++---- checks/check24 | 11 ++++---- checks/check25 | 11 ++++---- checks/check26 | 11 ++++---- checks/check27 | 11 ++++---- checks/check28 | 11 ++++---- checks/check31 | 11 ++++---- checks/check310 | 11 ++++---- checks/check311 | 11 ++++---- checks/check312 | 11 ++++---- checks/check313 | 11 ++++---- checks/check314 | 11 ++++---- checks/check315 | 11 ++++---- checks/check32 | 11 ++++---- checks/check33 | 11 ++++---- checks/check34 | 11 ++++---- checks/check35 | 11 ++++---- checks/check36 | 11 ++++---- checks/check37 | 11 ++++---- checks/check38 | 11 ++++---- checks/check39 | 11 ++++---- checks/check41 | 11 ++++---- checks/check42 | 11 ++++---- checks/check43 | 11 ++++---- checks/check44 | 11 ++++---- checks/check45 | 11 ++++---- checks/check_extra71 | 15 +++++------ checks/check_extra710 | 12 ++++----- checks/check_extra711 | 12 ++++----- checks/check_extra712 | 12 ++++----- checks/check_extra713 | 12 ++++----- checks/check_extra714 | 12 ++++----- checks/check_extra715 | 13 +++++----- checks/check_extra716 | 12 ++++----- checks/check_extra717 | 12 ++++----- checks/check_extra718 | 12 ++++----- checks/check_extra719 | 12 ++++----- checks/check_extra72 | 13 +++++----- checks/check_extra720 | 12 ++++----- checks/check_extra721 | 12 ++++----- checks/check_extra722 | 12 ++++----- checks/check_extra723 | 12 ++++----- checks/check_extra73 | 13 +++++----- checks/check_extra74 | 13 +++++----- checks/check_extra75 | 13 +++++----- checks/check_extra76 | 13 +++++----- checks/check_extra77 | 13 +++++----- checks/check_extra78 | 13 +++++----- checks/check_extra79 | 13 +++++----- groups/group0_init | 6 +++++ groups/group1_iam | 10 +++---- groups/group2_logging | 10 +++---- groups/group3_monitoring | 10 +++---- groups/group5_cislevel1 | 10 +++---- groups/group6_cislevel2 | 10 +++---- groups/group7_extras | 10 +++---- groups/group8_forensics | 10 +++---- groups/groupN_sample | 10 +++---- lll | 2 -- prowler2 | 56 +++++++++++++++------------------------- 86 files changed, 451 insertions(+), 508 deletions(-) create mode 100644 groups/group0_init delete mode 100644 lll diff --git a/checks/check11 b/checks/check11 index deee3ed521..07ea5c2c82 100644 --- a/checks/check11 +++ b/checks/check11 @@ -1,7 +1,6 @@ CHECK_ID_check11="1.1,1.01" CHECK_TITLE_check11="Avoid the use of the root account (Scored)" CHECK_SCORED_check11="SCORED" -CHECK_TYPE_check11="LEVEL1" CHECK_ALTERNATE_check101="check11" check11(){ diff --git a/checks/check110 b/checks/check110 index 3de5513a25..b016c23bcf 100644 --- a/checks/check110 +++ b/checks/check110 @@ -1,9 +1,8 @@ -CHECK_ID_check110="" -CHECK_TITLE_check110="" -CHECK_SCORED_check110="" -CHECK_TYPE_check110="" +CHECK_ID_check110="1.10" +CHECK_TITLE_check110="Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" +CHECK_SCORED_check110="SCORED" CHECK_ALTERNATE_check110="check110" - + check110(){ # "Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" COMMAND110=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' --output text 2> /dev/null) diff --git a/checks/check111 b/checks/check111 index 8348e4b4be..b78f2adcad 100644 --- a/checks/check111 +++ b/checks/check111 @@ -1,9 +1,8 @@ -CHECK_ID_check111="" -CHECK_TITLE_check111="" -CHECK_SCORED_check111="" -CHECK_TYPE_check111="" +CHECK_ID_check111="1.11" +CHECK_TITLE_check111="Ensure IAM password policy expires passwords within 90 days or less (Scored)" +CHECK_SCORED_check111="SCORED" CHECK_ALTERNATE_check111="check111" - + check111(){ # "Ensure IAM password policy expires passwords within 90 days or less (Scored)" COMMAND111=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g' 2> /dev/null) diff --git a/checks/check112 b/checks/check112 index c1e85c3f03..dc2682f9e4 100644 --- a/checks/check112 +++ b/checks/check112 @@ -1,9 +1,8 @@ -CHECK_ID_check112="" -CHECK_TITLE_check112="" -CHECK_SCORED_check112="" -CHECK_TYPE_check112="" -CHECK_ALTERNATE_check112="check112" - +CHECK_ID_check112="1.12" +CHECK_TITLE_check112="Ensure no root account access key exists (Scored)" +CHECK_SCORED_check112="SCORED" +CHECK_ALTERNATE_check112="check112" + check112(){ # "Ensure no root account access key exists (Scored)" # ensure the access_key_1_active and access_key_2_active fields are set to FALSE. diff --git a/checks/check113 b/checks/check113 index 839857858d..e6992d5505 100644 --- a/checks/check113 +++ b/checks/check113 @@ -1,9 +1,8 @@ -CHECK_ID_check113="" -CHECK_TITLE_check113="" -CHECK_SCORED_check113="" -CHECK_TYPE_check113="" +CHECK_ID_check113="1.13" +CHECK_TITLE_check113="Ensure MFA is enabled for the root account (Scored)" +CHECK_SCORED_check113="SCORED" CHECK_ALTERNATE_check113="check113" - + check113(){ # "Ensure MFA is enabled for the root account (Scored)" COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') diff --git a/checks/check114 b/checks/check114 index 8fae9dcbfb..cf1d7b0643 100644 --- a/checks/check114 +++ b/checks/check114 @@ -1,9 +1,8 @@ -CHECK_ID_check114="" -CHECK_TITLE_check114="" -CHECK_SCORED_check114="" -CHECK_TYPE_check114="" +CHECK_ID_check114="1.14" +CHECK_TITLE_check114="Ensure hardware MFA is enabled for the root account (Scored)" +CHECK_SCORED_check114="SCORED" CHECK_ALTERNATE_check114="check114" - + check114(){ # "Ensure hardware MFA is enabled for the root account (Scored)" COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') diff --git a/checks/check115 b/checks/check115 index 9512805771..13b0bc8978 100644 --- a/checks/check115 +++ b/checks/check115 @@ -1,9 +1,8 @@ -CHECK_ID_check115="" -CHECK_TITLE_check115="" -CHECK_SCORED_check115="" -CHECK_TYPE_check115="" +CHECK_ID_check115="1.15" +CHECK_TITLE_check115="Ensure security questions are registered in the AWS account (Not Scored)" +CHECK_SCORED_check115="SCORED" CHECK_ALTERNATE_check115="check115" - + check115(){ # "Ensure security questions are registered in the AWS account (Not Scored)" textTitle "$ID115" "$TITLE115" "NOT_SCORED" "LEVEL2" diff --git a/checks/check116 b/checks/check116 index 5df186fc6f..c6afa34bea 100644 --- a/checks/check116 +++ b/checks/check116 @@ -1,9 +1,8 @@ -CHECK_ID_check116="" -CHECK_TITLE_check116="" -CHECK_SCORED_check116="" -CHECK_TYPE_check116="" +CHECK_ID_check116="1.16" +CHECK_TITLE_check116="Ensure IAM policies are attached only to groups or roles (Scored)" +CHECK_SCORED_check116="SCORED" CHECK_ALTERNATE_check116="check116" - + check116(){ # "Ensure IAM policies are attached only to groups or roles (Scored)" textTitle "$ID116" "$TITLE116" "SCORED" "LEVEL1" diff --git a/checks/check117 b/checks/check117 index 4badfe9af9..e37c9f6b02 100644 --- a/checks/check117 +++ b/checks/check117 @@ -1,9 +1,8 @@ -CHECK_ID_check117="" -CHECK_TITLE_check117="" -CHECK_SCORED_check117="" -CHECK_TYPE_check117="" +CHECK_ID_check117="1.17" +CHECK_TITLE_check117="Enable detailed billing (Scored)" +CHECK_SCORED_check117="SCORED" CHECK_ALTERNATE_check117="check117" - + check117(){ # "Enable detailed billing (Scored)" # No command available diff --git a/checks/check118 b/checks/check118 index d81bb6adc3..a3d0537a3c 100644 --- a/checks/check118 +++ b/checks/check118 @@ -1,9 +1,8 @@ -CHECK_ID_check118="" -CHECK_TITLE_check118="" -CHECK_SCORED_check118="" -CHECK_TYPE_check118="" +CHECK_ID_check118="1.18" +CHECK_TITLE_check118="Ensure IAM Master and IAM Manager roles are active (Scored)" +CHECK_SCORED_check118="SCORED" CHECK_ALTERNATE_check118="check118" - + check118(){ # "Ensure IAM Master and IAM Manager roles are active (Scored)" textTitle "$ID118" "$TITLE118" "SCORED" "LEVEL1" diff --git a/checks/check119 b/checks/check119 index c1095b3df2..b4fe37d585 100644 --- a/checks/check119 +++ b/checks/check119 @@ -1,9 +1,8 @@ -CHECK_ID_check119="" -CHECK_TITLE_check119="" -CHECK_SCORED_check119="" -CHECK_TYPE_check119="" +CHECK_ID_check119="1.19" +CHECK_TITLE_check119="Maintain current contact details (Scored)" +CHECK_SCORED_check119="SCORED" CHECK_ALTERNATE_check119="check119" - + check119(){ # "Maintain current contact details (Scored)" # No command available diff --git a/checks/check12 b/checks/check12 index 638e29d94c..62f803dfb5 100644 --- a/checks/check12 +++ b/checks/check12 @@ -1,7 +1,6 @@ CHECK_ID_check12="1.2,1.02" CHECK_TITLE_check12="Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" CHECK_SCORED_check12="SCORED" -CHECK_TYPE_check12="LEVEL1" CHECK_ALTERNATE_check102="check12" check12(){ diff --git a/checks/check120 b/checks/check120 index d319f64d33..20de93c38e 100644 --- a/checks/check120 +++ b/checks/check120 @@ -1,9 +1,8 @@ -CHECK_ID_check120="" -CHECK_TITLE_check120="" -CHECK_SCORED_check120="" -CHECK_TYPE_check120="" +CHECK_ID_check120="1.20" +CHECK_TITLE_check120="Ensure security contact information is registered (Scored)" +CHECK_SCORED_check120="SCORED" CHECK_ALTERNATE_check120="check120" - + check120(){ # "Ensure security contact information is registered (Scored)" # No command available diff --git a/checks/check121 b/checks/check121 index fc0f048f00..d593576be3 100644 --- a/checks/check121 +++ b/checks/check121 @@ -1,9 +1,8 @@ -CHECK_ID_check121="" -CHECK_TITLE_check121="" -CHECK_SCORED_check121="" -CHECK_TYPE_check121="" +CHECK_ID_check121="1.21" +CHECK_TITLE_check121="Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" +CHECK_SCORED_check121="NOT_SCORED" CHECK_ALTERNATE_check121="check121" - + check121(){ # "Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" textTitle "$ID121" "$TITLE121" "NOT_SCORED" "LEVEL2" diff --git a/checks/check122 b/checks/check122 index aa5117c493..0cea82df30 100644 --- a/checks/check122 +++ b/checks/check122 @@ -1,9 +1,8 @@ -CHECK_ID_check122="" -CHECK_TITLE_check122="" -CHECK_SCORED_check122="" -CHECK_TYPE_check122="" +CHECK_ID_check122="1.22" +CHECK_TITLE_check122="Ensure a support role has been created to manage incidents with AWS Support (Scored)" +CHECK_SCORED_check122="SCORED" CHECK_ALTERNATE_check122="check122" - + check122(){ # "Ensure a support role has been created to manage incidents with AWS Support (Scored)" textTitle "$ID122" "$TITLE122" "SCORED" "LEVEL1" diff --git a/checks/check123 b/checks/check123 index b46248964d..6cdda330d0 100644 --- a/checks/check123 +++ b/checks/check123 @@ -1,9 +1,8 @@ -CHECK_ID_check123="" -CHECK_TITLE_check123="" -CHECK_SCORED_check123="" -CHECK_TYPE_check123="" -CHECK_ALTERNATE_check123="check123" - +CHECK_ID_check123="1.23" +CHECK_TITLE_check123="Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" +CHECK_SCORED_check123="NOT_SCORED" +CHECK_ALTERNATE_check123="check123" + check123(){ # "Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" textTitle "$ID123" "$TITLE123" "NOT_SCORED" "LEVEL1" diff --git a/checks/check124 b/checks/check124 index d5635f20dc..95e1eaf006 100644 --- a/checks/check124 +++ b/checks/check124 @@ -1,9 +1,8 @@ -CHECK_ID_check124="" -CHECK_TITLE_check124="" -CHECK_SCORED_check124="" -CHECK_TYPE_check124="" +CHECK_ID_check124="1.24" +CHECK_TITLE_check124="Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" +CHECK_SCORED_check124="SCORED" CHECK_ALTERNATE_check124="check124" - + check124(){ # "Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" textTitle "$ID124" "$TITLE124" "SCORED" "LEVEL1" diff --git a/checks/check13 b/checks/check13 index a981b900c0..154dad3bf2 100644 --- a/checks/check13 +++ b/checks/check13 @@ -1,9 +1,8 @@ -CHECK_ID_check13="" -CHECK_TITLE_check13="" -CHECK_SCORED_check13="" -CHECK_TYPE_check13="" -CHECK_ALTERNATE_check13="check13" - +CHECK_ID_check13="1.3,1.03" +CHECK_TITLE_check13="Ensure credentials unused for 90 days or greater are disabled (Scored)" +CHECK_SCORED_check13="SCORED" +CHECK_ALTERNATE_check103="check13" + check13(){ # "Ensure credentials unused for 90 days or greater are disabled (Scored)" textTitle "$ID13" "$TITLE13" "SCORED" "LEVEL1" @@ -11,8 +10,7 @@ check13(){ if [[ $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED ]]; then COMMAND13=$( for i in $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED; do - cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$5 }' |grep $i| awk '{ print $1 }'|tr ' -' ' '; + cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$5 }' |grep $i| 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_OPT --region $REGION) diff --git a/checks/check14 b/checks/check14 index 129b69f713..0a1d4a02a9 100644 --- a/checks/check14 +++ b/checks/check14 @@ -1,9 +1,8 @@ -CHECK_ID_check14="" -CHECK_TITLE_check14="" -CHECK_SCORED_check14="" -CHECK_TYPE_check14="" -CHECK_ALTERNATE_check14="check14" - +CHECK_ID_check14="1.4,1.04" +CHECK_TITLE_check14="Ensure access keys are rotated every 90 days or less (Scored)" +CHECK_SCORED_check14="SCORED" +CHECK_ALTERNATE_check104="check14" + check14(){ # "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 }') diff --git a/checks/check15 b/checks/check15 index 9ef12a6bfc..0cb0b2359d 100644 --- a/checks/check15 +++ b/checks/check15 @@ -1,9 +1,8 @@ -CHECK_ID_check15="" -CHECK_TITLE_check15="" -CHECK_SCORED_check15="" -CHECK_TYPE_check15="" -CHECK_ALTERNATE_check15="check15" - +CHECK_ID_check15="1.5,1.05" +CHECK_TITLE_check15="Ensure IAM password policy requires at least one uppercase letter (Scored)" +CHECK_SCORED_check15="SCORED" +CHECK_ALTERNATE_check105="check15" + check15(){ # "Ensure IAM password policy requires at least one uppercase letter (Scored)" COMMAND15=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireUppercaseCharacters' 2> /dev/null) # must be true diff --git a/checks/check16 b/checks/check16 index 5562a6ea3d..255d4780f8 100644 --- a/checks/check16 +++ b/checks/check16 @@ -1,8 +1,7 @@ -CHECK_ID_check16="" -CHECK_TITLE_check16="" -CHECK_SCORED_check16="" -CHECK_TYPE_check16="" -CHECK_ALTERNATE_check16="check16" +CHECK_ID_check16="1.6,1.06" +CHECK_TITLE_check16="Ensure IAM password policy require at least one lowercase letter (Scored)" +CHECK_SCORED_check16="SCORED" +CHECK_ALTERNATE_check106="check16" check16(){ # "Ensure IAM password policy require at least one lowercase letter (Scored)" diff --git a/checks/check17 b/checks/check17 index 97162b446a..c031f18745 100644 --- a/checks/check17 +++ b/checks/check17 @@ -1,9 +1,8 @@ -CHECK_ID_check17="" -CHECK_TITLE_check17="" -CHECK_SCORED_check17="" -CHECK_TYPE_check17="" -CHECK_ALTERNATE_check17="check17" - +CHECK_ID_check17="1.7,1.07" +CHECK_TITLE_check17="Ensure IAM password policy require at least one symbol (Scored)" +CHECK_SCORED_check17="SCORED" +CHECK_ALTERNATE_check107="check17" + check17(){ # "Ensure IAM password policy require at least one symbol (Scored)" COMMAND17=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireSymbols' 2> /dev/null) # must be true diff --git a/checks/check18 b/checks/check18 index 48bf56e0f9..f2acba9f61 100644 --- a/checks/check18 +++ b/checks/check18 @@ -1,9 +1,8 @@ -CHECK_ID_check18="" -CHECK_TITLE_check18="" -CHECK_SCORED_check18="" -CHECK_TYPE_check18="" -CHECK_ALTERNATE_check18="check18" - +CHECK_ID_check18="1.8,1.08" +CHECK_TITLE_check18="Ensure IAM password policy require at least one number (Scored)" +CHECK_SCORED_check18="SCORED" +CHECK_ALTERNATE_check18="check18" + check18(){ # "Ensure IAM password policy require at least one number (Scored)" COMMAND18=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireNumbers' 2> /dev/null) # must be true diff --git a/checks/check19 b/checks/check19 index f4e5647110..1c20e6d809 100644 --- a/checks/check19 +++ b/checks/check19 @@ -1,9 +1,8 @@ -CHECK_ID_check19="" -CHECK_TITLE_check19="" -CHECK_SCORED_check19="" -CHECK_TYPE_check19="" -CHECK_ALTERNATE_check19="check19" - +CHECK_ID_check19="1.9,1.09" +CHECK_TITLE_check19="Ensure IAM password policy requires minimum length of 14 or greater (Scored)" +CHECK_SCORED_check19="SCORED" +CHECK_ALTERNATE_check109="check19" + check19(){ # "Ensure IAM password policy requires minimum length of 14 or greater (Scored)" COMMAND19=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.MinimumPasswordLength' 2> /dev/null) diff --git a/checks/check21 b/checks/check21 index 627b738b35..58056d0b5e 100644 --- a/checks/check21 +++ b/checks/check21 @@ -1,9 +1,8 @@ -CHECK_ID_check21="" -CHECK_TITLE_check21="" -CHECK_SCORED_check21="" -CHECK_TYPE_check21="" -CHECK_ALTERNATE_check21="check21" - +CHECK_ID_check21="2.1,2.01" +CHECK_TITLE_check21="Ensure CloudTrail is enabled in all regions (Scored)" +CHECK_SCORED_check21="SCORED" +CHECK_ALTERNATE_check201="check21" + check21(){ # "Ensure CloudTrail is enabled in all regions (Scored)" textTitle "$ID21" "$TITLE21" "SCORED" "LEVEL1" diff --git a/checks/check22 b/checks/check22 index 55a9c9b6c9..36c1514f92 100644 --- a/checks/check22 +++ b/checks/check22 @@ -1,9 +1,8 @@ -CHECK_ID_check22="" -CHECK_TITLE_check22="" -CHECK_SCORED_check22="" -CHECK_TYPE_check22="" -CHECK_ALTERNATE_check22="check22" - +CHECK_ID_check22="2.2,2.02" +CHECK_TITLE_check22="Ensure CloudTrail log file validation is enabled (Scored)" +CHECK_SCORED_check22="SCORED" +CHECK_ALTERNATE_check202="check22" + check22(){ # "Ensure CloudTrail log file validation is enabled (Scored)" textTitle "$ID22" "$TITLE22" "SCORED" "LEVEL2" diff --git a/checks/check23 b/checks/check23 index b06dbc0555..4306145e2c 100644 --- a/checks/check23 +++ b/checks/check23 @@ -1,9 +1,8 @@ -CHECK_ID_check23="" -CHECK_TITLE_check23="" -CHECK_SCORED_check23="" -CHECK_TYPE_check23="" -CHECK_ALTERNATE_check23="check23" - +CHECK_ID_check23="2.3,2.03" +CHECK_TITLE_check23="Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" +CHECK_SCORED_check23="SCORED" +CHECK_ALTERNATE_check203="check23" + check23(){ # "Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" textTitle "$ID23" "$TITLE23" "SCORED" "LEVEL1" diff --git a/checks/check24 b/checks/check24 index 95f22f792c..690f572bef 100644 --- a/checks/check24 +++ b/checks/check24 @@ -1,9 +1,8 @@ -CHECK_ID_check24="" -CHECK_TITLE_check24="" -CHECK_SCORED_check24="" -CHECK_TYPE_check24="" -CHECK_ALTERNATE_check24="check24" - +CHECK_ID_check24="2.4,2.04" +CHECK_TITLE_check24="Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" +CHECK_SCORED_check24="SCORED" +CHECK_ALTERNATE_check204="check24" + check24(){ # "Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" textTitle "$ID24" "$TITLE24" "SCORED" "LEVEL1" diff --git a/checks/check25 b/checks/check25 index b6c9cff5d8..b97adefcab 100644 --- a/checks/check25 +++ b/checks/check25 @@ -1,9 +1,8 @@ -CHECK_ID_check25="" -CHECK_TITLE_check25="" -CHECK_SCORED_check25="" -CHECK_TYPE_check25="" -CHECK_ALTERNATE_check25="check25" - +CHECK_ID_check25="2.5,2.05" +CHECK_TITLE_check25="Ensure AWS Config is enabled in all regions (Scored)" +CHECK_SCORED_check25="SCORED" +CHECK_ALTERNATE_check205="check25" + check25(){ # "Ensure AWS Config is enabled in all regions (Scored)" textTitle "$ID25" "$TITLE25" "SCORED" "LEVEL1" diff --git a/checks/check26 b/checks/check26 index 7158da6174..33f68e900e 100644 --- a/checks/check26 +++ b/checks/check26 @@ -1,9 +1,8 @@ -CHECK_ID_check26="" -CHECK_TITLE_check26="" -CHECK_SCORED_check26="" -CHECK_TYPE_check26="" -CHECK_ALTERNATE_check26="check26" - +CHECK_ID_check26="2.6,2.06" +CHECK_TITLE_check26="Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" +CHECK_SCORED_check26="SCORED" +CHECK_ALTERNATE_check206="check26" + check26(){ # "Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" textTitle "$ID26" "$TITLE26" "SCORED" "LEVEL1" diff --git a/checks/check27 b/checks/check27 index 0106ad70dc..f0feff85e3 100644 --- a/checks/check27 +++ b/checks/check27 @@ -1,9 +1,8 @@ -CHECK_ID_check27="" -CHECK_TITLE_check27="" -CHECK_SCORED_check27="" -CHECK_TYPE_check27="" -CHECK_ALTERNATE_check27="check27" - +CHECK_ID_check27="2.7,2.07" +CHECK_TITLE_check27="Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" +CHECK_SCORED_check27="SCORED" +CHECK_ALTERNATE_check207="check27" + check27(){ # "Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" textTitle "$ID27" "$TITLE27" "SCORED" "LEVEL2" diff --git a/checks/check28 b/checks/check28 index 56cd89a2e5..fa0b0a4d71 100644 --- a/checks/check28 +++ b/checks/check28 @@ -1,9 +1,8 @@ -CHECK_ID_check28="" -CHECK_TITLE_check28="" -CHECK_SCORED_check28="" -CHECK_TYPE_check28="" -CHECK_ALTERNATE_check28="check28" - +CHECK_ID_check28="2.8,2.08" +CHECK_TITLE_check28="Ensure rotation for customer created CMKs is enabled (Scored)" +CHECK_SCORED_check28="SCORED" +CHECK_ALTERNATE_check208="check28" + check28(){ # "Ensure rotation for customer created CMKs is enabled (Scored)" textTitle "$ID28" "$TITLE28" "SCORED" "LEVEL2" diff --git a/checks/check31 b/checks/check31 index 59ae384b0b..4ca73f4079 100644 --- a/checks/check31 +++ b/checks/check31 @@ -1,9 +1,8 @@ -CHECK_ID_check31="" -CHECK_TITLE_check31="" -CHECK_SCORED_check31="" -CHECK_TYPE_check31="" -CHECK_ALTERNATE_check31="check31" - +CHECK_ID_check31="3.1,3.01" +CHECK_TITLE_check31="Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" +CHECK_SCORED_check31="SCORED" +CHECK_ALTERNATE_check301="check31" + check31(){ # "Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" textTitle "$ID31" "$TITLE31" "SCORED" "LEVEL1" diff --git a/checks/check310 b/checks/check310 index 9860acdcf4..a28a76a304 100644 --- a/checks/check310 +++ b/checks/check310 @@ -1,9 +1,8 @@ -CHECK_ID_check310="" -CHECK_TITLE_check310="" -CHECK_SCORED_check310="" -CHECK_TYPE_check310="" -CHECK_ALTERNATE_check310="check310" - +CHECK_ID_check310="3.10" +CHECK_TITLE_check310="Ensure a log metric filter and alarm exist for security group changes (Scored)" +CHECK_SCORED_check310="SCORED" +CHECK_ALTERNATE_check310="check310" + check310(){ # "Ensure a log metric filter and alarm exist for security group changes (Scored)" textTitle "$ID310" "$TITLE310" "SCORED" "LEVEL2" diff --git a/checks/check311 b/checks/check311 index d097c8b4a6..c2e26c8806 100644 --- a/checks/check311 +++ b/checks/check311 @@ -1,9 +1,8 @@ -CHECK_ID_check311="" -CHECK_TITLE_check311="" -CHECK_SCORED_check311="" -CHECK_TYPE_check311="" -CHECK_ALTERNATE_check311="check311" - +CHECK_ID_check311="3.11" +CHECK_TITLE_check311="Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" +CHECK_SCORED_check311="SCORED" +CHECK_ALTERNATE_check311="check311" + check311(){ # "Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" textTitle "$ID311" "$TITLE311" "SCORED" "LEVEL2" diff --git a/checks/check312 b/checks/check312 index 70a0aa9f29..ecfd969a14 100644 --- a/checks/check312 +++ b/checks/check312 @@ -1,9 +1,8 @@ -CHECK_ID_check312="" -CHECK_TITLE_check312="" -CHECK_SCORED_check312="" -CHECK_TYPE_check312="" -CHECK_ALTERNATE_check312="check312" - +CHECK_ID_check312="3.12" +CHECK_TITLE_check312="Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" +CHECK_SCORED_check312="SCORED" +CHECK_ALTERNATE_check312="check312" + check312(){ # "Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" textTitle "$ID312" "$TITLE312" "SCORED" "LEVEL1" diff --git a/checks/check313 b/checks/check313 index 7e293c3546..3ab3531b46 100644 --- a/checks/check313 +++ b/checks/check313 @@ -1,9 +1,8 @@ -CHECK_ID_check313="" -CHECK_TITLE_check313="" -CHECK_SCORED_check313="" -CHECK_TYPE_check313="" -CHECK_ALTERNATE_check313="check313" - +CHECK_ID_check313="3.13" +CHECK_TITLE_check313="Ensure a log metric filter and alarm exist for route table changes (Scored)" +CHECK_SCORED_check313="SCORED" +CHECK_ALTERNATE_check313="check313" + check313(){ # "Ensure a log metric filter and alarm exist for route table changes (Scored)" textTitle "$ID313" "$TITLE313" "SCORED" "LEVEL1" diff --git a/checks/check314 b/checks/check314 index 437452d65c..0bec02fa99 100644 --- a/checks/check314 +++ b/checks/check314 @@ -1,9 +1,8 @@ -CHECK_ID_check314="" -CHECK_TITLE_check314="" -CHECK_SCORED_check314="" -CHECK_TYPE_check314="" -CHECK_ALTERNATE_check314="check314" - +CHECK_ID_check314="3.14" +CHECK_TITLE_check314="Ensure a log metric filter and alarm exist for VPC changes (Scored)" +CHECK_SCORED_check314="SCORED" +CHECK_ALTERNATE_check314="check314" + check314(){ # "Ensure a log metric filter and alarm exist for VPC changes (Scored)" textTitle "$ID314" "$TITLE314" "SCORED" "LEVEL1" diff --git a/checks/check315 b/checks/check315 index df71f78652..68f30c5550 100644 --- a/checks/check315 +++ b/checks/check315 @@ -1,9 +1,8 @@ -CHECK_ID_check315="" -CHECK_TITLE_check315="" -CHECK_SCORED_check315="" -CHECK_TYPE_check315="" -CHECK_ALTERNATE_check315="check315" - +CHECK_ID_check315="3.15" +CHECK_TITLE_check315="Ensure appropriate subscribers to each SNS topic (Not Scored)" +CHECK_SCORED_check315="SCORED" +CHECK_ALTERNATE_check315="check315" + check315(){ # "Ensure appropriate subscribers to each SNS topic (Not Scored)" textTitle "$ID315" "$TITLE315" "NOT_SCORED" "LEVEL1" diff --git a/checks/check32 b/checks/check32 index 68e42787e2..f07cb1a632 100644 --- a/checks/check32 +++ b/checks/check32 @@ -1,9 +1,8 @@ -CHECK_ID_check32="" -CHECK_TITLE_check32="" -CHECK_SCORED_check32="" -CHECK_TYPE_check32="" -CHECK_ALTERNATE_check32="check32" - +CHECK_ID_check32="3.2,3.02" +CHECK_TITLE_check32="Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" +CHECK_SCORED_check32="SCORED" +CHECK_ALTERNATE_check302="check32" + check32(){ # "Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" textTitle "$ID32" "$TITLE32" "SCORED" "LEVEL1" diff --git a/checks/check33 b/checks/check33 index 6e6362e25a..49e04219bc 100644 --- a/checks/check33 +++ b/checks/check33 @@ -1,9 +1,8 @@ -CHECK_ID_check33="" -CHECK_TITLE_check33="" -CHECK_SCORED_check33="" -CHECK_TYPE_check33="" -CHECK_ALTERNATE_check33="check33" - +CHECK_ID_check33="3.3,3.03" +CHECK_TITLE_check33="Ensure a log metric filter and alarm exist for usage of root account (Scored)" +CHECK_SCORED_check33="SCORED" +CHECK_ALTERNATE_check303="check33" + check33(){ # "Ensure a log metric filter and alarm exist for usage of root account (Scored)" textTitle "$ID33" "$TITLE33" "SCORED" "LEVEL1" diff --git a/checks/check34 b/checks/check34 index e84790c78c..3d9e89449f 100644 --- a/checks/check34 +++ b/checks/check34 @@ -1,9 +1,8 @@ -CHECK_ID_check34="" -CHECK_TITLE_check34="" -CHECK_SCORED_check34="" -CHECK_TYPE_check34="" -CHECK_ALTERNATE_check34="check34" - +CHECK_ID_check34="3.4,3.04" +CHECK_TITLE_check34="Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" +CHECK_SCORED_check34="SCORED" +CHECK_ALTERNATE_check304="check34" + check34(){ # "Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" textTitle "$ID34" "$TITLE34" "SCORED" "LEVEL1" diff --git a/checks/check35 b/checks/check35 index 0d93635ab2..a4d144a893 100644 --- a/checks/check35 +++ b/checks/check35 @@ -1,9 +1,8 @@ -CHECK_ID_check35="" -CHECK_TITLE_check35="" -CHECK_SCORED_check35="" -CHECK_TYPE_check35="" -CHECK_ALTERNATE_check35="check35" - +CHECK_ID_check35="3.5,3.05" +CHECK_TITLE_check35="Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" +CHECK_SCORED_check35="SCORED" +CHECK_ALTERNATE_check305="check35" + check35(){ # "Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" textTitle "$ID35" "$TITLE35" "SCORED" "LEVEL1" diff --git a/checks/check36 b/checks/check36 index 62f31c7505..2306196427 100644 --- a/checks/check36 +++ b/checks/check36 @@ -1,9 +1,8 @@ -CHECK_ID_check36="" -CHECK_TITLE_check36="" -CHECK_SCORED_check36="" -CHECK_TYPE_check36="" -CHECK_ALTERNATE_check36="check36" - +CHECK_ID_check36="3.6,3.06" +CHECK_TITLE_check36="Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" +CHECK_SCORED_check36="SCORED" +CHECK_ALTERNATE_check306="check36" + check36(){ # "Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" textTitle "$ID36" "$TITLE36" "SCORED" "LEVEL2" diff --git a/checks/check37 b/checks/check37 index 6809b5d0dd..2ffc48c2d8 100644 --- a/checks/check37 +++ b/checks/check37 @@ -1,9 +1,8 @@ -CHECK_ID_check37="" -CHECK_TITLE_check37="" -CHECK_SCORED_check37="" -CHECK_TYPE_check37="" -CHECK_ALTERNATE_check37="check37" - +CHECK_ID_check37="3.7,3.07" +CHECK_TITLE_check37="Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" +CHECK_SCORED_check37="SCORED" +CHECK_ALTERNATE_check307="check37" + check37(){ # "Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" textTitle "$ID37" "$TITLE37" "SCORED" "LEVEL2" diff --git a/checks/check38 b/checks/check38 index e51edccfd0..0445fb988f 100644 --- a/checks/check38 +++ b/checks/check38 @@ -1,9 +1,8 @@ -CHECK_ID_check38="" -CHECK_TITLE_check38="" -CHECK_SCORED_check38="" -CHECK_TYPE_check38="" -CHECK_ALTERNATE_check38="check38" - +CHECK_ID_check38="3.8,3.08" +CHECK_TITLE_check38="Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" +CHECK_SCORED_check38="SCORED" +CHECK_ALTERNATE_check308="check38" + check38(){ # "Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" textTitle "$ID38" "$TITLE38" "SCORED" "LEVEL1" diff --git a/checks/check39 b/checks/check39 index 7a66fceb84..0f595b15c9 100644 --- a/checks/check39 +++ b/checks/check39 @@ -1,9 +1,8 @@ -CHECK_ID_check39="" -CHECK_TITLE_check39="" -CHECK_SCORED_check39="" -CHECK_TYPE_check39="" -CHECK_ALTERNATE_check39="check39" - +CHECK_ID_check39="3.9,3.09" +CHECK_TITLE_check39="Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" +CHECK_SCORED_check39="SCORED" +CHECK_ALTERNATE_check309="check39" + check39(){ # "Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" textTitle "$ID39" "$TITLE39" "SCORED" "LEVEL2" diff --git a/checks/check41 b/checks/check41 index 0e63eb4d09..a7cfa7ccd8 100644 --- a/checks/check41 +++ b/checks/check41 @@ -1,9 +1,8 @@ -CHECK_ID_check41="" -CHECK_TITLE_check41="" -CHECK_SCORED_check41="" -CHECK_TYPE_check41="" -CHECK_ALTERNATE_check41="check41" - +CHECK_ID_check41="4.1,4.01" +CHECK_TITLE_check41="Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" +CHECK_SCORED_check41="SCORED" +CHECK_ALTERNATE_check401="check41" + check41(){ # "Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" textTitle "$ID41" "$TITLE41" "SCORED" "LEVEL1" diff --git a/checks/check42 b/checks/check42 index 7334c30492..d912c749d9 100644 --- a/checks/check42 +++ b/checks/check42 @@ -1,9 +1,8 @@ -CHECK_ID_check42="" -CHECK_TITLE_check42="" -CHECK_SCORED_check42="" -CHECK_TYPE_check42="" -CHECK_ALTERNATE_check42="check42" - +CHECK_ID_check42="4.2,4.02" +CHECK_TITLE_check42="Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" +CHECK_SCORED_check42="SCORED" +CHECK_ALTERNATE_check402="check42" + check42(){ # "Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" textTitle "$ID42" "$TITLE42" "SCORED" "LEVEL1" diff --git a/checks/check43 b/checks/check43 index 627eca2b80..913e5f876c 100644 --- a/checks/check43 +++ b/checks/check43 @@ -1,9 +1,8 @@ -CHECK_ID_check43="" -CHECK_TITLE_check43="" -CHECK_SCORED_check43="" -CHECK_TYPE_check43="" -CHECK_ALTERNATE_check43="check43" - +CHECK_ID_check43="4.3,4.03" +CHECK_TITLE_check43="Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" +CHECK_SCORED_check43="SCORED" +CHECK_ALTERNATE_check403="check43" + check43(){ # "Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" textTitle "$ID43" "$TITLE43" "SCORED" "LEVEL2" diff --git a/checks/check44 b/checks/check44 index afdbbfcb89..7dc223347f 100644 --- a/checks/check44 +++ b/checks/check44 @@ -1,9 +1,8 @@ -CHECK_ID_check44="" -CHECK_TITLE_check44="" -CHECK_SCORED_check44="" -CHECK_TYPE_check44="" -CHECK_ALTERNATE_check44="check44" - +CHECK_ID_check44="4.4,4.04" +CHECK_TITLE_check44="Ensure the default security group of every VPC restricts all traffic (Scored)" +CHECK_SCORED_check44="SCORED" +CHECK_ALTERNATE_check404="check44" + check44(){ # "Ensure the default security group of every VPC restricts all traffic (Scored)" textTitle "$ID44" "$TITLE44" "SCORED" "LEVEL2" diff --git a/checks/check45 b/checks/check45 index ac8764d052..2940146261 100644 --- a/checks/check45 +++ b/checks/check45 @@ -1,9 +1,8 @@ -CHECK_ID_check45="" -CHECK_TITLE_check45="" -CHECK_SCORED_check45="" -CHECK_TYPE_check45="" -CHECK_ALTERNATE_check45="check45" - +CHECK_ID_check45="4.5,4.05" +CHECK_TITLE_check45="Ensure routing tables for VPC peering are \"least access\" (Not Scored)" +CHECK_SCORED_check45="NOT_SCORED" +CHECK_ALTERNATE_check405="check45" + check45(){ # "Ensure routing tables for VPC peering are \"least access\" (Not Scored)" textTitle "$ID45" "$TITLE45" "NOT_SCORED" "LEVEL2" diff --git a/checks/check_extra71 b/checks/check_extra71 index b757559887..e10a12fd34 100644 --- a/checks/check_extra71 +++ b/checks/check_extra71 @@ -1,13 +1,13 @@ -CHECK_ID_check_extra71="" -CHECK_TITLE_check_extra71="" -CHECK_SCORED_check_extra71="" -CHECK_TYPE_check_extra71="" -CHECK_ALTERNATE_check_extra71="check_extra71" - +CHECK_ID_extra71="7.1,7.01" +CHECK_TITLE_extra71="Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra71="NOT_SCORED" +CHECK_ALTERNATE_extra701="extra71" +CHECK_ALTERNATE_check71="extra71" +CHECK_ALTERNATE_check701="extra71" + extra71(){ # "Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID71" "$TITLE71" "NOT_SCORED" "EXTRA" - ADMIN_GROUPS='' AWS_GROUPS=$($AWSCLI $PROFILE_OPT iam list-groups --output text --query 'Groups[].GroupName') for grp in $AWS_GROUPS; do @@ -33,5 +33,4 @@ extra71(){ textNotice "$grp group provides non-administrative access" fi done - # set +x } diff --git a/checks/check_extra710 b/checks/check_extra710 index 1f7cb26e02..48fdcb010c 100644 --- a/checks/check_extra710 +++ b/checks/check_extra710 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra710="" -CHECK_TITLE_check_extra710="" -CHECK_SCORED_check_extra710="" -CHECK_TYPE_check_extra710="" -CHECK_ALTERNATE_check_extra710="check_extra710" - +CHECK_ID_extra710="7.10" +CHECK_TITLE_extra710="Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra710="NOT_SCORED" +CHECK_ALTERNATE_extra710="extra710" +CHECK_ALTERNATE_check710="extra710" + extra710(){ # "Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" textTitle "$ID710" "$TITLE710" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra711 b/checks/check_extra711 index b2a0c8e405..4be784451d 100644 --- a/checks/check_extra711 +++ b/checks/check_extra711 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra711="" -CHECK_TITLE_check_extra711="" -CHECK_SCORED_check_extra711="" -CHECK_TYPE_check_extra711="" -CHECK_ALTERNATE_check_extra711="check_extra711" - +CHECK_ID_extra711="7.11" +CHECK_TITLE_extra711="Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra711="NOT_SCORED" +CHECK_ALTERNATE_extra711="extra711" +CHECK_ALTERNATE_check711="extra711" + extra711(){ # "Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" textTitle "$ID711" "$TITLE711" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra712 b/checks/check_extra712 index 3515484c56..ae653c1318 100644 --- a/checks/check_extra712 +++ b/checks/check_extra712 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra712="" -CHECK_TITLE_check_extra712="" -CHECK_SCORED_check_extra712="" -CHECK_TYPE_check_extra712="" -CHECK_ALTERNATE_check_extra712="check_extra712" - +CHECK_ID_extra712="7.12" +CHECK_TITLE_extra712="Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra712="NOT_SCORED" +CHECK_ALTERNATE_extra712="extra712" +CHECK_ALTERNATE_check712="extra712" + extra712(){ # "Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID712" "$TITLE712" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra713 b/checks/check_extra713 index a64cd24f3a..457d36cce1 100644 --- a/checks/check_extra713 +++ b/checks/check_extra713 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra713="" -CHECK_TITLE_check_extra713="" -CHECK_SCORED_check_extra713="" -CHECK_TYPE_check_extra713="" -CHECK_ALTERNATE_check_extra713="check_extra713" - +CHECK_ID_extra713="7.13" +CHECK_TITLE_extra713="Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra713="NOT_SCORED" +CHECK_ALTERNATE_extra713="extra713" +CHECK_ALTERNATE_check713="extra713" + extra713(){ # "Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID713" "$TITLE713" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra714 b/checks/check_extra714 index 5fab1be2f2..00c625d102 100644 --- a/checks/check_extra714 +++ b/checks/check_extra714 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra714="" -CHECK_TITLE_check_extra714="" -CHECK_SCORED_check_extra714="" -CHECK_TYPE_check_extra714="" -CHECK_ALTERNATE_check_extra714="check_extra714" - +CHECK_ID_extra714="7.14" +CHECK_TITLE_extra714="Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra714="NOT_SCORED" +CHECK_ALTERNATE_extra714="extra714" +CHECK_ALTERNATE_check714="extra714" + extra714(){ # "Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID714" "$TITLE714" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra715 b/checks/check_extra715 index 503d7c2c41..b27e4def87 100644 --- a/checks/check_extra715 +++ b/checks/check_extra715 @@ -1,11 +1,10 @@ -CHECK_ID_check_extra715="" -CHECK_TITLE_check_extra715="" -CHECK_SCORED_check_extra715="" -CHECK_TYPE_check_extra715="" -CHECK_ALTERNATE_check_extra715="check_extra715" - +CHECK_ID_extra715="7.15" +CHECK_TITLE_extra715="Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra715="NOT_SCORED" +CHECK_ALTERNATE_extra715="extra715" +CHECK_ALTERNATE_check715="extra715" + extra715(){ - # "Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID715" "$TITLE715" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text) diff --git a/checks/check_extra716 b/checks/check_extra716 index 7749af1d3d..b42ccc87f6 100644 --- a/checks/check_extra716 +++ b/checks/check_extra716 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra716="" -CHECK_TITLE_check_extra716="" -CHECK_SCORED_check_extra716="" -CHECK_TYPE_check_extra716="" -CHECK_ALTERNATE_check_extra716="check_extra716" - +CHECK_ID_extra716="7.16" +CHECK_TITLE_extra716="Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra716="NOT_SCORED" +CHECK_ALTERNATE_extra716="extra716" +CHECK_ALTERNATE_check716="extra716" + extra716(){ # "Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" textTitle "$ID716" "$TITLE716" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra717 b/checks/check_extra717 index 7dac48b5e6..d52669ba4a 100644 --- a/checks/check_extra717 +++ b/checks/check_extra717 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra717="" -CHECK_TITLE_check_extra717="" -CHECK_SCORED_check_extra717="" -CHECK_TYPE_check_extra717="" -CHECK_ALTERNATE_check_extra717="check_extra717" - +CHECK_ID_extra717="7.17" +CHECK_TITLE_extra717="Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra717="NOT_SCORED" +CHECK_ALTERNATE_extra717="extra717" +CHECK_ALTERNATE_check717="extra717" + extra717(){ # "Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID717" "$TITLE717" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra718 b/checks/check_extra718 index 6d3108b628..f5a2b8bd0f 100644 --- a/checks/check_extra718 +++ b/checks/check_extra718 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra718="" -CHECK_TITLE_check_extra718="" -CHECK_SCORED_check_extra718="" -CHECK_TYPE_check_extra718="" -CHECK_ALTERNATE_check_extra718="check_extra718" - +CHECK_ID_extra718="7.18" +CHECK_TITLE_extra718="Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra718="NOT_SCORED" +CHECK_ALTERNATE_extra718="extra718" +CHECK_ALTERNATE_check718="extra718" + extra718(){ # "Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID718" "$TITLE718" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra719 b/checks/check_extra719 index d260f66fae..4158a3438e 100644 --- a/checks/check_extra719 +++ b/checks/check_extra719 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra719="" -CHECK_TITLE_check_extra719="" -CHECK_SCORED_check_extra719="" -CHECK_TYPE_check_extra719="" -CHECK_ALTERNATE_check_extra719="check_extra719" - +CHECK_ID_extra719="7.19" +CHECK_TITLE_extra719="Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra719="NOT_SCORED" +CHECK_ALTERNATE_extra719="extra719" +CHECK_ALTERNATE_check719="extra719" + extra719(){ # "Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" textTitle "$ID719" "$TITLE719" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra72 b/checks/check_extra72 index 86fd88f299..06b80ea988 100644 --- a/checks/check_extra72 +++ b/checks/check_extra72 @@ -1,9 +1,10 @@ -CHECK_ID_check_extra72="" -CHECK_TITLE_check_extra72="" -CHECK_SCORED_check_extra72="" -CHECK_TYPE_check_extra72="" -CHECK_ALTERNATE_check_extra72="check_extra72" - +CHECK_ID_extra72="7.2,7.02" +CHECK_TITLE_extra72="Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra72="NOT_SCORED" +CHECK_ALTERNATE_extra702="extra72" +CHECK_ALTERNATE_check72="extra72" +CHECK_ALTERNATE_check702="extra72" + extra72(){ # "Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" textTitle "$ID72" "$TITLE72" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra720 b/checks/check_extra720 index 975d6f92c0..5c440297b9 100644 --- a/checks/check_extra720 +++ b/checks/check_extra720 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra720="" -CHECK_TITLE_check_extra720="" -CHECK_SCORED_check_extra720="" -CHECK_TYPE_check_extra720="" -CHECK_ALTERNATE_check_extra720="check_extra720" - +CHECK_ID_extra720="7.20" +CHECK_TITLE_extra720="Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra720="NOT_SCORED" +CHECK_ALTERNATE_extra720="extra720" +CHECK_ALTERNATE_check720="extra720" + extra720(){ # "Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" textTitle "$ID720" "$TITLE720" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra721 b/checks/check_extra721 index 2a5f5f4f1f..82b78045ae 100644 --- a/checks/check_extra721 +++ b/checks/check_extra721 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra721="" -CHECK_TITLE_check_extra721="" -CHECK_SCORED_check_extra721="" -CHECK_TYPE_check_extra721="" -CHECK_ALTERNATE_check_extra721="check_extra721" - +CHECK_ID_extra721="7.21" +CHECK_TITLE_extra721="Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra721="NOT_SCORED" +CHECK_ALTERNATE_extra721="extra721" +CHECK_ALTERNATE_check721="extra721" + extra721(){ # "Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID721" "$TITLE721" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra722 b/checks/check_extra722 index bcd7ab4702..6a16714c72 100644 --- a/checks/check_extra722 +++ b/checks/check_extra722 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra722="" -CHECK_TITLE_check_extra722="" -CHECK_SCORED_check_extra722="" -CHECK_TYPE_check_extra722="" -CHECK_ALTERNATE_check_extra722="check_extra722" - +CHECK_ID_extra722="7.22" +CHECK_TITLE_extra722="Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra722="NOT_SCORED" +CHECK_ALTERNATE_check722="extra722" +CHECK_ALTERNATE_extra722="extra722" + extra722(){ # "Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" textTitle "$ID722" "$TITLE722" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra723 b/checks/check_extra723 index 470ce3ad75..3f46fb2188 100644 --- a/checks/check_extra723 +++ b/checks/check_extra723 @@ -1,9 +1,9 @@ -CHECK_ID_check_extra723="" -CHECK_TITLE_check_extra723="" -CHECK_SCORED_check_extra723="" -CHECK_TYPE_check_extra723="" -CHECK_ALTERNATE_check_extra723="check_extra723" - +CHECK_ID_extra723="7.23" +CHECK_TITLE_extra723="Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra723="NOT_SCORED" +CHECK_ALTERNATE_check723="extra723" +CHECK_ALTERNATE_extra723="extra723" + extra723(){ # "Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" textTitle "$ID723" "$TITLE723" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra73 b/checks/check_extra73 index 273d0813dd..7c45d1ee13 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -1,9 +1,10 @@ -CHECK_ID_check_extra73="" -CHECK_TITLE_check_extra73="" -CHECK_SCORED_check_extra73="" -CHECK_TYPE_check_extra73="" -CHECK_ALTERNATE_check_extra73="check_extra73" - +CHECK_ID_extra73="7.3,7.03" +CHECK_TITLE_extra73="Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra73="NOT_SCORED" +CHECK_ALTERNATE_extra703="extra73" +CHECK_ALTERNATE_check73="extra73" +CHECK_ALTERNATE_check703="extra73" + extra73(){ # "Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" textTitle "$ID73" "$TITLE73" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra74 b/checks/check_extra74 index c1e527274a..ee264999f3 100644 --- a/checks/check_extra74 +++ b/checks/check_extra74 @@ -1,9 +1,10 @@ -CHECK_ID_check_extra74="" -CHECK_TITLE_check_extra74="" -CHECK_SCORED_check_extra74="" -CHECK_TYPE_check_extra74="" -CHECK_ALTERNATE_check_extra74="check_extra74" - +CHECK_ID_extra74="7.4,7.04" +CHECK_TITLE_extra74="Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra74="NOT_SCORED" +CHECK_ALTERNATE_extra704="extra74" +CHECK_ALTERNATE_check74="extra74" +CHECK_ALTERNATE_check704="extra74" + extra74(){ # "Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" textTitle "$ID74" "$TITLE74" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra75 b/checks/check_extra75 index bc5a8a87e9..24af2099df 100644 --- a/checks/check_extra75 +++ b/checks/check_extra75 @@ -1,9 +1,10 @@ -CHECK_ID_check_extra75="" -CHECK_TITLE_check_extra75="" -CHECK_SCORED_check_extra75="" -CHECK_TYPE_check_extra75="" -CHECK_ALTERNATE_check_extra75="check_extra75" - +CHECK_ID_extra75="7.5,7.05" +CHECK_TITLE_extra75="Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra75="NOT_SCORED" +CHECK_ALTERNATE_extra705="extra75" +CHECK_ALTERNATE_check75="extra75" +CHECK_ALTERNATE_check705="extra75" + extra75(){ # "Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" textTitle "$ID75" "$TITLE75" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra76 b/checks/check_extra76 index bd0ebafc42..0af33a1c20 100644 --- a/checks/check_extra76 +++ b/checks/check_extra76 @@ -1,9 +1,10 @@ -CHECK_ID_check_extra76="" -CHECK_TITLE_check_extra76="" -CHECK_SCORED_check_extra76="" -CHECK_TYPE_check_extra76="" -CHECK_ALTERNATE_check_extra76="check_extra76" - +CHECK_ID_extra76="7.6,7.06" +CHECK_TITLE_extra76="Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra76="NOT_SCORED" +CHECK_ALTERNATE_extra706="extra76" +CHECK_ALTERNATE_check76="extra76" +CHECK_ALTERNATE_check706="extra76" + extra76(){ # "Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" textTitle "$ID76" "$TITLE76" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra77 b/checks/check_extra77 index f90c34ffa5..bf4a9cffb6 100644 --- a/checks/check_extra77 +++ b/checks/check_extra77 @@ -1,9 +1,10 @@ -CHECK_ID_check_extra77="" -CHECK_TITLE_check_extra77="" -CHECK_SCORED_check_extra77="" -CHECK_TYPE_check_extra77="" -CHECK_ALTERNATE_check_extra77="check_extra77" - +CHECK_ID_extra77="7.7,7.07" +CHECK_TITLE_extra77="Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra77="NOT_SCORED" +CHECK_ALTERNATE_extra707="extra77" +CHECK_ALTERNATE_check77="extra77" +CHECK_ALTERNATE_check707="extra77" + extra77(){ # "Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" textTitle "$ID77" "$TITLE77" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra78 b/checks/check_extra78 index 8baf0f59e4..a243d7bd20 100644 --- a/checks/check_extra78 +++ b/checks/check_extra78 @@ -1,9 +1,10 @@ -CHECK_ID_check_extra78="" -CHECK_TITLE_check_extra78="" -CHECK_SCORED_check_extra78="" -CHECK_TYPE_check_extra78="" -CHECK_ALTERNATE_check_extra78="check_extra78" - +CHECK_ID_extra78="7.8,7.08" +CHECK_TITLE_extra78="Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra78="NOT_SCORED" +CHECK_ALTERNATE_extra708="extra78" +CHECK_ALTERNATE_check78="extra78" +CHECK_ALTERNATE_check708="extra78" + extra78(){ # "Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" textTitle "$ID78" "$TITLE78" "NOT_SCORED" "EXTRA" diff --git a/checks/check_extra79 b/checks/check_extra79 index ff24bd2e1a..51fc1cac99 100644 --- a/checks/check_extra79 +++ b/checks/check_extra79 @@ -1,9 +1,10 @@ -CHECK_ID_check_extra79="" -CHECK_TITLE_check_extra79="" -CHECK_SCORED_check_extra79="" -CHECK_TYPE_check_extra79="" -CHECK_ALTERNATE_check_extra79="check_extra79" - +CHECK_ID_extra79="7.9,7.09" +CHECK_TITLE_extra79="Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra79="NOT_SCORED" +CHECK_ALTERNATE_extra709="extra79" +CHECK_ALTERNATE_check79="extra79" +CHECK_ALTERNATE_check709="extra79" + extra79(){ # "Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" textTitle "$ID79" "$TITLE79" "NOT_SCORED" "EXTRA" diff --git a/groups/group0_init b/groups/group0_init new file mode 100644 index 0000000000..8b7d2410e9 --- /dev/null +++ b/groups/group0_init @@ -0,0 +1,6 @@ +GROUP_ID[0]='init' # this group make easier to understand the array of groups +GROUP_NUMBER[0]='0.0' +GROUP_TITLE[0]='Init ****************************************************************' +GROUP_RUN_BY_DEFAULT[0]='N' # run it when execute_all is called +GROUP_CHECKS[0]='' + diff --git a/groups/group1_iam b/groups/group1_iam index 73a4e6498f..6145bff4b3 100644 --- a/groups/group1_iam +++ b/groups/group1_iam @@ -1,5 +1,5 @@ -GROUP_ID[1]="group1" -GROUP_NUMBER[1]="1.0" -GROUP_TITLE[1]="Identity and Access Management ****************************************" -GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called -GROUP_CHECKS[1]="check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check114,check115,check116,check117,check118,check119,check120,check121,check122,check123,check124" +GROUP_ID[1]='group1' +GROUP_NUMBER[1]='1.0' +GROUP_TITLE[1]='Identity and Access Management ****************************************' +GROUP_RUN_BY_DEFAULT[1]='Y' # run it when execute_all is called +GROUP_CHECKS[1]='check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check114,check115,check116,check117,check118,check119,check120,check121,check122,check123,check124' diff --git a/groups/group2_logging b/groups/group2_logging index c9225cacf0..da10a1d41b 100644 --- a/groups/group2_logging +++ b/groups/group2_logging @@ -1,5 +1,5 @@ -GROUP_ID[2]="group2" -GROUP_NUMBER[2]="2.0" -GROUP_TITLE[2]="Logging ***************************************************************" -GROUP_RUN_BY_DEFAULT[2]="Y" # run it when execute_all is called -GROUP_CHECKS[2]="check21,check22,check23,check24,check25,check26,check27,check28" +GROUP_ID[2]='group2' +GROUP_NUMBER[2]='2.0' +GROUP_TITLE[2]='Logging ***************************************************************' +GROUP_RUN_BY_DEFAULT[2]='Y' # run it when execute_all is called +GROUP_CHECKS[2]='check21,check22,check23,check24,check25,check26,check27,check28' diff --git a/groups/group3_monitoring b/groups/group3_monitoring index c74d4cf137..56356f84ec 100644 --- a/groups/group3_monitoring +++ b/groups/group3_monitoring @@ -1,5 +1,5 @@ -GROUP_ID[3]="group3" -GROUP_NUMBER[3]="3.0" -GROUP_TITLE[3]="Monitoring ************************************************************" -GROUP_RUN_BY_DEFAULT[3]="Y" # run it when execute_all is called -GROUP_CHECKS[3]="check31,check32,check33,check34,check35,check36,check37,check38,check39,check310,check311,check312,check313,check314,check315" +GROUP_ID[3]='group3' +GROUP_NUMBER[3]='3.0' +GROUP_TITLE[3]='Monitoring ************************************************************' +GROUP_RUN_BY_DEFAULT[3]='Y' # run it when execute_all is called +GROUP_CHECKS[3]='check31,check32,check33,check34,check35,check36,check37,check38,check39,check310,check311,check312,check313,check314,check315' diff --git a/groups/group5_cislevel1 b/groups/group5_cislevel1 index 99656963ef..a1958a5f95 100644 --- a/groups/group5_cislevel1 +++ b/groups/group5_cislevel1 @@ -1,5 +1,5 @@ -GROUP_ID[5]="level1" -GROUP_NUMBER[5]="5.0" -GROUP_TITLE[5]="CIS Level 1 **********************************************************" -GROUP_RUN_BY_DEFAULT[5]="N" # run it when execute_all is called -GROUP_CHECKS[5]="check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check115,check116,check117,check118,check119,check120,check122,check123,check124,check21,check23,check24,check25,check26,check31,check32,check33,check34,check35,check38,check312,check313,check314,check315,check41,check42" +GROUP_ID[5]='level1' +GROUP_NUMBER[5]='5.0' +GROUP_TITLE[5]='CIS Level 1 **********************************************************' +GROUP_RUN_BY_DEFAULT[5]='N' # run it when execute_all is called +GROUP_CHECKS[5]='check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check115,check116,check117,check118,check119,check120,check122,check123,check124,check21,check23,check24,check25,check26,check31,check32,check33,check34,check35,check38,check312,check313,check314,check315,check41,check42' diff --git a/groups/group6_cislevel2 b/groups/group6_cislevel2 index 698b926b2c..369848ba33 100644 --- a/groups/group6_cislevel2 +++ b/groups/group6_cislevel2 @@ -1,5 +1,5 @@ -GROUP_ID[6]="level2" -GROUP_NUMBER[6]="6.0" -GROUP_TITLE[6]="CIS Level 2 **********************************************************" -GROUP_RUN_BY_DEFAULT[6]="N" # run it when execute_all is called -GROUP_CHECKS[6]="check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check114,check115,check116,check117,check118,check119,check120,check121,check122,check123,check124,check21,check22,check23,check24,check25,check26,check27,check28,check31,check32,check33,check34,check35,check36,check37,check38,check39,check310,check311,check312,check313,check314,check315,check41,check42,check43,check44,check45" +GROUP_ID[6]='level2' +GROUP_NUMBER[6]='6.0' +GROUP_TITLE[6]='CIS Level 2 **********************************************************' +GROUP_RUN_BY_DEFAULT[6]='N' # run it when execute_all is called +GROUP_CHECKS[6]='check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check114,check115,check116,check117,check118,check119,check120,check121,check122,check123,check124,check21,check22,check23,check24,check25,check26,check27,check28,check31,check32,check33,check34,check35,check36,check37,check38,check39,check310,check311,check312,check313,check314,check315,check41,check42,check43,check44,check45' diff --git a/groups/group7_extras b/groups/group7_extras index 1cdd6ebee3..0c3319b279 100644 --- a/groups/group7_extras +++ b/groups/group7_extras @@ -1,5 +1,5 @@ -GROUP_ID[7]="extras" -GROUP_NUMBER[7]="7.0" -GROUP_TITLE[7]="Extras ****************************************************************" -GROUP_RUN_BY_DEFAULT[7]="Y" # run it when execute_all is called -GROUP_CHECKS[7]="extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723" +GROUP_ID[7]='extras' +GROUP_NUMBER[7]='7.0' +GROUP_TITLE[7]='Extras ****************************************************************' +GROUP_RUN_BY_DEFAULT[7]='Y' # run it when execute_all is called +GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723' diff --git a/groups/group8_forensics b/groups/group8_forensics index c199de7092..704b31ac3c 100644 --- a/groups/group8_forensics +++ b/groups/group8_forensics @@ -1,5 +1,5 @@ -GROUP_ID[8]="forensics-ready" -GROUP_NUMBER[8]="8.0" -GROUP_TITLE[8]="Forensics Readiness ***************************************************" -GROUP_RUN_BY_DEFAULT[8]="N" # run it when execute_all is called -GROUP_CHECKS[8]="check21,check22,check23,check24,check25,check26,check27,check43,extra712,extra713,extra714,extra715,extra717,extra718,extra719,extra720,extra721,extra722" +GROUP_ID[8]='forensics-ready' +GROUP_NUMBER[8]='8.0' +GROUP_TITLE[8]='Forensics Readiness ***************************************************' +GROUP_RUN_BY_DEFAULT[8]='N' # run it when execute_all is called +GROUP_CHECKS[8]='check21,check22,check23,check24,check25,check26,check27,check43,extra712,extra713,extra714,extra715,extra717,extra718,extra719,extra720,extra721,extra722' diff --git a/groups/groupN_sample b/groups/groupN_sample index 27678c86f7..a286c9f8e6 100644 --- a/groups/groupN_sample +++ b/groups/groupN_sample @@ -1,5 +1,5 @@ -GROUP_ID[9]="my-custom-group" -GROUP_NUMBER[9]="9.0" -GROUP_TITLE[9]="My Custom Group **********************************************" -GROUP_RUN_BY_DEFAULT[9]="N" # run it when execute_all is called -GROUP_CHECKS[9]="checkNN,checkMM" +GROUP_ID[9]='my-custom-group' +GROUP_NUMBER[9]='9.0' +GROUP_TITLE[9]='My Custom Group **********************************************' +GROUP_RUN_BY_DEFAULT[9]='N' # run it when execute_all is called +GROUP_CHECKS[9]='checkNN,checkMM' diff --git a/lll b/lll deleted file mode 100644 index 66f5ad2d26..0000000000 --- a/lll +++ /dev/null @@ -1,2 +0,0 @@ -check11 -check12 diff --git a/prowler2 b/prowler2 index 082c293515..9fc59819e1 100755 --- a/prowler2 +++ b/prowler2 @@ -136,42 +136,20 @@ REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ --region $REGION \ --region-names $FILTERREGION) - callCheck(){ - if [[ $CHECKNUMBER ]];then - execute_check $CHECKNUMBER - # case "$CHECKNUMBER" in - # check11|check101 ) execute_check check11;; - # check12|check102 ) execute_check check12;; - # * ) - # textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n"; - # esac - cleanTemp - exit $EXITCODE - fi - } - -# List only check tittles -if [[ $PRINTCHECKSONLY == "1" ]]; then - prowlerBanner - show_all_titles - exit $EXITCODE -fi - -# Load all of the groups of checks inside groups folder named as "group*" -for group in $(ls groups/group*); do +# Load all of the groups of checks inside groups folder named as "groupNumber*" +for group in $(ls groups/group[0-9]*|grep -v groupN_sample); do . "$group" done # Load all of the checks inside checks folder named as "check*" # this includes also extra checks since they are "check_extraNN" -for checks in $(ls checks/check*); do +for checks in $(ls checks/check*|grep -v check_sample); do . "$checks" done # Function to show the title of the check # using this way instead of arrays to keep bash3 (osx) and bash4(linux) compatibility show_check_title() { - # This would just call textTitle local check_id=CHECK_ID_$1 local check_title=CHECK_TITLE_$1 local check_scored=CHECK_SCORED_$1 @@ -205,7 +183,7 @@ execute_check() { show_check_title $1 $1 else - textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n"; + textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)"; fi fi } @@ -231,7 +209,7 @@ execute_group_by_name() { # Function to execute all checks in all groups execute_all() { - for i in ${#GROUP_TITLE[@]}; do + for i in "${!GROUP_TITLE[@]}"; do if [ "${GROUP_RUN_BY_DEFAULT[$i]}" == "Y" ]; then execute_group $i fi @@ -240,16 +218,30 @@ execute_all() { # Function to show the titles of everything show_all_titles() { - for i in ${#GROUP_TITLE[@]}; do + for i in "${!GROUP_TITLE[@]}"; do show_group_title $i # Display the title of the checks IFS=',' read -ra CHECKS <<< ${GROUP_CHECKS[$i]} - for j in "${CHECKS[@]}"; do + for j in "${GROUP_CHECKS[@]}"; do show_check_title $j done done } +# Execute single check if called with -c +if [[ $CHECKNUMBER ]];then + execute_check $CHECKNUMBER + cleanTemp + exit $EXITCODE +fi + +# List only check tittles +if [[ $PRINTCHECKSONLY == "1" ]]; then + prowlerBanner + show_all_titles + exit $EXITCODE +fi + ### All functions defined above ... run the workflow if [[ $MODE != "csv" ]]; then prowlerBanner @@ -263,11 +255,5 @@ saveReport execute_all - -# if [[ ! $EXTRAS ]]; then -# textTitle "7" "$TITLE7" "NOT_SCORED" "SUPPORT" -# execute_group 7 -# fi - cleanTemp exit $EXITCODE From 7866d42df9cea275d6b74cf2e2391ffb5518a82d Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 26 Mar 2018 15:40:40 -0400 Subject: [PATCH 08/41] changed output to PASS and FAIL --- checks/check11 | 1 - checks/check12 | 1 - checks/list | 166 --- checks/lista | 73 -- include/outputs | 4 +- prowler2 => prowler | 2 +- prowler1 | 2471 ------------------------------------------- 7 files changed, 3 insertions(+), 2715 deletions(-) delete mode 100644 checks/list delete mode 100644 checks/lista rename prowler2 => prowler (99%) delete mode 100755 prowler1 diff --git a/checks/check11 b/checks/check11 index 07ea5c2c82..d56d70f6d4 100644 --- a/checks/check11 +++ b/checks/check11 @@ -6,6 +6,5 @@ CHECK_ALTERNATE_check101="check11" check11(){ # "Avoid the use of the root account (Scored)." COMMAND11=$(cat $TEMP_REPORT_FILE| grep '' | cut -d, -f5,11,16 | sed 's/,/\ /g') - textTitle "$ID11" "$TITLE11" "SCORED" "LEVEL1" textNotice "Root account last accessed (password key_1 key_2): $COMMAND11" } diff --git a/checks/check12 b/checks/check12 index 62f803dfb5..54d68e8bc4 100644 --- a/checks/check12 +++ b/checks/check12 @@ -11,7 +11,6 @@ check12(){ 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 }' done) - textTitle "$ID12" "$TITLE12" "SCORED" "LEVEL1" if [[ $COMMAND12 ]]; then for u in $COMMAND12; do textWarn "User $u has Password enabled but MFA disabled" diff --git a/checks/list b/checks/list deleted file mode 100644 index bb66eca356..0000000000 --- a/checks/list +++ /dev/null @@ -1,166 +0,0 @@ - _ - _ __ _ __ _____ _| | ___ _ __ - | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__| - | |_) | | | (_) \ V V /| | __/ | - | .__/|_| \___/ \_/\_/ |_|\___|_| - |_| CIS based AWS Account Hardening Tool - - Date: Tue Mar 20 21:50:38 EDT 2018 - - 1 Identity and Access Management **************************************** - - 1.1 Avoid the use of the root account (Scored). - - 1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) - - 1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) - - 1.4 Ensure access keys are rotated every 90 days or less (Scored) - - 1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) - - 1.6 Ensure IAM password policy require at least one lowercase letter (Scored) - - 1.7 Ensure IAM password policy require at least one symbol (Scored) - - 1.8 Ensure IAM password policy require at least one number (Scored) - - 1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) - - 1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) - - 1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) - - 1.12 Ensure no root account access key exists (Scored) - - 1.13 Ensure MFA is enabled for the root account (Scored) - - 1.14 Ensure hardware MFA is enabled for the root account (Scored) - - 1.15 Ensure security questions are registered in the AWS account (Not Scored) - - 1.16 Ensure IAM policies are attached only to groups or roles (Scored) - - 1.17 Enable detailed billing (Scored) - - 1.18 Ensure IAM Master and IAM Manager roles are active (Scored) - - 1.19 Maintain current contact details (Scored) - - 1.20 Ensure security contact information is registered (Scored) - - 1.21 Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) - - 1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) - - 1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) - - 1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) - - 2 Logging *************************************************************** - - 2.1 Ensure CloudTrail is enabled in all regions (Scored) - - 2.2 Ensure CloudTrail log file validation is enabled (Scored) - - 2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) - - 2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) - - 2.5 Ensure AWS Config is enabled in all regions (Scored) - - 2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) - - 2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) - - 2.8 Ensure rotation for customer created CMKs is enabled (Scored) - - 3 Monitoring ************************************************************ - - 3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) - - 3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) - - 3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) - - 3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) - - 3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) - - 3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) - - 3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) - - 3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) - - 3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) - - 3.10 Ensure a log metric filter and alarm exist for security group changes (Scored) - - 3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) - - 3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) - - 3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) - - 3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) - - 3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) - - 4 Networking ************************************************************ - - 4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) - - 4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) - - 4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) - - 4.4 Ensure the default security group of every VPC restricts all traffic (Scored) - - 4.5 Ensure routing tables for VPC peering are "least access" (Not Scored) - - 7 Extras **************************************************************** - - 7.1 Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark) - - 7.2 Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark) - - 7.3 Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark) - - 7.4 Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark) - - 7.5 Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark) - - 7.6 Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark) - - 7.7 Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark) - - 7.8 Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark) - - 7.9 Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark) - - 7.10 Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark) - - 7.11 Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark) - - 7.12 Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) - - 7.13 Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) - - 7.14 Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) - - 7.15 Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) - - 7.16 Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark) - - 7.17 Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) - - 7.18 Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) - - 7.19 Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) - - 7.20 Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) - - 7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) - - 7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) diff --git a/checks/lista b/checks/lista deleted file mode 100644 index 4640ead066..0000000000 --- a/checks/lista +++ /dev/null @@ -1,73 +0,0 @@ -check13 -check14 -check15 -check16 -check17 -check18 -check19 -check110 -check111 -check112 -check113 -check114 -check115 -check116 -check117 -check118 -check119 -check120 -check121 -check122 -check123 -check124 -check21 -check22 -check23 -check24 -check25 -check26 -check27 -check28 -check31 -check32 -check33 -check34 -check35 -check36 -check37 -check38 -check39 -check310 -check311 -check312 -check313 -check314 -check315 -check41 -check42 -check43 -check44 -check45 -check_extra71 -check_extra72 -check_extra73 -check_extra74 -check_extra75 -check_extra76 -check_extra77 -check_extra78 -check_extra79 -check_extra710 -check_extra711 -check_extra712 -check_extra713 -check_extra714 -check_extra715 -check_extra716 -check_extra717 -check_extra718 -check_extra719 -check_extra720 -check_extra721 -check_extra722 -check_extra723 diff --git a/include/outputs b/include/outputs index 42ad7336a1..ae9e260e70 100644 --- a/include/outputs +++ b/include/outputs @@ -8,7 +8,7 @@ textOK(){ fi echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" else - echo " $OK OK! $NORMAL $1" + echo " $OK PASS! $NORMAL $1" fi } @@ -35,7 +35,7 @@ textWarn(){ fi echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" else - echo " $BAD WARNING! $1 $NORMAL" + echo " $BAD FAIL! $1 $NORMAL" fi } diff --git a/prowler2 b/prowler similarity index 99% rename from prowler2 rename to prowler index 9fc59819e1..4ac90f4420 100755 --- a/prowler2 +++ b/prowler @@ -222,7 +222,7 @@ show_all_titles() { show_group_title $i # Display the title of the checks IFS=',' read -ra CHECKS <<< ${GROUP_CHECKS[$i]} - for j in "${GROUP_CHECKS[@]}"; do + for j in $CHECKS; do show_check_title $j done done diff --git a/prowler1 b/prowler1 deleted file mode 100755 index fffc0d8c46..0000000000 --- a/prowler1 +++ /dev/null @@ -1,2471 +0,0 @@ -#!/usr/bin/env bash - -# Prowler is a tool that provides automate auditing and hardening guidance of an AWS account. -# It is based on AWS-CLI commands. It follows guidelines present in the CIS Amazon -# Web Services Foundations Benchmark at: -# https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf - -# This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 -# International Public License. The link to the license terms can be found at -# https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode -# -# Author: Toni de la Fuente - @ToniBlyx / Alfresco Software Inc. - -# Prowler - Iron Maiden -# -# Walking through the city, looking oh so pretty -# I've just got to find my way -# See the ladies flashing -# All there legs and lashes -# I've just got to find my way... - -# Exit if a pipeline results in an error. -# set -ue -# set -o pipefail -# set -vx -# Exits if any error is found -# set -e - -OPTRED="" -OPTNORMAL="" - -# Set the defaults for these getopts variables -REGION="us-east-1" -FILTERREGION="" -MAXITEMS=100 -MONOCHROME=0 -MODE="text" -SEP=',' -KEEPCREDREPORT=0 -EXITCODE=0 - - -# Command usage menu -usage(){ - echo " -USAGE: - `basename $0` -p -r [ -h ] - - Options: - -p specify your AWS profile to use (i.e.: default) - -r specify an AWS region to direct API requests to - (i.e.: us-east-1), all regions are checked anyway - -c specify a check number or group from the AWS CIS benchmark - (i.e.: "check11" for check 1.1, "check3" for entire section 3, "level1" for CIS Level 1 Profile Definitions or "forensics-ready") - -f specify an AWS region to run checks against - (i.e.: us-west-1) - -m specify the maximum number of items to return for long-running requests (default: 100) - -M output mode: text (defalut), mono, csv (separator is ","; data is on stdout; progress on stderr) - -k keep the credential report - -n show check numbers to sort easier - (i.e.: 1.01 instead of 1.1) - -l list all available checks only (does not perform any check) - -e exclude extras - -h this help - " - exit -} - -while getopts ":hlkp:r:c:f:m:M:en" OPTION; do - case $OPTION in - h ) - usage - EXITCODE=1 - exit $EXITCODE - ;; - l ) - PRINTCHECKSONLY=1 - ;; - k ) - KEEPCREDREPORT=1 - ;; - p ) - PROFILE=$OPTARG - ;; - r ) - REGION=$OPTARG - ;; - c ) - CHECKNUMBER=$OPTARG - ;; - f ) - FILTERREGION=$OPTARG - ;; - m ) - MAXITEMS=$OPTARG - ;; - M ) - MODE=$OPTARG - ;; - n ) - NUMERAL=1 - ;; - e ) - EXTRAS=1 - ;; - : ) - echo "" - echo "$OPTRED ERROR!$OPTNORMAL -$OPTARG requires an argument" - usage - EXITCODE=1 - exit $EXITCODE - ;; - ? ) - echo "" - echo "$OPTRED ERROR!$OPTNORMAL Invalid option" - usage - EXITCODE=1 - exit $EXITCODE - ;; - esac -done - -if [[ $MODE != "mono" && $MODE != "text" && $MODE != "csv" ]]; then - echo "" - echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, or csv." - usage - EXITCODE=1 - exit $EXITCODE -fi - -if [[ "$MODE" == "mono" || "$MODE" == "csv" ]]; then - MONOCHROME=1 -fi - -if [[ $MONOCHROME -eq 1 ]]; then - # Colors - NORMAL='' - WARNING='' # Bad (red) - SECTION='' # Section (yellow) - NOTICE='' # Notice (yellow) - OK='' # Ok (green) - BAD='' # Bad (red) - CYAN='' - BLUE='' - BROWN='' - DARKGRAY='' - GRAY='' - GREEN='' - MAGENTA='' - PURPLE='' - RED='' - YELLOW='' - WHITE='' -else - # Colors - # NOTE: Your editor may NOT show the 0x1b / escape character left of the '[' - NORMAL="" - WARNING="" # Bad (red) - SECTION="" # Section (yellow) - NOTICE="" # Notice (yellow) - OK="" # Ok (green) - BAD="" # Bad (red) - CYAN="" - BLUE="" - BROWN="" - DARKGRAY="" - GRAY="" - GREEN="" - MAGENTA="" - PURPLE="" - RED="" - YELLOW="" - WHITE="" -fi - -SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) - -# Functions to manage dates depending on OS -if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then - TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) - # 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 - } - decode_report() - { - base64 -d - } -elif [[ "$OSTYPE" == "darwin"* ]]; then - # BSD/OSX commands compatibility - TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX) - 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 - } - decode_report() - { - base64 -D - } -elif [[ "$OSTYPE" == "cygwin" ]]; then - # POSIX compatibility layer and Linux environment emulation for Windows - TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) - 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 - } - decode_report() - { - base64 -d - } -else - echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin" - echo "Found: $OSTYPE" - EXITCODE=1 - exit $EXITCODE -fi - -# It checks -p optoin first and use it as profile, if not -p provided then -# check environment variables and if not, it checks and loads credentials from -# instance profile (metadata server) if runs in an EC2 instance - -if [[ $PROFILE ]]; then - PROFILE_OPT="--profile $PROFILE" -else - # if Prowler runs insinde an AWS instance with IAM instance profile attached - INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) - if [[ $INSTANCE_PROFILE ]]; then - AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g') - AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') - AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') - fi - if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then - PROFILE="ENV" - PROFILE_OPT="" - else - PROFILE="default" - PROFILE_OPT="--profile $PROFILE" - fi -fi - -# AWS-CLI variables -AWSCLI=$(which aws) -if [ -z "${AWSCLI}" ]; then - echo -e "\n$RED ERROR!$NORMAL AWS-CLI (aws command) not found. Make sure it is installed correctly and in your \$PATH\n" - EXITCODE=1 - exit $EXITCODE -fi - -TITLE_ID="" -TITLE_TEXT="CALLER ERROR - UNSET TITLE" -## Output formatting functions -textOK(){ - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $OK OK! $NORMAL $1" - fi -} - -textNotice(){ - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $NOTICE INFO! $1 $NORMAL" - fi -} - -textWarn(){ - EXITCODE=3 - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $BAD WARNING! $1 $NORMAL" - fi -} - -textTitle(){ - TITLE_ID=$1 - if [[ $NUMERAL ]]; then - TITLE_ID=$(echo $TITLE_ID | cut -d, -f2) - else - TITLE_ID=$(echo $TITLE_ID | cut -d, -f1) - fi - - TITLE_TEXT=$2 - - case "$3" in - 0|No|NOT_SCORED) - ITEM_SCORED="Not Scored" - ;; - 1|Yes|SCORED) - ITEM_SCORED="Scored" - ;; - *) - ITEM_SCORED="Unspecified" - ;; - esac - - case "$4" in - LEVEL1) ITEM_LEVEL="Level 1";; - LEVEL2) ITEM_LEVEL="Level 2";; - EXTRA) ITEM_LEVEL="Extra";; - SUPPORT) ITEM_LEVEL="Support";; - *) ITEM_LEVEL="Unspecified or Invalid";; - esac - - if [[ "$MODE" == "csv" ]]; then - >&2 echo "$TITLE_ID $TITLE_TEXT" - else - if [[ "$ITEM_SCORED" == "Scored" ]]; then - echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT" - else - echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" - fi - fi -} - -# List of checks IDs and Titles -TITLE1="Identity and Access Management ****************************************" -ID11="1.1,1.01" -TITLE11="Avoid the use of the root account (Scored)." -ID12="1.2,1.02" -TITLE12="Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" -ID13="1.3,1.03" -TITLE13="Ensure credentials unused for 90 days or greater are disabled (Scored)" -ID14="1.4,1.04" -TITLE14="Ensure access keys are rotated every 90 days or less (Scored)" # also checked by Security Monkey -ID15="1.5,1.05" -TITLE15="Ensure IAM password policy requires at least one uppercase letter (Scored)" -ID16="1.6,1.06" -TITLE16="Ensure IAM password policy require at least one lowercase letter (Scored)" -ID17="1.7,1.07" -TITLE17="Ensure IAM password policy require at least one symbol (Scored)" -ID18="1.8,1.08" -TITLE18="Ensure IAM password policy require at least one number (Scored)" -ID19="1.9,1.09" -TITLE19="Ensure IAM password policy requires minimum length of 14 or greater (Scored)" -ID110="1.10" -TITLE110="Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" -ID111="1.11" -TITLE111="Ensure IAM password policy expires passwords within 90 days or less (Scored)" -ID112="1.12" -TITLE112="Ensure no root account access key exists (Scored)" -ID113="1.13" -TITLE113="Ensure MFA is enabled for the root account (Scored)" -ID114="1.14" -TITLE114="Ensure hardware MFA is enabled for the root account (Scored)" -ID115="1.15" -TITLE115="Ensure security questions are registered in the AWS account (Not Scored)" -ID116="1.16" -TITLE116="Ensure IAM policies are attached only to groups or roles (Scored)" -ID117="1.17" -TITLE117="Enable detailed billing (Scored)" -ID118="1.18" -TITLE118="Ensure IAM Master and IAM Manager roles are active (Scored)" -ID119="1.19" -TITLE119="Maintain current contact details (Scored)" -ID120="1.20" -TITLE120="Ensure security contact information is registered (Scored)" -ID121="1.21" -TITLE121="Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" -ID122="1.22" -TITLE122="Ensure a support role has been created to manage incidents with AWS Support (Scored)" -ID123="1.23" -TITLE123="Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" -ID124="1.24" -TITLE124="Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" -TITLE2="Logging ***************************************************************" -ID21="2.1,2.01" -TITLE21="Ensure CloudTrail is enabled in all regions (Scored)" -ID22="2.2,2.02" -TITLE22="Ensure CloudTrail log file validation is enabled (Scored)" -ID23="2.3,2.03" -TITLE23="Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" -ID24="2.4,2.04" -TITLE24="Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" -ID25="2.5,2.05" -TITLE25="Ensure AWS Config is enabled in all regions (Scored)" -ID26="2.6,2.06" -TITLE26="Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" -ID27="2.7,2.07" -TITLE27="Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" -ID28="2.8,2.08" -TITLE28="Ensure rotation for customer created CMKs is enabled (Scored)" -TITLE3="Monitoring ************************************************************" -ID31="3.1,3.01" -TITLE31="Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" -ID32="3.2,3.02" -TITLE32="Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" -ID33="3.3,3.03" -TITLE33="Ensure a log metric filter and alarm exist for usage of root account (Scored)" -ID34="3.4,3.04" -TITLE34="Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" -ID35="3.5,3.05" -TITLE35="Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" -ID36="3.6,3.06" -TITLE36="Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" -ID37="3.7,3.07" -TITLE37="Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" -ID38="3.8,3.08" -TITLE38="Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" -ID39="3.9,3.09" -TITLE39="Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" -ID310="3.10" -TITLE310="Ensure a log metric filter and alarm exist for security group changes (Scored)" -ID311="3.11" -TITLE311="Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" -ID312="3.12" -TITLE312="Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" -ID313="3.13" -TITLE313="Ensure a log metric filter and alarm exist for route table changes (Scored)" -ID314="3.14" -TITLE314="Ensure a log metric filter and alarm exist for VPC changes (Scored)" -ID315="3.15" -TITLE315="Ensure appropriate subscribers to each SNS topic (Not Scored)" -TITLE4="Networking ************************************************************" -ID41="4.1,4.01" -TITLE41="Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" -ID42="4.2,4.02" -TITLE42="Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" -ID43="4.3,4.03" -TITLE43="Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" -ID44="4.4,4.04" -TITLE44="Ensure the default security group of every VPC restricts all traffic (Scored)" -ID45="4.5,4.05" -TITLE45="Ensure routing tables for VPC peering are \"least access\" (Not Scored)" -TITLE7="Extras ****************************************************************" -ID71="7.1,7.01" -TITLE71="Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" -ID72="7.2,7.02" -TITLE72="Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" -ID73="7.3,7.03" -TITLE73="Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" -ID74="7.4,7.04" -TITLE74="Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" -ID75="7.5,7.05" -TITLE75="Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" -ID76="7.6,7.06" -TITLE76="Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" -ID77="7.7,7.07" -TITLE77="Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" -ID78="7.8,7.08" -TITLE78="Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" -ID79="7.9,7.09" -TITLE79="Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" -ID710="7.10,7.10" -TITLE710="Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" -ID711="7.11,7.11" -TITLE711="Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" -ID712="7.12,7.12" -TITLE712="Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" -ID713="7.13,7.13" -TITLE713="Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" -ID714="7.14,7.14" -TITLE714="Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" -ID715="7.15,7.15" -TITLE715="Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" -ID716="7.16,7.16" -TITLE716="Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" -ID717="7.17,7.17" -TITLE717="Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" -ID718="7.18,7.18" -TITLE718="Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" -ID719="7.19,7.19" -TITLE719="Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" -ID720="7.20,7.20" -TITLE720="Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" -ID721="7.21,7.21" -TITLE721="Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" -ID722="7.22,7.22" -TITLE722="Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" - -printCsvHeader() { - >&2 echo "" - >&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM" - echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES" -} - -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" - echo -e "$YELLOW Date: $(date)" -} - -# Get whoami in AWS, who is the user running this shell script -getWhoami(){ - ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"') - if [[ "$MODE" == "csv" ]]; then - CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn") - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - EXITCODE=2 - exit $EXITCODE - fi - CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') - printCsvHeader - textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT" - textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" - else - echo "" - echo "This report is being generated using credentials below:" - echo "" - echo -e "AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n" - if [[ $MONOCHROME -eq 1 ]]; then - echo "Caller Identity:" - $AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn" - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - exit 2 - fi - echo "" - else - echo "Caller Identity:" - $AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo variable $PROFILE_OPT - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - EXITCODE=2 - exit $EXITCODE - fi - echo "" - fi - fi -} - -printColorsCode(){ - if [[ $MONOCHROME -eq 0 ]]; then - echo -e "\nColors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL \n" - fi -} - -# Generate Credential Report -genCredReport() { - textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT" - until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do - sleep 1 - done -} - -# Save report to a file, decode it, deletion at finish and after every single check -saveReport(){ - $AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE - if [[ $KEEPCREDREPORT -eq 1 ]]; then - textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT" - textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE" - fi -} - -# Delete temporary report file -cleanTemp(){ - if [[ $KEEPCREDREPORT -ne 1 ]]; then - rm -fr $TEMP_REPORT_FILE - fi -} - -# Delete the temporary report file if we get interrupted/terminated -trap cleanTemp EXIT - -# Get a list of all available AWS Regions -REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ - --output text \ - $PROFILE_OPT \ - --region $REGION \ - --region-names $FILTERREGION) - -infoReferenceLong(){ - # Report review note: - echo -e "" - echo -e "For more information on the Prowler, feedback and issue reporting:" - echo -e "https://github.com/Alfresco/prowler" - echo -e "" - echo -e "For more information on the CIS benchmark:" - echo -e "https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf" - -} - -check11(){ - # "Avoid the use of the root account (Scored)." - COMMAND11=$(cat $TEMP_REPORT_FILE| grep '' | cut -d, -f5,11,16 | sed 's/,/\ /g') - textTitle "$ID11" "$TITLE11" "SCORED" "LEVEL1" - textNotice "Root account last accessed (password key_1 key_2): $COMMAND11" -} - -check12(){ - # "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 }' - done) - textTitle "$ID12" "$TITLE12" "SCORED" "LEVEL1" - if [[ $COMMAND12 ]]; then - for u in $COMMAND12; do - textWarn "User $u has Password enabled but MFA disabled" - done - else - textOK "No users found with Password enabled and MFA disabled" - fi -} - -check13(){ - # "Ensure credentials unused for 90 days or greater are disabled (Scored)" - textTitle "$ID13" "$TITLE13" "SCORED" "LEVEL1" - COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED=$(cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$4 }' |grep true | awk '{ print $1 }') - if [[ $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED ]]; then - COMMAND13=$( - for i in $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED; do - cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$5 }' |grep $i| 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_OPT --region $REGION) - if [[ $USERS_PASSWORD_USED ]]; then - # look for users with a password last used more or equal to 90 days - for i in $USERS_PASSWORD_USED; do - DATEUSED=$($AWSCLI iam list-users --query "Users[?UserName=='$i'].PasswordLastUsed" --output text $PROFILE_OPT --region $REGION | cut -d'T' -f1) - HOWOLDER=$(how_older_from_today $DATEUSED) - if [ $HOWOLDER -gt "90" ];then - textWarn "User \"$i\" has not logged in during the last 90 days " - else - textOK "User \"$i\" found with credentials used in the last 90 days" - fi - done - fi - else - textOK "No users found with password enabled" - fi - -} - -check14(){ - # "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 }') - textTitle "$ID14" "$TITLE14" "SCORED" "LEVEL1" - C14_NUM_USERS1=0 - C14_NUM_USERS2=0 - if [[ $LIST_OF_USERS_WITH_ACCESS_KEY1 ]]; then - # textWarn "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 -v user_creation_time | 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 - textWarn " $user has not rotated access key1 in over 90 days " - C14_NUM_USERS1=$(expr $C14_NUM_USERS1 + 1) - fi - done - if [[ $C14_NUM_USERS1 -eq 0 ]]; then - textOK "No users with access key 1 older than 90 days." - fi - else - textOK "No users with access key 1." - fi - - if [[ $LIST_OF_USERS_WITH_ACCESS_KEY2 ]]; then - # textWarn "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 -v user_creation_time | 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 - textWarn " $user has not rotated access key2. " - C14_NUM_USERS2=$(expr $C14_NUM_USERS2 + 1) - fi - done - if [[ $C14_NUM_USERS2 -eq 0 ]]; then - textOK "No users with access key 2 older than 90 days." - fi - else - textOK "No users with access key 2." - fi -} - -check15(){ - # "Ensure IAM password policy requires at least one uppercase letter (Scored)" - COMMAND15=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireUppercaseCharacters' 2> /dev/null) # must be true - textTitle "$ID15" "$TITLE15" "SCORED" "LEVEL1" - if [[ "$COMMAND15" == "true" ]];then - textOK "Password Policy requires upper case" - else - textWarn "Password Policy missing upper-case requirement" - fi -} - -check16(){ - # "Ensure IAM password policy require at least one lowercase letter (Scored)" - COMMAND16=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireLowercaseCharacters' 2> /dev/null) # must be true - textTitle "$ID16" "$TITLE16" "SCORED" "LEVEL1" - if [[ "$COMMAND16" == "true" ]];then - textOK "Password Policy requires lower case" - else - textWarn "Password Policy missing lower-case requirement" - fi -} - -check17(){ - # "Ensure IAM password policy require at least one symbol (Scored)" - COMMAND17=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireSymbols' 2> /dev/null) # must be true - textTitle "$ID17" "$TITLE17" "SCORED" "LEVEL1" - if [[ "$COMMAND17" == "true" ]];then - textOK "Password Policy requires symbol" - else - textWarn "Password Policy missing symbol requirement" - fi -} - -check18(){ - # "Ensure IAM password policy require at least one number (Scored)" - COMMAND18=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireNumbers' 2> /dev/null) # must be true - textTitle "$ID18" "$TITLE18" "SCORED" "LEVEL1" - if [[ "$COMMAND18" == "true" ]];then - textOK "Password Policy requires number" - else - textWarn "Password Policy missing number requirement" - fi -} - -check19(){ - # "Ensure IAM password policy requires minimum length of 14 or greater (Scored)" - COMMAND19=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.MinimumPasswordLength' 2> /dev/null) - textTitle "$ID19" "$TITLE19" "SCORED" "LEVEL1" - if [[ $COMMAND19 -gt "13" ]];then - textOK "Password Policy requires more than 13 characters" - else - textWarn "Password Policy missing or weak length requirement" - fi -} - -check110(){ - # "Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" - COMMAND110=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' --output text 2> /dev/null) - textTitle "$ID110" "$TITLE110" "SCORED" "LEVEL1" - if [[ $COMMAND110 ]];then - if [[ $COMMAND110 -gt "23" ]];then - textOK "Password Policy limits reuse" - else - textWarn "Password Policy has weak reuse requirement (lower than 24)" - fi - else - textWarn "Password Policy missing reuse requirement" - fi -} - -check111(){ - # "Ensure IAM password policy expires passwords within 90 days or less (Scored)" - COMMAND111=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g' 2> /dev/null) - textTitle "$ID111" "$TITLE111" "SCORED" "LEVEL1" - if [[ $COMMAND111 ]];then - if [ "$COMMAND111" == "90" ];then - textOK "Password Policy includes expiration" - fi - else - textWarn "Password expiration not set or set greater than 90 days " - fi -} - -check112(){ - # "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 }') - textTitle "$ID112" "$TITLE112" "SCORED" "LEVEL1" - if [ "$ROOTKEY1" == "false" ];then - textOK "No access key 1 found for root" - else - textWarn "Found access key 1 for root " - fi - if [ "$ROOTKEY2" == "false" ];then - textOK "No access key 2 found for root" - else - textWarn "Found access key 2 for root " - fi -} - -check113(){ - # "Ensure MFA is enabled for the root account (Scored)" - COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') - textTitle "$ID113" "$TITLE113" "SCORED" "LEVEL1" - if [ "$COMMAND113" == "1" ]; then - textOK "Virtual MFA is enabled for root" - else - textWarn "MFA is not ENABLED for root account " - fi -} - -check114(){ - # "Ensure hardware MFA is enabled for the root account (Scored)" - COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') - textTitle "$ID114" "$TITLE114" "SCORED" "LEVEL1" - if [ "$COMMAND113" == "1" ]; then - COMMAND114=$($AWSCLI iam list-virtual-mfa-devices $PROFILE_OPT --region $REGION --output text --assignment-status Assigned --query 'VirtualMFADevices[*].[SerialNumber]' | grep '^arn:aws:iam::[0-9]\{12\}:mfa/root-account-mfa-device$') - if [[ "$COMMAND114" ]]; then - textWarn "Only Virtual MFA is enabled for root" - else - textOK "Hardware MFA is enabled for root " - fi - else - textWarn "MFA is not ENABLED for root account " - fi -} - -check115(){ - # "Ensure security questions are registered in the AWS account (Not Scored)" - textTitle "$ID115" "$TITLE115" "NOT_SCORED" "LEVEL2" - textNotice "No command available for check 1.15 " - textNotice "Login to the AWS Console as root & click on the Account " - textNotice "Name -> My Account -> Configure Security Challenge Questions " -} - -check116(){ - # "Ensure IAM policies are attached only to groups or roles (Scored)" - textTitle "$ID116" "$TITLE116" "SCORED" "LEVEL1" - LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION) - C116_NUM_USERS=0 - for user in $LIST_USERS;do - USER_POLICY=$($AWSCLI iam list-attached-user-policies --output text $PROFILE_OPT --region $REGION --user-name $user) - if [[ $USER_POLICY ]]; then - textWarn "$user has policy directly attached " - C116_NUM_USERS=$(expr $C116_NUM_USERS + 1) - fi - done - if [[ $C116_NUM_USERS -eq 0 ]]; then - textOK "No policies attached to users." - fi -} - -check117(){ - # "Enable detailed billing (Scored)" - # No command available - textTitle "$ID117" "$TITLE117" "SCORED" "LEVEL1" - textNotice "No command available for check 1.17 " - textNotice "See section 1.17 on the CIS Benchmark guide for details " -} - -check118(){ - # "Ensure IAM Master and IAM Manager roles are active (Scored)" - textTitle "$ID118" "$TITLE118" "SCORED" "LEVEL1" - FINDMASTERANDMANAGER=$($AWSCLI iam list-roles $PROFILE_OPT --region $REGION --query "Roles[*].{RoleName:RoleName}" --output text | grep -E 'Master|Manager'| tr '\n' ' ') - if [[ $FINDMASTERANDMANAGER ]];then - textNotice "Found next roles as possible IAM Master and IAM Manager candidates: " - textNotice "$FINDMASTERANDMANAGER " - textNotice "run the commands below to check their policies with section 1.18 in the guide..." - for role in $FINDMASTERANDMANAGER;do - # find inline policies in found roles - INLINEPOLICIES=$($AWSCLI iam list-role-policies --role-name $role $PROFILE_OPT --region $REGION --query "PolicyNames[*]" --output text) - for policy in $INLINEPOLICIES;do - textNotice "INLINE: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json" - done - # find attached policies in found roles - ATTACHEDPOLICIES=$($AWSCLI iam list-attached-role-policies --role-name $role $PROFILE_OPT --region $REGION --query "AttachedPolicies[*]" --output text) - for policy in $ATTACHEDPOLICIES;do - textNotice "ATTACHED: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json" - done - done - else - textWarn "IAM Master and IAM Manager roles not found" - fi -} - -check119(){ - # "Maintain current contact details (Scored)" - # No command available - textTitle "$ID119" "$TITLE119" "SCORED" "LEVEL1" - textNotice "No command available for check 1.19 " - textNotice "See section 1.19 on the CIS Benchmark guide for details " -} - -check120(){ - # "Ensure security contact information is registered (Scored)" - # No command available - textTitle "$ID120" "$TITLE120" "SCORED" "LEVEL1" - textNotice "No command available for check 1.20 " - textNotice "See section 1.20 on the CIS Benchmark guide for details " -} - -check121(){ - # "Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" - textTitle "$ID121" "$TITLE121" "NOT_SCORED" "LEVEL2" - textNotice "No command available for check 1.21 " - textNotice "See section 1.21 on the CIS Benchmark guide for details " -} - -check122(){ - # "Ensure a support role has been created to manage incidents with AWS Support (Scored)" - textTitle "$ID122" "$TITLE122" "SCORED" "LEVEL1" - SUPPORTPOLICYARN=$($AWSCLI iam list-policies --query "Policies[?PolicyName == 'AWSSupportAccess'].Arn" $PROFILE_OPT --region $REGION --output text) - if [[ $SUPPORTPOLICYARN ]];then - for policyarn in $SUPPORTPOLICYARN;do - POLICYUSERS=$($AWSCLI iam list-entities-for-policy --policy-arn $SUPPORTPOLICYARN $PROFILE_OPT --region $REGION --output json) - if [[ $POLICYUSERS ]];then - textOK "Support Policy attached to $policyarn" - for user in $(echo "$POLICYUSERS" | grep UserName | cut -d'"' -f4) ; do - textNotice "User $user has support access via $policyarn" - done - # textNotice "Make sure your team can create a Support case with AWS " - else - textWarn "Support Policy not applied to any Group / User / Role " - fi - done - else - textWarn "No Support Policy found" - fi -} - -check123(){ - # "Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" - textTitle "$ID123" "$TITLE123" "NOT_SCORED" "LEVEL1" - LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION) - # List of USERS with KEY1 last_used_date as N/A - LIST_USERS_KEY1_NA=$(for user in $LIST_USERS; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$11 }'|grep N/A |awk '{ print $1 }'; done) - LIST_USERS_KEY1_ACTIVE=$(for user in $LIST_USERS_KEY1_NA; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$9 }'|grep "true$"|awk '{ print $1 }'|sed 's/[[:blank:]]+/,/g' ; done) - if [[ $LIST_USERS_KEY1_ACTIVE ]]; then - for user in $LIST_USERS_KEY1_ACTIVE; do - textNotice "$user has never used Access Key 1" - done - else - textOK "No users found with Access Key 1 never used" - fi - # List of USERS with KEY2 last_used_date as N/A - LIST_USERS_KEY2_NA=$(for user in $LIST_USERS; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$16 }'|grep N/A |awk '{ print $1 }' ; done) - LIST_USERS_KEY2_ACTIVE=$(for user in $LIST_USERS_KEY2_NA; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$14 }'|grep "true$" |awk '{ print $1 }' ; done) - if [[ $LIST_USERS_KEY2_ACTIVE ]]; then - for user in $LIST_USERS_KEY2_ACTIVE; do - textNotice "$user has never used Access Key 2" - done - else - textOK "No users found with Access Key 2 never used" - fi -} - -check124(){ - # "Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" - textTitle "$ID124" "$TITLE124" "SCORED" "LEVEL1" - LIST_CUSTOM_POLICIES=$($AWSCLI iam list-policies --output text $PROFILE_OPT --region $REGION|grep 'arn:aws:iam::[0-9]\{12\}:'|awk '{ print $2 }') - if [[ $LIST_CUSTOM_POLICIES ]]; then - textNotice "Looking for custom policies: (skipping default policies - it may take few seconds...)" - for policy in $LIST_CUSTOM_POLICIES; do - POLICY_VERSION=$($AWSCLI iam list-policies $PROFILE_OPT --region $REGION --query 'Policies[*].[Arn,DefaultVersionId]' --output text |awk "\$1 == \"$policy\" { print \$2 }") - POLICY_WITH_FULL=$($AWSCLI iam get-policy-version --output text --policy-arn $policy --version-id $POLICY_VERSION --query "PolicyVersion.Document.Statement[?Effect == 'Allow' && contains(Resource, '*') && contains (Action, '*')]" $PROFILE_OPT --region $REGION) - if [[ $POLICY_WITH_FULL ]]; then - POLICIES_ALLOW_LIST="$POLICIES_ALLOW_LIST $policy" - fi - done - if [[ $POLICIES_ALLOW_LIST ]]; then - textNotice "List of custom policies: " - for policy in $POLICIES_ALLOW_LIST; do - textNotice "Policy $policy allows \"*:*\"" - done - else - textOK "No custom policy found that allow full \"*:*\" administrative privileges" - fi - else - textOK "No custom policies found" - fi -} - -check21(){ - # "Ensure CloudTrail is enabled in all regions (Scored)" - textTitle "$ID21" "$TITLE21" "SCORED" "LEVEL1" - LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].Name' --output text) - if [[ $LIST_OF_TRAILS ]];then - for trail in $LIST_OF_TRAILS;do - MULTIREGION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].IsMultiRegionTrail' --output text --trail-name-list $trail) - if [[ "$MULTIREGION_TRAIL_STATUS" == 'False' ]];then - textWarn "$trail trail in $REGION is not enabled in multi region mode" - else - textOK "$trail trail in $REGION is enabled for all regions" - fi - done - else - textWarn "No CloudTrail trails found!" - fi -} - -check22(){ - # "Ensure CloudTrail log file validation is enabled (Scored)" - textTitle "$ID22" "$TITLE22" "SCORED" "LEVEL2" - LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].Name' --output text) - if [[ $LIST_OF_TRAILS ]];then - for trail in $LIST_OF_TRAILS;do - LOGFILEVALIDATION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].LogFileValidationEnabled' --output text --trail-name-list $trail) - if [[ "$LOGFILEVALIDATION_TRAIL_STATUS" == 'False' ]];then - textWarn "$trail trail in $REGION has not log file validation enabled" - else - textOK "$trail trail in $REGION has log file validation enabled" - fi - done - else - textWarn "No CloudTrail trails found!" - fi -} - -check23(){ - # "Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" - textTitle "$ID23" "$TITLE23" "SCORED" "LEVEL1" - CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text $PROFILE_OPT --region $REGION) - if [[ $CLOUDTRAILBUCKET ]];then - for bucket in $CLOUDTRAILBUCKET;do - CLOUDTRAILBUCKET_HASALLPERMISIONS=$($AWSCLI s3api get-bucket-acl --bucket $bucket --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' $PROFILE_OPT --region $REGION --output text) - if [[ $CLOUDTRAILBUCKET_HASALLPERMISIONS ]];then - textWarn "check your $bucket CloudTrail bucket ACL and Policy!" - else - textOK "Bucket $bucket is set correctly" - fi - done - else - textWarn "No CloudTrail bucket found!" - fi -} - -check24(){ - # "Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" - textTitle "$ID24" "$TITLE24" "SCORED" "LEVEL1" - TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion}' --output text | tr "\t" ',') - if [[ $TRAILS_AND_REGIONS ]];then - for reg_trail in $TRAILS_AND_REGIONS;do - trail=$(echo $reg_trail | cut -d',' -f2) - TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) - LATESTDELIVERY_TIMESTAMP=$($AWSCLI cloudtrail get-trail-status --name $trail $PROFILE_OPT --region $TRAIL_REGION --query 'LatestCloudWatchLogsDeliveryTime' --output text|grep -v None) - if [[ ! $LATESTDELIVERY_TIMESTAMP ]];then - textWarn "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" - else - LATESTDELIVERY_DATE=$(timestamp_to_date $LATESTDELIVERY_TIMESTAMP) - HOWOLDER=$(how_older_from_today $LATESTDELIVERY_DATE) - if [ $HOWOLDER -gt "1" ];then - textWarn "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" - else - textOK "$trail trail has been logging during the last 24h (it is in $TRAIL_REGION)" - fi - fi - done - else - textWarn "No CloudTrail trails found!" - fi -} - -check25(){ - # "Ensure AWS Config is enabled in all regions (Scored)" - textTitle "$ID25" "$TITLE25" "SCORED" "LEVEL1" - for regx in $REGIONS; do - CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice get-status $PROFILE_OPT --region $regx --output json| grep "recorder: ON") - if [[ $CHECK_AWSCONFIG_STATUS ]];then - textOK "Region $regx has AWS Config recorder: ON" "$regx" - else - textWarn "Region $regx has AWS Config disabled or not configured" "$regx" - fi - done -} - -check26(){ - # "Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" - textTitle "$ID26" "$TITLE26" "SCORED" "LEVEL1" - CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text $PROFILE_OPT --region $REGION) - if [[ $CLOUDTRAILBUCKET ]];then - for bucket in $CLOUDTRAILBUCKET;do - CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --region $REGION --query 'LoggingEnabled.TargetBucket' --output text|grep -v None) - if [[ $CLOUDTRAILBUCKET_LOGENABLED ]];then - textOK "Bucket access logging enabled in $bucket" - else - textWarn "access logging is not enabled in $bucket CloudTrail S3 bucket!" - fi - done - else - textWarn "CloudTrail bucket not found!" - fi -} - -check27(){ - # "Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" - textTitle "$ID27" "$TITLE27" "SCORED" "LEVEL2" - CLOUDTRAILNAME=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].Name' --output text $PROFILE_OPT --region $REGION) - if [[ $CLOUDTRAILNAME ]];then - for trail in $CLOUDTRAILNAME;do - CLOUDTRAILENC_ENABLED=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --trail $trail --query 'trailList[*].KmsKeyId' --output text) - if [[ $CLOUDTRAILENC_ENABLED ]];then - textOK "KMS key found for $trail" - else - textWarn "encryption is not enabled in your CloudTrail trail $trail (KMS key not found)!" - fi - done - else - textWarn "CloudTrail bucket doesn't exist!" - fi -} - -check28(){ - # "Ensure rotation for customer created CMKs is enabled (Scored)" - textTitle "$ID28" "$TITLE28" "SCORED" "LEVEL2" - for regx in $REGIONS; do - CHECK_KMS_KEYLIST=$($AWSCLI kms list-keys $PROFILE_OPT --region $regx --output text --query 'Keys[*].KeyId') - if [[ $CHECK_KMS_KEYLIST ]];then - CHECK_KMS_KEYLIST_NO_DEFAULT=$(for key in $CHECK_KMS_KEYLIST ; do $AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --output text --query 'KeyMetadata.[KeyId, KeyManager]'|grep -v 'AWS'|awk '{ print $1 }'; done) - for key in $CHECK_KMS_KEYLIST_NO_DEFAULT; do - CHECK_KMS_KEY_TYPE=$($AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --query 'KeyMetadata.Origin' | sed 's/["]//g') - if [[ "$CHECK_KMS_KEY_TYPE" == "EXTERNAL" ]];then - textOK "Key $key in Region $regx Customer Uploaded Key Material." "$regx" - else - CHECK_KMS_KEY_ROTATION=$($AWSCLI kms get-key-rotation-status --key-id $key $PROFILE_OPT --region $regx --output text) - if [[ "$CHECK_KMS_KEY_ROTATION" == "True" ]];then - textOK "Key $key in Region $regx is set correctly" - else - textWarn "Key $key in Region $regx is not set to rotate!!!" "$regx" - fi - fi - done - - else - textNotice "Region $regx doesn't have encryption keys" "$regx" - fi - done -} - -check31(){ - # "Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" - textTitle "$ID31" "$TITLE31" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text| tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | grep $group | awk -F: '{ print $4 }') - #METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | awk '/UnauthorizedOperation/ || /AccessDenied/ {print $3}') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --output text | grep METRICFILTERS | awk 'BEGIN {IGNORECASE=1}; /UnauthorizedOperation/ || /AccessDenied/ {print $3};') - if [[ $METRICFILTER_SET ]];then - for metric in $METRICFILTER_SET; do - metric_name=$($AWSCLI logs describe-metric-filters $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --log-group-name $group --filter-name-prefix $metric --output text --query 'metricFilters[0].metricTransformations[0].metricName') - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[?MetricName==`'$metric_name'`]' --output text) - if [[ $HAS_ALARM_ASSOCIATED ]];then - CHECK31OK="$CHECK31OK $group:$metric" - else - CHECK31WARN="$CHECK31WARN $group:$metric" - fi - done - else - CHECK31WARN="$CHECK31WARN $group" - fi - done - - if [[ $CHECK31OK ]]; then - for group in $CHECK31OK; do - metric=${group#*:} - group=${group%:*} - textOK "CloudWatch group $group found with metric filter $metric and alarms set for Unauthorized Operation and Access Denied" - done - fi - if [[ $CHECK31WARN ]]; then - for group in $CHECK31WARN; do - case $group in - *:*) metric=${group#*:} - group=${group%:*} - textWarn "CloudWatch group $group found with metric filter $metric but no alarms associated" - ;; - *) textWarn "CloudWatch group $group found but no metric filters or alarms associated" - esac - done - fi - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check32(){ - # "Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" - textTitle "$ID32" "$TITLE32" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' |grep filterPattern|grep MFAUsed| awk '/ConsoleLogin/ && (/additionalEventData.MFAUsed.*\!=.*\"Yes/) {print $1}') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /ConsoleLogin/ || /MFAUsed/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms set for sign-in Console without MFA enabled" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check33(){ - # "Ensure a log metric filter and alarm exist for usage of root account (Scored)" - textTitle "$ID33" "$TITLE33" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION |grep -E 'userIdentity.*Root.*AwsServiceEvent') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /userIdentity/ || /Root/ || /AwsServiceEvent/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms set for usage of root account" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check34(){ - # "Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" - textTitle "$ID34" "$TITLE34" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'DeleteGroupPolicy.*DeleteRolePolicy.*DeleteUserPolicy.*PutGroupPolicy.*PutRolePolicy.*PutUserPolicy.*CreatePolicy.*DeletePolicy.*CreatePolicyVersion.*DeletePolicyVersion.*AttachRolePolicy.*DetachRolePolicy.*AttachUserPolicy.*DetachUserPolicy.*AttachGroupPolicy.*DetachGroupPolicy') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /DeletePolicy/ || /DeletePolicies/ || /Policies/ || /Policy/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for IAM policy changes" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check35(){ - # "Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" - textTitle "$ID35" "$TITLE35" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateTrail.*UpdateTrail.*DeleteTrail.*StartLogging.*StopLogging') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /TrailChange/ || /Trails/ || /CreateTrail/ || /UpdateTrail/ || /DeleteTrail/ || /StartLogging/ || /StopLogging/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for CloudTrail configuration changes" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check36(){ - # "Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" - textTitle "$ID36" "$TITLE36" "SCORED" "LEVEL2" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'ConsoleLogin.*Failed') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /FailedLogin/ || /ConsoleLogin/ || /Failed/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for AWS Management Console authentication failures" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check37(){ - # "Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" - textTitle "$ID37" "$TITLE37" "SCORED" "LEVEL2" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'kms.amazonaws.com.*DisableKey.*ScheduleKeyDeletion') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /DisableKey/ || /ScheduleKeyDeletion/ || /kms/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for changes of customer created CMKs" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check38(){ - # "Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" - textTitle "$ID38" "$TITLE38" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 's3.amazonaws.com.*PutBucketAcl.*PutBucketPolicy.*PutBucketCors.*PutBucketLifecycle.*PutBucketReplication.*DeleteBucketPolicy.*DeleteBucketCors.*DeleteBucketLifecycle.*DeleteBucketReplication') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /S3/ || /BucketPolicy/ || /BucketPolicies/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for S3 bucket policy changes" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check39(){ - # "Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" - textTitle "$ID39" "$TITLE39" "SCORED" "LEVEL2" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'config.amazonaws.com.*StopConfigurationRecorder.*DeleteDeliveryChannel.*PutDeliveryChannel.*PutConfigurationRecorder') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /config/ || /ConfigurationRecorder/ || /DeliveryChannel/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for AWS Config configuration changes" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check310(){ - # "Ensure a log metric filter and alarm exist for security group changes (Scored)" - textTitle "$ID310" "$TITLE310" "SCORED" "LEVEL2" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'AuthorizeSecurityGroupIngress.*AuthorizeSecurityGroupEgress.*RevokeSecurityGroupIngress.*RevokeSecurityGroupEgress.*CreateSecurityGroup.*DeleteSecurityGroup') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /SecurityGroup/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for security group changes" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check311(){ - # "Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" - textTitle "$ID311" "$TITLE311" "SCORED" "LEVEL2" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateNetworkAcl.*CreateNetworkAclEntry.*DeleteNetworkAcl.*DeleteNetworkAclEntry.*ReplaceNetworkAclEntry.*ReplaceNetworkAclAssociation') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /NetworkAcl/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for changes to NACLs" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check312(){ - # "Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" - textTitle "$ID312" "$TITLE312" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateCustomerGateway.*DeleteCustomerGateway.*AttachInternetGateway.*CreateInternetGateway.*DeleteInternetGateway.*DetachInternetGateway') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /InternetGateway/ || /CustomerGateway/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for changes to network gateways" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check313(){ - # "Ensure a log metric filter and alarm exist for route table changes (Scored)" - textTitle "$ID313" "$TITLE313" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateRoute.*CreateRouteTable.*ReplaceRoute.*ReplaceRouteTableAssociation.*DeleteRouteTable.*DeleteRoute.*DisassociateRouteTable') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /Route/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for route table changes" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check314(){ - # "Ensure a log metric filter and alarm exist for VPC changes (Scored)" - textTitle "$ID314" "$TITLE314" "SCORED" "LEVEL1" - CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr '\011' '\012' | awk -F: '{ print $7 }') - if [[ $CLOUDWATCH_GROUP ]];then - for group in $CLOUDWATCH_GROUP; do - CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $4 }') - METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | grep -E 'CreateVpc.*DeleteVpc.*ModifyVpcAttribute.*AcceptVpcPeeringConnection.*CreateVpcPeeringConnection.*DeleteVpcPeeringConnection.*RejectVpcPeeringConnection.*AttachClassicLinkVpc.*DetachClassicLinkVpc.*DisableVpcClassicLink.*EnableVpcClassicLink') - if [[ $METRICFILTER_SET ]];then - HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /VPC/;') - if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for VPC changes" - else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" - fi - else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" - fi - done - else - textWarn "No CloudWatch group found for CloudTrail events" - fi -} - -check315(){ - # "Ensure appropriate subscribers to each SNS topic (Not Scored)" - textTitle "$ID315" "$TITLE315" "NOT_SCORED" "LEVEL1" - CAN_SNS_LIST_SUBS=1 - for regx in $REGIONS; do - TOPICS_LIST=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --output text --query 'Topics[*].TopicArn') - ntopics=$(echo $TOPICS_LIST | wc -w ) - if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then - textNotice "Region $regx has $ntopics topics" "$regx" - for topic in $TOPICS_LIST; do - TOPIC_SHORT=$(echo $topic | awk -F: '{ print $6 }') - CHECK_TOPIC_LIST=$($AWSCLI sns list-subscriptions-by-topic --topic-arn $topic $PROFILE_OPT --region $regx --query 'Subscriptions[*].{Endpoint:Endpoint,Protocol:Protocol}' --output text --max-items $MAXITEMS 2> /dev/null) - if [[ $? -eq 255 ]]; then - # Permission error - export CAN_SNS_LIST_SUBS=0 - ntopics=$(echo $TOPICS_LIST | wc -w ) - textNotice "Region $regx / $ntopics Topics / Subscriptions NO_PERMISSION" "$regx" - break; - fi - if [[ "Z" != "Z${CHECK_TOPIC_LIST}" ]]; then - printf '%s\n' "$CHECK_TOPIC_LIST" | while IFS= read -r dest ; do - textNotice "Region $regx / Topic $TOPIC_SHORT / Subscription $dest" "$regx" - done - else - textWarn "Region $regx / Topic $TOPIC_SHORT / Subscription NONE" "$regx" - fi - done - elif [[ $CAN_SNS_LIST_SUBS -eq 0 ]]; then - textNotice "Region $regx has $ntopics topics - unable to list subscribers" "$regx" - # break - else - textOK "Region $regx has 0 topics" "$regx" - fi - done -} - -check41(){ - # "Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" - textTitle "$ID41" "$TITLE41" "SCORED" "LEVEL1" - for regx in $REGIONS; do - SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`22` && ToPort>=`22`)) && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text) - if [[ $SG_LIST ]];then - for SG in $SG_LIST;do - textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" - done - else - textOK "No Security Groups found in $regx with port 22 TCP open to 0.0.0.0/0" "$regx" - fi - done -} - -check42(){ - # "Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" - textTitle "$ID42" "$TITLE42" "SCORED" "LEVEL1" - for regx in $REGIONS; do - SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`3389` && ToPort>=`3389`)) && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text) - if [[ $SG_LIST ]];then - for SG in $SG_LIST;do - textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" - done - else - textOK "No Security Groups found in $regx with port 3389 TCP open to 0.0.0.0/0" "$regx" - fi - done -} - -check43(){ - # "Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" - textTitle "$ID43" "$TITLE43" "SCORED" "LEVEL2" - for regx in $REGIONS; do - CHECK_FL=$($AWSCLI ec2 describe-flow-logs $PROFILE_OPT --region $regx --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].LogGroupName' --output text) - if [[ $CHECK_FL ]];then - for FL in $CHECK_FL;do - textOK "VPCFlowLog is enabled for LogGroupName: $FL in Region $regx" "$regx" - done - else - textWarn "No VPCFlowLog has been found in Region $regx" "$regx" - fi - done -} - -check44(){ - # "Ensure the default security group of every VPC restricts all traffic (Scored)" - textTitle "$ID44" "$TITLE44" "SCORED" "LEVEL2" - for regx in $REGIONS; do - CHECK_SGDEFAULT=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters Name=group-name,Values='default' --query 'SecurityGroups[*].{IpPermissions:IpPermissions,IpPermissionsEgress:IpPermissionsEgress,GroupId:GroupId}' --output text |grep 0.0.0.0) - if [[ $CHECK_SGDEFAULT ]];then - textWarn "Default Security Groups found that allow 0.0.0.0 IN or OUT traffic in Region $regx" "$regx" - else - textOK "No Default Security Groups open to 0.0.0.0 found in Region $regx" "$regx" - fi - done -} - -check45(){ - # "Ensure routing tables for VPC peering are \"least access\" (Not Scored)" - textTitle "$ID45" "$TITLE45" "NOT_SCORED" "LEVEL2" - textNotice "Looking for VPC peering in all regions... " - for regx in $REGIONS; do - LIST_OF_VPCS_PEERING_CONNECTIONS=$($AWSCLI ec2 describe-vpc-peering-connections --output text $PROFILE_OPT --region $regx --query 'VpcPeeringConnections[*].VpcPeeringConnectionId') - if [[ $LIST_OF_VPCS_PEERING_CONNECTIONS ]];then - textNotice "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS - review routing tables" "$regx" - #LIST_OF_VPCS=$($AWSCLI ec2 describe-vpcs $PROFILE_OPT --region $regx --query 'Vpcs[*].VpcId' --output text) - #aws ec2 describe-route-tables --filter "Name=vpc-id,Values=vpc-0213e864" --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" $PROFILE_OPT --region $regx - # for vpc in $LIST_OF_VPCS; do - # VPCS_WITH_PEERING=$($AWSCLI ec2 describe-route-tables --filter "Name=vpc-id,Values=$vpc" $PROFILE_OPT --region $regx --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" |grep GatewayId|grep pcx-) - # done - #echo $VPCS_WITH_PEERING - else - textOK "$regx: No VPC peering found" "$regx" - fi - done -} - -extra71(){ - # "Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID71" "$TITLE71" "NOT_SCORED" "EXTRA" - - ADMIN_GROUPS='' - AWS_GROUPS=$($AWSCLI $PROFILE_OPT iam list-groups --output text --query 'Groups[].GroupName') - for grp in $AWS_GROUPS; do - # aws --profile onlinetraining iam list-attached-group-policies --group-name Administrators --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess' - # list-attached-group-policies - CHECK_ADMIN_GROUP=$($AWSCLI $PROFILE_OPT iam list-attached-group-policies --group-name $grp --output json --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess') - if [[ $CHECK_ADMIN_GROUP ]]; then - ADMIN_GROUPS="$ADMIN_GROUPS $grp" - textNotice "$grp group provides administrative access" - ADMIN_USERS=$($AWSCLI $PROFILE_OPT iam get-group --group-name $grp --output json --query 'Users[].UserName' | grep '"' | cut -d'"' -f2 ) - for auser in $ADMIN_USERS; do - # users in group are Administrators - # users - # check for user MFA device in credential report - USER_MFA_ENABLED=$( cat $TEMP_REPORT_FILE | grep "^$auser," | cut -d',' -f8) - if [[ "true" == $USER_MFA_ENABLED ]]; then - textOK "$auser / MFA Enabled / admin via group $grp" - else - textWarn "$auser / MFA DISABLED / admin via group $grp" - fi - done - else - textNotice "$grp group provides non-administrative access" - fi - done - # set +x -} - -extra72(){ - # "Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID72" "$TITLE72" "NOT_SCORED" "EXTRA" - textNotice "Looking for EBS Snapshots in all regions... " - for regx in $REGIONS; do - LIST_OF_EBS_SNAPSHOTS=$($AWSCLI ec2 describe-snapshots $PROFILE_OPT --region $regx --owner-ids $ACCOUNT_NUM --output text --query 'Snapshots[*].{ID:SnapshotId}' --max-items $MAXITEMS | grep -v None 2> /dev/null) - for snapshot in $LIST_OF_EBS_SNAPSHOTS; do - SNAPSHOT_IS_PUBLIC=$($AWSCLI ec2 describe-snapshot-attribute $PROFILE_OPT --region $regx --output text --snapshot-id $snapshot --attribute createVolumePermission --query "CreateVolumePermissions[?Group=='all']") - if [[ $SNAPSHOT_IS_PUBLIC ]];then - textWarn "$regx: $snapshot is currently Public!" "$regx" - else - textOK "$regx: $snapshot is not Public" "$regx" - fi - done - done - -} - -extra73(){ - # "Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID73" "$TITLE73" "NOT_SCORED" "EXTRA" - textNotice "Looking for open S3 Buckets (ACLs and Policies) in all regions... " - ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' $PROFILE_OPT --region $REGION --output text) - for bucket in $ALL_BUCKETS_LIST; do - BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket $PROFILE_OPT --region $REGION --output text) - if [[ "None" == $BUCKET_LOCATION ]]; then - BUCKET_LOCATION="us-east-1" - fi - if [[ "EU" == $BUCKET_LOCATION ]]; then - BUCKET_LOCATION="eu-west-1" - fi - # check if AllUsers is in the ACL as Grantee - CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE) - CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL) - # check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only - CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE) - CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL) - # to prevent error NoSuchBucketPolicy first clean the output controlling stderr - TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX) - $AWSCLI s3api get-bucket-policy $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null - # check if the S3 policy has Principal as * - CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*) - if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then - if [[ $CHECK_BUCKET_ALLUSERS_ACL ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" - fi - if [[ $CHECK_BUCKET_AUTHUSERS_ACL ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" - fi - if [[ $CHECK_BUCKET_ALLUSERS_POLICY ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" - fi - else - textOK "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" - fi - rm -fr $TEMP_POLICY_FILE - done -} - -extra74(){ - # "Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID74" "$TITLE74" "NOT_SCORED" "EXTRA" - textNotice "Looking for Security Groups in all regions... " - for regx in $REGIONS; do - LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS) - for SG_ID in $LIST_OF_SECURITYGROUPS; do - SG_NO_INGRESS_FILTER=$($AWSCLI ec2 describe-network-interfaces $PROFILE_OPT --region $regx --filters "Name=group-id,Values=$SG_ID" --query "length(NetworkInterfaces)" --output text) - if [[ $SG_NO_INGRESS_FILTER -ne 0 ]];then - textWarn "$regx: $SG_ID has not ingress filtering and it is being used!" "$regx" - else - textNotice "$regx: $SG_ID has not ingress filtering but it is no being used" "$regx" - fi - done - done - -} - -extra75(){ - # "Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID75" "$TITLE75" "NOT_SCORED" "EXTRA" - textNotice "Looking for Security Groups in all regions... " - for regx in $REGIONS; do - LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS) - for SG_ID in $LIST_OF_SECURITYGROUPS; do - SG_NOT_USED=$($AWSCLI ec2 describe-network-interfaces $PROFILE_OPT --region $regx --filters "Name=group-id,Values=$SG_ID" --query "length(NetworkInterfaces)" --output text) - if [[ $SG_NOT_USED -eq 0 ]];then - textWarn "$regx: $SG_ID is not being used!" "$regx" - else - textOK "$regx: $SG_ID is being used" "$regx" - fi - done - done -} - -extra76(){ - # "Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID76" "$TITLE76" "NOT_SCORED" "EXTRA" - textNotice "Looking for AMIs in all regions... " - for regx in $REGIONS; do - LIST_OF_PUBLIC_AMIS=$($AWSCLI ec2 describe-images --owners self $PROFILE_OPT --region $regx --filters "Name=is-public,Values=true" --query 'Images[*].{ID:ImageId}' --output text) - if [[ $LIST_OF_PUBLIC_AMIS ]];then - for ami in $LIST_OF_PUBLIC_AMIS; do - textWarn "$regx: $ami is currently Public!" "$regx" - done - else - textOK "$regx: No Public AMIs found" "$regx" - fi - done -} - -extra77(){ - # "Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID77" "$TITLE77" "NOT_SCORED" "EXTRA" - textNotice "Looking for ECR repos in all regions... " - for regx in $REGIONS; do - LIST_OF_ECR_REPOS=$($AWSCLI ecr describe-repositories $PROFILE_OPT --region $regx --query 'repositories[*].{Name:repositoryName}' --output text) - for ecr_repo in $LIST_OF_ECR_REPOS; do - TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-ecr-repo.policy.XXXXXXXXXX) - $AWSCLI ecr get-repository-policy --repository-name $ecr_repo $PROFILE_OPT --region $regx --output text > $TEMP_POLICY_FILE 2> /dev/null - # check if the policy has Principal as * - CHECK_ECR_REPO_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep \"Principal|grep \*) - if [[ $CHECK_ECR_REPO_ALLUSERS_POLICY ]];then - textWarn "$regx: $ecr_repo policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" - else - textOK "$regx: $ecr_repo is not open" "$regx" - fi - done - rm -fr $TEMP_POLICY_FILE - done -} - -extra78(){ - # "Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID78" "$TITLE78" "NOT_SCORED" "EXTRA" - textNotice "Looking for RDS instances in all regions... " - for regx in $REGIONS; do - LIST_OF_RDS_PUBLIC_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[?PubliclyAccessible==`true`].[DBInstanceIdentifier,Endpoint.Address]' --output text) - if [[ $LIST_OF_RDS_PUBLIC_INSTANCES ]];then - while read -r rds_instance;do - RDS_NAME=$(echo $rds_instance | awk '{ print $1; }') - RDS_DNSNAME=$(echo $rds_instance | awk '{ print $2; }') - textWarn "$regx: RDS instance: $RDS_NAME at $RDS_DNSNAME is set as Publicly Accessible!" "$regx" - done <<< "$LIST_OF_RDS_PUBLIC_INSTANCES" - else - textOK "$regx: no Publicly Accessible RDS instances found" "$regx" - fi - done -} - -extra79(){ - # "Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID79" "$TITLE79" "NOT_SCORED" "EXTRA" - textNotice "Looking for Elastic Load Balancers in all regions... " - for regx in $REGIONS; do - LIST_OF_PUBLIC_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text) - LIST_OF_PUBLIC_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text) - LIST_OF_ALL_ELBS=$( echo $LIST_OF_PUBLIC_ELBS; echo $LIST_OF_PUBLIC_ELBSV2) - LIST_OF_ALL_ELBS_PER_LINE=$( echo $LIST_OF_ALL_ELBS| xargs -n2 ) - if [[ $LIST_OF_ALL_ELBS ]];then - while read -r elb;do - ELB_NAME=$(echo $elb | awk '{ print $1; }') - ELB_DNSNAME=$(echo $elb | awk '{ print $2; }') - textWarn "$regx: ELB: $ELB_NAME at DNS: $ELB_DNSNAME is internet-facing!" "$regx" - done <<< "$LIST_OF_ALL_ELBS_PER_LINE" - else - textOK "$regx: no Internet Facing ELBs found" "$regx" - fi - done -} - -extra710(){ - # "Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID710" "$TITLE710" "NOT_SCORED" "EXTRA" - textNotice "Looking for instances in all regions... " - for regx in $REGIONS; do - LIST_OF_PUBLIC_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]' --output text) - if [[ $LIST_OF_PUBLIC_INSTANCES ]];then - while read -r instance;do - INSTANCE_ID=$(echo $instance | awk '{ print $1; }') - PUBLIC_IP=$(echo $instance | awk '{ print $2; }') - textWarn "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx" - done <<< "$LIST_OF_PUBLIC_INSTANCES" - else - textOK "$regx: no Internet Facing EC2 Instances found" "$regx" - fi - done -} - -extra711(){ - # "Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID711" "$TITLE711" "NOT_SCORED" "EXTRA" - textNotice "Looking for Reshift clusters in all regions... " - for regx in $REGIONS; do - LIST_OF_PUBLIC_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[?PubliclyAccessible == `true`].[ClusterIdentifier,Endpoint.Address]' --output text) - if [[ $LIST_OF_PUBLIC_REDSHIFT_CLUSTERS ]];then - while read -r cluster;do - CLUSTER_ID=$(echo $cluster | awk '{ print $1; }') - CLUSTER_ENDPOINT=$(echo $cluster | awk '{ print $2; }') - textWarn "$regx: Cluster: $CLUSTER_ID at Endpoint: $CLUSTER_ENDPOINT is publicly accessible!" "$regx" - done <<< "$LIST_OF_PUBLIC_REDSHIFT_CLUSTERS" - else - textOK "$regx: no Publicly Accessible Redshift Clusters found" "$regx" - fi - done -} - -extra712(){ - # "Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID712" "$TITLE712" "NOT_SCORED" "EXTRA" - textNotice "No API commands available to check if Macie is enabled," - textNotice "just looking if IAM Macie related permissions exist. " - MACIE_IAM_ROLES_CREATED=$($AWSCLI iam list-roles $PROFILE_OPT --query 'Roles[*].Arn'|grep AWSMacieServiceCustomer|wc -l) - if [[ $MACIE_IAM_ROLES_CREATED -eq 2 ]];then - textOK "Macie related IAM roles exist, so it might be enabled. Check it out manually." - else - textWarn "No Macie related IAM roles found. It is most likely not to be enabled" - fi -} - -extra713(){ - # "Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID713" "$TITLE713" "NOT_SCORED" "EXTRA" - for regx in $REGIONS; do - LIST_OF_GUARDDUTY_DETECTORS=$($AWSCLI guardduty list-detectors $PROFILE_OPT --region $regx --output text |cut -f2) - if [[ $LIST_OF_GUARDDUTY_DETECTORS ]];then - while read -r detector;do - DETECTOR_ENABLED=$($AWSCLI guardduty get-detector --detector-id $detector $PROFILE_OPT --region $regx --output text| cut -f3|grep ENABLED) - if [[ $DETECTOR_ENABLED ]]; then - textOK "$regx: GuardDuty detector $detector enabled" "$regx" - else - textWarn "$regx: GuardDuty detector $detector configured but suspended" "$regx" - fi - done <<< "$LIST_OF_GUARDDUTY_DETECTORS" - else - textWarn "$regx: GuardDuty detector not configured!" "$regx" - fi - done -} - -extra714(){ - # "Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID714" "$TITLE714" "NOT_SCORED" "EXTRA" - for regx in $REGIONS; do - LIST_OF_DISTRIBUTIONS=$($AWSCLI cloudfront list-distributions $PROFILE_OPT --region $regx --query 'DistributionList.Items[].Id' --output text |grep -v "^None") - if [[ $LIST_OF_DISTRIBUTIONS ]]; then - for cdn in $LIST_OF_DISTRIBUTIONS;do - CDN_LOG_ENABLED=$($AWSCLI cloudfront get-distribution $PROFILE_OPT --region $regx --id "$cdn" --query 'Distribution.DistributionConfig.Logging.Enabled' | grep true) - if [[ $CDN_LOG_ENABLED ]];then - textOK "$regx: CDN $cdn logging enabled" "$regx" - else - textWarn "$regx: CDN $cdn logging disabled!" "$regx" - fi - done - else - textNotice "$regx: No CDN configured" "$regx" - fi - done -} - -extra715(){ - # "Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID715" "$TITLE715" "NOT_SCORED" "EXTRA" - for regx in $REGIONS; do - LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text) - if [[ $LIST_OF_DOMAINS ]]; then - for domain in $LIST_OF_DOMAINS;do - SEARCH_SLOWLOG_ENABLED=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.LogPublishingOptions.Options.SEARCH_SLOW_LOGS.Enabled --output text |grep -v ^None|grep -v ^False) - if [[ $SEARCH_SLOWLOG_ENABLED ]];then - textOK "$regx: ElasticSearch Service domain $domain SEARCH_SLOW_LOGS enabled" "$regx" - else - textWarn "$regx: ElasticSearch Service domain $domain SEARCH_SLOW_LOGS disabled!" "$regx" - fi - INDEX_SLOWLOG_ENABLED=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.LogPublishingOptions.Options.INDEX_SLOW_LOGS.Enabled --output text |grep -v ^None|grep -v ^False) - if [[ $INDEX_SLOWLOG_ENABLED ]];then - textOK "$regx: ElasticSearch Service domain $domain INDEX_SLOW_LOGS enabled" "$regx" - else - textWarn "$regx: ElasticSearch Service domain $domain INDEX_SLOW_LOGS disabled!" "$regx" - fi - done - else - textNotice "$regx: No Elasticsearch Service domain found" "$regx" - fi - done -} - -extra716(){ - # "Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID716" "$TITLE716" "NOT_SCORED" "EXTRA" - for regx in $REGIONS; do - LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text) - if [[ $LIST_OF_DOMAINS ]]; then - for domain in $LIST_OF_DOMAINS;do - CHECK_IF_MEMBER_OF_VPC=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.VPCOptions.Options.VPCId --output text|grep -v ^None) - if [[ ! $CHECK_IF_MEMBER_OF_VPC ]];then - TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.policy.XXXXXXXXXX) - $AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.AccessPolicies.Options --output text > $TEMP_POLICY_FILE 2> /dev/null - # check if the policy has Principal as * - CHECK_ES_DOMAIN_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep \"Principal|grep \*) - if [[ $CHECK_ES_DOMAIN_ALLUSERS_POLICY ]];then - textWarn "$regx: $domain policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" - else - textOK "$regx: $domain is not open" "$regx" - fi - else - textOK "$regx: $domain is in a VPC" "$regx" - fi - done - fi - textNotice "$regx: No Elasticsearch Service domain found" "$regx" - rm -fr $TEMP_POLICY_FILE - done -} - -extra717(){ - # "Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID717" "$TITLE717" "NOT_SCORED" "EXTRA" - for regx in $REGIONS; do - LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text|xargs -n1) - LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text|xargs -n1) - if [[ $LIST_OF_ELBS || $LIST_OF_ELBSV2 ]]; then - if [[ $LIST_OF_ELBS ]]; then - for elb in $LIST_OF_ELBS; do - CHECK_ELBS_LOG_ENABLED=$($AWSCLI elb describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-name $elb --query 'LoadBalancerAttributes.AccessLog.Enabled'|grep "^true") - if [[ $CHECK_ELBS_LOG_ENABLED ]]; then - textOK "$regx: $elb has access logs to S3 configured" "$regx" - else - textWarn "$regx: $elb has not configured access logs" "$regx" - fi - done - fi - if [[ $LIST_OF_ELBSV2 ]]; then - for elbarn in $LIST_OF_ELBSV2; do - CHECK_ELBSV2_LOG_ENABLED=$($AWSCLI elbv2 describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-arn $elbarn --query Attributes[*] --output text|grep "^access_logs.s3.enabled"|cut -f2|grep true) - ELBV2_NAME=$(echo $elbarn|cut -d\/ -f3) - if [[ $CHECK_ELBSV2_LOG_ENABLED ]]; then - textOK "$regx: $ELBV2_NAME has access logs to S3 configured" "$regx" - else - textWarn "$regx: $ELBV2_NAME has not configured access logs" "$regx" - fi - done - fi - else - textNotice "$regx: No ELBs found" "$regx" - fi - done -} - -extra718(){ - # "Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID718" "$TITLE718" "NOT_SCORED" "EXTRA" - LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --query Buckets[*].Name --output text|xargs -n1) - if [[ $LIST_OF_BUCKETS ]]; then - for bucket in $LIST_OF_BUCKETS;do - BUCKET_SERVER_LOG_ENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --query [LoggingEnabled] --output text|grep -v "^None$") - if [[ $BUCKET_SERVER_LOG_ENABLED ]];then - textOK "Bucket $bucket has server access logging enabled" - else - textWarn "Bucket $bucket has server access logging disabled!" - fi - done - else - textNotice "No S3 Buckets found" - fi -} - -extra719(){ - # "Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID719" "$TITLE719" "NOT_SCORED" "EXTRA" - LIST_OF_HOSTED_ZONES=$($AWSCLI route53 list-hosted-zones $PROFILE_OPT --query HostedZones[*].Id --output text|xargs -n1) - if [[ $LIST_OF_HOSTED_ZONES ]]; then - for hostedzoneid in $LIST_OF_HOSTED_ZONES;do - HOSTED_ZONE_QUERY_LOG_ENABLED=$($AWSCLI route53 list-query-logging-configs --hosted-zone-id $hostedzoneid $PROFILE_OPT --query QueryLoggingConfigs[*].CloudWatchLogsLogGroupArn --output text|cut -d: -f7) - if [[ $HOSTED_ZONE_QUERY_LOG_ENABLED ]];then - textOK "Route53 hosted zone Id $hostedzoneid has query logging enabled in Log Group $HOSTED_ZONE_QUERY_LOG_ENABLED" - else - textWarn "Route53 hosted zone Id $hostedzoneid has query logging disabled!" - fi - done - else - textNotice "No Route53 hosted zones found" - fi -} - -extra720(){ - # "Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID720" "$TITLE720" "NOT_SCORED" "EXTRA" - for regx in $REGIONS; do - LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text) - if [[ $LIST_OF_FUNCTIONS ]]; then - for lambdafunction in $LIST_OF_FUNCTIONS;do - LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query trailList[?HomeRegion==\`$regx\`].Name --output text) - if [[ $LIST_OF_TRAILS ]]; then - for trail in $LIST_OF_TRAILS; do - FUNCTION_ENABLED_IN_TRAIL=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $regx --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") - if [[ $FUNCTION_ENABLED_IN_TRAIL ]]; then - textOK "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" - else - textWarn "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" - fi - done - # LIST_OF_MULTIREGION_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\`].Name" --output text) - # if [[ $LIST_OF_MULTIREGION_TRAILS ]]; then - # for trail in $LIST_OF_MULTIREGION_TRAILS; do - # REGION_OF_TRAIL=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\` && Name == \`$trail\` ].HomeRegion" --output text) - # FUNCTION_ENABLED_IN_THIS_REGION=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $REGION_OF_TRAIL --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") - # if [[ $FUNCTION_ENABLED_IN_THIS_REGION ]]; then - # textOK "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" - # else - # textWarn "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" - # fi - # done - # else - # textWarn "$regx: Lambda function $lambdafunction is not being recorded!" "$regx" - # fi - else - textWarn "$regx: Lambda function $lambdafunction is not being recorded no CloudTrail found!" "$regx" - fi - done - else - textNotice "$regx: No Lambda functions found" "$regx" - fi - done -} - -extra721(){ - # "Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID721" "$TITLE721" "NOT_SCORED" "EXTRA" - for regx in $REGIONS; do - LIST_OF_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*].ClusterIdentifier' --output text) - if [[ $LIST_OF_REDSHIFT_CLUSTERS ]]; then - for redshiftcluster in $LIST_OF_REDSHIFT_CLUSTERS;do - REDSHIFT_LOG_ENABLED=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query LoggingEnabled --output text | grep True) - if [[ $REDSHIFT_LOG_ENABLED ]];then - REDSHIFT_LOG_ENABLED_BUCKET=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query BucketName --output text) - textOK "$regx: Redshift cluster $redshiftcluster has audit logging enabled to bucket $REDSHIFT_LOG_ENABLED_BUCKET" "$regx" - else - textWarn "$regx: Redshift cluster $redshiftcluster logging disabled!" "$regx" - fi - done - else - textNotice "$regx: No Redshift cluster configured" "$regx" - fi - done -} - -extra722(){ - # "Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID722" "$TITLE722" "NOT_SCORED" "EXTRA" - for regx in $REGIONS; do - LIST_OF_API_GW=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query items[*].id --output text) - if [[ $LIST_OF_API_GW ]];then - for apigwid in $LIST_OF_API_GW;do - API_GW_NAME=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query "items[?id==\`$apigwid\`].name" --output text) - CHECK_STAGES_NAME=$($AWSCLI apigateway get-stages $PROFILE_OPT --region $regx --rest-api-id $apigwid --query "item[*].stageName" --output text) - if [[ $CHECK_STAGES_NAME ]];then - for stagname in $CHECK_STAGES_NAME;do - CHECK_STAGE_METHOD_LOGGING=$($AWSCLI apigateway get-stages $PROFILE_OPT --region $regx --rest-api-id $apigwid --query "item[?stageName == \`$stagname\` ].methodSettings" --output text|awk '{ print $1" log level "$6}') - if [[ $CHECK_STAGE_METHOD_LOGGING ]];then - textOK "$regx: API Gateway $API_GW_NAME has stage logging enabled for $CHECK_STAGE_METHOD_LOGGING" "$regx" - else - textWarn "$regx: API Gateway $API_GW_NAME logging disabled for stage $stagname!" "$regx" - fi - done - else - textWarn "$regx: No Stage name found for $API_GW_NAME" "$regx" - fi - done - else - textNotice "$regx: No API Gateway found" "$regx" - fi - done -} - -callCheck(){ - if [[ $CHECKNUMBER ]];then - case "$CHECKNUMBER" in - check11|check101 ) check11;; - check12|check102 ) check12;; - check13|check103 ) check13;; - check14|check104 ) check14;; - check15|check105 ) check15;; - check16|check106 ) check16;; - check17|check107 ) check17;; - check18|check108 ) check18;; - check19|check109 ) check19;; - check110 ) check110;; - check111 ) check111;; - check112 ) check112;; - check113 ) check113;; - check114 ) check114;; - check115 ) check115;; - check116 ) check116;; - check117 ) check117;; - check118 ) check118;; - check119 ) check119;; - check120 ) check120;; - check121 ) check121;; - check122 ) check122;; - check123 ) check123;; - check124 ) check124;; - check21|check201 ) check21;; - check22|check202 ) check22;; - check23|check203 ) check23;; - check24|check204 ) check24;; - check25|check205 ) check25;; - check26|check206 ) check26;; - check27|check207 ) check27;; - check28|check208 ) check28;; - check31|check301 ) check31;; - check32|check302 ) check32;; - check33|check303 ) check33;; - check34|check304 ) check34;; - check35|check305 ) check35;; - check36|check306 ) check36;; - check37|check307 ) check37;; - check38|check308 ) check38;; - check39|check309 ) check39;; - check310 ) check310;; - check311 ) check311;; - check312 ) check312;; - check313 ) check313;; - check314 ) check314;; - check315 ) check315;; - check41|check401 ) check41;; - check42|check402 ) check42;; - check43|check403 ) check43;; - check44|check404 ) check44;; - check45|check405 ) check45;; - extra71|extra701 ) extra71;; - extra72|extra702 ) extra72;; - extra73|extra703 ) extra73;; - extra74|extra704 ) extra74;; - extra75|extra705 ) extra75;; - extra76|extra706 ) extra76;; - extra77|extra707 ) extra77;; - extra78|extra708 ) extra78;; - extra79|extra709 ) extra79;; - extra710 ) extra710;; - extra711 ) extra711;; - extra712 ) extra712;; - extra713 ) extra713;; - extra714 ) extra714;; - extra715 ) extra715;; - extra716 ) extra716;; - extra717 ) extra717;; - extra718 ) extra718;; - extra719 ) extra719;; - extra720 ) extra720;; - extra721 ) extra721;; - extra722 ) extra722;; - - - ## Groups of Checks - check1 ) - check11;check12;check13;check14;check15;check16;check17;check18; - check19;check110;check111;check112;check113;check114;check115; - check116;check117;check118;check119;check120;check121;check122; - check123;check124; - ;; - check2 ) - check21;check22;check23;check24;check25;check26;check27;check28 - ;; - check3 ) - check31;check32;check33;check34;check35;check36;check37;check38; - check39;check310;check311;check312;check313;check314;check315 - ;; - check4 ) - check41;check42;check43;check44;check45 - ;; - level1 ) - check11;check12;check13;check14;check15;check16;check17;check18; - check19;check110;check111;check112;check113;check115;check116;check117; - check118;check119;check120;check122;check123;check124;check21;check23; - check24;check25;check26;check31;check32;check33;check34;check35; - check38;check312;check313;check314;check315;check41;check42 - ;; - level2 ) - check11;check12;check13;check14;check15;check16;check17;check18; - check19;check110;check111;check112;check113;check114;check115;check116; - check117;check118;check119;check120;check121;check122;check123;check124; - check21;check22;check23;check24;check25;check26;check27;check28;check31; - check32;check33;check34;check35;check36;check37;check38;check39; - check310;check311;check312;check313;check314;check315;check41;check42; - check43;check44;check45 - ;; - extras ) - extra71;extra72;extra73;extra74;extra75;extra76;extra77;extra78; - extra79;extra710;extra711;extra712;extra713;extra714;extra715;extra716; - extra717;extra718;extra719;extra720;extra721;extra722 - ;; - forensics-ready ) - check21;check22;check23;check24;check25;check26;check27; - check43; - extra712;extra713;extra714;extra715;extra717;extra718;extra719; - extra720;extra721;extra722 - ;; - * ) - textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n"; - esac - cleanTemp - exit $EXITCODE - fi -} - -# List only check tittles - -if [[ $PRINTCHECKSONLY == "1" ]]; then - prowlerBanner - textTitle "1" "$TITLE1" "NOT_SCORED" "SUPPORT" - textTitle "$ID11" "$TITLE11" "SCORED" "LEVEL1" - textTitle "$ID12" "$TITLE12" "SCORED" "LEVEL1" - textTitle "$ID13" "$TITLE13" "SCORED" "LEVEL1" - textTitle "$ID14" "$TITLE14" "SCORED" "LEVEL1" - textTitle "$ID15" "$TITLE15" "SCORED" "LEVEL1" - textTitle "$ID16" "$TITLE16" "SCORED" "LEVEL1" - textTitle "$ID17" "$TITLE17" "SCORED" "LEVEL1" - textTitle "$ID18" "$TITLE18" "SCORED" "LEVEL1" - textTitle "$ID19" "$TITLE19" "SCORED" "LEVEL1" - textTitle "$ID110" "$TITLE110" "SCORED" "LEVEL1" - textTitle "$ID111" "$TITLE111" "SCORED" "LEVEL1" - textTitle "$ID112" "$TITLE112" "SCORED" "LEVEL1" - textTitle "$ID113" "$TITLE113" "SCORED" "LEVEL1" - textTitle "$ID114" "$TITLE114" "SCORED" "LEVEL1" - textTitle "$ID115" "$TITLE115" "NOT_SCORED" "LEVEL2" - textTitle "$ID116" "$TITLE116" "SCORED" "LEVEL1" - textTitle "$ID117" "$TITLE117" "SCORED" "LEVEL1" - textTitle "$ID118" "$TITLE118" "SCORED" "LEVEL1" - textTitle "$ID119" "$TITLE119" "SCORED" "LEVEL1" - textTitle "$ID120" "$TITLE120" "SCORED" "LEVEL1" - textTitle "$ID121" "$TITLE121" "NOT_SCORED" "LEVEL2" - textTitle "$ID122" "$TITLE122" "SCORED" "LEVEL1" - textTitle "$ID123" "$TITLE123" "NOT_SCORED" "LEVEL1" - textTitle "$ID124" "$TITLE124" "SCORED" "LEVEL1" - textTitle "2" "$TITLE2" "NOT_SCORED" "SUPPORT" - textTitle "$ID21" "$TITLE21" "SCORED" "LEVEL1" - textTitle "$ID22" "$TITLE22" "SCORED" "LEVEL2" - textTitle "$ID23" "$TITLE23" "SCORED" "LEVEL1" - textTitle "$ID24" "$TITLE24" "SCORED" "LEVEL1" - textTitle "$ID25" "$TITLE25" "SCORED" "LEVEL1" - textTitle "$ID26" "$TITLE26" "SCORED" "LEVEL1" - textTitle "$ID27" "$TITLE27" "SCORED" "LEVEL2" - textTitle "$ID28" "$TITLE28" "SCORED" "LEVEL2" - textTitle "3" "$TITLE3" "NOT_SCORED" "SUPPORT" - textTitle "$ID31" "$TITLE31" "SCORED" "LEVEL1" - textTitle "$ID32" "$TITLE32" "SCORED" "LEVEL1" - textTitle "$ID33" "$TITLE33" "SCORED" "LEVEL1" - textTitle "$ID34" "$TITLE34" "SCORED" "LEVEL1" - textTitle "$ID35" "$TITLE35" "SCORED" "LEVEL1" - textTitle "$ID36" "$TITLE36" "SCORED" "LEVEL2" - textTitle "$ID37" "$TITLE37" "SCORED" "LEVEL2" - textTitle "$ID38" "$TITLE38" "SCORED" "LEVEL1" - textTitle "$ID39" "$TITLE39" "SCORED" "LEVEL2" - textTitle "$ID310" "$TITLE310" "SCORED" "LEVEL2" - textTitle "$ID311" "$TITLE311" "SCORED" "LEVEL2" - textTitle "$ID312" "$TITLE312" "SCORED" "LEVEL1" - textTitle "$ID313" "$TITLE313" "SCORED" "LEVEL1" - textTitle "$ID314" "$TITLE314" "SCORED" "LEVEL1" - textTitle "$ID315" "$TITLE315" "NOT_SCORED" "LEVEL1" - textTitle "4" "$TITLE4" "NOT_SCORED" "SUPPORT" - textTitle "$ID41" "$TITLE41" "SCORED" "LEVEL1" - textTitle "$ID42" "$TITLE42" "SCORED" "LEVEL1" - textTitle "$ID43" "$TITLE43" "SCORED" "LEVEL2" - textTitle "$ID44" "$TITLE44" "SCORED" "LEVEL2" - textTitle "$ID45" "$TITLE45" "NOT_SCORED" "LEVEL2" - textTitle "7" "$TITLE7" "NOT_SCORED" "SUPPORT" - textTitle "$ID71" "$TITLE71" "NOT_SCORED" "EXTRA" - textTitle "$ID72" "$TITLE72" "NOT_SCORED" "EXTRA" - textTitle "$ID73" "$TITLE73" "NOT_SCORED" "EXTRA" - textTitle "$ID74" "$TITLE74" "NOT_SCORED" "EXTRA" - textTitle "$ID75" "$TITLE75" "NOT_SCORED" "EXTRA" - textTitle "$ID76" "$TITLE76" "NOT_SCORED" "EXTRA" - textTitle "$ID77" "$TITLE77" "NOT_SCORED" "EXTRA" - textTitle "$ID78" "$TITLE78" "NOT_SCORED" "EXTRA" - textTitle "$ID79" "$TITLE79" "NOT_SCORED" "EXTRA" - textTitle "$ID710" "$TITLE710" "NOT_SCORED" "EXTRA" - textTitle "$ID711" "$TITLE711" "NOT_SCORED" "EXTRA" - textTitle "$ID712" "$TITLE712" "NOT_SCORED" "EXTRA" - textTitle "$ID713" "$TITLE713" "NOT_SCORED" "EXTRA" - textTitle "$ID714" "$TITLE714" "NOT_SCORED" "EXTRA" - textTitle "$ID715" "$TITLE715" "NOT_SCORED" "EXTRA" - textTitle "$ID716" "$TITLE716" "NOT_SCORED" "EXTRA" - textTitle "$ID717" "$TITLE717" "NOT_SCORED" "EXTRA" - textTitle "$ID718" "$TITLE718" "NOT_SCORED" "EXTRA" - textTitle "$ID719" "$TITLE719" "NOT_SCORED" "EXTRA" - textTitle "$ID720" "$TITLE720" "NOT_SCORED" "EXTRA" - textTitle "$ID721" "$TITLE721" "NOT_SCORED" "EXTRA" - textTitle "$ID722" "$TITLE722" "NOT_SCORED" "EXTRA" - exit $EXITCODE -fi - -### All functions defined above ... run the workflow - -if [[ $MODE != "csv" ]]; then - prowlerBanner - printColorsCode -fi -getWhoami -genCredReport -saveReport -callCheck - -textTitle "1" "$TITLE1" "NOT_SCORED" "SUPPORT" -check11 -check12 -check13 -check14 -check15 -check16 -check17 -check18 -check19 -check110 -check111 -check112 -check113 -check114 -check115 -check116 -check117 -check118 -check119 -check120 -check121 -check122 -check123 -check124 - -textTitle "2" "$TITLE2" "NOT_SCORED" "SUPPORT" -check21 -check22 -check23 -check24 -check25 -check26 -check27 -check28 - -textTitle "3" "$TITLE3" "NOT_SCORED" "SUPPORT" -# 3 Monitoring check commands / Mostly covered by SecurityMonkey -check31 -check32 -check33 -check34 -check35 -check36 -check37 -check38 -check39 -check310 -check311 -check312 -check313 -check314 -check315 - -textTitle "4" "$TITLE4" "NOT_SCORED" "SUPPORT" -check41 -check42 -check43 -check44 -check45 - -if [[ ! $EXTRAS ]]; then - textTitle "7" "$TITLE7" "NOT_SCORED" "SUPPORT" - extra71 - extra72 - extra73 - extra74 - extra75 - extra76 - extra77 - extra78 - extra79 - extra710 - extra711 - extra712 - extra713 - extra714 - extra715 - extra716 - extra717 - extra718 - extra719 - extra720 - extra721 - extra722 -fi - -cleanTemp -exit $EXITCODE From 6647702d90b1d1f12869d7c87a15373e4ee5e92b Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 26 Mar 2018 21:32:15 -0400 Subject: [PATCH 09/41] added support of -g groups --- checks/check110 | 1 - checks/check111 | 1 - checks/check112 | 1 - checks/check113 | 1 - checks/check114 | 1 - checks/check115 | 1 - checks/check116 | 1 - checks/check117 | 1 - checks/check118 | 1 - checks/check119 | 1 - checks/check120 | 1 - checks/check121 | 1 - checks/check122 | 1 - checks/check123 | 1 - checks/check124 | 1 - checks/check13 | 1 - checks/check14 | 1 - checks/check15 | 1 - checks/check16 | 1 - checks/check17 | 1 - checks/check18 | 1 - checks/check19 | 1 - checks/check21 | 1 - checks/check22 | 1 - checks/check23 | 1 - checks/check24 | 1 - checks/check25 | 1 - checks/check26 | 1 - checks/check27 | 1 - checks/check28 | 1 - checks/check31 | 1 - checks/check310 | 1 - checks/check311 | 1 - checks/check312 | 1 - checks/check313 | 1 - checks/check314 | 1 - checks/check315 | 1 - checks/check32 | 1 - checks/check33 | 1 - checks/check34 | 1 - checks/check35 | 1 - checks/check36 | 1 - checks/check37 | 1 - checks/check38 | 1 - checks/check39 | 1 - checks/check41 | 1 - checks/check42 | 1 - checks/check43 | 1 - checks/check44 | 1 - checks/check45 | 1 - checks/check_extra71 | 1 - checks/check_extra710 | 1 - checks/check_extra711 | 1 - checks/check_extra712 | 1 - checks/check_extra713 | 1 - checks/check_extra714 | 1 - checks/check_extra715 | 1 - checks/check_extra716 | 1 - checks/check_extra717 | 1 - checks/check_extra718 | 1 - checks/check_extra719 | 1 - checks/check_extra72 | 1 - checks/check_extra720 | 1 - checks/check_extra721 | 1 - checks/check_extra722 | 1 - checks/check_extra723 | 1 - checks/check_extra73 | 1 - checks/check_extra74 | 1 - checks/check_extra75 | 1 - checks/check_extra76 | 1 - checks/check_extra77 | 1 - checks/check_extra78 | 1 - checks/check_extra79 | 1 - groups/group0_init | 6 ------ include/banner | 17 ++++++++++------- include/colors | 2 +- include/outputs | 2 +- prowler | 41 +++++++++++++++++++++++++++++------------ 78 files changed, 41 insertions(+), 100 deletions(-) delete mode 100644 groups/group0_init diff --git a/checks/check110 b/checks/check110 index b016c23bcf..5f31e84423 100644 --- a/checks/check110 +++ b/checks/check110 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check110="check110" check110(){ # "Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" COMMAND110=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' --output text 2> /dev/null) - textTitle "$ID110" "$TITLE110" "SCORED" "LEVEL1" if [[ $COMMAND110 ]];then if [[ $COMMAND110 -gt "23" ]];then textOK "Password Policy limits reuse" diff --git a/checks/check111 b/checks/check111 index b78f2adcad..3d93a54826 100644 --- a/checks/check111 +++ b/checks/check111 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check111="check111" check111(){ # "Ensure IAM password policy expires passwords within 90 days or less (Scored)" COMMAND111=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g' 2> /dev/null) - textTitle "$ID111" "$TITLE111" "SCORED" "LEVEL1" if [[ $COMMAND111 ]];then if [ "$COMMAND111" == "90" ];then textOK "Password Policy includes expiration" diff --git a/checks/check112 b/checks/check112 index dc2682f9e4..84472b5c14 100644 --- a/checks/check112 +++ b/checks/check112 @@ -8,7 +8,6 @@ check112(){ # 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 }') - textTitle "$ID112" "$TITLE112" "SCORED" "LEVEL1" if [ "$ROOTKEY1" == "false" ];then textOK "No access key 1 found for root" else diff --git a/checks/check113 b/checks/check113 index e6992d5505..9f9fb57932 100644 --- a/checks/check113 +++ b/checks/check113 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check113="check113" check113(){ # "Ensure MFA is enabled for the root account (Scored)" COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') - textTitle "$ID113" "$TITLE113" "SCORED" "LEVEL1" if [ "$COMMAND113" == "1" ]; then textOK "Virtual MFA is enabled for root" else diff --git a/checks/check114 b/checks/check114 index cf1d7b0643..058c38497f 100644 --- a/checks/check114 +++ b/checks/check114 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check114="check114" check114(){ # "Ensure hardware MFA is enabled for the root account (Scored)" COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') - textTitle "$ID114" "$TITLE114" "SCORED" "LEVEL1" if [ "$COMMAND113" == "1" ]; then COMMAND114=$($AWSCLI iam list-virtual-mfa-devices $PROFILE_OPT --region $REGION --output text --assignment-status Assigned --query 'VirtualMFADevices[*].[SerialNumber]' | grep '^arn:aws:iam::[0-9]\{12\}:mfa/root-account-mfa-device$') if [[ "$COMMAND114" ]]; then diff --git a/checks/check115 b/checks/check115 index 13b0bc8978..007d9f04d6 100644 --- a/checks/check115 +++ b/checks/check115 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check115="check115" check115(){ # "Ensure security questions are registered in the AWS account (Not Scored)" - textTitle "$ID115" "$TITLE115" "NOT_SCORED" "LEVEL2" textNotice "No command available for check 1.15 " textNotice "Login to the AWS Console as root & click on the Account " textNotice "Name -> My Account -> Configure Security Challenge Questions " diff --git a/checks/check116 b/checks/check116 index c6afa34bea..ae9aee0c7b 100644 --- a/checks/check116 +++ b/checks/check116 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check116="check116" check116(){ # "Ensure IAM policies are attached only to groups or roles (Scored)" - textTitle "$ID116" "$TITLE116" "SCORED" "LEVEL1" LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION) C116_NUM_USERS=0 for user in $LIST_USERS;do diff --git a/checks/check117 b/checks/check117 index e37c9f6b02..352e3960ef 100644 --- a/checks/check117 +++ b/checks/check117 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check117="check117" check117(){ # "Enable detailed billing (Scored)" # No command available - textTitle "$ID117" "$TITLE117" "SCORED" "LEVEL1" textNotice "No command available for check 1.17 " textNotice "See section 1.17 on the CIS Benchmark guide for details " } diff --git a/checks/check118 b/checks/check118 index a3d0537a3c..e98769123f 100644 --- a/checks/check118 +++ b/checks/check118 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check118="check118" check118(){ # "Ensure IAM Master and IAM Manager roles are active (Scored)" - textTitle "$ID118" "$TITLE118" "SCORED" "LEVEL1" FINDMASTERANDMANAGER=$($AWSCLI iam list-roles $PROFILE_OPT --region $REGION --query "Roles[*].{RoleName:RoleName}" --output text | grep -E 'Master|Manager'| tr ' ' ' ') if [[ $FINDMASTERANDMANAGER ]];then diff --git a/checks/check119 b/checks/check119 index b4fe37d585..4c3b797b50 100644 --- a/checks/check119 +++ b/checks/check119 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check119="check119" check119(){ # "Maintain current contact details (Scored)" # No command available - textTitle "$ID119" "$TITLE119" "SCORED" "LEVEL1" textNotice "No command available for check 1.19 " textNotice "See section 1.19 on the CIS Benchmark guide for details " } diff --git a/checks/check120 b/checks/check120 index 20de93c38e..6bce3e6e2b 100644 --- a/checks/check120 +++ b/checks/check120 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check120="check120" check120(){ # "Ensure security contact information is registered (Scored)" # No command available - textTitle "$ID120" "$TITLE120" "SCORED" "LEVEL1" textNotice "No command available for check 1.20 " textNotice "See section 1.20 on the CIS Benchmark guide for details " } diff --git a/checks/check121 b/checks/check121 index d593576be3..3457ec0605 100644 --- a/checks/check121 +++ b/checks/check121 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check121="check121" check121(){ # "Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" - textTitle "$ID121" "$TITLE121" "NOT_SCORED" "LEVEL2" textNotice "No command available for check 1.21 " textNotice "See section 1.21 on the CIS Benchmark guide for details " } diff --git a/checks/check122 b/checks/check122 index 0cea82df30..d5c2a81cbc 100644 --- a/checks/check122 +++ b/checks/check122 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check122="check122" check122(){ # "Ensure a support role has been created to manage incidents with AWS Support (Scored)" - textTitle "$ID122" "$TITLE122" "SCORED" "LEVEL1" SUPPORTPOLICYARN=$($AWSCLI iam list-policies --query "Policies[?PolicyName == 'AWSSupportAccess'].Arn" $PROFILE_OPT --region $REGION --output text) if [[ $SUPPORTPOLICYARN ]];then for policyarn in $SUPPORTPOLICYARN;do diff --git a/checks/check123 b/checks/check123 index 6cdda330d0..4118f796d2 100644 --- a/checks/check123 +++ b/checks/check123 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check123="check123" check123(){ # "Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" - textTitle "$ID123" "$TITLE123" "NOT_SCORED" "LEVEL1" LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION) # List of USERS with KEY1 last_used_date as N/A LIST_USERS_KEY1_NA=$(for user in $LIST_USERS; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$11 }'|grep N/A |awk '{ print $1 }'; done) diff --git a/checks/check124 b/checks/check124 index 95e1eaf006..7ae7855222 100644 --- a/checks/check124 +++ b/checks/check124 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check124="check124" check124(){ # "Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" - textTitle "$ID124" "$TITLE124" "SCORED" "LEVEL1" LIST_CUSTOM_POLICIES=$($AWSCLI iam list-policies --output text $PROFILE_OPT --region $REGION|grep 'arn:aws:iam::[0-9]\{12\}:'|awk '{ print $2 }') if [[ $LIST_CUSTOM_POLICIES ]]; then textNotice "Looking for custom policies: (skipping default policies - it may take few seconds...)" diff --git a/checks/check13 b/checks/check13 index 154dad3bf2..0ef66c7cec 100644 --- a/checks/check13 +++ b/checks/check13 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check103="check13" check13(){ # "Ensure credentials unused for 90 days or greater are disabled (Scored)" - textTitle "$ID13" "$TITLE13" "SCORED" "LEVEL1" COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED=$(cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$4 }' |grep true | awk '{ print $1 }') if [[ $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED ]]; then COMMAND13=$( diff --git a/checks/check14 b/checks/check14 index 0a1d4a02a9..8aaf408713 100644 --- a/checks/check14 +++ b/checks/check14 @@ -7,7 +7,6 @@ check14(){ # "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 }') - textTitle "$ID14" "$TITLE14" "SCORED" "LEVEL1" C14_NUM_USERS1=0 C14_NUM_USERS2=0 if [[ $LIST_OF_USERS_WITH_ACCESS_KEY1 ]]; then diff --git a/checks/check15 b/checks/check15 index 0cb0b2359d..698fae1aa4 100644 --- a/checks/check15 +++ b/checks/check15 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check105="check15" check15(){ # "Ensure IAM password policy requires at least one uppercase letter (Scored)" COMMAND15=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireUppercaseCharacters' 2> /dev/null) # must be true - textTitle "$ID15" "$TITLE15" "SCORED" "LEVEL1" if [[ "$COMMAND15" == "true" ]];then textOK "Password Policy requires upper case" else diff --git a/checks/check16 b/checks/check16 index 255d4780f8..8ae18a2225 100644 --- a/checks/check16 +++ b/checks/check16 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check106="check16" check16(){ # "Ensure IAM password policy require at least one lowercase letter (Scored)" COMMAND16=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireLowercaseCharacters' 2> /dev/null) # must be true - textTitle "$ID16" "$TITLE16" "SCORED" "LEVEL1" if [[ "$COMMAND16" == "true" ]];then textOK "Password Policy requires lower case" else diff --git a/checks/check17 b/checks/check17 index c031f18745..18177b6132 100644 --- a/checks/check17 +++ b/checks/check17 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check107="check17" check17(){ # "Ensure IAM password policy require at least one symbol (Scored)" COMMAND17=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireSymbols' 2> /dev/null) # must be true - textTitle "$ID17" "$TITLE17" "SCORED" "LEVEL1" if [[ "$COMMAND17" == "true" ]];then textOK "Password Policy requires symbol" else diff --git a/checks/check18 b/checks/check18 index f2acba9f61..2f2189ee0f 100644 --- a/checks/check18 +++ b/checks/check18 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check18="check18" check18(){ # "Ensure IAM password policy require at least one number (Scored)" COMMAND18=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireNumbers' 2> /dev/null) # must be true - textTitle "$ID18" "$TITLE18" "SCORED" "LEVEL1" if [[ "$COMMAND18" == "true" ]];then textOK "Password Policy requires number" else diff --git a/checks/check19 b/checks/check19 index 1c20e6d809..08f880a07b 100644 --- a/checks/check19 +++ b/checks/check19 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check109="check19" check19(){ # "Ensure IAM password policy requires minimum length of 14 or greater (Scored)" COMMAND19=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.MinimumPasswordLength' 2> /dev/null) - textTitle "$ID19" "$TITLE19" "SCORED" "LEVEL1" if [[ $COMMAND19 -gt "13" ]];then textOK "Password Policy requires more than 13 characters" else diff --git a/checks/check21 b/checks/check21 index 58056d0b5e..bd7b0fcf79 100644 --- a/checks/check21 +++ b/checks/check21 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check201="check21" check21(){ # "Ensure CloudTrail is enabled in all regions (Scored)" - textTitle "$ID21" "$TITLE21" "SCORED" "LEVEL1" LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].Name' --output text) if [[ $LIST_OF_TRAILS ]];then for trail in $LIST_OF_TRAILS;do diff --git a/checks/check22 b/checks/check22 index 36c1514f92..ca3d48ae55 100644 --- a/checks/check22 +++ b/checks/check22 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check202="check22" check22(){ # "Ensure CloudTrail log file validation is enabled (Scored)" - textTitle "$ID22" "$TITLE22" "SCORED" "LEVEL2" LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].Name' --output text) if [[ $LIST_OF_TRAILS ]];then for trail in $LIST_OF_TRAILS;do diff --git a/checks/check23 b/checks/check23 index 4306145e2c..5e44808f4e 100644 --- a/checks/check23 +++ b/checks/check23 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check203="check23" check23(){ # "Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" - textTitle "$ID23" "$TITLE23" "SCORED" "LEVEL1" CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text $PROFILE_OPT --region $REGION) if [[ $CLOUDTRAILBUCKET ]];then for bucket in $CLOUDTRAILBUCKET;do diff --git a/checks/check24 b/checks/check24 index 690f572bef..438d6bd20a 100644 --- a/checks/check24 +++ b/checks/check24 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check204="check24" check24(){ # "Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" - textTitle "$ID24" "$TITLE24" "SCORED" "LEVEL1" TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion}' --output text | tr " " ',') if [[ $TRAILS_AND_REGIONS ]];then for reg_trail in $TRAILS_AND_REGIONS;do diff --git a/checks/check25 b/checks/check25 index b97adefcab..d321b0a42a 100644 --- a/checks/check25 +++ b/checks/check25 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check205="check25" check25(){ # "Ensure AWS Config is enabled in all regions (Scored)" - textTitle "$ID25" "$TITLE25" "SCORED" "LEVEL1" for regx in $REGIONS; do CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice get-status $PROFILE_OPT --region $regx --output json| grep "recorder: ON") if [[ $CHECK_AWSCONFIG_STATUS ]];then diff --git a/checks/check26 b/checks/check26 index 33f68e900e..8f72cbbae8 100644 --- a/checks/check26 +++ b/checks/check26 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check206="check26" check26(){ # "Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" - textTitle "$ID26" "$TITLE26" "SCORED" "LEVEL1" CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text $PROFILE_OPT --region $REGION) if [[ $CLOUDTRAILBUCKET ]];then for bucket in $CLOUDTRAILBUCKET;do diff --git a/checks/check27 b/checks/check27 index f0feff85e3..8b1964c168 100644 --- a/checks/check27 +++ b/checks/check27 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check207="check27" check27(){ # "Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" - textTitle "$ID27" "$TITLE27" "SCORED" "LEVEL2" CLOUDTRAILNAME=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].Name' --output text $PROFILE_OPT --region $REGION) if [[ $CLOUDTRAILNAME ]];then for trail in $CLOUDTRAILNAME;do diff --git a/checks/check28 b/checks/check28 index fa0b0a4d71..9f016dc4c0 100644 --- a/checks/check28 +++ b/checks/check28 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check208="check28" check28(){ # "Ensure rotation for customer created CMKs is enabled (Scored)" - textTitle "$ID28" "$TITLE28" "SCORED" "LEVEL2" for regx in $REGIONS; do CHECK_KMS_KEYLIST=$($AWSCLI kms list-keys $PROFILE_OPT --region $regx --output text --query 'Keys[*].KeyId') if [[ $CHECK_KMS_KEYLIST ]];then diff --git a/checks/check31 b/checks/check31 index 4ca73f4079..1a29627844 100644 --- a/checks/check31 +++ b/checks/check31 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check301="check31" check31(){ # "Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" - textTitle "$ID31" "$TITLE31" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text| tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check310 b/checks/check310 index a28a76a304..78c0ad9793 100644 --- a/checks/check310 +++ b/checks/check310 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check310="check310" check310(){ # "Ensure a log metric filter and alarm exist for security group changes (Scored)" - textTitle "$ID310" "$TITLE310" "SCORED" "LEVEL2" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check311 b/checks/check311 index c2e26c8806..b363f3f2de 100644 --- a/checks/check311 +++ b/checks/check311 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check311="check311" check311(){ # "Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" - textTitle "$ID311" "$TITLE311" "SCORED" "LEVEL2" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check312 b/checks/check312 index ecfd969a14..e37273804f 100644 --- a/checks/check312 +++ b/checks/check312 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check312="check312" check312(){ # "Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" - textTitle "$ID312" "$TITLE312" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check313 b/checks/check313 index 3ab3531b46..8e92c7d5c0 100644 --- a/checks/check313 +++ b/checks/check313 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check313="check313" check313(){ # "Ensure a log metric filter and alarm exist for route table changes (Scored)" - textTitle "$ID313" "$TITLE313" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check314 b/checks/check314 index 0bec02fa99..a840929d3b 100644 --- a/checks/check314 +++ b/checks/check314 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check314="check314" check314(){ # "Ensure a log metric filter and alarm exist for VPC changes (Scored)" - textTitle "$ID314" "$TITLE314" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check315 b/checks/check315 index 68f30c5550..239bd8dece 100644 --- a/checks/check315 +++ b/checks/check315 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check315="check315" check315(){ # "Ensure appropriate subscribers to each SNS topic (Not Scored)" - textTitle "$ID315" "$TITLE315" "NOT_SCORED" "LEVEL1" CAN_SNS_LIST_SUBS=1 for regx in $REGIONS; do TOPICS_LIST=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --output text --query 'Topics[*].TopicArn') diff --git a/checks/check32 b/checks/check32 index f07cb1a632..9122b14817 100644 --- a/checks/check32 +++ b/checks/check32 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check302="check32" check32(){ # "Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" - textTitle "$ID32" "$TITLE32" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check33 b/checks/check33 index 49e04219bc..37c56daf99 100644 --- a/checks/check33 +++ b/checks/check33 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check303="check33" check33(){ # "Ensure a log metric filter and alarm exist for usage of root account (Scored)" - textTitle "$ID33" "$TITLE33" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check34 b/checks/check34 index 3d9e89449f..3d576033c6 100644 --- a/checks/check34 +++ b/checks/check34 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check304="check34" check34(){ # "Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" - textTitle "$ID34" "$TITLE34" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check35 b/checks/check35 index a4d144a893..9bcf623db9 100644 --- a/checks/check35 +++ b/checks/check35 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check305="check35" check35(){ # "Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" - textTitle "$ID35" "$TITLE35" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check36 b/checks/check36 index 2306196427..92a5fb36bb 100644 --- a/checks/check36 +++ b/checks/check36 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check306="check36" check36(){ # "Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" - textTitle "$ID36" "$TITLE36" "SCORED" "LEVEL2" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check37 b/checks/check37 index 2ffc48c2d8..064e85654e 100644 --- a/checks/check37 +++ b/checks/check37 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check307="check37" check37(){ # "Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" - textTitle "$ID37" "$TITLE37" "SCORED" "LEVEL2" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check38 b/checks/check38 index 0445fb988f..d2d17ab7bd 100644 --- a/checks/check38 +++ b/checks/check38 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check308="check38" check38(){ # "Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" - textTitle "$ID38" "$TITLE38" "SCORED" "LEVEL1" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check39 b/checks/check39 index 0f595b15c9..c23b67b3eb 100644 --- a/checks/check39 +++ b/checks/check39 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check309="check39" check39(){ # "Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" - textTitle "$ID39" "$TITLE39" "SCORED" "LEVEL2" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then diff --git a/checks/check41 b/checks/check41 index a7cfa7ccd8..72b6a7f7dd 100644 --- a/checks/check41 +++ b/checks/check41 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check401="check41" check41(){ # "Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" - textTitle "$ID41" "$TITLE41" "SCORED" "LEVEL1" for regx in $REGIONS; do SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`22` && ToPort>=`22`)) && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text) if [[ $SG_LIST ]];then diff --git a/checks/check42 b/checks/check42 index d912c749d9..41746d2dfa 100644 --- a/checks/check42 +++ b/checks/check42 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check402="check42" check42(){ # "Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" - textTitle "$ID42" "$TITLE42" "SCORED" "LEVEL1" for regx in $REGIONS; do SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`3389` && ToPort>=`3389`)) && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text) if [[ $SG_LIST ]];then diff --git a/checks/check43 b/checks/check43 index 913e5f876c..847e175371 100644 --- a/checks/check43 +++ b/checks/check43 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check403="check43" check43(){ # "Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" - textTitle "$ID43" "$TITLE43" "SCORED" "LEVEL2" for regx in $REGIONS; do CHECK_FL=$($AWSCLI ec2 describe-flow-logs $PROFILE_OPT --region $regx --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].LogGroupName' --output text) if [[ $CHECK_FL ]];then diff --git a/checks/check44 b/checks/check44 index 7dc223347f..f19150c066 100644 --- a/checks/check44 +++ b/checks/check44 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check404="check44" check44(){ # "Ensure the default security group of every VPC restricts all traffic (Scored)" - textTitle "$ID44" "$TITLE44" "SCORED" "LEVEL2" for regx in $REGIONS; do CHECK_SGDEFAULT=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters Name=group-name,Values='default' --query 'SecurityGroups[*].{IpPermissions:IpPermissions,IpPermissionsEgress:IpPermissionsEgress,GroupId:GroupId}' --output text |grep 0.0.0.0) if [[ $CHECK_SGDEFAULT ]];then diff --git a/checks/check45 b/checks/check45 index 2940146261..b71e5c0ac5 100644 --- a/checks/check45 +++ b/checks/check45 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_check405="check45" check45(){ # "Ensure routing tables for VPC peering are \"least access\" (Not Scored)" - textTitle "$ID45" "$TITLE45" "NOT_SCORED" "LEVEL2" textNotice "Looking for VPC peering in all regions... " for regx in $REGIONS; do LIST_OF_VPCS_PEERING_CONNECTIONS=$($AWSCLI ec2 describe-vpc-peering-connections --output text $PROFILE_OPT --region $regx --query 'VpcPeeringConnections[*].VpcPeeringConnectionId') diff --git a/checks/check_extra71 b/checks/check_extra71 index e10a12fd34..ef672fcfa6 100644 --- a/checks/check_extra71 +++ b/checks/check_extra71 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check701="extra71" extra71(){ # "Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID71" "$TITLE71" "NOT_SCORED" "EXTRA" ADMIN_GROUPS='' AWS_GROUPS=$($AWSCLI $PROFILE_OPT iam list-groups --output text --query 'Groups[].GroupName') for grp in $AWS_GROUPS; do diff --git a/checks/check_extra710 b/checks/check_extra710 index 48fdcb010c..4230686c37 100644 --- a/checks/check_extra710 +++ b/checks/check_extra710 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check710="extra710" extra710(){ # "Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID710" "$TITLE710" "NOT_SCORED" "EXTRA" textNotice "Looking for instances in all regions... " for regx in $REGIONS; do LIST_OF_PUBLIC_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]' --output text) diff --git a/checks/check_extra711 b/checks/check_extra711 index 4be784451d..00206c36e5 100644 --- a/checks/check_extra711 +++ b/checks/check_extra711 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check711="extra711" extra711(){ # "Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID711" "$TITLE711" "NOT_SCORED" "EXTRA" textNotice "Looking for Reshift clusters in all regions... " for regx in $REGIONS; do LIST_OF_PUBLIC_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[?PubliclyAccessible == `true`].[ClusterIdentifier,Endpoint.Address]' --output text) diff --git a/checks/check_extra712 b/checks/check_extra712 index ae653c1318..b2996e5a41 100644 --- a/checks/check_extra712 +++ b/checks/check_extra712 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check712="extra712" extra712(){ # "Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID712" "$TITLE712" "NOT_SCORED" "EXTRA" textNotice "No API commands available to check if Macie is enabled," textNotice "just looking if IAM Macie related permissions exist. " MACIE_IAM_ROLES_CREATED=$($AWSCLI iam list-roles $PROFILE_OPT --query 'Roles[*].Arn'|grep AWSMacieServiceCustomer|wc -l) diff --git a/checks/check_extra713 b/checks/check_extra713 index 457d36cce1..ac1b3bf894 100644 --- a/checks/check_extra713 +++ b/checks/check_extra713 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check713="extra713" extra713(){ # "Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID713" "$TITLE713" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_GUARDDUTY_DETECTORS=$($AWSCLI guardduty list-detectors $PROFILE_OPT --region $regx --output text |cut -f2) if [[ $LIST_OF_GUARDDUTY_DETECTORS ]];then diff --git a/checks/check_extra714 b/checks/check_extra714 index 00c625d102..6e7de69b45 100644 --- a/checks/check_extra714 +++ b/checks/check_extra714 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check714="extra714" extra714(){ # "Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID714" "$TITLE714" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_DISTRIBUTIONS=$($AWSCLI cloudfront list-distributions $PROFILE_OPT --region $regx --query 'DistributionList.Items[].Id' --output text |grep -v "^None") if [[ $LIST_OF_DISTRIBUTIONS ]]; then diff --git a/checks/check_extra715 b/checks/check_extra715 index b27e4def87..883dac35da 100644 --- a/checks/check_extra715 +++ b/checks/check_extra715 @@ -5,7 +5,6 @@ CHECK_ALTERNATE_extra715="extra715" CHECK_ALTERNATE_check715="extra715" extra715(){ - textTitle "$ID715" "$TITLE715" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text) if [[ $LIST_OF_DOMAINS ]]; then diff --git a/checks/check_extra716 b/checks/check_extra716 index b42ccc87f6..7289d1b37b 100644 --- a/checks/check_extra716 +++ b/checks/check_extra716 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check716="extra716" extra716(){ # "Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID716" "$TITLE716" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text) if [[ $LIST_OF_DOMAINS ]]; then diff --git a/checks/check_extra717 b/checks/check_extra717 index d52669ba4a..997c44c632 100644 --- a/checks/check_extra717 +++ b/checks/check_extra717 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check717="extra717" extra717(){ # "Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID717" "$TITLE717" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text|xargs -n1) LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text|xargs -n1) diff --git a/checks/check_extra718 b/checks/check_extra718 index f5a2b8bd0f..1cbe05e6e4 100644 --- a/checks/check_extra718 +++ b/checks/check_extra718 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check718="extra718" extra718(){ # "Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID718" "$TITLE718" "NOT_SCORED" "EXTRA" LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --query Buckets[*].Name --output text|xargs -n1) if [[ $LIST_OF_BUCKETS ]]; then for bucket in $LIST_OF_BUCKETS;do diff --git a/checks/check_extra719 b/checks/check_extra719 index 4158a3438e..ac69548351 100644 --- a/checks/check_extra719 +++ b/checks/check_extra719 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check719="extra719" extra719(){ # "Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID719" "$TITLE719" "NOT_SCORED" "EXTRA" LIST_OF_HOSTED_ZONES=$($AWSCLI route53 list-hosted-zones $PROFILE_OPT --query HostedZones[*].Id --output text|xargs -n1) if [[ $LIST_OF_HOSTED_ZONES ]]; then for hostedzoneid in $LIST_OF_HOSTED_ZONES;do diff --git a/checks/check_extra72 b/checks/check_extra72 index 06b80ea988..738b723c8b 100644 --- a/checks/check_extra72 +++ b/checks/check_extra72 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check702="extra72" extra72(){ # "Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID72" "$TITLE72" "NOT_SCORED" "EXTRA" textNotice "Looking for EBS Snapshots in all regions... " for regx in $REGIONS; do LIST_OF_EBS_SNAPSHOTS=$($AWSCLI ec2 describe-snapshots $PROFILE_OPT --region $regx --owner-ids $ACCOUNT_NUM --output text --query 'Snapshots[*].{ID:SnapshotId}' --max-items $MAXITEMS | grep -v None 2> /dev/null) diff --git a/checks/check_extra720 b/checks/check_extra720 index 5c440297b9..3790544c00 100644 --- a/checks/check_extra720 +++ b/checks/check_extra720 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check720="extra720" extra720(){ # "Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID720" "$TITLE720" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text) if [[ $LIST_OF_FUNCTIONS ]]; then diff --git a/checks/check_extra721 b/checks/check_extra721 index 82b78045ae..06d2e60165 100644 --- a/checks/check_extra721 +++ b/checks/check_extra721 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_check721="extra721" extra721(){ # "Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID721" "$TITLE721" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*].ClusterIdentifier' --output text) if [[ $LIST_OF_REDSHIFT_CLUSTERS ]]; then diff --git a/checks/check_extra722 b/checks/check_extra722 index 6a16714c72..6ad42e5bf0 100644 --- a/checks/check_extra722 +++ b/checks/check_extra722 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_extra722="extra722" extra722(){ # "Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID722" "$TITLE722" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do LIST_OF_API_GW=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query items[*].id --output text) if [[ $LIST_OF_API_GW ]];then diff --git a/checks/check_extra723 b/checks/check_extra723 index 3f46fb2188..0c4e91f8ba 100644 --- a/checks/check_extra723 +++ b/checks/check_extra723 @@ -6,7 +6,6 @@ CHECK_ALTERNATE_extra723="extra723" extra723(){ # "Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID723" "$TITLE723" "NOT_SCORED" "EXTRA" for regx in $REGIONS; do # RDS snapshots LIST_OF_RDS_SNAPSHOTS=$($AWSCLI rds describe-db-snapshots $PROFILE_OPT --region $regx --query DBSnapshots[*].DBSnapshotIdentifier --output text) diff --git a/checks/check_extra73 b/checks/check_extra73 index 7c45d1ee13..cf3c890efb 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check703="extra73" extra73(){ # "Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID73" "$TITLE73" "NOT_SCORED" "EXTRA" textNotice "Looking for open S3 Buckets (ACLs and Policies) in all regions... " ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' $PROFILE_OPT --region $REGION --output text) for bucket in $ALL_BUCKETS_LIST; do diff --git a/checks/check_extra74 b/checks/check_extra74 index ee264999f3..98210efd0c 100644 --- a/checks/check_extra74 +++ b/checks/check_extra74 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check704="extra74" extra74(){ # "Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID74" "$TITLE74" "NOT_SCORED" "EXTRA" textNotice "Looking for Security Groups in all regions... " for regx in $REGIONS; do LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS) diff --git a/checks/check_extra75 b/checks/check_extra75 index 24af2099df..2aeab90aac 100644 --- a/checks/check_extra75 +++ b/checks/check_extra75 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check705="extra75" extra75(){ # "Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID75" "$TITLE75" "NOT_SCORED" "EXTRA" textNotice "Looking for Security Groups in all regions... " for regx in $REGIONS; do LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS) diff --git a/checks/check_extra76 b/checks/check_extra76 index 0af33a1c20..1103e2b3ba 100644 --- a/checks/check_extra76 +++ b/checks/check_extra76 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check706="extra76" extra76(){ # "Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID76" "$TITLE76" "NOT_SCORED" "EXTRA" textNotice "Looking for AMIs in all regions... " for regx in $REGIONS; do LIST_OF_PUBLIC_AMIS=$($AWSCLI ec2 describe-images --owners self $PROFILE_OPT --region $regx --filters "Name=is-public,Values=true" --query 'Images[*].{ID:ImageId}' --output text) diff --git a/checks/check_extra77 b/checks/check_extra77 index bf4a9cffb6..2d0de92af3 100644 --- a/checks/check_extra77 +++ b/checks/check_extra77 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check707="extra77" extra77(){ # "Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID77" "$TITLE77" "NOT_SCORED" "EXTRA" textNotice "Looking for ECR repos in all regions... " for regx in $REGIONS; do LIST_OF_ECR_REPOS=$($AWSCLI ecr describe-repositories $PROFILE_OPT --region $regx --query 'repositories[*].{Name:repositoryName}' --output text) diff --git a/checks/check_extra78 b/checks/check_extra78 index a243d7bd20..41f70f2dc0 100644 --- a/checks/check_extra78 +++ b/checks/check_extra78 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check708="extra78" extra78(){ # "Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID78" "$TITLE78" "NOT_SCORED" "EXTRA" textNotice "Looking for RDS instances in all regions... " for regx in $REGIONS; do LIST_OF_RDS_PUBLIC_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[?PubliclyAccessible==`true`].[DBInstanceIdentifier,Endpoint.Address]' --output text) diff --git a/checks/check_extra79 b/checks/check_extra79 index 51fc1cac99..c868408f8b 100644 --- a/checks/check_extra79 +++ b/checks/check_extra79 @@ -7,7 +7,6 @@ CHECK_ALTERNATE_check709="extra79" extra79(){ # "Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" - textTitle "$ID79" "$TITLE79" "NOT_SCORED" "EXTRA" textNotice "Looking for Elastic Load Balancers in all regions... " for regx in $REGIONS; do LIST_OF_PUBLIC_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text) diff --git a/groups/group0_init b/groups/group0_init deleted file mode 100644 index 8b7d2410e9..0000000000 --- a/groups/group0_init +++ /dev/null @@ -1,6 +0,0 @@ -GROUP_ID[0]='init' # this group make easier to understand the array of groups -GROUP_NUMBER[0]='0.0' -GROUP_TITLE[0]='Init ****************************************************************' -GROUP_RUN_BY_DEFAULT[0]='N' # run it when execute_all is called -GROUP_CHECKS[0]='' - diff --git a/include/banner b/include/banner index 2dcfbc9916..3e39ed2c12 100644 --- a/include/banner +++ b/include/banner @@ -1,11 +1,14 @@ prowlerBanner() { - echo -e "$CYAN _" - echo -e " _ __ _ __ _____ _| | ___ _ __" - echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|" - echo -e " | |_) | | | (_) \ V V /| | __/ |" - echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|v2.0" - echo -e " |_|$NORMAL$BLUE the handy cloud security tool$NORMAL\n" - echo -e "$YELLOW Date: $(date)" + if [[ $BANNER != "0" ]]; then + echo -e "$CYAN _" + echo -e " _ __ _ __ _____ _| | ___ _ __" + echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|" + echo -e " | |_) | | | (_) \ V V /| | __/ |" + echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|v2.0" + echo -e " |_|$NORMAL$BLUE the handy cloud security tool$NORMAL\n" + echo -e "$YELLOW Date: $(date)" + printColorsCode + fi } infoReferenceLong(){ diff --git a/include/colors b/include/colors index cd738b86bc..a8e63f809b 100644 --- a/include/colors +++ b/include/colors @@ -53,6 +53,6 @@ fi printColorsCode(){ if [[ $MONOCHROME -eq 0 ]]; then - echo -e "\n$NORMAL Colors code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL" + echo -e "\n$NORMAL Colors code for results: $NOTICE INFO (Information)$NORMAL,$OK PASS (Recommended value)$NORMAL, $BAD FAIL (Fix required)$NORMAL" fi } diff --git a/include/outputs b/include/outputs index ae9e260e70..c873d619e3 100644 --- a/include/outputs +++ b/include/outputs @@ -33,7 +33,7 @@ textWarn(){ else REPREGION=$REGION fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}FAIL${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" else echo " $BAD FAIL! $1 $NORMAL" fi diff --git a/prowler b/prowler index 4ac90f4420..19c2c68c47 100755 --- a/prowler +++ b/prowler @@ -11,6 +11,8 @@ # # Author: Toni de la Fuente - @ToniBlyx - https://blyx.com/contact +# http://prowler.cloud + # Prowler - Iron Maiden # # Walking through the city, looking oh so pretty @@ -44,9 +46,11 @@ USAGE: Options: -p specify your AWS profile to use (i.e.: default) -r specify an AWS region to direct API requests to - (i.e.: us-east-1), all regions are checked anyway - -c specify a check number or group from the AWS CIS benchmark - (i.e.: "check11" for check 1.1, "check3" for entire section 3, "level1" for CIS Level 1 Profile Definitions or "forensics-ready") + (i.e.: us-east-1), all regions are checked anyway if the check requires it + -c specify a check id, to see all available checks use "-l" option + (i.e.: "check11" for check 1.1 or "extra71" for extra check 71) + -g specify a group of checks by id, to see all available group of checks use "-l" + (i.e.: "check3" for entire section 3, "level1" for CIS Level 1 Profile Definitions or "forensics-ready") -f specify an AWS region to run checks against (i.e.: us-west-1) -m specify the maximum number of items to return for long-running requests (default: 100) @@ -62,7 +66,7 @@ USAGE: exit } -while getopts ":hlkp:r:c:f:m:M:enb" OPTION; do +while getopts ":hlkp:r:c:g:f:m:M:enb" OPTION; do case $OPTION in h ) usage @@ -82,7 +86,10 @@ while getopts ":hlkp:r:c:f:m:M:enb" OPTION; do REGION=$OPTARG ;; c ) - CHECKNUMBER=$OPTARG + CHECK_ID=$OPTARG + ;; + g ) + GROUP_ID=$OPTARG ;; f ) FILTERREGION=$OPTARG @@ -97,7 +104,7 @@ while getopts ":hlkp:r:c:f:m:M:enb" OPTION; do NUMERAL=1 ;; b ) - BANNER=1 + BANNER=0 ;; e ) EXTRAS=1 @@ -184,6 +191,7 @@ execute_check() { $1 else textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)"; + exit $EXITCODE fi fi } @@ -199,10 +207,13 @@ execute_group() { } # Function to execute group by name -execute_group_by_name() { - for i in ${#GROUP_NAME[@]}; do - if [ "${GROUP_NAME[$i]}" == "$1" ]; then +execute_group_by_id() { + for i in "${!GROUP_ID[@]}"; do + if [ "${GROUP_ID[$i]}" == "$1" ]; then execute_group $i + else + textWarn "ERROR! Use a valid group check name (i.e. group1 or extras or forensics-ready)"; + exit $EXITCODE fi done } @@ -229,8 +240,15 @@ show_all_titles() { } # Execute single check if called with -c -if [[ $CHECKNUMBER ]];then - execute_check $CHECKNUMBER +if [[ $CHECK_ID ]];then + execute_check $CHECK_ID + cleanTemp + exit $EXITCODE +fi + +# Execute group of checks if called with -g +if [[ $GROUP_ID ]];then + execute_group_by_id $GROUP_ID cleanTemp exit $EXITCODE fi @@ -245,7 +263,6 @@ fi ### All functions defined above ... run the workflow if [[ $MODE != "csv" ]]; then prowlerBanner - printColorsCode fi getWhoami genCredReport From 2648067ac6f6f1b27b7bb69583979acff2a35261 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 26 Mar 2018 22:54:21 -0400 Subject: [PATCH 10/41] fully functional beta 2.0 --- groups/group5_cislevel1 | 2 +- groups/group6_cislevel2 | 2 +- include/outputs | 2 +- prowler | 18 +++++++++--------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/groups/group5_cislevel1 b/groups/group5_cislevel1 index a1958a5f95..277ec060f9 100644 --- a/groups/group5_cislevel1 +++ b/groups/group5_cislevel1 @@ -1,4 +1,4 @@ -GROUP_ID[5]='level1' +GROUP_ID[5]='cislevel1' GROUP_NUMBER[5]='5.0' GROUP_TITLE[5]='CIS Level 1 **********************************************************' GROUP_RUN_BY_DEFAULT[5]='N' # run it when execute_all is called diff --git a/groups/group6_cislevel2 b/groups/group6_cislevel2 index 369848ba33..3d627e3bde 100644 --- a/groups/group6_cislevel2 +++ b/groups/group6_cislevel2 @@ -1,4 +1,4 @@ -GROUP_ID[6]='level2' +GROUP_ID[6]='cislevel2' GROUP_NUMBER[6]='6.0' GROUP_TITLE[6]='CIS Level 2 **********************************************************' GROUP_RUN_BY_DEFAULT[6]='N' # run it when execute_all is called diff --git a/include/outputs b/include/outputs index c873d619e3..f9bbaa04af 100644 --- a/include/outputs +++ b/include/outputs @@ -75,7 +75,7 @@ textTitle(){ if [[ "$ITEM_SCORED" == "Scored" ]]; then echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT" else - echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" + echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" fi fi } diff --git a/prowler b/prowler index 19c2c68c47..10eeca1be1 100755 --- a/prowler +++ b/prowler @@ -11,7 +11,7 @@ # # Author: Toni de la Fuente - @ToniBlyx - https://blyx.com/contact -# http://prowler.cloud +# http://prowler.cloud # Prowler - Iron Maiden # @@ -199,7 +199,7 @@ execute_check() { # Function to execute all checks in a group execute_group() { show_group_title $1 - # run the checks in the group + # run the checks in the group IFS=',' read -ra CHECKS <<< ${GROUP_CHECKS[$1]} for i in ${CHECKS[@]}; do execute_check $i @@ -208,12 +208,14 @@ execute_group() { # Function to execute group by name execute_group_by_id() { + if [ "${GROUP_ID[$1]}" == "group1" ]; then + genCredReport + saveReport + fi + prowlerBanner for i in "${!GROUP_ID[@]}"; do if [ "${GROUP_ID[$i]}" == "$1" ]; then execute_group $i - else - textWarn "ERROR! Use a valid group check name (i.e. group1 or extras or forensics-ready)"; - exit $EXITCODE fi done } @@ -264,12 +266,10 @@ fi if [[ $MODE != "csv" ]]; then prowlerBanner fi -getWhoami + genCredReport saveReport - -#callCheck - +getWhoami execute_all cleanTemp From ef9b7cef1a691684958897ac7c46e34ec170cb5a Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 26 Mar 2018 23:01:52 -0400 Subject: [PATCH 11/41] clean up extras --- checks/check_extra710 | 1 - checks/check_extra711 | 1 - checks/check_extra712 | 1 - checks/check_extra713 | 1 - checks/check_extra714 | 1 - checks/check_extra715 | 1 - checks/check_extra716 | 1 - checks/check_extra717 | 1 - checks/check_extra718 | 1 - checks/check_extra719 | 1 - checks/check_extra720 | 1 - checks/check_extra721 | 1 - checks/check_extra722 | 1 - checks/check_extra723 | 1 - checks/check_sample | 21 +++++++++++++++++++++ 15 files changed, 21 insertions(+), 14 deletions(-) diff --git a/checks/check_extra710 b/checks/check_extra710 index 4230686c37..bafb10f00f 100644 --- a/checks/check_extra710 +++ b/checks/check_extra710 @@ -1,7 +1,6 @@ CHECK_ID_extra710="7.10" CHECK_TITLE_extra710="Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra710="NOT_SCORED" -CHECK_ALTERNATE_extra710="extra710" CHECK_ALTERNATE_check710="extra710" extra710(){ diff --git a/checks/check_extra711 b/checks/check_extra711 index 00206c36e5..9918d71627 100644 --- a/checks/check_extra711 +++ b/checks/check_extra711 @@ -1,7 +1,6 @@ CHECK_ID_extra711="7.11" CHECK_TITLE_extra711="Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra711="NOT_SCORED" -CHECK_ALTERNATE_extra711="extra711" CHECK_ALTERNATE_check711="extra711" extra711(){ diff --git a/checks/check_extra712 b/checks/check_extra712 index b2996e5a41..a3b59b8407 100644 --- a/checks/check_extra712 +++ b/checks/check_extra712 @@ -1,7 +1,6 @@ CHECK_ID_extra712="7.12" CHECK_TITLE_extra712="Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra712="NOT_SCORED" -CHECK_ALTERNATE_extra712="extra712" CHECK_ALTERNATE_check712="extra712" extra712(){ diff --git a/checks/check_extra713 b/checks/check_extra713 index ac1b3bf894..93ed5ab646 100644 --- a/checks/check_extra713 +++ b/checks/check_extra713 @@ -1,7 +1,6 @@ CHECK_ID_extra713="7.13" CHECK_TITLE_extra713="Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra713="NOT_SCORED" -CHECK_ALTERNATE_extra713="extra713" CHECK_ALTERNATE_check713="extra713" extra713(){ diff --git a/checks/check_extra714 b/checks/check_extra714 index 6e7de69b45..92a7118efb 100644 --- a/checks/check_extra714 +++ b/checks/check_extra714 @@ -1,7 +1,6 @@ CHECK_ID_extra714="7.14" CHECK_TITLE_extra714="Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra714="NOT_SCORED" -CHECK_ALTERNATE_extra714="extra714" CHECK_ALTERNATE_check714="extra714" extra714(){ diff --git a/checks/check_extra715 b/checks/check_extra715 index 883dac35da..04e24f84ce 100644 --- a/checks/check_extra715 +++ b/checks/check_extra715 @@ -1,7 +1,6 @@ CHECK_ID_extra715="7.15" CHECK_TITLE_extra715="Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra715="NOT_SCORED" -CHECK_ALTERNATE_extra715="extra715" CHECK_ALTERNATE_check715="extra715" extra715(){ diff --git a/checks/check_extra716 b/checks/check_extra716 index 7289d1b37b..00c2d1e83b 100644 --- a/checks/check_extra716 +++ b/checks/check_extra716 @@ -1,7 +1,6 @@ CHECK_ID_extra716="7.16" CHECK_TITLE_extra716="Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra716="NOT_SCORED" -CHECK_ALTERNATE_extra716="extra716" CHECK_ALTERNATE_check716="extra716" extra716(){ diff --git a/checks/check_extra717 b/checks/check_extra717 index 997c44c632..d887169c65 100644 --- a/checks/check_extra717 +++ b/checks/check_extra717 @@ -1,7 +1,6 @@ CHECK_ID_extra717="7.17" CHECK_TITLE_extra717="Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra717="NOT_SCORED" -CHECK_ALTERNATE_extra717="extra717" CHECK_ALTERNATE_check717="extra717" extra717(){ diff --git a/checks/check_extra718 b/checks/check_extra718 index 1cbe05e6e4..8184daeb49 100644 --- a/checks/check_extra718 +++ b/checks/check_extra718 @@ -1,7 +1,6 @@ CHECK_ID_extra718="7.18" CHECK_TITLE_extra718="Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra718="NOT_SCORED" -CHECK_ALTERNATE_extra718="extra718" CHECK_ALTERNATE_check718="extra718" extra718(){ diff --git a/checks/check_extra719 b/checks/check_extra719 index ac69548351..df90a99431 100644 --- a/checks/check_extra719 +++ b/checks/check_extra719 @@ -1,7 +1,6 @@ CHECK_ID_extra719="7.19" CHECK_TITLE_extra719="Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra719="NOT_SCORED" -CHECK_ALTERNATE_extra719="extra719" CHECK_ALTERNATE_check719="extra719" extra719(){ diff --git a/checks/check_extra720 b/checks/check_extra720 index 3790544c00..ade6d3ae78 100644 --- a/checks/check_extra720 +++ b/checks/check_extra720 @@ -1,7 +1,6 @@ CHECK_ID_extra720="7.20" CHECK_TITLE_extra720="Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra720="NOT_SCORED" -CHECK_ALTERNATE_extra720="extra720" CHECK_ALTERNATE_check720="extra720" extra720(){ diff --git a/checks/check_extra721 b/checks/check_extra721 index 06d2e60165..43b0778f74 100644 --- a/checks/check_extra721 +++ b/checks/check_extra721 @@ -1,7 +1,6 @@ CHECK_ID_extra721="7.21" CHECK_TITLE_extra721="Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra721="NOT_SCORED" -CHECK_ALTERNATE_extra721="extra721" CHECK_ALTERNATE_check721="extra721" extra721(){ diff --git a/checks/check_extra722 b/checks/check_extra722 index 6ad42e5bf0..1310d00cd5 100644 --- a/checks/check_extra722 +++ b/checks/check_extra722 @@ -2,7 +2,6 @@ CHECK_ID_extra722="7.22" CHECK_TITLE_extra722="Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra722="NOT_SCORED" CHECK_ALTERNATE_check722="extra722" -CHECK_ALTERNATE_extra722="extra722" extra722(){ # "Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" diff --git a/checks/check_extra723 b/checks/check_extra723 index 0c4e91f8ba..ee32ce476e 100644 --- a/checks/check_extra723 +++ b/checks/check_extra723 @@ -2,7 +2,6 @@ CHECK_ID_extra723="7.23" CHECK_TITLE_extra723="Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra723="NOT_SCORED" CHECK_ALTERNATE_check723="extra723" -CHECK_ALTERNATE_extra723="extra723" extra723(){ # "Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" diff --git a/checks/check_sample b/checks/check_sample index e69de29bb2..c57223a1ed 100644 --- a/checks/check_sample +++ b/checks/check_sample @@ -0,0 +1,21 @@ +# CHECK_ID_checkN="N.N" +# CHECK_TITLE_checkN="Description (Not Scored) (Not part of CIS benchmark)" +# CHECK_SCORED_checkN="NOT_SCORED" +# CHECK_ALTERNATE_checkN="extraN" +# +# extraN(){ +# # "Description (Not Scored) (Not part of CIS benchmark)" +# textNotice "Looking for instances in all regions... " +# for regx in $REGIONS; do +# LIST_OF_PUBLIC_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]' --output text) +# if [[ $LIST_OF_PUBLIC_INSTANCES ]];then +# while read -r instance;do +# INSTANCE_ID=$(echo $instance | awk '{ print $1; }') +# PUBLIC_IP=$(echo $instance | awk '{ print $2; }') +# textWarn "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx" +# done <<< "$LIST_OF_PUBLIC_INSTANCES" +# else +# textOK "$regx: no Internet Facing EC2 Instances found" "$regx" +# fi +# done +# } From 70483ba81b50f82d3602c04583027ef151726729 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 27 Mar 2018 18:07:03 -0400 Subject: [PATCH 12/41] updated README and usage --- README.md | 40 +++++++++++++++--------- checks/check_extra73 | 72 +++++++++++++++++++++++--------------------- prowler | 4 +-- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index f33dad90ee..340a1490d3 100644 --- a/README.md +++ b/README.md @@ -125,22 +125,26 @@ xargs -n 1 -L 1 -I @ -r -P 4 ./prowler -p @ -M csv 2> /dev/null >> all-account ./prowler -h USAGE: - prowler -p -r [ -h ] + prowler [ -p -r -h ] + Options: -p specify your AWS profile to use (i.e.: default) -r specify an AWS region to direct API requests to - (i.e.: us-east-1), all regions are checked anyway - -c specify a check number or group from the AWS CIS benchmark - (i.e.: "check11" for check 1.1, "check3" for entire section 3, "level1" for CIS Level 1 Profile Definitions or "forensics-ready") + (i.e.: us-east-1), all regions are checked anyway if the check requires it + -c specify a check id, to see all available checks use -l option + (i.e.: check11 for check 1.1 or extra71 for extra check 71) + -g specify a group of checks by id, to see all available group of checks use -l + (i.e.: check3 for entire section 3, level1 for CIS Level 1 Profile Definitions or forensics-ready) -f specify an AWS region to run checks against (i.e.: us-west-1) -m specify the maximum number of items to return for long-running requests (default: 100) - -M output mode: text (defalut), mono, csv (separator is ","; data is on stdout; progress on stderr) + -M output mode: text (default), mono, csv (separator is ,; data is on stdout; progress on stderr) -k keep the credential report -n show check numbers to sort easier (i.e.: 1.01 instead of 1.1) -l list all available checks only (does not perform any check) - -e exclude extras + -e exclude group extras + -b do not print Prowler banner -h this help ``` @@ -330,7 +334,7 @@ We are adding additional checks to improve the information gather from each acco Note: Some of these checks for publicly facing resources may not actually be fully public due to other layered controls like S3 Bucket Policies, Security Groups or Network ACLs. -At this moment we have 22 extra checks: +At this moment we have 23 extra checks: - 7.1 (`extra71`) Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark) - 7.2 (`extra72`) Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark) @@ -354,6 +358,7 @@ At this moment we have 22 extra checks: - 7.20 (`extra720`) Check if Lambda functions are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) - 7.21 (`extra721`) Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) - 7.22 (`extra722`) Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) +- 7.23 (`extra723`) Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark) To check all extras in one command: @@ -394,14 +399,21 @@ The `forensics-ready` group of checks uses existing and extra checks. To get a f ## Add Custom Checks -In order to add any new check feel free to create a new extra check in the extras section. To do so, you will need to follow these steps: +In order to add any new check feel free to create a new extra check in the extras group or other group. To do so, you will need to follow these steps: -1. use any existing extra check as reference -2. add `ID7N` and `TITLE7N`, where N is a new check number part of the extras section (7) around line 361 `# List of checks IDs and Titles` -3. add your new extra check function name at `callCheck` function (around line 1817) and below in that case inside extras option (around line 1853) -4. finally add it in `# List only check tittles` around line 1930 -5. save changes and run it as ./prowler -c extraNN -6. send me a pull request! :) +1. Follow structure in file `checks/check_sample` +2. Name your check with a number part of an existing group or a new one +3. Save changes and run it as ./prowler -c extraNN` +4. Send me a pull request! :) + +## Add Custom Groups + +1. Follow structure in file `groups/groupN_sample` +2. Name your group with a non existing number +3. Save changes and run it as `./prowler -g extraNN` +4. Send me a pull request! :) + +* You can also create a group with only the checks that you want to perform in your company, for instance a group named `group9_mycompany` with only the list of checks that you care or your particular compliance applies. ## Third Party Integrations diff --git a/checks/check_extra73 b/checks/check_extra73 index cf3c890efb..0bdb6469ca 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -6,41 +6,45 @@ CHECK_ALTERNATE_check73="extra73" CHECK_ALTERNATE_check703="extra73" extra73(){ - # "Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" textNotice "Looking for open S3 Buckets (ACLs and Policies) in all regions... " - ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' $PROFILE_OPT --region $REGION --output text) + ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' --profile $PROFILE --region $REGION --output text) for bucket in $ALL_BUCKETS_LIST; do - BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket $PROFILE_OPT --region $REGION --output text) - if [[ "None" == $BUCKET_LOCATION ]]; then - BUCKET_LOCATION="us-east-1" - fi - if [[ "EU" == $BUCKET_LOCATION ]]; then - BUCKET_LOCATION="eu-west-1" - fi - # check if AllUsers is in the ACL as Grantee - CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE) - CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL) - # check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only - CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE) - CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL) - # to prevent error NoSuchBucketPolicy first clean the output controlling stderr - TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX) - $AWSCLI s3api get-bucket-policy $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null - # check if the S3 policy has Principal as * - CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*) - if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then - if [[ $CHECK_BUCKET_ALLUSERS_ACL ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" - fi - if [[ $CHECK_BUCKET_AUTHUSERS_ACL ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" - fi - if [[ $CHECK_BUCKET_ALLUSERS_POLICY ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" - fi - else - textOK "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" - fi - rm -fr $TEMP_POLICY_FILE + extra73Thread $bucket & done + wait +} +extra73Thread(){ + bucket=$1 + BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket --profile $PROFILE --region $REGION --output text) + if [[ "None" == $BUCKET_LOCATION ]]; then + BUCKET_LOCATION="us-east-1" + fi + if [[ "EU" == $BUCKET_LOCATION ]]; then + BUCKET_LOCATION="eu-west-1" + fi + # check if AllUsers is in the ACL as Grantee + CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE) + CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL) + # check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only + CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE) + CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL) + # to prevent error NoSuchBucketPolicy first clean the output controlling stderr + TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX) + $AWSCLI s3api get-bucket-policy --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null + # check if the S3 policy has Principal as * + CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*) + if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then + if [[ $CHECK_BUCKET_ALLUSERS_ACL ]];then + textWarn "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" + fi + if [[ $CHECK_BUCKET_AUTHUSERS_ACL ]];then + textWarn "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" + fi + if [[ $CHECK_BUCKET_ALLUSERS_POLICY ]];then + textWarn "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" + fi + else + textOK "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" + fi + rm -fr $TEMP_POLICY_FILE } diff --git a/prowler b/prowler index 10eeca1be1..fe67941bc2 100755 --- a/prowler +++ b/prowler @@ -54,12 +54,12 @@ USAGE: -f specify an AWS region to run checks against (i.e.: us-west-1) -m specify the maximum number of items to return for long-running requests (default: 100) - -M output mode: text (defalut), mono, csv (separator is ","; data is on stdout; progress on stderr) + -M output mode: text (default), mono, csv (separator is ","; data is on stdout; progress on stderr) -k keep the credential report -n show check numbers to sort easier (i.e.: 1.01 instead of 1.1) -l list all available checks only (does not perform any check) - -e exclude extras + -e exclude group extras -b do not print Prowler banner -h this help " From a535e66d06e706e0c8cc0f9dee5e79e65a2b791b Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 27 Mar 2018 18:09:02 -0400 Subject: [PATCH 13/41] updated README and usage --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 340a1490d3..d196c3e2ff 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ It covers hardening and security best practices for all AWS regions related to: - Logging (8 checks) - Monitoring (15 checks) - Networking (5 checks) -- Extras (22 checks) *see Extras section* +- Extras (23 checks) *see Extras section* - Forensics related group of checks For a comprehesive list and resolution look at the guide on the link above. From 39b597ee4764d2cdfed08b3f8c13191ba07b2ea8 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 27 Mar 2018 18:11:13 -0400 Subject: [PATCH 14/41] updated README and usage --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d196c3e2ff..950398eefd 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ arn:aws:iam::aws:policy/SecurityAudit ./prowler ``` +Use `-l` to list all available checks and group of checks (sections) + 2 - For custom AWS-CLI profile and region, use the following: (it will use your custom profile and run checks over all regions when needed): ``` @@ -88,7 +90,7 @@ or for custom profile and region ``` or for a group of checks use group name: ``` -./prowler -c check3 +./prowler -g group1 # for iam related checks ``` Valid check numbers are based on the AWS CIS Benchmark guide, so 1.1 is check11 and 3.10 is check310 @@ -148,7 +150,7 @@ USAGE: -h this help ``` -## Fix: +## Fix every FAIL: Check your report and fix the issues following all specific guidelines per check in https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf ## Screenshots From 1c0229e1a3b35ae1f2b3c3b11a41464d64348b05 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 27 Mar 2018 18:43:58 -0400 Subject: [PATCH 15/41] added new CHECKLIST.md file --- CHECKLIST.md | 395 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 CHECKLIST.md diff --git a/CHECKLIST.md b/CHECKLIST.md new file mode 100644 index 0000000000..d22470dd25 --- /dev/null +++ b/CHECKLIST.md @@ -0,0 +1,395 @@ +``` _ + _ __ _ __ _____ _| | ___ _ __ +| '_ \| '__/ _ \ \ /\ / / |/ _ \ '__| +| |_) | | | (_) \ V V /| | __/ | +| .__/|_| \___/ \_/\_/ |_|\___|_|v2.0 +|_| the handy cloud security tool + +Date: Tue Mar 27 18:38:53 EDT 2018 + +Colors code for results: INFO (Information), PASS (Recommended value), FAIL (Fix required) + +1.0 (group1) Identity and Access Management **************************************** + +1.1 Avoid the use of the root account (Scored) + +1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) + +1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) + +1.4 Ensure access keys are rotated every 90 days or less (Scored) + +1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) + +1.6 Ensure IAM password policy require at least one lowercase letter (Scored) + +1.7 Ensure IAM password policy require at least one symbol (Scored) + +1.8 Ensure IAM password policy require at least one number (Scored) + +1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) + +1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) + +1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) + +1.12 Ensure no root account access key exists (Scored) + +1.13 Ensure MFA is enabled for the root account (Scored) + +1.14 Ensure hardware MFA is enabled for the root account (Scored) + +1.15 Ensure security questions are registered in the AWS account (Not Scored) + +1.16 Ensure IAM policies are attached only to groups or roles (Scored) + +1.17 Enable detailed billing (Scored) + +1.18 Ensure IAM Master and IAM Manager roles are active (Scored) + +1.19 Maintain current contact details (Scored) + +1.20 Ensure security contact information is registered (Scored) + +1.21 Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) + +1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) + +1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) + +1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) + +2.0 (group2) Logging *************************************************************** + +2.1 Ensure CloudTrail is enabled in all regions (Scored) + +2.2 Ensure CloudTrail log file validation is enabled (Scored) + +2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) + +2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) + +2.5 Ensure AWS Config is enabled in all regions (Scored) + +2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) + +2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) + +2.8 Ensure rotation for customer created CMKs is enabled (Scored) + +3.0 (group3) Monitoring ************************************************************ + +3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) + +3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) + +3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) + +3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) + +3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) + +3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) + +3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) + +3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) + +3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) + +3.10 Ensure a log metric filter and alarm exist for security group changes (Scored) + +3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) + +3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) + +3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) + +3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) + +3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) + +4.0 (group4) Networking ************************************************************ + +4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) + +4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) + +4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) + +4.4 Ensure the default security group of every VPC restricts all traffic (Scored) + +4.5 Ensure routing tables for VPC peering are "least access" (Not Scored) + +5.0 (cislevel1) CIS Level 1 ********************************************************** + +1.1 Avoid the use of the root account (Scored) + +1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) + +1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) + +1.4 Ensure access keys are rotated every 90 days or less (Scored) + +1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) + +1.6 Ensure IAM password policy require at least one lowercase letter (Scored) + +1.7 Ensure IAM password policy require at least one symbol (Scored) + +1.8 Ensure IAM password policy require at least one number (Scored) + +1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) + +1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) + +1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) + +1.12 Ensure no root account access key exists (Scored) + +1.13 Ensure MFA is enabled for the root account (Scored) + +1.15 Ensure security questions are registered in the AWS account (Not Scored) + +1.16 Ensure IAM policies are attached only to groups or roles (Scored) + +1.17 Enable detailed billing (Scored) + +1.18 Ensure IAM Master and IAM Manager roles are active (Scored) + +1.19 Maintain current contact details (Scored) + +1.20 Ensure security contact information is registered (Scored) + +1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) + +1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) + +1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) + +2.1 Ensure CloudTrail is enabled in all regions (Scored) + +2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) + +2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) + +2.5 Ensure AWS Config is enabled in all regions (Scored) + +2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) + +3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) + +3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) + +3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) + +3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) + +3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) + +3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) + +3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) + +3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) + +3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) + +3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) + +4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) + +4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) + +6.0 (cislevel2) CIS Level 2 ********************************************************** + +1.1 Avoid the use of the root account (Scored) + +1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) + +1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) + +1.4 Ensure access keys are rotated every 90 days or less (Scored) + +1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) + +1.6 Ensure IAM password policy require at least one lowercase letter (Scored) + +1.7 Ensure IAM password policy require at least one symbol (Scored) + +1.8 Ensure IAM password policy require at least one number (Scored) + +1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) + +1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) + +1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) + +1.12 Ensure no root account access key exists (Scored) + +1.13 Ensure MFA is enabled for the root account (Scored) + +1.14 Ensure hardware MFA is enabled for the root account (Scored) + +1.15 Ensure security questions are registered in the AWS account (Not Scored) + +1.16 Ensure IAM policies are attached only to groups or roles (Scored) + +1.17 Enable detailed billing (Scored) + +1.18 Ensure IAM Master and IAM Manager roles are active (Scored) + +1.19 Maintain current contact details (Scored) + +1.20 Ensure security contact information is registered (Scored) + +1.21 Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) + +1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) + +1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) + +1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) + +2.1 Ensure CloudTrail is enabled in all regions (Scored) + +2.2 Ensure CloudTrail log file validation is enabled (Scored) + +2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) + +2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) + +2.5 Ensure AWS Config is enabled in all regions (Scored) + +2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) + +2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) + +2.8 Ensure rotation for customer created CMKs is enabled (Scored) + +3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) + +3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) + +3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) + +3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) + +3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) + +3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) + +3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) + +3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) + +3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) + +3.10 Ensure a log metric filter and alarm exist for security group changes (Scored) + +3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) + +3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) + +3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) + +3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) + +3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) + +4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) + +4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) + +4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) + +4.4 Ensure the default security group of every VPC restricts all traffic (Scored) + +4.5 Ensure routing tables for VPC peering are "least access" (Not Scored) + +7.0 (extras) Extras **************************************************************** + +7.1 Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark) + +7.2 Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark) + +7.3 Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark) + +7.4 Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark) + +7.5 Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark) + +7.6 Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark) + +7.7 Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark) + +7.8 Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark) + +7.9 Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark) + +7.10 Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark) + +7.11 Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark) + +7.12 Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) + +7.13 Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) + +7.14 Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) + +7.15 Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) + +7.16 Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark) + +7.17 Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) + +7.18 Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) + +7.19 Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) + +7.20 Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) + +7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) + +7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) + +7.23 Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark) + +8.0 (forensics-ready) Forensics Readiness *************************************************** + +2.1 Ensure CloudTrail is enabled in all regions (Scored) + +2.2 Ensure CloudTrail log file validation is enabled (Scored) + +2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) + +2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) + +2.5 Ensure AWS Config is enabled in all regions (Scored) + +2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) + +2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) + +4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) + +7.12 Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) + +7.13 Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) + +7.14 Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) + +7.15 Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) + +7.17 Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) + +7.18 Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) + +7.19 Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) + +7.20 Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) + +7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) + +7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) +``` From f130c899e551f4d86c5f0a095c23344e895d0430 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 10:44:36 -0400 Subject: [PATCH 16/41] added check extra724 Certificate Transparency --- CHECKLIST.md => LIST_OF_CHECKS_AND_GROUPS.md | 4 ++++ README.md | 1 + checks/check_extra724 | 24 ++++++++++++++++++++ groups/group7_extras | 2 +- 4 files changed, 30 insertions(+), 1 deletion(-) rename CHECKLIST.md => LIST_OF_CHECKS_AND_GROUPS.md (98%) create mode 100644 checks/check_extra724 diff --git a/CHECKLIST.md b/LIST_OF_CHECKS_AND_GROUPS.md similarity index 98% rename from CHECKLIST.md rename to LIST_OF_CHECKS_AND_GROUPS.md index d22470dd25..45da426449 100644 --- a/CHECKLIST.md +++ b/LIST_OF_CHECKS_AND_GROUPS.md @@ -392,4 +392,8 @@ Colors code for results: INFO (Information), PASS (Recommended value), FAIL (F 7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) 7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) + +7.23 Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark) + +7.24 Check if ACM certificates have Certificate Transparence enabled (Not Scored) (Not part of CIS benchmark) ``` diff --git a/README.md b/README.md index 950398eefd..0f89e34e6b 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ - [Forensics Ready Checks](#forensics-ready-checks) - [Add Custom Checks](#add-custom-checks) - [Third Party Integrations](#third-party-integrations) +- [Full list of checks and groups] (LIST_OF_CHECKS_AND_GROUPS.md) ## Description diff --git a/checks/check_extra724 b/checks/check_extra724 new file mode 100644 index 0000000000..d355a9caab --- /dev/null +++ b/checks/check_extra724 @@ -0,0 +1,24 @@ +CHECK_ID_extra724="7.24" +CHECK_TITLE_extra724="Check if ACM certificates have Certificate Transparence enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra724="NOT_SCORED" +CHECK_ALTERNATE_check724="extra724" + +extra724(){ + # "Check if ACM certificates have Certificate Transparence enabled (Not Scored) (Not part of CIS benchmark)" + for regx in $REGIONS; do + LIST_OF_CERTS=$($AWSCLI acm list-certificates $PROFILE_OPT --region $regx --query CertificateSummaryList[].CertificateArn --output text) + if [[ $LIST_OF_CERTS ]];then + for cert_arn in $LIST_OF_CERTS;do + CT_ENABLED=$($AWSCLI acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.Options.CertificateTransparencyLoggingPreference --output text) + if [[ $CT_ENABLED == "ENABLED" ]];then + CERT_DOMAIN_NAME=$(aws acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.DomainName --output text) + textWarn "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" + else + textOK "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" + fi + done + else + textNotice "$regx: No ACM Certificates found" "$regx" + fi + done +} diff --git a/groups/group7_extras b/groups/group7_extras index 0c3319b279..bddb4c8403 100644 --- a/groups/group7_extras +++ b/groups/group7_extras @@ -2,4 +2,4 @@ GROUP_ID[7]='extras' GROUP_NUMBER[7]='7.0' GROUP_TITLE[7]='Extras ****************************************************************' GROUP_RUN_BY_DEFAULT[7]='Y' # run it when execute_all is called -GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723' +GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723,extra724' From 94e7faa1c18e341f1e1843cf9f42d754f40cbd26 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 10:49:00 -0400 Subject: [PATCH 17/41] added check extra724 Certificate Transparency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f89e34e6b..02cbadfbab 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - [Forensics Ready Checks](#forensics-ready-checks) - [Add Custom Checks](#add-custom-checks) - [Third Party Integrations](#third-party-integrations) -- [Full list of checks and groups] (LIST_OF_CHECKS_AND_GROUPS.md) +- [Full list of checks and groups] (/LIST_OF_CHECKS_AND_GROUPS.md) ## Description From 919c53015561533de8d01b21725983bec837cb31 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 10:49:39 -0400 Subject: [PATCH 18/41] added check extra724 Certificate Transparency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 02cbadfbab..258207e5e0 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - [Forensics Ready Checks](#forensics-ready-checks) - [Add Custom Checks](#add-custom-checks) - [Third Party Integrations](#third-party-integrations) -- [Full list of checks and groups] (/LIST_OF_CHECKS_AND_GROUPS.md) +- [Full list of checks and groups](/LIST_OF_CHECKS_AND_GROUPS.md) ## Description From db8b5a4d0b79d2508e50f3bd3c062d0bfdb237b9 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 10:50:56 -0400 Subject: [PATCH 19/41] added check extra724 Certificate Transparency --- LIST_OF_CHECKS_AND_GROUPS.md | 2 +- checks/check_extra724 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LIST_OF_CHECKS_AND_GROUPS.md b/LIST_OF_CHECKS_AND_GROUPS.md index 45da426449..893bf802c8 100644 --- a/LIST_OF_CHECKS_AND_GROUPS.md +++ b/LIST_OF_CHECKS_AND_GROUPS.md @@ -395,5 +395,5 @@ Colors code for results: INFO (Information), PASS (Recommended value), FAIL (F 7.23 Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark) -7.24 Check if ACM certificates have Certificate Transparence enabled (Not Scored) (Not part of CIS benchmark) +7.24 Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark) ``` diff --git a/checks/check_extra724 b/checks/check_extra724 index d355a9caab..5acc182c93 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -1,10 +1,10 @@ CHECK_ID_extra724="7.24" -CHECK_TITLE_extra724="Check if ACM certificates have Certificate Transparence enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra724="Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra724="NOT_SCORED" CHECK_ALTERNATE_check724="extra724" extra724(){ - # "Check if ACM certificates have Certificate Transparence enabled (Not Scored) (Not part of CIS benchmark)" + # "Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark)" for regx in $REGIONS; do LIST_OF_CERTS=$($AWSCLI acm list-certificates $PROFILE_OPT --region $regx --query CertificateSummaryList[].CertificateArn --output text) if [[ $LIST_OF_CERTS ]];then From 1acc6e45d0ef2db6a7acc0260ab817010910d4b7 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 10:54:59 -0400 Subject: [PATCH 20/41] added check extra724 Certificate Transparency --- checks/check_extra724 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/check_extra724 b/checks/check_extra724 index 5acc182c93..d0636a6767 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -10,8 +10,8 @@ extra724(){ if [[ $LIST_OF_CERTS ]];then for cert_arn in $LIST_OF_CERTS;do CT_ENABLED=$($AWSCLI acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.Options.CertificateTransparencyLoggingPreference --output text) + CERT_DOMAIN_NAME=$(aws acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.DomainName --output text) if [[ $CT_ENABLED == "ENABLED" ]];then - CERT_DOMAIN_NAME=$(aws acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.DomainName --output text) textWarn "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" else textOK "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" From 07b166baa9e4792b0deb7c9e856d1fadef082c96 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 11:07:46 -0400 Subject: [PATCH 21/41] changed outputs to the new ones --- checks/check11 | 2 +- checks/check110 | 6 +++--- checks/check111 | 4 ++-- checks/check112 | 8 ++++---- checks/check113 | 4 ++-- checks/check114 | 6 +++--- checks/check115 | 6 +++--- checks/check116 | 4 ++-- checks/check117 | 4 ++-- checks/check118 | 12 ++++++------ checks/check119 | 4 ++-- checks/check12 | 4 ++-- checks/check120 | 4 ++-- checks/check121 | 4 ++-- checks/check122 | 10 +++++----- checks/check123 | 8 ++++---- checks/check124 | 10 +++++----- checks/check13 | 6 +++--- checks/check14 | 16 ++++++++-------- checks/check15 | 4 ++-- checks/check16 | 4 ++-- checks/check17 | 4 ++-- checks/check18 | 4 ++-- checks/check19 | 4 ++-- checks/check21 | 6 +++--- checks/check22 | 6 +++--- checks/check23 | 6 +++--- checks/check24 | 8 ++++---- checks/check25 | 4 ++-- checks/check26 | 6 +++--- checks/check27 | 6 +++--- checks/check28 | 8 ++++---- checks/check31 | 8 ++++---- checks/check310 | 8 ++++---- checks/check311 | 8 ++++---- checks/check312 | 8 ++++---- checks/check313 | 8 ++++---- checks/check314 | 8 ++++---- checks/check315 | 12 ++++++------ checks/check32 | 8 ++++---- checks/check33 | 8 ++++---- checks/check34 | 8 ++++---- checks/check35 | 8 ++++---- checks/check36 | 8 ++++---- checks/check37 | 8 ++++---- checks/check38 | 8 ++++---- checks/check39 | 8 ++++---- checks/check41 | 4 ++-- checks/check42 | 4 ++-- checks/check43 | 4 ++-- checks/check44 | 4 ++-- checks/check45 | 6 +++--- checks/check_extra71 | 8 ++++---- checks/check_extra710 | 6 +++--- checks/check_extra711 | 6 +++--- checks/check_extra712 | 8 ++++---- checks/check_extra713 | 6 +++--- checks/check_extra714 | 6 +++--- checks/check_extra715 | 10 +++++----- checks/check_extra716 | 8 ++++---- checks/check_extra717 | 10 +++++----- checks/check_extra718 | 6 +++--- checks/check_extra719 | 6 +++--- checks/check_extra72 | 6 +++--- checks/check_extra720 | 14 +++++++------- checks/check_extra721 | 6 +++--- checks/check_extra722 | 8 ++++---- checks/check_extra723 | 12 ++++++------ checks/check_extra724 | 6 +++--- checks/check_extra73 | 10 +++++----- checks/check_extra74 | 6 +++--- checks/check_extra75 | 6 +++--- checks/check_extra76 | 6 +++--- checks/check_extra77 | 6 +++--- checks/check_extra78 | 6 +++--- checks/check_extra79 | 6 +++--- checks/check_sample | 6 +++--- include/credentials_report | 2 +- include/outputs | 6 +++--- include/whoami | 2 +- prowler | 2 +- 81 files changed, 267 insertions(+), 267 deletions(-) diff --git a/checks/check11 b/checks/check11 index d56d70f6d4..4db6163342 100644 --- a/checks/check11 +++ b/checks/check11 @@ -6,5 +6,5 @@ CHECK_ALTERNATE_check101="check11" check11(){ # "Avoid the use of the root account (Scored)." COMMAND11=$(cat $TEMP_REPORT_FILE| grep '' | cut -d, -f5,11,16 | sed 's/,/\ /g') - textNotice "Root account last accessed (password key_1 key_2): $COMMAND11" + textInfo "Root account last accessed (password key_1 key_2): $COMMAND11" } diff --git a/checks/check110 b/checks/check110 index 5f31e84423..4aada2f0f9 100644 --- a/checks/check110 +++ b/checks/check110 @@ -8,11 +8,11 @@ check110(){ COMMAND110=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' --output text 2> /dev/null) if [[ $COMMAND110 ]];then if [[ $COMMAND110 -gt "23" ]];then - textOK "Password Policy limits reuse" + textPass "Password Policy limits reuse" else - textWarn "Password Policy has weak reuse requirement (lower than 24)" + textFail "Password Policy has weak reuse requirement (lower than 24)" fi else - textWarn "Password Policy missing reuse requirement" + textFail "Password Policy missing reuse requirement" fi } diff --git a/checks/check111 b/checks/check111 index 3d93a54826..5ff5845f19 100644 --- a/checks/check111 +++ b/checks/check111 @@ -8,9 +8,9 @@ check111(){ COMMAND111=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g' 2> /dev/null) if [[ $COMMAND111 ]];then if [ "$COMMAND111" == "90" ];then - textOK "Password Policy includes expiration" + textPass "Password Policy includes expiration" fi else - textWarn "Password expiration not set or set greater than 90 days " + textFail "Password expiration not set or set greater than 90 days " fi } diff --git a/checks/check112 b/checks/check112 index 84472b5c14..3d79f6e001 100644 --- a/checks/check112 +++ b/checks/check112 @@ -9,13 +9,13 @@ check112(){ ROOTKEY1=$(cat $TEMP_REPORT_FILE |grep root_account|awk -F',' '{ print $9 }') ROOTKEY2=$(cat $TEMP_REPORT_FILE |grep root_account|awk -F',' '{ print $14 }') if [ "$ROOTKEY1" == "false" ];then - textOK "No access key 1 found for root" + textPass "No access key 1 found for root" else - textWarn "Found access key 1 for root " + textFail "Found access key 1 for root " fi if [ "$ROOTKEY2" == "false" ];then - textOK "No access key 2 found for root" + textPass "No access key 2 found for root" else - textWarn "Found access key 2 for root " + textFail "Found access key 2 for root " fi } diff --git a/checks/check113 b/checks/check113 index 9f9fb57932..46aaf4a582 100644 --- a/checks/check113 +++ b/checks/check113 @@ -7,8 +7,8 @@ check113(){ # "Ensure MFA is enabled for the root account (Scored)" COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json --query 'SummaryMap.AccountMFAEnabled') if [ "$COMMAND113" == "1" ]; then - textOK "Virtual MFA is enabled for root" + textPass "Virtual MFA is enabled for root" else - textWarn "MFA is not ENABLED for root account " + textFail "MFA is not ENABLED for root account " fi } diff --git a/checks/check114 b/checks/check114 index 058c38497f..d98371be71 100644 --- a/checks/check114 +++ b/checks/check114 @@ -9,11 +9,11 @@ check114(){ if [ "$COMMAND113" == "1" ]; then COMMAND114=$($AWSCLI iam list-virtual-mfa-devices $PROFILE_OPT --region $REGION --output text --assignment-status Assigned --query 'VirtualMFADevices[*].[SerialNumber]' | grep '^arn:aws:iam::[0-9]\{12\}:mfa/root-account-mfa-device$') if [[ "$COMMAND114" ]]; then - textWarn "Only Virtual MFA is enabled for root" + textFail "Only Virtual MFA is enabled for root" else - textOK "Hardware MFA is enabled for root " + textPass "Hardware MFA is enabled for root " fi else - textWarn "MFA is not ENABLED for root account " + textFail "MFA is not ENABLED for root account " fi } diff --git a/checks/check115 b/checks/check115 index 007d9f04d6..19a5c2a974 100644 --- a/checks/check115 +++ b/checks/check115 @@ -5,7 +5,7 @@ CHECK_ALTERNATE_check115="check115" check115(){ # "Ensure security questions are registered in the AWS account (Not Scored)" - textNotice "No command available for check 1.15 " - textNotice "Login to the AWS Console as root & click on the Account " - textNotice "Name -> My Account -> Configure Security Challenge Questions " + textInfo "No command available for check 1.15 " + textInfo "Login to the AWS Console as root & click on the Account " + textInfo "Name -> My Account -> Configure Security Challenge Questions " } diff --git a/checks/check116 b/checks/check116 index ae9aee0c7b..0534903f94 100644 --- a/checks/check116 +++ b/checks/check116 @@ -10,11 +10,11 @@ check116(){ for user in $LIST_USERS;do USER_POLICY=$($AWSCLI iam list-attached-user-policies --output text $PROFILE_OPT --region $REGION --user-name $user) if [[ $USER_POLICY ]]; then - textWarn "$user has policy directly attached " + textFail "$user has policy directly attached " C116_NUM_USERS=$(expr $C116_NUM_USERS + 1) fi done if [[ $C116_NUM_USERS -eq 0 ]]; then - textOK "No policies attached to users." + textPass "No policies attached to users." fi } diff --git a/checks/check117 b/checks/check117 index 352e3960ef..49818cc89a 100644 --- a/checks/check117 +++ b/checks/check117 @@ -6,6 +6,6 @@ CHECK_ALTERNATE_check117="check117" check117(){ # "Enable detailed billing (Scored)" # No command available - textNotice "No command available for check 1.17 " - textNotice "See section 1.17 on the CIS Benchmark guide for details " + textInfo "No command available for check 1.17 " + textInfo "See section 1.17 on the CIS Benchmark guide for details " } diff --git a/checks/check118 b/checks/check118 index e98769123f..62961ce0dd 100644 --- a/checks/check118 +++ b/checks/check118 @@ -8,22 +8,22 @@ check118(){ FINDMASTERANDMANAGER=$($AWSCLI iam list-roles $PROFILE_OPT --region $REGION --query "Roles[*].{RoleName:RoleName}" --output text | grep -E 'Master|Manager'| tr ' ' ' ') if [[ $FINDMASTERANDMANAGER ]];then - textNotice "Found next roles as possible IAM Master and IAM Manager candidates: " - textNotice "$FINDMASTERANDMANAGER " - textNotice "run the commands below to check their policies with section 1.18 in the guide..." + textInfo "Found next roles as possible IAM Master and IAM Manager candidates: " + textInfo "$FINDMASTERANDMANAGER " + textInfo "run the commands below to check their policies with section 1.18 in the guide..." for role in $FINDMASTERANDMANAGER;do # find inline policies in found roles INLINEPOLICIES=$($AWSCLI iam list-role-policies --role-name $role $PROFILE_OPT --region $REGION --query "PolicyNames[*]" --output text) for policy in $INLINEPOLICIES;do - textNotice "INLINE: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json" + textInfo "INLINE: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json" done # find attached policies in found roles ATTACHEDPOLICIES=$($AWSCLI iam list-attached-role-policies --role-name $role $PROFILE_OPT --region $REGION --query "AttachedPolicies[*]" --output text) for policy in $ATTACHEDPOLICIES;do - textNotice "ATTACHED: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json" + textInfo "ATTACHED: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json" done done else - textWarn "IAM Master and IAM Manager roles not found" + textFail "IAM Master and IAM Manager roles not found" fi } diff --git a/checks/check119 b/checks/check119 index 4c3b797b50..66c70b6a89 100644 --- a/checks/check119 +++ b/checks/check119 @@ -6,6 +6,6 @@ CHECK_ALTERNATE_check119="check119" check119(){ # "Maintain current contact details (Scored)" # No command available - textNotice "No command available for check 1.19 " - textNotice "See section 1.19 on the CIS Benchmark guide for details " + textInfo "No command available for check 1.19 " + textInfo "See section 1.19 on the CIS Benchmark guide for details " } diff --git a/checks/check12 b/checks/check12 index 54d68e8bc4..ad88e9b985 100644 --- a/checks/check12 +++ b/checks/check12 @@ -13,9 +13,9 @@ check12(){ done) if [[ $COMMAND12 ]]; then for u in $COMMAND12; do - textWarn "User $u has Password enabled but MFA disabled" + textFail "User $u has Password enabled but MFA disabled" done else - textOK "No users found with Password enabled and MFA disabled" + textPass "No users found with Password enabled and MFA disabled" fi } diff --git a/checks/check120 b/checks/check120 index 6bce3e6e2b..5a0c462593 100644 --- a/checks/check120 +++ b/checks/check120 @@ -6,6 +6,6 @@ CHECK_ALTERNATE_check120="check120" check120(){ # "Ensure security contact information is registered (Scored)" # No command available - textNotice "No command available for check 1.20 " - textNotice "See section 1.20 on the CIS Benchmark guide for details " + textInfo "No command available for check 1.20 " + textInfo "See section 1.20 on the CIS Benchmark guide for details " } diff --git a/checks/check121 b/checks/check121 index 3457ec0605..581affcae1 100644 --- a/checks/check121 +++ b/checks/check121 @@ -5,6 +5,6 @@ CHECK_ALTERNATE_check121="check121" check121(){ # "Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" - textNotice "No command available for check 1.21 " - textNotice "See section 1.21 on the CIS Benchmark guide for details " + textInfo "No command available for check 1.21 " + textInfo "See section 1.21 on the CIS Benchmark guide for details " } diff --git a/checks/check122 b/checks/check122 index d5c2a81cbc..52f9b3b503 100644 --- a/checks/check122 +++ b/checks/check122 @@ -10,16 +10,16 @@ check122(){ for policyarn in $SUPPORTPOLICYARN;do POLICYUSERS=$($AWSCLI iam list-entities-for-policy --policy-arn $SUPPORTPOLICYARN $PROFILE_OPT --region $REGION --output json) if [[ $POLICYUSERS ]];then - textOK "Support Policy attached to $policyarn" + textPass "Support Policy attached to $policyarn" for user in $(echo "$POLICYUSERS" | grep UserName | cut -d'"' -f4) ; do - textNotice "User $user has support access via $policyarn" + textInfo "User $user has support access via $policyarn" done - # textNotice "Make sure your team can create a Support case with AWS " + # textInfo "Make sure your team can create a Support case with AWS " else - textWarn "Support Policy not applied to any Group / User / Role " + textFail "Support Policy not applied to any Group / User / Role " fi done else - textWarn "No Support Policy found" + textFail "No Support Policy found" fi } diff --git a/checks/check123 b/checks/check123 index 4118f796d2..766df86666 100644 --- a/checks/check123 +++ b/checks/check123 @@ -11,19 +11,19 @@ check123(){ LIST_USERS_KEY1_ACTIVE=$(for user in $LIST_USERS_KEY1_NA; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$9 }'|grep "true$"|awk '{ print $1 }'|sed 's/[[:blank:]]+/,/g' ; done) if [[ $LIST_USERS_KEY1_ACTIVE ]]; then for user in $LIST_USERS_KEY1_ACTIVE; do - textNotice "$user has never used Access Key 1" + textInfo "$user has never used Access Key 1" done else - textOK "No users found with Access Key 1 never used" + textPass "No users found with Access Key 1 never used" fi # List of USERS with KEY2 last_used_date as N/A LIST_USERS_KEY2_NA=$(for user in $LIST_USERS; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$16 }'|grep N/A |awk '{ print $1 }' ; done) LIST_USERS_KEY2_ACTIVE=$(for user in $LIST_USERS_KEY2_NA; do grep "^${user}," $TEMP_REPORT_FILE|awk -F, '{ print $1,$14 }'|grep "true$" |awk '{ print $1 }' ; done) if [[ $LIST_USERS_KEY2_ACTIVE ]]; then for user in $LIST_USERS_KEY2_ACTIVE; do - textNotice "$user has never used Access Key 2" + textInfo "$user has never used Access Key 2" done else - textOK "No users found with Access Key 2 never used" + textPass "No users found with Access Key 2 never used" fi } diff --git a/checks/check124 b/checks/check124 index 7ae7855222..03bbb44a93 100644 --- a/checks/check124 +++ b/checks/check124 @@ -7,7 +7,7 @@ check124(){ # "Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" LIST_CUSTOM_POLICIES=$($AWSCLI iam list-policies --output text $PROFILE_OPT --region $REGION|grep 'arn:aws:iam::[0-9]\{12\}:'|awk '{ print $2 }') if [[ $LIST_CUSTOM_POLICIES ]]; then - textNotice "Looking for custom policies: (skipping default policies - it may take few seconds...)" + textInfo "Looking for custom policies: (skipping default policies - it may take few seconds...)" for policy in $LIST_CUSTOM_POLICIES; do POLICY_VERSION=$($AWSCLI iam list-policies $PROFILE_OPT --region $REGION --query 'Policies[*].[Arn,DefaultVersionId]' --output text |awk "\$1 == \"$policy\" { print \$2 }") POLICY_WITH_FULL=$($AWSCLI iam get-policy-version --output text --policy-arn $policy --version-id $POLICY_VERSION --query "PolicyVersion.Document.Statement[?Effect == 'Allow' && contains(Resource, '*') && contains (Action, '*')]" $PROFILE_OPT --region $REGION) @@ -16,14 +16,14 @@ check124(){ fi done if [[ $POLICIES_ALLOW_LIST ]]; then - textNotice "List of custom policies: " + textInfo "List of custom policies: " for policy in $POLICIES_ALLOW_LIST; do - textNotice "Policy $policy allows \"*:*\"" + textInfo "Policy $policy allows \"*:*\"" done else - textOK "No custom policy found that allow full \"*:*\" administrative privileges" + textPass "No custom policy found that allow full \"*:*\" administrative privileges" fi else - textOK "No custom policies found" + textPass "No custom policies found" fi } diff --git a/checks/check13 b/checks/check13 index 0ef66c7cec..a515ebc935 100644 --- a/checks/check13 +++ b/checks/check13 @@ -19,13 +19,13 @@ check13(){ DATEUSED=$($AWSCLI iam list-users --query "Users[?UserName=='$i'].PasswordLastUsed" --output text $PROFILE_OPT --region $REGION | cut -d'T' -f1) HOWOLDER=$(how_older_from_today $DATEUSED) if [ $HOWOLDER -gt "90" ];then - textWarn "User \"$i\" has not logged in during the last 90 days " + textFail "User \"$i\" has not logged in during the last 90 days " else - textOK "User \"$i\" found with credentials used in the last 90 days" + textPass "User \"$i\" found with credentials used in the last 90 days" fi done fi else - textOK "No users found with password enabled" + textPass "No users found with password enabled" fi } diff --git a/checks/check14 b/checks/check14 index 8aaf408713..d3cb2798cb 100644 --- a/checks/check14 +++ b/checks/check14 @@ -10,39 +10,39 @@ check14(){ C14_NUM_USERS1=0 C14_NUM_USERS2=0 if [[ $LIST_OF_USERS_WITH_ACCESS_KEY1 ]]; then - # textWarn "Users with access key 1 older than 90 days:" + # textFail "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 -v user_creation_time | 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 - textWarn " $user has not rotated access key1 in over 90 days " + textFail " $user has not rotated access key1 in over 90 days " C14_NUM_USERS1=$(expr $C14_NUM_USERS1 + 1) fi done if [[ $C14_NUM_USERS1 -eq 0 ]]; then - textOK "No users with access key 1 older than 90 days." + textPass "No users with access key 1 older than 90 days." fi else - textOK "No users with access key 1." + textPass "No users with access key 1." fi if [[ $LIST_OF_USERS_WITH_ACCESS_KEY2 ]]; then - # textWarn "Users with access key 2 older than 90 days:" + # textFail "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 -v user_creation_time | 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 - textWarn " $user has not rotated access key2. " + textFail " $user has not rotated access key2. " C14_NUM_USERS2=$(expr $C14_NUM_USERS2 + 1) fi done if [[ $C14_NUM_USERS2 -eq 0 ]]; then - textOK "No users with access key 2 older than 90 days." + textPass "No users with access key 2 older than 90 days." fi else - textOK "No users with access key 2." + textPass "No users with access key 2." fi } diff --git a/checks/check15 b/checks/check15 index 698fae1aa4..d9172d9236 100644 --- a/checks/check15 +++ b/checks/check15 @@ -7,8 +7,8 @@ check15(){ # "Ensure IAM password policy requires at least one uppercase letter (Scored)" COMMAND15=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireUppercaseCharacters' 2> /dev/null) # must be true if [[ "$COMMAND15" == "true" ]];then - textOK "Password Policy requires upper case" + textPass "Password Policy requires upper case" else - textWarn "Password Policy missing upper-case requirement" + textFail "Password Policy missing upper-case requirement" fi } diff --git a/checks/check16 b/checks/check16 index 8ae18a2225..f940a89df8 100644 --- a/checks/check16 +++ b/checks/check16 @@ -7,8 +7,8 @@ check16(){ # "Ensure IAM password policy require at least one lowercase letter (Scored)" COMMAND16=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireLowercaseCharacters' 2> /dev/null) # must be true if [[ "$COMMAND16" == "true" ]];then - textOK "Password Policy requires lower case" + textPass "Password Policy requires lower case" else - textWarn "Password Policy missing lower-case requirement" + textFail "Password Policy missing lower-case requirement" fi } diff --git a/checks/check17 b/checks/check17 index 18177b6132..df54d702dc 100644 --- a/checks/check17 +++ b/checks/check17 @@ -7,8 +7,8 @@ check17(){ # "Ensure IAM password policy require at least one symbol (Scored)" COMMAND17=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireSymbols' 2> /dev/null) # must be true if [[ "$COMMAND17" == "true" ]];then - textOK "Password Policy requires symbol" + textPass "Password Policy requires symbol" else - textWarn "Password Policy missing symbol requirement" + textFail "Password Policy missing symbol requirement" fi } diff --git a/checks/check18 b/checks/check18 index 2f2189ee0f..279c5e0917 100644 --- a/checks/check18 +++ b/checks/check18 @@ -7,8 +7,8 @@ check18(){ # "Ensure IAM password policy require at least one number (Scored)" COMMAND18=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireNumbers' 2> /dev/null) # must be true if [[ "$COMMAND18" == "true" ]];then - textOK "Password Policy requires number" + textPass "Password Policy requires number" else - textWarn "Password Policy missing number requirement" + textFail "Password Policy missing number requirement" fi } diff --git a/checks/check19 b/checks/check19 index 08f880a07b..876babdd6f 100644 --- a/checks/check19 +++ b/checks/check19 @@ -7,8 +7,8 @@ check19(){ # "Ensure IAM password policy requires minimum length of 14 or greater (Scored)" COMMAND19=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.MinimumPasswordLength' 2> /dev/null) if [[ $COMMAND19 -gt "13" ]];then - textOK "Password Policy requires more than 13 characters" + textPass "Password Policy requires more than 13 characters" else - textWarn "Password Policy missing or weak length requirement" + textFail "Password Policy missing or weak length requirement" fi } diff --git a/checks/check21 b/checks/check21 index bd7b0fcf79..f7d4f9df2b 100644 --- a/checks/check21 +++ b/checks/check21 @@ -10,12 +10,12 @@ check21(){ for trail in $LIST_OF_TRAILS;do MULTIREGION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].IsMultiRegionTrail' --output text --trail-name-list $trail) if [[ "$MULTIREGION_TRAIL_STATUS" == 'False' ]];then - textWarn "$trail trail in $REGION is not enabled in multi region mode" + textFail "$trail trail in $REGION is not enabled in multi region mode" else - textOK "$trail trail in $REGION is enabled for all regions" + textPass "$trail trail in $REGION is enabled for all regions" fi done else - textWarn "No CloudTrail trails found!" + textFail "No CloudTrail trails found!" fi } diff --git a/checks/check22 b/checks/check22 index ca3d48ae55..8c329a8b13 100644 --- a/checks/check22 +++ b/checks/check22 @@ -10,12 +10,12 @@ check22(){ for trail in $LIST_OF_TRAILS;do LOGFILEVALIDATION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].LogFileValidationEnabled' --output text --trail-name-list $trail) if [[ "$LOGFILEVALIDATION_TRAIL_STATUS" == 'False' ]];then - textWarn "$trail trail in $REGION has not log file validation enabled" + textFail "$trail trail in $REGION has not log file validation enabled" else - textOK "$trail trail in $REGION has log file validation enabled" + textPass "$trail trail in $REGION has log file validation enabled" fi done else - textWarn "No CloudTrail trails found!" + textFail "No CloudTrail trails found!" fi } diff --git a/checks/check23 b/checks/check23 index 5e44808f4e..e3b0da34fb 100644 --- a/checks/check23 +++ b/checks/check23 @@ -10,12 +10,12 @@ check23(){ for bucket in $CLOUDTRAILBUCKET;do CLOUDTRAILBUCKET_HASALLPERMISIONS=$($AWSCLI s3api get-bucket-acl --bucket $bucket --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' $PROFILE_OPT --region $REGION --output text) if [[ $CLOUDTRAILBUCKET_HASALLPERMISIONS ]];then - textWarn "check your $bucket CloudTrail bucket ACL and Policy!" + textFail "check your $bucket CloudTrail bucket ACL and Policy!" else - textOK "Bucket $bucket is set correctly" + textPass "Bucket $bucket is set correctly" fi done else - textWarn "No CloudTrail bucket found!" + textFail "No CloudTrail bucket found!" fi } diff --git a/checks/check24 b/checks/check24 index 438d6bd20a..36c1f12394 100644 --- a/checks/check24 +++ b/checks/check24 @@ -12,18 +12,18 @@ check24(){ TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) LATESTDELIVERY_TIMESTAMP=$($AWSCLI cloudtrail get-trail-status --name $trail $PROFILE_OPT --region $TRAIL_REGION --query 'LatestCloudWatchLogsDeliveryTime' --output text|grep -v None) if [[ ! $LATESTDELIVERY_TIMESTAMP ]];then - textWarn "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" + textFail "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" else LATESTDELIVERY_DATE=$(timestamp_to_date $LATESTDELIVERY_TIMESTAMP) HOWOLDER=$(how_older_from_today $LATESTDELIVERY_DATE) if [ $HOWOLDER -gt "1" ];then - textWarn "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" + textFail "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" else - textOK "$trail trail has been logging during the last 24h (it is in $TRAIL_REGION)" + textPass "$trail trail has been logging during the last 24h (it is in $TRAIL_REGION)" fi fi done else - textWarn "No CloudTrail trails found!" + textFail "No CloudTrail trails found!" fi } diff --git a/checks/check25 b/checks/check25 index d321b0a42a..fb5e3551cb 100644 --- a/checks/check25 +++ b/checks/check25 @@ -8,9 +8,9 @@ check25(){ for regx in $REGIONS; do CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice get-status $PROFILE_OPT --region $regx --output json| grep "recorder: ON") if [[ $CHECK_AWSCONFIG_STATUS ]];then - textOK "Region $regx has AWS Config recorder: ON" "$regx" + textPass "Region $regx has AWS Config recorder: ON" "$regx" else - textWarn "Region $regx has AWS Config disabled or not configured" "$regx" + textFail "Region $regx has AWS Config disabled or not configured" "$regx" fi done } diff --git a/checks/check26 b/checks/check26 index 8f72cbbae8..9d73568eda 100644 --- a/checks/check26 +++ b/checks/check26 @@ -10,12 +10,12 @@ check26(){ for bucket in $CLOUDTRAILBUCKET;do CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --region $REGION --query 'LoggingEnabled.TargetBucket' --output text|grep -v None) if [[ $CLOUDTRAILBUCKET_LOGENABLED ]];then - textOK "Bucket access logging enabled in $bucket" + textPass "Bucket access logging enabled in $bucket" else - textWarn "access logging is not enabled in $bucket CloudTrail S3 bucket!" + textFail "access logging is not enabled in $bucket CloudTrail S3 bucket!" fi done else - textWarn "CloudTrail bucket not found!" + textFail "CloudTrail bucket not found!" fi } diff --git a/checks/check27 b/checks/check27 index 8b1964c168..0e9654a0bb 100644 --- a/checks/check27 +++ b/checks/check27 @@ -10,12 +10,12 @@ check27(){ for trail in $CLOUDTRAILNAME;do CLOUDTRAILENC_ENABLED=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --trail $trail --query 'trailList[*].KmsKeyId' --output text) if [[ $CLOUDTRAILENC_ENABLED ]];then - textOK "KMS key found for $trail" + textPass "KMS key found for $trail" else - textWarn "encryption is not enabled in your CloudTrail trail $trail (KMS key not found)!" + textFail "encryption is not enabled in your CloudTrail trail $trail (KMS key not found)!" fi done else - textWarn "CloudTrail bucket doesn't exist!" + textFail "CloudTrail bucket doesn't exist!" fi } diff --git a/checks/check28 b/checks/check28 index 9f016dc4c0..172bc1009a 100644 --- a/checks/check28 +++ b/checks/check28 @@ -12,19 +12,19 @@ check28(){ for key in $CHECK_KMS_KEYLIST_NO_DEFAULT; do CHECK_KMS_KEY_TYPE=$($AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --query 'KeyMetadata.Origin' | sed 's/["]//g') if [[ "$CHECK_KMS_KEY_TYPE" == "EXTERNAL" ]];then - textOK "Key $key in Region $regx Customer Uploaded Key Material." "$regx" + textPass "Key $key in Region $regx Customer Uploaded Key Material." "$regx" else CHECK_KMS_KEY_ROTATION=$($AWSCLI kms get-key-rotation-status --key-id $key $PROFILE_OPT --region $regx --output text) if [[ "$CHECK_KMS_KEY_ROTATION" == "True" ]];then - textOK "Key $key in Region $regx is set correctly" + textPass "Key $key in Region $regx is set correctly" else - textWarn "Key $key in Region $regx is not set to rotate!!!" "$regx" + textFail "Key $key in Region $regx is not set to rotate!!!" "$regx" fi fi done else - textNotice "Region $regx doesn't have encryption keys" "$regx" + textInfo "Region $regx doesn't have encryption keys" "$regx" fi done } diff --git a/checks/check31 b/checks/check31 index 1a29627844..09d7ef1bdd 100644 --- a/checks/check31 +++ b/checks/check31 @@ -32,7 +32,7 @@ check31(){ for group in $CHECK31OK; do metric=${group#*:} group=${group%:*} - textOK "CloudWatch group $group found with metric filter $metric and alarms set for Unauthorized Operation and Access Denied" + textPass "CloudWatch group $group found with metric filter $metric and alarms set for Unauthorized Operation and Access Denied" done fi if [[ $CHECK31WARN ]]; then @@ -40,13 +40,13 @@ check31(){ case $group in *:*) metric=${group#*:} group=${group%:*} - textWarn "CloudWatch group $group found with metric filter $metric but no alarms associated" + textFail "CloudWatch group $group found with metric filter $metric but no alarms associated" ;; - *) textWarn "CloudWatch group $group found but no metric filters or alarms associated" + *) textFail "CloudWatch group $group found but no metric filters or alarms associated" esac done fi else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check310 b/checks/check310 index 78c0ad9793..7e43cd31b0 100644 --- a/checks/check310 +++ b/checks/check310 @@ -14,15 +14,15 @@ check310(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /SecurityGroup/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for security group changes" + textPass "CloudWatch group $group found with metric filters and alarms for security group changes" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check311 b/checks/check311 index b363f3f2de..b7a5ea917d 100644 --- a/checks/check311 +++ b/checks/check311 @@ -14,15 +14,15 @@ check311(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /NetworkAcl/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for changes to NACLs" + textPass "CloudWatch group $group found with metric filters and alarms for changes to NACLs" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check312 b/checks/check312 index e37273804f..32e3c33ed2 100644 --- a/checks/check312 +++ b/checks/check312 @@ -14,15 +14,15 @@ check312(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /InternetGateway/ || /CustomerGateway/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for changes to network gateways" + textPass "CloudWatch group $group found with metric filters and alarms for changes to network gateways" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check313 b/checks/check313 index 8e92c7d5c0..1c25be028a 100644 --- a/checks/check313 +++ b/checks/check313 @@ -14,15 +14,15 @@ check313(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /Route/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for route table changes" + textPass "CloudWatch group $group found with metric filters and alarms for route table changes" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check314 b/checks/check314 index a840929d3b..87d67b4125 100644 --- a/checks/check314 +++ b/checks/check314 @@ -14,15 +14,15 @@ check314(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /VPC/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for VPC changes" + textPass "CloudWatch group $group found with metric filters and alarms for VPC changes" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check315 b/checks/check315 index 239bd8dece..2598fd8337 100644 --- a/checks/check315 +++ b/checks/check315 @@ -10,7 +10,7 @@ check315(){ TOPICS_LIST=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --output text --query 'Topics[*].TopicArn') ntopics=$(echo $TOPICS_LIST | wc -w ) if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then - textNotice "Region $regx has $ntopics topics" "$regx" + textInfo "Region $regx has $ntopics topics" "$regx" for topic in $TOPICS_LIST; do TOPIC_SHORT=$(echo $topic | awk -F: '{ print $6 }') CHECK_TOPIC_LIST=$($AWSCLI sns list-subscriptions-by-topic --topic-arn $topic $PROFILE_OPT --region $regx --query 'Subscriptions[*].{Endpoint:Endpoint,Protocol:Protocol}' --output text --max-items $MAXITEMS 2> /dev/null) @@ -18,23 +18,23 @@ check315(){ # Permission error export CAN_SNS_LIST_SUBS=0 ntopics=$(echo $TOPICS_LIST | wc -w ) - textNotice "Region $regx / $ntopics Topics / Subscriptions NO_PERMISSION" "$regx" + textInfo "Region $regx / $ntopics Topics / Subscriptions NO_PERMISSION" "$regx" break; fi if [[ "Z" != "Z${CHECK_TOPIC_LIST}" ]]; then printf '%s ' "$CHECK_TOPIC_LIST" | while IFS= read -r dest ; do - textNotice "Region $regx / Topic $TOPIC_SHORT / Subscription $dest" "$regx" + textInfo "Region $regx / Topic $TOPIC_SHORT / Subscription $dest" "$regx" done else - textWarn "Region $regx / Topic $TOPIC_SHORT / Subscription NONE" "$regx" + textFail "Region $regx / Topic $TOPIC_SHORT / Subscription NONE" "$regx" fi done elif [[ $CAN_SNS_LIST_SUBS -eq 0 ]]; then - textNotice "Region $regx has $ntopics topics - unable to list subscribers" "$regx" + textInfo "Region $regx has $ntopics topics - unable to list subscribers" "$regx" # break else - textOK "Region $regx has 0 topics" "$regx" + textPass "Region $regx has 0 topics" "$regx" fi done } diff --git a/checks/check32 b/checks/check32 index 9122b14817..516eefd06b 100644 --- a/checks/check32 +++ b/checks/check32 @@ -14,15 +14,15 @@ check32(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /ConsoleLogin/ || /MFAUsed/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms set for sign-in Console without MFA enabled" + textPass "CloudWatch group $group found with metric filters and alarms set for sign-in Console without MFA enabled" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check33 b/checks/check33 index 37c56daf99..9dc3ed94d5 100644 --- a/checks/check33 +++ b/checks/check33 @@ -14,15 +14,15 @@ check33(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | tr '[:upper:]' '[:lower:]'| grep -Ei 'userIdentity|Root|AwsServiceEvent') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms set for usage of root account" + textPass "CloudWatch group $group found with metric filters and alarms set for usage of root account" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check34 b/checks/check34 index 3d576033c6..83c5cbb689 100644 --- a/checks/check34 +++ b/checks/check34 @@ -14,15 +14,15 @@ check34(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /DeletePolicy/ || /DeletePolicies/ || /Policies/ || /Policy/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for IAM policy changes" + textPass "CloudWatch group $group found with metric filters and alarms for IAM policy changes" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check35 b/checks/check35 index 9bcf623db9..50fd288960 100644 --- a/checks/check35 +++ b/checks/check35 @@ -14,15 +14,15 @@ check35(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /TrailChange/ || /Trails/ || /CreateTrail/ || /UpdateTrail/ || /DeleteTrail/ || /StartLogging/ || /StopLogging/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for CloudTrail configuration changes" + textPass "CloudWatch group $group found with metric filters and alarms for CloudTrail configuration changes" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check36 b/checks/check36 index 92a5fb36bb..54e320f707 100644 --- a/checks/check36 +++ b/checks/check36 @@ -14,15 +14,15 @@ check36(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /FailedLogin/ || /ConsoleLogin/ || /Failed/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for AWS Management Console authentication failures" + textPass "CloudWatch group $group found with metric filters and alarms for AWS Management Console authentication failures" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check37 b/checks/check37 index 064e85654e..01147afdee 100644 --- a/checks/check37 +++ b/checks/check37 @@ -14,15 +14,15 @@ check37(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /DisableKey/ || /ScheduleKeyDeletion/ || /kms/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for changes of customer created CMKs" + textPass "CloudWatch group $group found with metric filters and alarms for changes of customer created CMKs" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check38 b/checks/check38 index d2d17ab7bd..9ddfa902ea 100644 --- a/checks/check38 +++ b/checks/check38 @@ -14,15 +14,15 @@ check38(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /S3/ || /BucketPolicy/ || /BucketPolicies/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for S3 bucket policy changes" + textPass "CloudWatch group $group found with metric filters and alarms for S3 bucket policy changes" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check39 b/checks/check39 index c23b67b3eb..3aa14527b6 100644 --- a/checks/check39 +++ b/checks/check39 @@ -14,15 +14,15 @@ check39(){ if [[ $METRICFILTER_SET ]];then HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[].MetricName' --output text | awk 'BEGIN {IGNORECASE=1}; /config/ || /ConfigurationRecorder/ || /DeliveryChannel/;') if [[ $HAS_ALARM_ASSOCIATED ]];then - textOK "CloudWatch group $group found with metric filters and alarms for AWS Config configuration changes" + textPass "CloudWatch group $group found with metric filters and alarms for AWS Config configuration changes" else - textWarn "CloudWatch group $group found with metric filters but no alarms associated" + textFail "CloudWatch group $group found with metric filters but no alarms associated" fi else - textWarn "CloudWatch group $group found but no metric filters or alarms associated" + textFail "CloudWatch group $group found but no metric filters or alarms associated" fi done else - textWarn "No CloudWatch group found for CloudTrail events" + textFail "No CloudWatch group found for CloudTrail events" fi } diff --git a/checks/check41 b/checks/check41 index 72b6a7f7dd..d63ae4ded5 100644 --- a/checks/check41 +++ b/checks/check41 @@ -9,10 +9,10 @@ check41(){ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`22` && ToPort>=`22`)) && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text) if [[ $SG_LIST ]];then for SG in $SG_LIST;do - textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" + textFail "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" done else - textOK "No Security Groups found in $regx with port 22 TCP open to 0.0.0.0/0" "$regx" + textPass "No Security Groups found in $regx with port 22 TCP open to 0.0.0.0/0" "$regx" fi done } diff --git a/checks/check42 b/checks/check42 index 41746d2dfa..6db241f44c 100644 --- a/checks/check42 +++ b/checks/check42 @@ -9,10 +9,10 @@ check42(){ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`3389` && ToPort>=`3389`)) && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text) if [[ $SG_LIST ]];then for SG in $SG_LIST;do - textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" + textFail "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" done else - textOK "No Security Groups found in $regx with port 3389 TCP open to 0.0.0.0/0" "$regx" + textPass "No Security Groups found in $regx with port 3389 TCP open to 0.0.0.0/0" "$regx" fi done } diff --git a/checks/check43 b/checks/check43 index 847e175371..1da367d77f 100644 --- a/checks/check43 +++ b/checks/check43 @@ -9,10 +9,10 @@ check43(){ CHECK_FL=$($AWSCLI ec2 describe-flow-logs $PROFILE_OPT --region $regx --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].LogGroupName' --output text) if [[ $CHECK_FL ]];then for FL in $CHECK_FL;do - textOK "VPCFlowLog is enabled for LogGroupName: $FL in Region $regx" "$regx" + textPass "VPCFlowLog is enabled for LogGroupName: $FL in Region $regx" "$regx" done else - textWarn "No VPCFlowLog has been found in Region $regx" "$regx" + textFail "No VPCFlowLog has been found in Region $regx" "$regx" fi done } diff --git a/checks/check44 b/checks/check44 index f19150c066..0d1e3bbe70 100644 --- a/checks/check44 +++ b/checks/check44 @@ -8,9 +8,9 @@ check44(){ for regx in $REGIONS; do CHECK_SGDEFAULT=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters Name=group-name,Values='default' --query 'SecurityGroups[*].{IpPermissions:IpPermissions,IpPermissionsEgress:IpPermissionsEgress,GroupId:GroupId}' --output text |grep 0.0.0.0) if [[ $CHECK_SGDEFAULT ]];then - textWarn "Default Security Groups found that allow 0.0.0.0 IN or OUT traffic in Region $regx" "$regx" + textFail "Default Security Groups found that allow 0.0.0.0 IN or OUT traffic in Region $regx" "$regx" else - textOK "No Default Security Groups open to 0.0.0.0 found in Region $regx" "$regx" + textPass "No Default Security Groups open to 0.0.0.0 found in Region $regx" "$regx" fi done } diff --git a/checks/check45 b/checks/check45 index b71e5c0ac5..5776a6b034 100644 --- a/checks/check45 +++ b/checks/check45 @@ -5,11 +5,11 @@ CHECK_ALTERNATE_check405="check45" check45(){ # "Ensure routing tables for VPC peering are \"least access\" (Not Scored)" - textNotice "Looking for VPC peering in all regions... " + textInfo "Looking for VPC peering in all regions... " for regx in $REGIONS; do LIST_OF_VPCS_PEERING_CONNECTIONS=$($AWSCLI ec2 describe-vpc-peering-connections --output text $PROFILE_OPT --region $regx --query 'VpcPeeringConnections[*].VpcPeeringConnectionId') if [[ $LIST_OF_VPCS_PEERING_CONNECTIONS ]];then - textNotice "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS - review routing tables" "$regx" + textInfo "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS - review routing tables" "$regx" #LIST_OF_VPCS=$($AWSCLI ec2 describe-vpcs $PROFILE_OPT --region $regx --query 'Vpcs[*].VpcId' --output text) #aws ec2 describe-route-tables --filter "Name=vpc-id,Values=vpc-0213e864" --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" $PROFILE_OPT --region $regx # for vpc in $LIST_OF_VPCS; do @@ -17,7 +17,7 @@ check45(){ # done #echo $VPCS_WITH_PEERING else - textOK "$regx: No VPC peering found" "$regx" + textPass "$regx: No VPC peering found" "$regx" fi done } diff --git a/checks/check_extra71 b/checks/check_extra71 index ef672fcfa6..0cb0632cc5 100644 --- a/checks/check_extra71 +++ b/checks/check_extra71 @@ -15,7 +15,7 @@ extra71(){ CHECK_ADMIN_GROUP=$($AWSCLI $PROFILE_OPT iam list-attached-group-policies --group-name $grp --output json --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess') if [[ $CHECK_ADMIN_GROUP ]]; then ADMIN_GROUPS="$ADMIN_GROUPS $grp" - textNotice "$grp group provides administrative access" + textInfo "$grp group provides administrative access" ADMIN_USERS=$($AWSCLI $PROFILE_OPT iam get-group --group-name $grp --output json --query 'Users[].UserName' | grep '"' | cut -d'"' -f2 ) for auser in $ADMIN_USERS; do # users in group are Administrators @@ -23,13 +23,13 @@ extra71(){ # check for user MFA device in credential report USER_MFA_ENABLED=$( cat $TEMP_REPORT_FILE | grep "^$auser," | cut -d',' -f8) if [[ "true" == $USER_MFA_ENABLED ]]; then - textOK "$auser / MFA Enabled / admin via group $grp" + textPass "$auser / MFA Enabled / admin via group $grp" else - textWarn "$auser / MFA DISABLED / admin via group $grp" + textFail "$auser / MFA DISABLED / admin via group $grp" fi done else - textNotice "$grp group provides non-administrative access" + textInfo "$grp group provides non-administrative access" fi done } diff --git a/checks/check_extra710 b/checks/check_extra710 index bafb10f00f..a30bf720ce 100644 --- a/checks/check_extra710 +++ b/checks/check_extra710 @@ -5,17 +5,17 @@ CHECK_ALTERNATE_check710="extra710" extra710(){ # "Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for instances in all regions... " + textInfo "Looking for instances in all regions... " for regx in $REGIONS; do LIST_OF_PUBLIC_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]' --output text) if [[ $LIST_OF_PUBLIC_INSTANCES ]];then while read -r instance;do INSTANCE_ID=$(echo $instance | awk '{ print $1; }') PUBLIC_IP=$(echo $instance | awk '{ print $2; }') - textWarn "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx" + textFail "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx" done <<< "$LIST_OF_PUBLIC_INSTANCES" else - textOK "$regx: no Internet Facing EC2 Instances found" "$regx" + textPass "$regx: no Internet Facing EC2 Instances found" "$regx" fi done } diff --git a/checks/check_extra711 b/checks/check_extra711 index 9918d71627..7cd41c827d 100644 --- a/checks/check_extra711 +++ b/checks/check_extra711 @@ -5,17 +5,17 @@ CHECK_ALTERNATE_check711="extra711" extra711(){ # "Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for Reshift clusters in all regions... " + textInfo "Looking for Reshift clusters in all regions... " for regx in $REGIONS; do LIST_OF_PUBLIC_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[?PubliclyAccessible == `true`].[ClusterIdentifier,Endpoint.Address]' --output text) if [[ $LIST_OF_PUBLIC_REDSHIFT_CLUSTERS ]];then while read -r cluster;do CLUSTER_ID=$(echo $cluster | awk '{ print $1; }') CLUSTER_ENDPOINT=$(echo $cluster | awk '{ print $2; }') - textWarn "$regx: Cluster: $CLUSTER_ID at Endpoint: $CLUSTER_ENDPOINT is publicly accessible!" "$regx" + textFail "$regx: Cluster: $CLUSTER_ID at Endpoint: $CLUSTER_ENDPOINT is publicly accessible!" "$regx" done <<< "$LIST_OF_PUBLIC_REDSHIFT_CLUSTERS" else - textOK "$regx: no Publicly Accessible Redshift Clusters found" "$regx" + textPass "$regx: no Publicly Accessible Redshift Clusters found" "$regx" fi done } diff --git a/checks/check_extra712 b/checks/check_extra712 index a3b59b8407..a16d9952c1 100644 --- a/checks/check_extra712 +++ b/checks/check_extra712 @@ -5,12 +5,12 @@ CHECK_ALTERNATE_check712="extra712" extra712(){ # "Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" - textNotice "No API commands available to check if Macie is enabled," - textNotice "just looking if IAM Macie related permissions exist. " + textInfo "No API commands available to check if Macie is enabled," + textInfo "just looking if IAM Macie related permissions exist. " MACIE_IAM_ROLES_CREATED=$($AWSCLI iam list-roles $PROFILE_OPT --query 'Roles[*].Arn'|grep AWSMacieServiceCustomer|wc -l) if [[ $MACIE_IAM_ROLES_CREATED -eq 2 ]];then - textOK "Macie related IAM roles exist, so it might be enabled. Check it out manually." + textPass "Macie related IAM roles exist, so it might be enabled. Check it out manually." else - textWarn "No Macie related IAM roles found. It is most likely not to be enabled" + textFail "No Macie related IAM roles found. It is most likely not to be enabled" fi } diff --git a/checks/check_extra713 b/checks/check_extra713 index 93ed5ab646..83355ca59f 100644 --- a/checks/check_extra713 +++ b/checks/check_extra713 @@ -11,13 +11,13 @@ extra713(){ while read -r detector;do DETECTOR_ENABLED=$($AWSCLI guardduty get-detector --detector-id $detector $PROFILE_OPT --region $regx --output text| cut -f3|grep ENABLED) if [[ $DETECTOR_ENABLED ]]; then - textOK "$regx: GuardDuty detector $detector enabled" "$regx" + textPass "$regx: GuardDuty detector $detector enabled" "$regx" else - textWarn "$regx: GuardDuty detector $detector configured but suspended" "$regx" + textFail "$regx: GuardDuty detector $detector configured but suspended" "$regx" fi done <<< "$LIST_OF_GUARDDUTY_DETECTORS" else - textWarn "$regx: GuardDuty detector not configured!" "$regx" + textFail "$regx: GuardDuty detector not configured!" "$regx" fi done } diff --git a/checks/check_extra714 b/checks/check_extra714 index 92a7118efb..c7672f7e43 100644 --- a/checks/check_extra714 +++ b/checks/check_extra714 @@ -11,13 +11,13 @@ extra714(){ for cdn in $LIST_OF_DISTRIBUTIONS;do CDN_LOG_ENABLED=$($AWSCLI cloudfront get-distribution $PROFILE_OPT --region $regx --id "$cdn" --query 'Distribution.DistributionConfig.Logging.Enabled' | grep true) if [[ $CDN_LOG_ENABLED ]];then - textOK "$regx: CDN $cdn logging enabled" "$regx" + textPass "$regx: CDN $cdn logging enabled" "$regx" else - textWarn "$regx: CDN $cdn logging disabled!" "$regx" + textFail "$regx: CDN $cdn logging disabled!" "$regx" fi done else - textNotice "$regx: No CDN configured" "$regx" + textInfo "$regx: No CDN configured" "$regx" fi done } diff --git a/checks/check_extra715 b/checks/check_extra715 index 04e24f84ce..e3af970684 100644 --- a/checks/check_extra715 +++ b/checks/check_extra715 @@ -10,19 +10,19 @@ extra715(){ for domain in $LIST_OF_DOMAINS;do SEARCH_SLOWLOG_ENABLED=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.LogPublishingOptions.Options.SEARCH_SLOW_LOGS.Enabled --output text |grep -v ^None|grep -v ^False) if [[ $SEARCH_SLOWLOG_ENABLED ]];then - textOK "$regx: ElasticSearch Service domain $domain SEARCH_SLOW_LOGS enabled" "$regx" + textPass "$regx: ElasticSearch Service domain $domain SEARCH_SLOW_LOGS enabled" "$regx" else - textWarn "$regx: ElasticSearch Service domain $domain SEARCH_SLOW_LOGS disabled!" "$regx" + textFail "$regx: ElasticSearch Service domain $domain SEARCH_SLOW_LOGS disabled!" "$regx" fi INDEX_SLOWLOG_ENABLED=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.LogPublishingOptions.Options.INDEX_SLOW_LOGS.Enabled --output text |grep -v ^None|grep -v ^False) if [[ $INDEX_SLOWLOG_ENABLED ]];then - textOK "$regx: ElasticSearch Service domain $domain INDEX_SLOW_LOGS enabled" "$regx" + textPass "$regx: ElasticSearch Service domain $domain INDEX_SLOW_LOGS enabled" "$regx" else - textWarn "$regx: ElasticSearch Service domain $domain INDEX_SLOW_LOGS disabled!" "$regx" + textFail "$regx: ElasticSearch Service domain $domain INDEX_SLOW_LOGS disabled!" "$regx" fi done else - textNotice "$regx: No Elasticsearch Service domain found" "$regx" + textInfo "$regx: No Elasticsearch Service domain found" "$regx" fi done } diff --git a/checks/check_extra716 b/checks/check_extra716 index 00c2d1e83b..30b669fbef 100644 --- a/checks/check_extra716 +++ b/checks/check_extra716 @@ -16,16 +16,16 @@ extra716(){ # check if the policy has Principal as * CHECK_ES_DOMAIN_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep \"Principal|grep \*) if [[ $CHECK_ES_DOMAIN_ALLUSERS_POLICY ]];then - textWarn "$regx: $domain policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" + textFail "$regx: $domain policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" else - textOK "$regx: $domain is not open" "$regx" + textPass "$regx: $domain is not open" "$regx" fi else - textOK "$regx: $domain is in a VPC" "$regx" + textPass "$regx: $domain is in a VPC" "$regx" fi done fi - textNotice "$regx: No Elasticsearch Service domain found" "$regx" + textInfo "$regx: No Elasticsearch Service domain found" "$regx" rm -fr $TEMP_POLICY_FILE done } diff --git a/checks/check_extra717 b/checks/check_extra717 index d887169c65..6a07975c71 100644 --- a/checks/check_extra717 +++ b/checks/check_extra717 @@ -13,9 +13,9 @@ extra717(){ for elb in $LIST_OF_ELBS; do CHECK_ELBS_LOG_ENABLED=$($AWSCLI elb describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-name $elb --query 'LoadBalancerAttributes.AccessLog.Enabled'|grep "^true") if [[ $CHECK_ELBS_LOG_ENABLED ]]; then - textOK "$regx: $elb has access logs to S3 configured" "$regx" + textPass "$regx: $elb has access logs to S3 configured" "$regx" else - textWarn "$regx: $elb has not configured access logs" "$regx" + textFail "$regx: $elb has not configured access logs" "$regx" fi done fi @@ -24,14 +24,14 @@ extra717(){ CHECK_ELBSV2_LOG_ENABLED=$($AWSCLI elbv2 describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-arn $elbarn --query Attributes[*] --output text|grep "^access_logs.s3.enabled"|cut -f2|grep true) ELBV2_NAME=$(echo $elbarn|cut -d\/ -f3) if [[ $CHECK_ELBSV2_LOG_ENABLED ]]; then - textOK "$regx: $ELBV2_NAME has access logs to S3 configured" "$regx" + textPass "$regx: $ELBV2_NAME has access logs to S3 configured" "$regx" else - textWarn "$regx: $ELBV2_NAME has not configured access logs" "$regx" + textFail "$regx: $ELBV2_NAME has not configured access logs" "$regx" fi done fi else - textNotice "$regx: No ELBs found" "$regx" + textInfo "$regx: No ELBs found" "$regx" fi done } diff --git a/checks/check_extra718 b/checks/check_extra718 index 8184daeb49..77c74783b2 100644 --- a/checks/check_extra718 +++ b/checks/check_extra718 @@ -10,12 +10,12 @@ extra718(){ for bucket in $LIST_OF_BUCKETS;do BUCKET_SERVER_LOG_ENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --query [LoggingEnabled] --output text|grep -v "^None$") if [[ $BUCKET_SERVER_LOG_ENABLED ]];then - textOK "Bucket $bucket has server access logging enabled" + textPass "Bucket $bucket has server access logging enabled" else - textWarn "Bucket $bucket has server access logging disabled!" + textFail "Bucket $bucket has server access logging disabled!" fi done else - textNotice "No S3 Buckets found" + textInfo "No S3 Buckets found" fi } diff --git a/checks/check_extra719 b/checks/check_extra719 index df90a99431..fba60d764b 100644 --- a/checks/check_extra719 +++ b/checks/check_extra719 @@ -10,12 +10,12 @@ extra719(){ for hostedzoneid in $LIST_OF_HOSTED_ZONES;do HOSTED_ZONE_QUERY_LOG_ENABLED=$($AWSCLI route53 list-query-logging-configs --hosted-zone-id $hostedzoneid $PROFILE_OPT --query QueryLoggingConfigs[*].CloudWatchLogsLogGroupArn --output text|cut -d: -f7) if [[ $HOSTED_ZONE_QUERY_LOG_ENABLED ]];then - textOK "Route53 hosted zone Id $hostedzoneid has query logging enabled in Log Group $HOSTED_ZONE_QUERY_LOG_ENABLED" + textPass "Route53 hosted zone Id $hostedzoneid has query logging enabled in Log Group $HOSTED_ZONE_QUERY_LOG_ENABLED" else - textWarn "Route53 hosted zone Id $hostedzoneid has query logging disabled!" + textFail "Route53 hosted zone Id $hostedzoneid has query logging disabled!" fi done else - textNotice "No Route53 hosted zones found" + textInfo "No Route53 hosted zones found" fi } diff --git a/checks/check_extra72 b/checks/check_extra72 index 738b723c8b..fc90c0b61c 100644 --- a/checks/check_extra72 +++ b/checks/check_extra72 @@ -7,15 +7,15 @@ CHECK_ALTERNATE_check702="extra72" extra72(){ # "Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for EBS Snapshots in all regions... " + textInfo "Looking for EBS Snapshots in all regions... " for regx in $REGIONS; do LIST_OF_EBS_SNAPSHOTS=$($AWSCLI ec2 describe-snapshots $PROFILE_OPT --region $regx --owner-ids $ACCOUNT_NUM --output text --query 'Snapshots[*].{ID:SnapshotId}' --max-items $MAXITEMS | grep -v None 2> /dev/null) for snapshot in $LIST_OF_EBS_SNAPSHOTS; do SNAPSHOT_IS_PUBLIC=$($AWSCLI ec2 describe-snapshot-attribute $PROFILE_OPT --region $regx --output text --snapshot-id $snapshot --attribute createVolumePermission --query "CreateVolumePermissions[?Group=='all']") if [[ $SNAPSHOT_IS_PUBLIC ]];then - textWarn "$regx: $snapshot is currently Public!" "$regx" + textFail "$regx: $snapshot is currently Public!" "$regx" else - textOK "$regx: $snapshot is not Public" "$regx" + textPass "$regx: $snapshot is not Public" "$regx" fi done done diff --git a/checks/check_extra720 b/checks/check_extra720 index ade6d3ae78..139f30e961 100644 --- a/checks/check_extra720 +++ b/checks/check_extra720 @@ -14,9 +14,9 @@ extra720(){ for trail in $LIST_OF_TRAILS; do FUNCTION_ENABLED_IN_TRAIL=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $regx --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") if [[ $FUNCTION_ENABLED_IN_TRAIL ]]; then - textOK "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" + textPass "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" else - textWarn "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" + textFail "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" fi done # LIST_OF_MULTIREGION_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\`].Name" --output text) @@ -25,20 +25,20 @@ extra720(){ # REGION_OF_TRAIL=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\` && Name == \`$trail\` ].HomeRegion" --output text) # FUNCTION_ENABLED_IN_THIS_REGION=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $REGION_OF_TRAIL --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") # if [[ $FUNCTION_ENABLED_IN_THIS_REGION ]]; then - # textOK "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" + # textPass "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" # else - # textWarn "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" + # textFail "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" # fi # done # else - # textWarn "$regx: Lambda function $lambdafunction is not being recorded!" "$regx" + # textFail "$regx: Lambda function $lambdafunction is not being recorded!" "$regx" # fi else - textWarn "$regx: Lambda function $lambdafunction is not being recorded no CloudTrail found!" "$regx" + textFail "$regx: Lambda function $lambdafunction is not being recorded no CloudTrail found!" "$regx" fi done else - textNotice "$regx: No Lambda functions found" "$regx" + textInfo "$regx: No Lambda functions found" "$regx" fi done } diff --git a/checks/check_extra721 b/checks/check_extra721 index 43b0778f74..b430025e81 100644 --- a/checks/check_extra721 +++ b/checks/check_extra721 @@ -12,13 +12,13 @@ extra721(){ REDSHIFT_LOG_ENABLED=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query LoggingEnabled --output text | grep True) if [[ $REDSHIFT_LOG_ENABLED ]];then REDSHIFT_LOG_ENABLED_BUCKET=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query BucketName --output text) - textOK "$regx: Redshift cluster $redshiftcluster has audit logging enabled to bucket $REDSHIFT_LOG_ENABLED_BUCKET" "$regx" + textPass "$regx: Redshift cluster $redshiftcluster has audit logging enabled to bucket $REDSHIFT_LOG_ENABLED_BUCKET" "$regx" else - textWarn "$regx: Redshift cluster $redshiftcluster logging disabled!" "$regx" + textFail "$regx: Redshift cluster $redshiftcluster logging disabled!" "$regx" fi done else - textNotice "$regx: No Redshift cluster configured" "$regx" + textInfo "$regx: No Redshift cluster configured" "$regx" fi done } diff --git a/checks/check_extra722 b/checks/check_extra722 index 1310d00cd5..d2621c61fd 100644 --- a/checks/check_extra722 +++ b/checks/check_extra722 @@ -15,17 +15,17 @@ extra722(){ for stagname in $CHECK_STAGES_NAME;do CHECK_STAGE_METHOD_LOGGING=$($AWSCLI apigateway get-stages $PROFILE_OPT --region $regx --rest-api-id $apigwid --query "item[?stageName == \`$stagname\` ].methodSettings" --output text|awk '{ print $1" log level "$6}') if [[ $CHECK_STAGE_METHOD_LOGGING ]];then - textOK "$regx: API Gateway $API_GW_NAME has stage logging enabled for $CHECK_STAGE_METHOD_LOGGING" "$regx" + textPass "$regx: API Gateway $API_GW_NAME has stage logging enabled for $CHECK_STAGE_METHOD_LOGGING" "$regx" else - textWarn "$regx: API Gateway $API_GW_NAME logging disabled for stage $stagname!" "$regx" + textFail "$regx: API Gateway $API_GW_NAME logging disabled for stage $stagname!" "$regx" fi done else - textWarn "$regx: No Stage name found for $API_GW_NAME" "$regx" + textFail "$regx: No Stage name found for $API_GW_NAME" "$regx" fi done else - textNotice "$regx: No API Gateway found" "$regx" + textInfo "$regx: No API Gateway found" "$regx" fi done } diff --git a/checks/check_extra723 b/checks/check_extra723 index ee32ce476e..31a3daa46e 100644 --- a/checks/check_extra723 +++ b/checks/check_extra723 @@ -12,13 +12,13 @@ extra723(){ for rdssnapshot in $LIST_OF_RDS_SNAPSHOTS;do SNAPSHOT_IS_PUBLIC=$($AWSCLI rds describe-db-snapshot-attributes $PROFILE_OPT --region $regx --db-snapshot-identifier $rdssnapshot --query DBSnapshotAttributesResult.DBSnapshotAttributes[*] --output text|grep ^ATTRIBUTEVALUES|cut -f2|grep all) if [[ $SNAPSHOT_IS_PUBLIC ]];then - textWarn "$regx: RDS Snapshot $rdssnapshot is public!" "$regx" + textFail "$regx: RDS Snapshot $rdssnapshot is public!" "$regx" else - textOK "$regx: RDS Snapshot $rdssnapshot is not shared" "$regx" + textPass "$regx: RDS Snapshot $rdssnapshot is not shared" "$regx" fi done else - textNotice "$regx: No RDS Snapshots found" "$regx" + textInfo "$regx: No RDS Snapshots found" "$regx" fi # RDS cluster snapshots LIST_OF_RDS_CLUSTER_SNAPSHOTS=$($AWSCLI rds describe-db-cluster-snapshots $PROFILE_OPT --region $regx --query DBClusterSnapshots[*].DBClusterSnapshotIdentifier --output text) @@ -26,13 +26,13 @@ extra723(){ for rdsclustersnapshot in $LIST_OF_RDS_CLUSTER_SNAPSHOTS;do CLUSTER_SNAPSHOT_IS_PUBLIC=$($AWSCLI rds describe-db-cluster-snapshot-attributes $PROFILE_OPT --region $regx --db-cluster-snapshot-identifier $rdsclustersnapshot --query DBClusterSnapshotAttributesResult.DBClusterSnapshotAttributes[*] --output text|grep ^ATTRIBUTEVALUES|cut -f2|grep all) if [[ $CLUSTER_SNAPSHOT_IS_PUBLIC ]];then - textWarn "$regx: RDS Cluster Snapshot $rdsclustersnapshot is public!" "$regx" + textFail "$regx: RDS Cluster Snapshot $rdsclustersnapshot is public!" "$regx" else - textOK "$regx: RDS Cluster Snapshot $rdsclustersnapshot is not shared" "$regx" + textPass "$regx: RDS Cluster Snapshot $rdsclustersnapshot is not shared" "$regx" fi done else - textNotice "$regx: No RDS Cluster Snapshots found" "$regx" + textInfo "$regx: No RDS Cluster Snapshots found" "$regx" fi done } diff --git a/checks/check_extra724 b/checks/check_extra724 index d0636a6767..23dd956536 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -12,13 +12,13 @@ extra724(){ CT_ENABLED=$($AWSCLI acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.Options.CertificateTransparencyLoggingPreference --output text) CERT_DOMAIN_NAME=$(aws acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.DomainName --output text) if [[ $CT_ENABLED == "ENABLED" ]];then - textWarn "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" + textFail "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" else - textOK "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" + textPass "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" fi done else - textNotice "$regx: No ACM Certificates found" "$regx" + textInfo "$regx: No ACM Certificates found" "$regx" fi done } diff --git a/checks/check_extra73 b/checks/check_extra73 index 0bdb6469ca..3dfc14c4f0 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -6,7 +6,7 @@ CHECK_ALTERNATE_check73="extra73" CHECK_ALTERNATE_check703="extra73" extra73(){ - textNotice "Looking for open S3 Buckets (ACLs and Policies) in all regions... " + textInfo "Looking for open S3 Buckets (ACLs and Policies) in all regions... " ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' --profile $PROFILE --region $REGION --output text) for bucket in $ALL_BUCKETS_LIST; do extra73Thread $bucket & @@ -35,16 +35,16 @@ extra73Thread(){ CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*) if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then if [[ $CHECK_BUCKET_ALLUSERS_ACL ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" + textFail "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" fi if [[ $CHECK_BUCKET_AUTHUSERS_ACL ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" + textFail "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" fi if [[ $CHECK_BUCKET_ALLUSERS_POLICY ]];then - textWarn "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" + textFail "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" fi else - textOK "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" + textPass "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" fi rm -fr $TEMP_POLICY_FILE } diff --git a/checks/check_extra74 b/checks/check_extra74 index 98210efd0c..80a69b7ead 100644 --- a/checks/check_extra74 +++ b/checks/check_extra74 @@ -7,15 +7,15 @@ CHECK_ALTERNATE_check704="extra74" extra74(){ # "Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for Security Groups in all regions... " + textInfo "Looking for Security Groups in all regions... " for regx in $REGIONS; do LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS) for SG_ID in $LIST_OF_SECURITYGROUPS; do SG_NO_INGRESS_FILTER=$($AWSCLI ec2 describe-network-interfaces $PROFILE_OPT --region $regx --filters "Name=group-id,Values=$SG_ID" --query "length(NetworkInterfaces)" --output text) if [[ $SG_NO_INGRESS_FILTER -ne 0 ]];then - textWarn "$regx: $SG_ID has not ingress filtering and it is being used!" "$regx" + textFail "$regx: $SG_ID has not ingress filtering and it is being used!" "$regx" else - textNotice "$regx: $SG_ID has not ingress filtering but it is no being used" "$regx" + textInfo "$regx: $SG_ID has not ingress filtering but it is no being used" "$regx" fi done done diff --git a/checks/check_extra75 b/checks/check_extra75 index 2aeab90aac..f004a0a874 100644 --- a/checks/check_extra75 +++ b/checks/check_extra75 @@ -7,15 +7,15 @@ CHECK_ALTERNATE_check705="extra75" extra75(){ # "Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for Security Groups in all regions... " + textInfo "Looking for Security Groups in all regions... " for regx in $REGIONS; do LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS) for SG_ID in $LIST_OF_SECURITYGROUPS; do SG_NOT_USED=$($AWSCLI ec2 describe-network-interfaces $PROFILE_OPT --region $regx --filters "Name=group-id,Values=$SG_ID" --query "length(NetworkInterfaces)" --output text) if [[ $SG_NOT_USED -eq 0 ]];then - textWarn "$regx: $SG_ID is not being used!" "$regx" + textFail "$regx: $SG_ID is not being used!" "$regx" else - textOK "$regx: $SG_ID is being used" "$regx" + textPass "$regx: $SG_ID is being used" "$regx" fi done done diff --git a/checks/check_extra76 b/checks/check_extra76 index 1103e2b3ba..aad168cf60 100644 --- a/checks/check_extra76 +++ b/checks/check_extra76 @@ -7,15 +7,15 @@ CHECK_ALTERNATE_check706="extra76" extra76(){ # "Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for AMIs in all regions... " + textInfo "Looking for AMIs in all regions... " for regx in $REGIONS; do LIST_OF_PUBLIC_AMIS=$($AWSCLI ec2 describe-images --owners self $PROFILE_OPT --region $regx --filters "Name=is-public,Values=true" --query 'Images[*].{ID:ImageId}' --output text) if [[ $LIST_OF_PUBLIC_AMIS ]];then for ami in $LIST_OF_PUBLIC_AMIS; do - textWarn "$regx: $ami is currently Public!" "$regx" + textFail "$regx: $ami is currently Public!" "$regx" done else - textOK "$regx: No Public AMIs found" "$regx" + textPass "$regx: No Public AMIs found" "$regx" fi done } diff --git a/checks/check_extra77 b/checks/check_extra77 index 2d0de92af3..147dc263ec 100644 --- a/checks/check_extra77 +++ b/checks/check_extra77 @@ -7,7 +7,7 @@ CHECK_ALTERNATE_check707="extra77" extra77(){ # "Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for ECR repos in all regions... " + textInfo "Looking for ECR repos in all regions... " for regx in $REGIONS; do LIST_OF_ECR_REPOS=$($AWSCLI ecr describe-repositories $PROFILE_OPT --region $regx --query 'repositories[*].{Name:repositoryName}' --output text) for ecr_repo in $LIST_OF_ECR_REPOS; do @@ -16,9 +16,9 @@ extra77(){ # check if the policy has Principal as * CHECK_ECR_REPO_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep \"Principal|grep \*) if [[ $CHECK_ECR_REPO_ALLUSERS_POLICY ]];then - textWarn "$regx: $ecr_repo policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" + textFail "$regx: $ecr_repo policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" else - textOK "$regx: $ecr_repo is not open" "$regx" + textPass "$regx: $ecr_repo is not open" "$regx" fi done rm -fr $TEMP_POLICY_FILE diff --git a/checks/check_extra78 b/checks/check_extra78 index 41f70f2dc0..34cbe83577 100644 --- a/checks/check_extra78 +++ b/checks/check_extra78 @@ -7,17 +7,17 @@ CHECK_ALTERNATE_check708="extra78" extra78(){ # "Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for RDS instances in all regions... " + textInfo "Looking for RDS instances in all regions... " for regx in $REGIONS; do LIST_OF_RDS_PUBLIC_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[?PubliclyAccessible==`true`].[DBInstanceIdentifier,Endpoint.Address]' --output text) if [[ $LIST_OF_RDS_PUBLIC_INSTANCES ]];then while read -r rds_instance;do RDS_NAME=$(echo $rds_instance | awk '{ print $1; }') RDS_DNSNAME=$(echo $rds_instance | awk '{ print $2; }') - textWarn "$regx: RDS instance: $RDS_NAME at $RDS_DNSNAME is set as Publicly Accessible!" "$regx" + textFail "$regx: RDS instance: $RDS_NAME at $RDS_DNSNAME is set as Publicly Accessible!" "$regx" done <<< "$LIST_OF_RDS_PUBLIC_INSTANCES" else - textOK "$regx: no Publicly Accessible RDS instances found" "$regx" + textPass "$regx: no Publicly Accessible RDS instances found" "$regx" fi done } diff --git a/checks/check_extra79 b/checks/check_extra79 index c868408f8b..5085df8de5 100644 --- a/checks/check_extra79 +++ b/checks/check_extra79 @@ -7,7 +7,7 @@ CHECK_ALTERNATE_check709="extra79" extra79(){ # "Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" - textNotice "Looking for Elastic Load Balancers in all regions... " + textInfo "Looking for Elastic Load Balancers in all regions... " for regx in $REGIONS; do LIST_OF_PUBLIC_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text) LIST_OF_PUBLIC_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text) @@ -17,10 +17,10 @@ extra79(){ while read -r elb;do ELB_NAME=$(echo $elb | awk '{ print $1; }') ELB_DNSNAME=$(echo $elb | awk '{ print $2; }') - textWarn "$regx: ELB: $ELB_NAME at DNS: $ELB_DNSNAME is internet-facing!" "$regx" + textFail "$regx: ELB: $ELB_NAME at DNS: $ELB_DNSNAME is internet-facing!" "$regx" done <<< "$LIST_OF_ALL_ELBS_PER_LINE" else - textOK "$regx: no Internet Facing ELBs found" "$regx" + textPass "$regx: no Internet Facing ELBs found" "$regx" fi done } diff --git a/checks/check_sample b/checks/check_sample index c57223a1ed..976635617a 100644 --- a/checks/check_sample +++ b/checks/check_sample @@ -5,17 +5,17 @@ # # extraN(){ # # "Description (Not Scored) (Not part of CIS benchmark)" -# textNotice "Looking for instances in all regions... " +# textInfo "Looking for instances in all regions... " # for regx in $REGIONS; do # LIST_OF_PUBLIC_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]' --output text) # if [[ $LIST_OF_PUBLIC_INSTANCES ]];then # while read -r instance;do # INSTANCE_ID=$(echo $instance | awk '{ print $1; }') # PUBLIC_IP=$(echo $instance | awk '{ print $2; }') -# textWarn "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx" +# textFail "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx" # done <<< "$LIST_OF_PUBLIC_INSTANCES" # else -# textOK "$regx: no Internet Facing EC2 Instances found" "$regx" +# textPass "$regx: no Internet Facing EC2 Instances found" "$regx" # fi # done # } diff --git a/include/credentials_report b/include/credentials_report index d958a76853..4a84a3c280 100644 --- a/include/credentials_report +++ b/include/credentials_report @@ -11,7 +11,7 @@ saveReport(){ $AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE if [[ $KEEPCREDREPORT -eq 1 ]]; then textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT" - textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE" + textInfo "IAM Credential Report saved in $TEMP_REPORT_FILE" fi } diff --git a/include/outputs b/include/outputs index f9bbaa04af..e48c58baa3 100644 --- a/include/outputs +++ b/include/outputs @@ -1,5 +1,5 @@ ## Output formatting functions -textOK(){ +textPass(){ if [[ "$MODE" == "csv" ]]; then if [[ $2 ]]; then REPREGION=$2 @@ -12,7 +12,7 @@ textOK(){ fi } -textNotice(){ +textInfo(){ if [[ "$MODE" == "csv" ]]; then if [[ $2 ]]; then REPREGION=$2 @@ -25,7 +25,7 @@ textNotice(){ fi } -textWarn(){ +textFail(){ EXITCODE=3 if [[ "$MODE" == "csv" ]]; then if [[ $2 ]]; then diff --git a/include/whoami b/include/whoami index 4a6f391389..9f77e4bd5a 100644 --- a/include/whoami +++ b/include/whoami @@ -13,7 +13,7 @@ getWhoami(){ CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') printCsvHeader textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT" - textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" + textInfo "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" else echo "" echo -e " This report is being generated using credentials below:\n" diff --git a/prowler b/prowler index fe67941bc2..5281eee3f0 100755 --- a/prowler +++ b/prowler @@ -190,7 +190,7 @@ execute_check() { show_check_title $1 $1 else - textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)"; + textFail "ERROR! Use a valid check name (i.e. check41 or extra71)"; exit $EXITCODE fi fi From 9a035b1a9482cee6c07001998f7baf5e439b2c89 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 11:12:59 -0400 Subject: [PATCH 22/41] updated check extra724 INFO instead of FAIL if enabled --- checks/check_extra724 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/check_extra724 b/checks/check_extra724 index 23dd956536..8c62548518 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -12,7 +12,7 @@ extra724(){ CT_ENABLED=$($AWSCLI acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.Options.CertificateTransparencyLoggingPreference --output text) CERT_DOMAIN_NAME=$(aws acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.DomainName --output text) if [[ $CT_ENABLED == "ENABLED" ]];then - textFail "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" + textInfo "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" else textPass "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" fi From 91b8a832eca9df6bffd95468cc8c856dd0b00257 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 12:32:51 -0400 Subject: [PATCH 23/41] hide banner on csv output for group mode --- groups/group9_gdpr | 5 +++++ prowler | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 groups/group9_gdpr diff --git a/groups/group9_gdpr b/groups/group9_gdpr new file mode 100644 index 0000000000..3707fbf70d --- /dev/null +++ b/groups/group9_gdpr @@ -0,0 +1,5 @@ +GROUP_ID[9]='gdpr' +GROUP_NUMBER[9]='8.0' +GROUP_TITLE[9]='GDPR Readiness ***************************************************' +GROUP_RUN_BY_DEFAULT[9]='N' # run it when execute_all is called +GROUP_CHECKS[9]='' diff --git a/prowler b/prowler index 5281eee3f0..415c559c2a 100755 --- a/prowler +++ b/prowler @@ -250,6 +250,9 @@ fi # Execute group of checks if called with -g if [[ $GROUP_ID ]];then + if [[ $MODE == "csv" ]]; then + BANNER=0 + fi execute_group_by_id $GROUP_ID cleanTemp exit $EXITCODE From fa474876e9c455bf47e7028ae040a3f4c6581e9d Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 12:51:13 -0400 Subject: [PATCH 24/41] changed extra742 to FAIL if not default value --- checks/check_extra724 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/checks/check_extra724 b/checks/check_extra724 index 8c62548518..c2cb2c583d 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -12,13 +12,14 @@ extra724(){ CT_ENABLED=$($AWSCLI acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.Options.CertificateTransparencyLoggingPreference --output text) CERT_DOMAIN_NAME=$(aws acm describe-certificate $PROFILE_OPT --region $regx --certificate-arn $cert_arn --query Certificate.DomainName --output text) if [[ $CT_ENABLED == "ENABLED" ]];then - textInfo "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" + textPass "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" else - textPass "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" + textWarn "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" fi done else textInfo "$regx: No ACM Certificates found" "$regx" fi done + textInfo " Read more about this here: https://aws.amazon.com/blogs/security/how-to-get-ready-for-certificate-transparency/" } From 058a8d5b33ed75e24be7b07d0c3ccb209cb7dfdb Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 13:51:32 -0400 Subject: [PATCH 25/41] changed extra742 to FAIL if not default value --- checks/check_extra724 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/check_extra724 b/checks/check_extra724 index c2cb2c583d..6b504f538d 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -14,7 +14,7 @@ extra724(){ if [[ $CT_ENABLED == "ENABLED" ]];then textPass "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging enabled!" "$regx" else - textWarn "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" + textFail "$regx: ACM Certificate $CERT_DOMAIN_NAME has Certificate Transparency logging disabled!" "$regx" fi done else From eaf0a6bf095025e51264053d18340ae230c2ed3d Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 13:58:07 -0400 Subject: [PATCH 26/41] added command to save report in S3 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 258207e5e0..a0df8ed6c7 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,10 @@ or if you want a pipe-delimited report file, do: ``` ./prowler -M csv > output.psv ``` +or save your report in a S3 bucket: +``` +./prowler -M mono | aws s3 cp - s3://bucket-name/prowler-report.txt +``` 5 - To perform an assessment based on CIS Profile Definitions you can use level1 or level2 with `-c` flag, more information about this [here, page 8](https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf): ``` From 7cde6f15e70b78d7ea0f917af76c2d8a302862fc Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 28 Mar 2018 14:24:37 -0400 Subject: [PATCH 27/41] removed some spaces from output --- checks/check_extra724 | 2 +- include/outputs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/checks/check_extra724 b/checks/check_extra724 index 6b504f538d..8fece770dd 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -21,5 +21,5 @@ extra724(){ textInfo "$regx: No ACM Certificates found" "$regx" fi done - textInfo " Read more about this here: https://aws.amazon.com/blogs/security/how-to-get-ready-for-certificate-transparency/" + textInfo "*Read more about this here: https://aws.amazon.com/blogs/security/how-to-get-ready-for-certificate-transparency/" } diff --git a/include/outputs b/include/outputs index e48c58baa3..d98ea1277a 100644 --- a/include/outputs +++ b/include/outputs @@ -8,7 +8,7 @@ textPass(){ fi echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" else - echo " $OK PASS! $NORMAL $1" + echo " $OK PASS!$NORMAL $1" fi } From cd41766e228033cdae8e16b51581b8b8a909cca4 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Thu, 29 Mar 2018 10:36:46 -0400 Subject: [PATCH 28/41] added checkid to every check and group title --- LIST_OF_CHECKS_AND_GROUPS.md | 392 +++++++++++++++++------------------ checks/check11 | 2 +- checks/check110 | 2 +- checks/check111 | 2 +- checks/check112 | 2 +- checks/check113 | 2 +- checks/check114 | 2 +- checks/check115 | 2 +- checks/check116 | 2 +- checks/check117 | 2 +- checks/check118 | 2 +- checks/check119 | 2 +- checks/check12 | 2 +- checks/check120 | 2 +- checks/check121 | 2 +- checks/check122 | 2 +- checks/check123 | 2 +- checks/check124 | 2 +- checks/check13 | 2 +- checks/check14 | 2 +- checks/check15 | 2 +- checks/check16 | 2 +- checks/check17 | 2 +- checks/check18 | 2 +- checks/check19 | 2 +- checks/check21 | 2 +- checks/check22 | 2 +- checks/check23 | 2 +- checks/check24 | 2 +- checks/check25 | 2 +- checks/check26 | 2 +- checks/check27 | 2 +- checks/check28 | 2 +- checks/check31 | 2 +- checks/check310 | 2 +- checks/check311 | 2 +- checks/check312 | 2 +- checks/check313 | 2 +- checks/check314 | 2 +- checks/check315 | 2 +- checks/check32 | 2 +- checks/check33 | 2 +- checks/check34 | 2 +- checks/check35 | 2 +- checks/check36 | 2 +- checks/check37 | 2 +- checks/check38 | 2 +- checks/check39 | 2 +- checks/check41 | 2 +- checks/check42 | 2 +- checks/check43 | 2 +- checks/check44 | 2 +- checks/check45 | 2 +- checks/check_extra71 | 2 +- checks/check_extra710 | 2 +- checks/check_extra711 | 2 +- checks/check_extra712 | 2 +- checks/check_extra713 | 2 +- checks/check_extra714 | 2 +- checks/check_extra715 | 2 +- checks/check_extra716 | 2 +- checks/check_extra717 | 2 +- checks/check_extra718 | 2 +- checks/check_extra719 | 2 +- checks/check_extra72 | 2 +- checks/check_extra720 | 2 +- checks/check_extra721 | 2 +- checks/check_extra722 | 2 +- checks/check_extra723 | 2 +- checks/check_extra724 | 2 +- checks/check_extra725 | 46 ++++ checks/check_extra726 | 48 +++++ checks/check_extra73 | 2 +- checks/check_extra74 | 2 +- checks/check_extra75 | 2 +- checks/check_extra76 | 2 +- checks/check_extra77 | 2 +- checks/check_extra78 | 2 +- checks/check_extra79 | 2 +- checks/check_sample | 2 +- groups/group1_iam | 2 +- groups/group2_logging | 2 +- groups/group3_monitoring | 2 +- groups/group4_networking | 2 +- groups/group5_cislevel1 | 2 +- groups/group6_cislevel2 | 2 +- groups/group7_extras | 2 +- groups/group8_forensics | 2 +- groups/group9_gdpr | 2 +- groups/groupN_sample | 4 +- 90 files changed, 378 insertions(+), 284 deletions(-) create mode 100644 checks/check_extra725 create mode 100644 checks/check_extra726 diff --git a/LIST_OF_CHECKS_AND_GROUPS.md b/LIST_OF_CHECKS_AND_GROUPS.md index 893bf802c8..03a9f6f608 100644 --- a/LIST_OF_CHECKS_AND_GROUPS.md +++ b/LIST_OF_CHECKS_AND_GROUPS.md @@ -1,399 +1,399 @@ -``` _ +``` + _ _ __ _ __ _____ _| | ___ _ __ | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__| | |_) | | | (_) \ V V /| | __/ | | .__/|_| \___/ \_/\_/ |_|\___|_|v2.0 |_| the handy cloud security tool -Date: Tue Mar 27 18:38:53 EDT 2018 +Date: Thu Mar 29 10:35:09 EDT 2018 Colors code for results: INFO (Information), PASS (Recommended value), FAIL (Fix required) -1.0 (group1) Identity and Access Management **************************************** +1.0 Identity and Access Management - [group1] ********************** -1.1 Avoid the use of the root account (Scored) +1.1 [check11] Avoid the use of the root account (Scored) -1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) +1.2 [check12] Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) -1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) +1.3 [check13] Ensure credentials unused for 90 days or greater are disabled (Scored) -1.4 Ensure access keys are rotated every 90 days or less (Scored) +1.4 [check14] Ensure access keys are rotated every 90 days or less (Scored) -1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) +1.5 [check15] Ensure IAM password policy requires at least one uppercase letter (Scored) -1.6 Ensure IAM password policy require at least one lowercase letter (Scored) +1.6 [check16] Ensure IAM password policy require at least one lowercase letter (Scored) -1.7 Ensure IAM password policy require at least one symbol (Scored) +1.7 [check17] Ensure IAM password policy require at least one symbol (Scored) -1.8 Ensure IAM password policy require at least one number (Scored) +1.8 [check18] Ensure IAM password policy require at least one number (Scored) -1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) +1.9 [check19] Ensure IAM password policy requires minimum length of 14 or greater (Scored) -1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) +1.10 [check110] Ensure IAM password policy prevents password reuse: 24 or greater (Scored) -1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) +1.11 [check111] Ensure IAM password policy expires passwords within 90 days or less (Scored) -1.12 Ensure no root account access key exists (Scored) +1.12 [check112] Ensure no root account access key exists (Scored) -1.13 Ensure MFA is enabled for the root account (Scored) +1.13 [check113] Ensure MFA is enabled for the root account (Scored) -1.14 Ensure hardware MFA is enabled for the root account (Scored) +1.14 [check114] Ensure hardware MFA is enabled for the root account (Scored) -1.15 Ensure security questions are registered in the AWS account (Not Scored) +1.15 [check115] Ensure security questions are registered in the AWS account (Not Scored) -1.16 Ensure IAM policies are attached only to groups or roles (Scored) +1.16 [check116] Ensure IAM policies are attached only to groups or roles (Scored) -1.17 Enable detailed billing (Scored) +1.17 [check117] Enable detailed billing (Scored) -1.18 Ensure IAM Master and IAM Manager roles are active (Scored) +1.18 [check118] Ensure IAM Master and IAM Manager roles are active (Scored) -1.19 Maintain current contact details (Scored) +1.19 [check119] Maintain current contact details (Scored) -1.20 Ensure security contact information is registered (Scored) +1.20 [check120] Ensure security contact information is registered (Scored) -1.21 Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) +1.21 [check121] Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) -1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) +1.22 [check122] Ensure a support role has been created to manage incidents with AWS Support (Scored) -1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) +1.23 [check123] Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) -1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) +1.24 [check124] Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) -2.0 (group2) Logging *************************************************************** +2.0 Logging - [group2] ********************************************* -2.1 Ensure CloudTrail is enabled in all regions (Scored) +2.1 [check21] Ensure CloudTrail is enabled in all regions (Scored) -2.2 Ensure CloudTrail log file validation is enabled (Scored) +2.2 [check22] Ensure CloudTrail log file validation is enabled (Scored) -2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) +2.3 [check23] Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) -2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) +2.4 [check24] Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) -2.5 Ensure AWS Config is enabled in all regions (Scored) +2.5 [check25] Ensure AWS Config is enabled in all regions (Scored) -2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) +2.6 [check26] Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) -2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) +2.7 [check27] Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) -2.8 Ensure rotation for customer created CMKs is enabled (Scored) +2.8 [check28] Ensure rotation for customer created CMKs is enabled (Scored) -3.0 (group3) Monitoring ************************************************************ +3.0 Monitoring - [group3] ****************************************** -3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) +3.1 [check31] Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) -3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) +3.2 [check32] Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) -3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) +3.3 [check33] Ensure a log metric filter and alarm exist for usage of root account (Scored) -3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) +3.4 [check34] Ensure a log metric filter and alarm exist for IAM policy changes (Scored) -3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) +3.5 [check35] Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) -3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) +3.6 [check36] Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) -3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) +3.7 [check37] Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) -3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) +3.8 [check38] Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) -3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) +3.9 [check39] Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) -3.10 Ensure a log metric filter and alarm exist for security group changes (Scored) +3.10 [check310] Ensure a log metric filter and alarm exist for security group changes (Scored) -3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) +3.11 [check311] Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) -3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) +3.12 [check312] Ensure a log metric filter and alarm exist for changes to network gateways (Scored) -3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) +3.13 [check313] Ensure a log metric filter and alarm exist for route table changes (Scored) -3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) +3.14 [check314] Ensure a log metric filter and alarm exist for VPC changes (Scored) -3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) +3.15 [check315] Ensure appropriate subscribers to each SNS topic (Not Scored) -4.0 (group4) Networking ************************************************************ +4.0 Networking - [group4] ****************************************** -4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) +4.1 [check41] Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) -4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) +4.2 [check42] Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) -4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) +4.3 [check43] Ensure VPC Flow Logging is Enabled in all VPCs (Scored) -4.4 Ensure the default security group of every VPC restricts all traffic (Scored) +4.4 [check44] Ensure the default security group of every VPC restricts all traffic (Scored) -4.5 Ensure routing tables for VPC peering are "least access" (Not Scored) +4.5 [check45] Ensure routing tables for VPC peering are "least access" (Not Scored) -5.0 (cislevel1) CIS Level 1 ********************************************************** +5.0 CIS Level 1 - [cislevel1] ************************************** -1.1 Avoid the use of the root account (Scored) +1.1 [check11] Avoid the use of the root account (Scored) -1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) +1.2 [check12] Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) -1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) +1.3 [check13] Ensure credentials unused for 90 days or greater are disabled (Scored) -1.4 Ensure access keys are rotated every 90 days or less (Scored) +1.4 [check14] Ensure access keys are rotated every 90 days or less (Scored) -1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) +1.5 [check15] Ensure IAM password policy requires at least one uppercase letter (Scored) -1.6 Ensure IAM password policy require at least one lowercase letter (Scored) +1.6 [check16] Ensure IAM password policy require at least one lowercase letter (Scored) -1.7 Ensure IAM password policy require at least one symbol (Scored) +1.7 [check17] Ensure IAM password policy require at least one symbol (Scored) -1.8 Ensure IAM password policy require at least one number (Scored) +1.8 [check18] Ensure IAM password policy require at least one number (Scored) -1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) +1.9 [check19] Ensure IAM password policy requires minimum length of 14 or greater (Scored) -1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) +1.10 [check110] Ensure IAM password policy prevents password reuse: 24 or greater (Scored) -1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) +1.11 [check111] Ensure IAM password policy expires passwords within 90 days or less (Scored) -1.12 Ensure no root account access key exists (Scored) +1.12 [check112] Ensure no root account access key exists (Scored) -1.13 Ensure MFA is enabled for the root account (Scored) +1.13 [check113] Ensure MFA is enabled for the root account (Scored) -1.15 Ensure security questions are registered in the AWS account (Not Scored) +1.15 [check115] Ensure security questions are registered in the AWS account (Not Scored) -1.16 Ensure IAM policies are attached only to groups or roles (Scored) +1.16 [check116] Ensure IAM policies are attached only to groups or roles (Scored) -1.17 Enable detailed billing (Scored) +1.17 [check117] Enable detailed billing (Scored) -1.18 Ensure IAM Master and IAM Manager roles are active (Scored) +1.18 [check118] Ensure IAM Master and IAM Manager roles are active (Scored) -1.19 Maintain current contact details (Scored) +1.19 [check119] Maintain current contact details (Scored) -1.20 Ensure security contact information is registered (Scored) +1.20 [check120] Ensure security contact information is registered (Scored) -1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) +1.22 [check122] Ensure a support role has been created to manage incidents with AWS Support (Scored) -1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) +1.23 [check123] Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) -1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) +1.24 [check124] Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) -2.1 Ensure CloudTrail is enabled in all regions (Scored) +2.1 [check21] Ensure CloudTrail is enabled in all regions (Scored) -2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) +2.3 [check23] Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) -2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) +2.4 [check24] Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) -2.5 Ensure AWS Config is enabled in all regions (Scored) +2.5 [check25] Ensure AWS Config is enabled in all regions (Scored) -2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) +2.6 [check26] Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) -3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) +3.1 [check31] Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) -3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) +3.2 [check32] Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) -3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) +3.3 [check33] Ensure a log metric filter and alarm exist for usage of root account (Scored) -3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) +3.4 [check34] Ensure a log metric filter and alarm exist for IAM policy changes (Scored) -3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) +3.5 [check35] Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) -3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) +3.8 [check38] Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) -3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) +3.12 [check312] Ensure a log metric filter and alarm exist for changes to network gateways (Scored) -3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) +3.13 [check313] Ensure a log metric filter and alarm exist for route table changes (Scored) -3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) +3.14 [check314] Ensure a log metric filter and alarm exist for VPC changes (Scored) -3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) +3.15 [check315] Ensure appropriate subscribers to each SNS topic (Not Scored) -4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) +4.1 [check41] Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) -4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) +4.2 [check42] Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) -6.0 (cislevel2) CIS Level 2 ********************************************************** +6.0 CIS Level 2 - [cislevel2] ************************************** -1.1 Avoid the use of the root account (Scored) +1.1 [check11] Avoid the use of the root account (Scored) -1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) +1.2 [check12] Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) -1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) +1.3 [check13] Ensure credentials unused for 90 days or greater are disabled (Scored) -1.4 Ensure access keys are rotated every 90 days or less (Scored) +1.4 [check14] Ensure access keys are rotated every 90 days or less (Scored) -1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) +1.5 [check15] Ensure IAM password policy requires at least one uppercase letter (Scored) -1.6 Ensure IAM password policy require at least one lowercase letter (Scored) +1.6 [check16] Ensure IAM password policy require at least one lowercase letter (Scored) -1.7 Ensure IAM password policy require at least one symbol (Scored) +1.7 [check17] Ensure IAM password policy require at least one symbol (Scored) -1.8 Ensure IAM password policy require at least one number (Scored) +1.8 [check18] Ensure IAM password policy require at least one number (Scored) -1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) +1.9 [check19] Ensure IAM password policy requires minimum length of 14 or greater (Scored) -1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) +1.10 [check110] Ensure IAM password policy prevents password reuse: 24 or greater (Scored) -1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) +1.11 [check111] Ensure IAM password policy expires passwords within 90 days or less (Scored) -1.12 Ensure no root account access key exists (Scored) +1.12 [check112] Ensure no root account access key exists (Scored) -1.13 Ensure MFA is enabled for the root account (Scored) +1.13 [check113] Ensure MFA is enabled for the root account (Scored) -1.14 Ensure hardware MFA is enabled for the root account (Scored) +1.14 [check114] Ensure hardware MFA is enabled for the root account (Scored) -1.15 Ensure security questions are registered in the AWS account (Not Scored) +1.15 [check115] Ensure security questions are registered in the AWS account (Not Scored) -1.16 Ensure IAM policies are attached only to groups or roles (Scored) +1.16 [check116] Ensure IAM policies are attached only to groups or roles (Scored) -1.17 Enable detailed billing (Scored) +1.17 [check117] Enable detailed billing (Scored) -1.18 Ensure IAM Master and IAM Manager roles are active (Scored) +1.18 [check118] Ensure IAM Master and IAM Manager roles are active (Scored) -1.19 Maintain current contact details (Scored) +1.19 [check119] Maintain current contact details (Scored) -1.20 Ensure security contact information is registered (Scored) +1.20 [check120] Ensure security contact information is registered (Scored) -1.21 Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) +1.21 [check121] Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) -1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) +1.22 [check122] Ensure a support role has been created to manage incidents with AWS Support (Scored) -1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) +1.23 [check123] Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) -1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) +1.24 [check124] Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) -2.1 Ensure CloudTrail is enabled in all regions (Scored) +2.1 [check21] Ensure CloudTrail is enabled in all regions (Scored) -2.2 Ensure CloudTrail log file validation is enabled (Scored) +2.2 [check22] Ensure CloudTrail log file validation is enabled (Scored) -2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) +2.3 [check23] Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) -2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) +2.4 [check24] Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) -2.5 Ensure AWS Config is enabled in all regions (Scored) +2.5 [check25] Ensure AWS Config is enabled in all regions (Scored) -2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) +2.6 [check26] Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) -2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) +2.7 [check27] Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) -2.8 Ensure rotation for customer created CMKs is enabled (Scored) +2.8 [check28] Ensure rotation for customer created CMKs is enabled (Scored) -3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) +3.1 [check31] Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) -3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) +3.2 [check32] Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) -3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) +3.3 [check33] Ensure a log metric filter and alarm exist for usage of root account (Scored) -3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) +3.4 [check34] Ensure a log metric filter and alarm exist for IAM policy changes (Scored) -3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) +3.5 [check35] Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) -3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) +3.6 [check36] Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) -3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) +3.7 [check37] Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) -3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) +3.8 [check38] Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) -3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) +3.9 [check39] Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) -3.10 Ensure a log metric filter and alarm exist for security group changes (Scored) +3.10 [check310] Ensure a log metric filter and alarm exist for security group changes (Scored) -3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) +3.11 [check311] Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) -3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) +3.12 [check312] Ensure a log metric filter and alarm exist for changes to network gateways (Scored) -3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) +3.13 [check313] Ensure a log metric filter and alarm exist for route table changes (Scored) -3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) +3.14 [check314] Ensure a log metric filter and alarm exist for VPC changes (Scored) -3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) +3.15 [check315] Ensure appropriate subscribers to each SNS topic (Not Scored) -4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) +4.1 [check41] Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) -4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) +4.2 [check42] Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) -4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) +4.3 [check43] Ensure VPC Flow Logging is Enabled in all VPCs (Scored) -4.4 Ensure the default security group of every VPC restricts all traffic (Scored) +4.4 [check44] Ensure the default security group of every VPC restricts all traffic (Scored) -4.5 Ensure routing tables for VPC peering are "least access" (Not Scored) +4.5 [check45] Ensure routing tables for VPC peering are "least access" (Not Scored) -7.0 (extras) Extras **************************************************************** +7.0 Extras - [extras] ********************************************** -7.1 Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark) +7.1 [extra71] Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark) -7.2 Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark) +7.2 [extra72] Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark) -7.3 Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark) +7.3 [extra73] Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark) -7.4 Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark) +7.4 [extra74] Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark) -7.5 Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark) +7.5 [extra75] Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark) -7.6 Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark) +7.6 [extra75] Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark) -7.7 Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark) +7.7 [extra77] Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark) -7.8 Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark) +7.8 [extra78] Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark) -7.9 Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark) +7.9 [extra79] Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark) -7.10 Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark) +7.10 [extra710] Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark) -7.11 Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark) +7.11 [extra711] Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark) -7.12 Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) +7.12 [extra712] Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) -7.13 Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) +7.13 [extra713] Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) -7.14 Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) +7.14 [extra714] Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) -7.15 Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) +7.15 [extra715] Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) -7.16 Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark) +7.16 [extra716] Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark) -7.17 Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) +7.17 [extra717] Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) -7.18 Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) +7.18 [extra718] Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) -7.19 Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) +7.19 [extra719] Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) -7.20 Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) +7.20 [extra720] Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) -7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) +7.21 [extra721] Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) -7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) +7.22 [extra722] Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) -7.23 Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark) +7.23 [extra723] Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark) -8.0 (forensics-ready) Forensics Readiness *************************************************** +7.24 [extra724] Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark) -2.1 Ensure CloudTrail is enabled in all regions (Scored) +8.0 Forensics Readiness - [forensics-ready] ************************ -2.2 Ensure CloudTrail log file validation is enabled (Scored) +2.1 [check21] Ensure CloudTrail is enabled in all regions (Scored) -2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) +2.2 [check22] Ensure CloudTrail log file validation is enabled (Scored) -2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) +2.3 [check23] Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) -2.5 Ensure AWS Config is enabled in all regions (Scored) +2.4 [check24] Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) -2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) +2.5 [check25] Ensure AWS Config is enabled in all regions (Scored) -2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) +2.6 [check26] Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) -4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) +2.7 [check27] Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) -7.12 Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) +4.3 [check43] Ensure VPC Flow Logging is Enabled in all VPCs (Scored) -7.13 Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) +7.12 [extra712] Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) -7.14 Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) +7.13 [extra713] Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) -7.15 Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) +7.14 [extra714] Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) -7.17 Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) +7.15 [extra715] Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) -7.18 Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) +7.17 [extra717] Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) -7.19 Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) +7.18 [extra718] Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) -7.20 Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) +7.19 [extra719] Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) -7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) +7.20 [extra720] Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) -7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) +7.21 [extra721] Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) -7.23 Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark) +7.22 [extra722] Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) -7.24 Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark) ``` diff --git a/checks/check11 b/checks/check11 index 4db6163342..751b981e70 100644 --- a/checks/check11 +++ b/checks/check11 @@ -1,5 +1,5 @@ CHECK_ID_check11="1.1,1.01" -CHECK_TITLE_check11="Avoid the use of the root account (Scored)" +CHECK_TITLE_check11="[check11] Avoid the use of the root account (Scored)" CHECK_SCORED_check11="SCORED" CHECK_ALTERNATE_check101="check11" diff --git a/checks/check110 b/checks/check110 index 4aada2f0f9..0432aa620e 100644 --- a/checks/check110 +++ b/checks/check110 @@ -1,5 +1,5 @@ CHECK_ID_check110="1.10" -CHECK_TITLE_check110="Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" +CHECK_TITLE_check110="[check110] Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" CHECK_SCORED_check110="SCORED" CHECK_ALTERNATE_check110="check110" diff --git a/checks/check111 b/checks/check111 index 5ff5845f19..9ef36c236b 100644 --- a/checks/check111 +++ b/checks/check111 @@ -1,5 +1,5 @@ CHECK_ID_check111="1.11" -CHECK_TITLE_check111="Ensure IAM password policy expires passwords within 90 days or less (Scored)" +CHECK_TITLE_check111="[check111] Ensure IAM password policy expires passwords within 90 days or less (Scored)" CHECK_SCORED_check111="SCORED" CHECK_ALTERNATE_check111="check111" diff --git a/checks/check112 b/checks/check112 index 3d79f6e001..611559801e 100644 --- a/checks/check112 +++ b/checks/check112 @@ -1,5 +1,5 @@ CHECK_ID_check112="1.12" -CHECK_TITLE_check112="Ensure no root account access key exists (Scored)" +CHECK_TITLE_check112="[check112] Ensure no root account access key exists (Scored)" CHECK_SCORED_check112="SCORED" CHECK_ALTERNATE_check112="check112" diff --git a/checks/check113 b/checks/check113 index 46aaf4a582..5b52c77c94 100644 --- a/checks/check113 +++ b/checks/check113 @@ -1,5 +1,5 @@ CHECK_ID_check113="1.13" -CHECK_TITLE_check113="Ensure MFA is enabled for the root account (Scored)" +CHECK_TITLE_check113="[check113] Ensure MFA is enabled for the root account (Scored)" CHECK_SCORED_check113="SCORED" CHECK_ALTERNATE_check113="check113" diff --git a/checks/check114 b/checks/check114 index d98371be71..c6a81a6a5d 100644 --- a/checks/check114 +++ b/checks/check114 @@ -1,5 +1,5 @@ CHECK_ID_check114="1.14" -CHECK_TITLE_check114="Ensure hardware MFA is enabled for the root account (Scored)" +CHECK_TITLE_check114="[check114] Ensure hardware MFA is enabled for the root account (Scored)" CHECK_SCORED_check114="SCORED" CHECK_ALTERNATE_check114="check114" diff --git a/checks/check115 b/checks/check115 index 19a5c2a974..41b7891505 100644 --- a/checks/check115 +++ b/checks/check115 @@ -1,5 +1,5 @@ CHECK_ID_check115="1.15" -CHECK_TITLE_check115="Ensure security questions are registered in the AWS account (Not Scored)" +CHECK_TITLE_check115="[check115] Ensure security questions are registered in the AWS account (Not Scored)" CHECK_SCORED_check115="SCORED" CHECK_ALTERNATE_check115="check115" diff --git a/checks/check116 b/checks/check116 index 0534903f94..b8dbde0113 100644 --- a/checks/check116 +++ b/checks/check116 @@ -1,5 +1,5 @@ CHECK_ID_check116="1.16" -CHECK_TITLE_check116="Ensure IAM policies are attached only to groups or roles (Scored)" +CHECK_TITLE_check116="[check116] Ensure IAM policies are attached only to groups or roles (Scored)" CHECK_SCORED_check116="SCORED" CHECK_ALTERNATE_check116="check116" diff --git a/checks/check117 b/checks/check117 index 49818cc89a..bace657574 100644 --- a/checks/check117 +++ b/checks/check117 @@ -1,5 +1,5 @@ CHECK_ID_check117="1.17" -CHECK_TITLE_check117="Enable detailed billing (Scored)" +CHECK_TITLE_check117="[check117] Enable detailed billing (Scored)" CHECK_SCORED_check117="SCORED" CHECK_ALTERNATE_check117="check117" diff --git a/checks/check118 b/checks/check118 index 62961ce0dd..abe009ee37 100644 --- a/checks/check118 +++ b/checks/check118 @@ -1,5 +1,5 @@ CHECK_ID_check118="1.18" -CHECK_TITLE_check118="Ensure IAM Master and IAM Manager roles are active (Scored)" +CHECK_TITLE_check118="[check118] Ensure IAM Master and IAM Manager roles are active (Scored)" CHECK_SCORED_check118="SCORED" CHECK_ALTERNATE_check118="check118" diff --git a/checks/check119 b/checks/check119 index 66c70b6a89..f0ec82e1ba 100644 --- a/checks/check119 +++ b/checks/check119 @@ -1,5 +1,5 @@ CHECK_ID_check119="1.19" -CHECK_TITLE_check119="Maintain current contact details (Scored)" +CHECK_TITLE_check119="[check119] Maintain current contact details (Scored)" CHECK_SCORED_check119="SCORED" CHECK_ALTERNATE_check119="check119" diff --git a/checks/check12 b/checks/check12 index ad88e9b985..3fd8e24f1f 100644 --- a/checks/check12 +++ b/checks/check12 @@ -1,5 +1,5 @@ CHECK_ID_check12="1.2,1.02" -CHECK_TITLE_check12="Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" +CHECK_TITLE_check12="[check12] Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" CHECK_SCORED_check12="SCORED" CHECK_ALTERNATE_check102="check12" diff --git a/checks/check120 b/checks/check120 index 5a0c462593..ba15cd21e7 100644 --- a/checks/check120 +++ b/checks/check120 @@ -1,5 +1,5 @@ CHECK_ID_check120="1.20" -CHECK_TITLE_check120="Ensure security contact information is registered (Scored)" +CHECK_TITLE_check120="[check120] Ensure security contact information is registered (Scored)" CHECK_SCORED_check120="SCORED" CHECK_ALTERNATE_check120="check120" diff --git a/checks/check121 b/checks/check121 index 581affcae1..01b4014e45 100644 --- a/checks/check121 +++ b/checks/check121 @@ -1,5 +1,5 @@ CHECK_ID_check121="1.21" -CHECK_TITLE_check121="Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" +CHECK_TITLE_check121="[check121] Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" CHECK_SCORED_check121="NOT_SCORED" CHECK_ALTERNATE_check121="check121" diff --git a/checks/check122 b/checks/check122 index 52f9b3b503..3c898a162e 100644 --- a/checks/check122 +++ b/checks/check122 @@ -1,5 +1,5 @@ CHECK_ID_check122="1.22" -CHECK_TITLE_check122="Ensure a support role has been created to manage incidents with AWS Support (Scored)" +CHECK_TITLE_check122="[check122] Ensure a support role has been created to manage incidents with AWS Support (Scored)" CHECK_SCORED_check122="SCORED" CHECK_ALTERNATE_check122="check122" diff --git a/checks/check123 b/checks/check123 index 766df86666..fa60d819d8 100644 --- a/checks/check123 +++ b/checks/check123 @@ -1,5 +1,5 @@ CHECK_ID_check123="1.23" -CHECK_TITLE_check123="Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" +CHECK_TITLE_check123="[check123] Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" CHECK_SCORED_check123="NOT_SCORED" CHECK_ALTERNATE_check123="check123" diff --git a/checks/check124 b/checks/check124 index 03bbb44a93..f9ca394352 100644 --- a/checks/check124 +++ b/checks/check124 @@ -1,5 +1,5 @@ CHECK_ID_check124="1.24" -CHECK_TITLE_check124="Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" +CHECK_TITLE_check124="[check124] Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" CHECK_SCORED_check124="SCORED" CHECK_ALTERNATE_check124="check124" diff --git a/checks/check13 b/checks/check13 index a515ebc935..c52a248005 100644 --- a/checks/check13 +++ b/checks/check13 @@ -1,5 +1,5 @@ CHECK_ID_check13="1.3,1.03" -CHECK_TITLE_check13="Ensure credentials unused for 90 days or greater are disabled (Scored)" +CHECK_TITLE_check13="[check13] Ensure credentials unused for 90 days or greater are disabled (Scored)" CHECK_SCORED_check13="SCORED" CHECK_ALTERNATE_check103="check13" diff --git a/checks/check14 b/checks/check14 index d3cb2798cb..ab1b823c65 100644 --- a/checks/check14 +++ b/checks/check14 @@ -1,5 +1,5 @@ CHECK_ID_check14="1.4,1.04" -CHECK_TITLE_check14="Ensure access keys are rotated every 90 days or less (Scored)" +CHECK_TITLE_check14="[check14] Ensure access keys are rotated every 90 days or less (Scored)" CHECK_SCORED_check14="SCORED" CHECK_ALTERNATE_check104="check14" diff --git a/checks/check15 b/checks/check15 index d9172d9236..998ed69865 100644 --- a/checks/check15 +++ b/checks/check15 @@ -1,5 +1,5 @@ CHECK_ID_check15="1.5,1.05" -CHECK_TITLE_check15="Ensure IAM password policy requires at least one uppercase letter (Scored)" +CHECK_TITLE_check15="[check15] Ensure IAM password policy requires at least one uppercase letter (Scored)" CHECK_SCORED_check15="SCORED" CHECK_ALTERNATE_check105="check15" diff --git a/checks/check16 b/checks/check16 index f940a89df8..04cb5d8954 100644 --- a/checks/check16 +++ b/checks/check16 @@ -1,5 +1,5 @@ CHECK_ID_check16="1.6,1.06" -CHECK_TITLE_check16="Ensure IAM password policy require at least one lowercase letter (Scored)" +CHECK_TITLE_check16="[check16] Ensure IAM password policy require at least one lowercase letter (Scored)" CHECK_SCORED_check16="SCORED" CHECK_ALTERNATE_check106="check16" diff --git a/checks/check17 b/checks/check17 index df54d702dc..b4dab41172 100644 --- a/checks/check17 +++ b/checks/check17 @@ -1,5 +1,5 @@ CHECK_ID_check17="1.7,1.07" -CHECK_TITLE_check17="Ensure IAM password policy require at least one symbol (Scored)" +CHECK_TITLE_check17="[check17] Ensure IAM password policy require at least one symbol (Scored)" CHECK_SCORED_check17="SCORED" CHECK_ALTERNATE_check107="check17" diff --git a/checks/check18 b/checks/check18 index 279c5e0917..4378ea889e 100644 --- a/checks/check18 +++ b/checks/check18 @@ -1,5 +1,5 @@ CHECK_ID_check18="1.8,1.08" -CHECK_TITLE_check18="Ensure IAM password policy require at least one number (Scored)" +CHECK_TITLE_check18="[check18] Ensure IAM password policy require at least one number (Scored)" CHECK_SCORED_check18="SCORED" CHECK_ALTERNATE_check18="check18" diff --git a/checks/check19 b/checks/check19 index 876babdd6f..b367556c2a 100644 --- a/checks/check19 +++ b/checks/check19 @@ -1,5 +1,5 @@ CHECK_ID_check19="1.9,1.09" -CHECK_TITLE_check19="Ensure IAM password policy requires minimum length of 14 or greater (Scored)" +CHECK_TITLE_check19="[check19] Ensure IAM password policy requires minimum length of 14 or greater (Scored)" CHECK_SCORED_check19="SCORED" CHECK_ALTERNATE_check109="check19" diff --git a/checks/check21 b/checks/check21 index f7d4f9df2b..56bc5fd0ce 100644 --- a/checks/check21 +++ b/checks/check21 @@ -1,5 +1,5 @@ CHECK_ID_check21="2.1,2.01" -CHECK_TITLE_check21="Ensure CloudTrail is enabled in all regions (Scored)" +CHECK_TITLE_check21="[check21] Ensure CloudTrail is enabled in all regions (Scored)" CHECK_SCORED_check21="SCORED" CHECK_ALTERNATE_check201="check21" diff --git a/checks/check22 b/checks/check22 index 8c329a8b13..0506228c0c 100644 --- a/checks/check22 +++ b/checks/check22 @@ -1,5 +1,5 @@ CHECK_ID_check22="2.2,2.02" -CHECK_TITLE_check22="Ensure CloudTrail log file validation is enabled (Scored)" +CHECK_TITLE_check22="[check22] Ensure CloudTrail log file validation is enabled (Scored)" CHECK_SCORED_check22="SCORED" CHECK_ALTERNATE_check202="check22" diff --git a/checks/check23 b/checks/check23 index e3b0da34fb..f7cea4e7f7 100644 --- a/checks/check23 +++ b/checks/check23 @@ -1,5 +1,5 @@ CHECK_ID_check23="2.3,2.03" -CHECK_TITLE_check23="Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" +CHECK_TITLE_check23="[check23] Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" CHECK_SCORED_check23="SCORED" CHECK_ALTERNATE_check203="check23" diff --git a/checks/check24 b/checks/check24 index 36c1f12394..84decf74fe 100644 --- a/checks/check24 +++ b/checks/check24 @@ -1,5 +1,5 @@ CHECK_ID_check24="2.4,2.04" -CHECK_TITLE_check24="Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" +CHECK_TITLE_check24="[check24] Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" CHECK_SCORED_check24="SCORED" CHECK_ALTERNATE_check204="check24" diff --git a/checks/check25 b/checks/check25 index fb5e3551cb..2544ef1639 100644 --- a/checks/check25 +++ b/checks/check25 @@ -1,5 +1,5 @@ CHECK_ID_check25="2.5,2.05" -CHECK_TITLE_check25="Ensure AWS Config is enabled in all regions (Scored)" +CHECK_TITLE_check25="[check25] Ensure AWS Config is enabled in all regions (Scored)" CHECK_SCORED_check25="SCORED" CHECK_ALTERNATE_check205="check25" diff --git a/checks/check26 b/checks/check26 index 9d73568eda..dc9d3b399b 100644 --- a/checks/check26 +++ b/checks/check26 @@ -1,5 +1,5 @@ CHECK_ID_check26="2.6,2.06" -CHECK_TITLE_check26="Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" +CHECK_TITLE_check26="[check26] Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" CHECK_SCORED_check26="SCORED" CHECK_ALTERNATE_check206="check26" diff --git a/checks/check27 b/checks/check27 index 0e9654a0bb..06036a0d6f 100644 --- a/checks/check27 +++ b/checks/check27 @@ -1,5 +1,5 @@ CHECK_ID_check27="2.7,2.07" -CHECK_TITLE_check27="Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" +CHECK_TITLE_check27="[check27] Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" CHECK_SCORED_check27="SCORED" CHECK_ALTERNATE_check207="check27" diff --git a/checks/check28 b/checks/check28 index 172bc1009a..3784a8b132 100644 --- a/checks/check28 +++ b/checks/check28 @@ -1,5 +1,5 @@ CHECK_ID_check28="2.8,2.08" -CHECK_TITLE_check28="Ensure rotation for customer created CMKs is enabled (Scored)" +CHECK_TITLE_check28="[check28] Ensure rotation for customer created CMKs is enabled (Scored)" CHECK_SCORED_check28="SCORED" CHECK_ALTERNATE_check208="check28" diff --git a/checks/check31 b/checks/check31 index 09d7ef1bdd..f3a92e6200 100644 --- a/checks/check31 +++ b/checks/check31 @@ -1,5 +1,5 @@ CHECK_ID_check31="3.1,3.01" -CHECK_TITLE_check31="Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" +CHECK_TITLE_check31="[check31] Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" CHECK_SCORED_check31="SCORED" CHECK_ALTERNATE_check301="check31" diff --git a/checks/check310 b/checks/check310 index 7e43cd31b0..70c0cf289f 100644 --- a/checks/check310 +++ b/checks/check310 @@ -1,5 +1,5 @@ CHECK_ID_check310="3.10" -CHECK_TITLE_check310="Ensure a log metric filter and alarm exist for security group changes (Scored)" +CHECK_TITLE_check310="[check310] Ensure a log metric filter and alarm exist for security group changes (Scored)" CHECK_SCORED_check310="SCORED" CHECK_ALTERNATE_check310="check310" diff --git a/checks/check311 b/checks/check311 index b7a5ea917d..e6744e02a0 100644 --- a/checks/check311 +++ b/checks/check311 @@ -1,5 +1,5 @@ CHECK_ID_check311="3.11" -CHECK_TITLE_check311="Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" +CHECK_TITLE_check311="[check311] Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" CHECK_SCORED_check311="SCORED" CHECK_ALTERNATE_check311="check311" diff --git a/checks/check312 b/checks/check312 index 32e3c33ed2..6c0a070669 100644 --- a/checks/check312 +++ b/checks/check312 @@ -1,5 +1,5 @@ CHECK_ID_check312="3.12" -CHECK_TITLE_check312="Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" +CHECK_TITLE_check312="[check312] Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" CHECK_SCORED_check312="SCORED" CHECK_ALTERNATE_check312="check312" diff --git a/checks/check313 b/checks/check313 index 1c25be028a..54ebef55b3 100644 --- a/checks/check313 +++ b/checks/check313 @@ -1,5 +1,5 @@ CHECK_ID_check313="3.13" -CHECK_TITLE_check313="Ensure a log metric filter and alarm exist for route table changes (Scored)" +CHECK_TITLE_check313="[check313] Ensure a log metric filter and alarm exist for route table changes (Scored)" CHECK_SCORED_check313="SCORED" CHECK_ALTERNATE_check313="check313" diff --git a/checks/check314 b/checks/check314 index 87d67b4125..e78aecb4d1 100644 --- a/checks/check314 +++ b/checks/check314 @@ -1,5 +1,5 @@ CHECK_ID_check314="3.14" -CHECK_TITLE_check314="Ensure a log metric filter and alarm exist for VPC changes (Scored)" +CHECK_TITLE_check314="[check314] Ensure a log metric filter and alarm exist for VPC changes (Scored)" CHECK_SCORED_check314="SCORED" CHECK_ALTERNATE_check314="check314" diff --git a/checks/check315 b/checks/check315 index 2598fd8337..df9c8ceb47 100644 --- a/checks/check315 +++ b/checks/check315 @@ -1,5 +1,5 @@ CHECK_ID_check315="3.15" -CHECK_TITLE_check315="Ensure appropriate subscribers to each SNS topic (Not Scored)" +CHECK_TITLE_check315="[check315] Ensure appropriate subscribers to each SNS topic (Not Scored)" CHECK_SCORED_check315="SCORED" CHECK_ALTERNATE_check315="check315" diff --git a/checks/check32 b/checks/check32 index 516eefd06b..35ceeb6d34 100644 --- a/checks/check32 +++ b/checks/check32 @@ -1,5 +1,5 @@ CHECK_ID_check32="3.2,3.02" -CHECK_TITLE_check32="Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" +CHECK_TITLE_check32="[check32] Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" CHECK_SCORED_check32="SCORED" CHECK_ALTERNATE_check302="check32" diff --git a/checks/check33 b/checks/check33 index 9dc3ed94d5..cb09c9bb50 100644 --- a/checks/check33 +++ b/checks/check33 @@ -1,5 +1,5 @@ CHECK_ID_check33="3.3,3.03" -CHECK_TITLE_check33="Ensure a log metric filter and alarm exist for usage of root account (Scored)" +CHECK_TITLE_check33="[check33] Ensure a log metric filter and alarm exist for usage of root account (Scored)" CHECK_SCORED_check33="SCORED" CHECK_ALTERNATE_check303="check33" diff --git a/checks/check34 b/checks/check34 index 83c5cbb689..c5a53224f7 100644 --- a/checks/check34 +++ b/checks/check34 @@ -1,5 +1,5 @@ CHECK_ID_check34="3.4,3.04" -CHECK_TITLE_check34="Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" +CHECK_TITLE_check34="[check34] Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" CHECK_SCORED_check34="SCORED" CHECK_ALTERNATE_check304="check34" diff --git a/checks/check35 b/checks/check35 index 50fd288960..a91679abd8 100644 --- a/checks/check35 +++ b/checks/check35 @@ -1,5 +1,5 @@ CHECK_ID_check35="3.5,3.05" -CHECK_TITLE_check35="Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" +CHECK_TITLE_check35="[check35] Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" CHECK_SCORED_check35="SCORED" CHECK_ALTERNATE_check305="check35" diff --git a/checks/check36 b/checks/check36 index 54e320f707..a32dc1029b 100644 --- a/checks/check36 +++ b/checks/check36 @@ -1,5 +1,5 @@ CHECK_ID_check36="3.6,3.06" -CHECK_TITLE_check36="Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" +CHECK_TITLE_check36="[check36] Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" CHECK_SCORED_check36="SCORED" CHECK_ALTERNATE_check306="check36" diff --git a/checks/check37 b/checks/check37 index 01147afdee..36f004812d 100644 --- a/checks/check37 +++ b/checks/check37 @@ -1,5 +1,5 @@ CHECK_ID_check37="3.7,3.07" -CHECK_TITLE_check37="Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" +CHECK_TITLE_check37="[check37] Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" CHECK_SCORED_check37="SCORED" CHECK_ALTERNATE_check307="check37" diff --git a/checks/check38 b/checks/check38 index 9ddfa902ea..87783438d2 100644 --- a/checks/check38 +++ b/checks/check38 @@ -1,5 +1,5 @@ CHECK_ID_check38="3.8,3.08" -CHECK_TITLE_check38="Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" +CHECK_TITLE_check38="[check38] Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" CHECK_SCORED_check38="SCORED" CHECK_ALTERNATE_check308="check38" diff --git a/checks/check39 b/checks/check39 index 3aa14527b6..deb7714c3b 100644 --- a/checks/check39 +++ b/checks/check39 @@ -1,5 +1,5 @@ CHECK_ID_check39="3.9,3.09" -CHECK_TITLE_check39="Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" +CHECK_TITLE_check39="[check39] Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" CHECK_SCORED_check39="SCORED" CHECK_ALTERNATE_check309="check39" diff --git a/checks/check41 b/checks/check41 index d63ae4ded5..74d986d7cd 100644 --- a/checks/check41 +++ b/checks/check41 @@ -1,5 +1,5 @@ CHECK_ID_check41="4.1,4.01" -CHECK_TITLE_check41="Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" +CHECK_TITLE_check41="[check41] Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" CHECK_SCORED_check41="SCORED" CHECK_ALTERNATE_check401="check41" diff --git a/checks/check42 b/checks/check42 index 6db241f44c..31e9f789ee 100644 --- a/checks/check42 +++ b/checks/check42 @@ -1,5 +1,5 @@ CHECK_ID_check42="4.2,4.02" -CHECK_TITLE_check42="Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" +CHECK_TITLE_check42="[check42] Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" CHECK_SCORED_check42="SCORED" CHECK_ALTERNATE_check402="check42" diff --git a/checks/check43 b/checks/check43 index 1da367d77f..257442dbdc 100644 --- a/checks/check43 +++ b/checks/check43 @@ -1,5 +1,5 @@ CHECK_ID_check43="4.3,4.03" -CHECK_TITLE_check43="Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" +CHECK_TITLE_check43="[check43] Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" CHECK_SCORED_check43="SCORED" CHECK_ALTERNATE_check403="check43" diff --git a/checks/check44 b/checks/check44 index 0d1e3bbe70..4b0d347842 100644 --- a/checks/check44 +++ b/checks/check44 @@ -1,5 +1,5 @@ CHECK_ID_check44="4.4,4.04" -CHECK_TITLE_check44="Ensure the default security group of every VPC restricts all traffic (Scored)" +CHECK_TITLE_check44="[check44] Ensure the default security group of every VPC restricts all traffic (Scored)" CHECK_SCORED_check44="SCORED" CHECK_ALTERNATE_check404="check44" diff --git a/checks/check45 b/checks/check45 index 5776a6b034..4e01e6c958 100644 --- a/checks/check45 +++ b/checks/check45 @@ -1,5 +1,5 @@ CHECK_ID_check45="4.5,4.05" -CHECK_TITLE_check45="Ensure routing tables for VPC peering are \"least access\" (Not Scored)" +CHECK_TITLE_check45="[check45] Ensure routing tables for VPC peering are \"least access\" (Not Scored)" CHECK_SCORED_check45="NOT_SCORED" CHECK_ALTERNATE_check405="check45" diff --git a/checks/check_extra71 b/checks/check_extra71 index 0cb0632cc5..25e60788e7 100644 --- a/checks/check_extra71 +++ b/checks/check_extra71 @@ -1,5 +1,5 @@ CHECK_ID_extra71="7.1,7.01" -CHECK_TITLE_extra71="Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra71="[extra71] Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra71="NOT_SCORED" CHECK_ALTERNATE_extra701="extra71" CHECK_ALTERNATE_check71="extra71" diff --git a/checks/check_extra710 b/checks/check_extra710 index a30bf720ce..940324bb8c 100644 --- a/checks/check_extra710 +++ b/checks/check_extra710 @@ -1,5 +1,5 @@ CHECK_ID_extra710="7.10" -CHECK_TITLE_extra710="Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra710="[extra710] Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra710="NOT_SCORED" CHECK_ALTERNATE_check710="extra710" diff --git a/checks/check_extra711 b/checks/check_extra711 index 7cd41c827d..1e0faa52db 100644 --- a/checks/check_extra711 +++ b/checks/check_extra711 @@ -1,5 +1,5 @@ CHECK_ID_extra711="7.11" -CHECK_TITLE_extra711="Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra711="[extra711] Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra711="NOT_SCORED" CHECK_ALTERNATE_check711="extra711" diff --git a/checks/check_extra712 b/checks/check_extra712 index a16d9952c1..86126c9afd 100644 --- a/checks/check_extra712 +++ b/checks/check_extra712 @@ -1,5 +1,5 @@ CHECK_ID_extra712="7.12" -CHECK_TITLE_extra712="Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra712="[extra712] Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra712="NOT_SCORED" CHECK_ALTERNATE_check712="extra712" diff --git a/checks/check_extra713 b/checks/check_extra713 index 83355ca59f..86aecfe4a3 100644 --- a/checks/check_extra713 +++ b/checks/check_extra713 @@ -1,5 +1,5 @@ CHECK_ID_extra713="7.13" -CHECK_TITLE_extra713="Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra713="[extra713] Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra713="NOT_SCORED" CHECK_ALTERNATE_check713="extra713" diff --git a/checks/check_extra714 b/checks/check_extra714 index c7672f7e43..6c0cf2c5a7 100644 --- a/checks/check_extra714 +++ b/checks/check_extra714 @@ -1,5 +1,5 @@ CHECK_ID_extra714="7.14" -CHECK_TITLE_extra714="Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra714="[extra714] Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra714="NOT_SCORED" CHECK_ALTERNATE_check714="extra714" diff --git a/checks/check_extra715 b/checks/check_extra715 index e3af970684..88a417152f 100644 --- a/checks/check_extra715 +++ b/checks/check_extra715 @@ -1,5 +1,5 @@ CHECK_ID_extra715="7.15" -CHECK_TITLE_extra715="Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra715="[extra715] Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra715="NOT_SCORED" CHECK_ALTERNATE_check715="extra715" diff --git a/checks/check_extra716 b/checks/check_extra716 index 30b669fbef..3d85d53cde 100644 --- a/checks/check_extra716 +++ b/checks/check_extra716 @@ -1,5 +1,5 @@ CHECK_ID_extra716="7.16" -CHECK_TITLE_extra716="Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra716="[extra716] Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra716="NOT_SCORED" CHECK_ALTERNATE_check716="extra716" diff --git a/checks/check_extra717 b/checks/check_extra717 index 6a07975c71..0c36dda432 100644 --- a/checks/check_extra717 +++ b/checks/check_extra717 @@ -1,5 +1,5 @@ CHECK_ID_extra717="7.17" -CHECK_TITLE_extra717="Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra717="[extra717] Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra717="NOT_SCORED" CHECK_ALTERNATE_check717="extra717" diff --git a/checks/check_extra718 b/checks/check_extra718 index 77c74783b2..927f3d7535 100644 --- a/checks/check_extra718 +++ b/checks/check_extra718 @@ -1,5 +1,5 @@ CHECK_ID_extra718="7.18" -CHECK_TITLE_extra718="Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra718="[extra718] Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra718="NOT_SCORED" CHECK_ALTERNATE_check718="extra718" diff --git a/checks/check_extra719 b/checks/check_extra719 index fba60d764b..fddc65fc57 100644 --- a/checks/check_extra719 +++ b/checks/check_extra719 @@ -1,5 +1,5 @@ CHECK_ID_extra719="7.19" -CHECK_TITLE_extra719="Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra719="[extra719] Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra719="NOT_SCORED" CHECK_ALTERNATE_check719="extra719" diff --git a/checks/check_extra72 b/checks/check_extra72 index fc90c0b61c..2523822cda 100644 --- a/checks/check_extra72 +++ b/checks/check_extra72 @@ -1,5 +1,5 @@ CHECK_ID_extra72="7.2,7.02" -CHECK_TITLE_extra72="Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra72="[extra72] Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra72="NOT_SCORED" CHECK_ALTERNATE_extra702="extra72" CHECK_ALTERNATE_check72="extra72" diff --git a/checks/check_extra720 b/checks/check_extra720 index 139f30e961..af9f63fe22 100644 --- a/checks/check_extra720 +++ b/checks/check_extra720 @@ -1,5 +1,5 @@ CHECK_ID_extra720="7.20" -CHECK_TITLE_extra720="Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra720="[extra720] Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra720="NOT_SCORED" CHECK_ALTERNATE_check720="extra720" diff --git a/checks/check_extra721 b/checks/check_extra721 index b430025e81..9a9f1b81ca 100644 --- a/checks/check_extra721 +++ b/checks/check_extra721 @@ -1,5 +1,5 @@ CHECK_ID_extra721="7.21" -CHECK_TITLE_extra721="Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra721="[extra721] Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra721="NOT_SCORED" CHECK_ALTERNATE_check721="extra721" diff --git a/checks/check_extra722 b/checks/check_extra722 index d2621c61fd..b08c5ba6e4 100644 --- a/checks/check_extra722 +++ b/checks/check_extra722 @@ -1,5 +1,5 @@ CHECK_ID_extra722="7.22" -CHECK_TITLE_extra722="Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra722="[extra722] Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra722="NOT_SCORED" CHECK_ALTERNATE_check722="extra722" diff --git a/checks/check_extra723 b/checks/check_extra723 index 31a3daa46e..1c9ef44716 100644 --- a/checks/check_extra723 +++ b/checks/check_extra723 @@ -1,5 +1,5 @@ CHECK_ID_extra723="7.23" -CHECK_TITLE_extra723="Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra723="[extra723] Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra723="NOT_SCORED" CHECK_ALTERNATE_check723="extra723" diff --git a/checks/check_extra724 b/checks/check_extra724 index 8fece770dd..fc3968441a 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -1,5 +1,5 @@ CHECK_ID_extra724="7.24" -CHECK_TITLE_extra724="Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra724="[extra724] Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra724="NOT_SCORED" CHECK_ALTERNATE_check724="extra724" diff --git a/checks/check_extra725 b/checks/check_extra725 new file mode 100644 index 0000000000..d8076b05bc --- /dev/null +++ b/checks/check_extra725 @@ -0,0 +1,46 @@ +# CHECK_ID_extra725="7.25" +# CHECK_TITLE_extra725="[extra725] Check if S3 buckets have Object-level logging enabled (Not Scored) (Not part of CIS benchmark)" +# CHECK_SCORED_extra725="NOT_SCORED" +# CHECK_ALTERNATE_check725="extra725" +# +# aws cloudtrail get-event-selectors --trail-name Default --profile security --region us-east-1 --query "EventSelectors[*].DataResources[?Type == \`AWS::S3::Object\`].Values" --output text |xargs -n1 |cut -d: -f 6|sed 's/\///g' +# +# extra725(){ +# # "Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" +# for regx in $REGIONS; do +# LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text) +# if [[ $LIST_OF_FUNCTIONS ]]; then +# for lambdafunction in $LIST_OF_FUNCTIONS;do +# LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query trailList[?HomeRegion==\`$regx\`].Name --output text) +# if [[ $LIST_OF_TRAILS ]]; then +# for trail in $LIST_OF_TRAILS; do +# FUNCTION_ENABLED_IN_TRAIL=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $regx --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") +# if [[ $FUNCTION_ENABLED_IN_TRAIL ]]; then +# textPass "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" +# else +# textFail "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" +# fi +# done +# # LIST_OF_MULTIREGION_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\`].Name" --output text) +# # if [[ $LIST_OF_MULTIREGION_TRAILS ]]; then +# # for trail in $LIST_OF_MULTIREGION_TRAILS; do +# # REGION_OF_TRAIL=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\` && Name == \`$trail\` ].HomeRegion" --output text) +# # FUNCTION_ENABLED_IN_THIS_REGION=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $REGION_OF_TRAIL --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") +# # if [[ $FUNCTION_ENABLED_IN_THIS_REGION ]]; then +# # textPass "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" +# # else +# # textFail "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" +# # fi +# # done +# # else +# # textFail "$regx: Lambda function $lambdafunction is not being recorded!" "$regx" +# # fi +# else +# textFail "$regx: Lambda function $lambdafunction is not being recorded no CloudTrail found!" "$regx" +# fi +# done +# else +# textInfo "$regx: No Lambda functions found" "$regx" +# fi +# done +# } diff --git a/checks/check_extra726 b/checks/check_extra726 new file mode 100644 index 0000000000..6d77d65bfb --- /dev/null +++ b/checks/check_extra726 @@ -0,0 +1,48 @@ +# CHECK_ID_extra726="7.26" +# CHECK_TITLE_extra726="[extra726] Check Trusted Advisor for errors and warnings (Not Scored) (Not part of CIS benchmark)" +# CHECK_SCORED_extra726="NOT_SCORED" +# CHECK_ALTERNATE_check726="extra726" +# +# tachecks=$(aws support describe-trusted-advisor-checks --language en --profile security --region us-east-1 --query checks[*].id --output text) +# +# for i in $tachecks; do aws support describe-trusted-advisor-check-result --check-id $i --language en --profile security --region us-east-1 --query result.status --output text; done +# +# extra726(){ +# # "Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" +# for regx in $REGIONS; do +# LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text) +# if [[ $LIST_OF_FUNCTIONS ]]; then +# for lambdafunction in $LIST_OF_FUNCTIONS;do +# LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query trailList[?HomeRegion==\`$regx\`].Name --output text) +# if [[ $LIST_OF_TRAILS ]]; then +# for trail in $LIST_OF_TRAILS; do +# FUNCTION_ENABLED_IN_TRAIL=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $regx --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") +# if [[ $FUNCTION_ENABLED_IN_TRAIL ]]; then +# textPass "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" +# else +# textFail "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" +# fi +# done +# # LIST_OF_MULTIREGION_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\`].Name" --output text) +# # if [[ $LIST_OF_MULTIREGION_TRAILS ]]; then +# # for trail in $LIST_OF_MULTIREGION_TRAILS; do +# # REGION_OF_TRAIL=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\` && Name == \`$trail\` ].HomeRegion" --output text) +# # FUNCTION_ENABLED_IN_THIS_REGION=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $REGION_OF_TRAIL --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") +# # if [[ $FUNCTION_ENABLED_IN_THIS_REGION ]]; then +# # textPass "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" +# # else +# # textFail "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" +# # fi +# # done +# # else +# # textFail "$regx: Lambda function $lambdafunction is not being recorded!" "$regx" +# # fi +# else +# textFail "$regx: Lambda function $lambdafunction is not being recorded no CloudTrail found!" "$regx" +# fi +# done +# else +# textInfo "$regx: No Lambda functions found" "$regx" +# fi +# done +# } diff --git a/checks/check_extra73 b/checks/check_extra73 index 3dfc14c4f0..0d8e3e809b 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -1,5 +1,5 @@ CHECK_ID_extra73="7.3,7.03" -CHECK_TITLE_extra73="Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra73="[extra73] Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra73="NOT_SCORED" CHECK_ALTERNATE_extra703="extra73" CHECK_ALTERNATE_check73="extra73" diff --git a/checks/check_extra74 b/checks/check_extra74 index 80a69b7ead..d106d4440d 100644 --- a/checks/check_extra74 +++ b/checks/check_extra74 @@ -1,5 +1,5 @@ CHECK_ID_extra74="7.4,7.04" -CHECK_TITLE_extra74="Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra74="[extra74] Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra74="NOT_SCORED" CHECK_ALTERNATE_extra704="extra74" CHECK_ALTERNATE_check74="extra74" diff --git a/checks/check_extra75 b/checks/check_extra75 index f004a0a874..20aba2357c 100644 --- a/checks/check_extra75 +++ b/checks/check_extra75 @@ -1,5 +1,5 @@ CHECK_ID_extra75="7.5,7.05" -CHECK_TITLE_extra75="Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra75="[extra75] Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra75="NOT_SCORED" CHECK_ALTERNATE_extra705="extra75" CHECK_ALTERNATE_check75="extra75" diff --git a/checks/check_extra76 b/checks/check_extra76 index aad168cf60..18bb4de2e6 100644 --- a/checks/check_extra76 +++ b/checks/check_extra76 @@ -1,5 +1,5 @@ CHECK_ID_extra76="7.6,7.06" -CHECK_TITLE_extra76="Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra76="[extra75] Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra76="NOT_SCORED" CHECK_ALTERNATE_extra706="extra76" CHECK_ALTERNATE_check76="extra76" diff --git a/checks/check_extra77 b/checks/check_extra77 index 147dc263ec..ac726e8e9c 100644 --- a/checks/check_extra77 +++ b/checks/check_extra77 @@ -1,5 +1,5 @@ CHECK_ID_extra77="7.7,7.07" -CHECK_TITLE_extra77="Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra77="[extra77] Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra77="NOT_SCORED" CHECK_ALTERNATE_extra707="extra77" CHECK_ALTERNATE_check77="extra77" diff --git a/checks/check_extra78 b/checks/check_extra78 index 34cbe83577..b2ff995494 100644 --- a/checks/check_extra78 +++ b/checks/check_extra78 @@ -1,5 +1,5 @@ CHECK_ID_extra78="7.8,7.08" -CHECK_TITLE_extra78="Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra78="[extra78] Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra78="NOT_SCORED" CHECK_ALTERNATE_extra708="extra78" CHECK_ALTERNATE_check78="extra78" diff --git a/checks/check_extra79 b/checks/check_extra79 index 5085df8de5..45c58a0cc0 100644 --- a/checks/check_extra79 +++ b/checks/check_extra79 @@ -1,5 +1,5 @@ CHECK_ID_extra79="7.9,7.09" -CHECK_TITLE_extra79="Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" +CHECK_TITLE_extra79="[extra79] Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra79="NOT_SCORED" CHECK_ALTERNATE_extra709="extra79" CHECK_ALTERNATE_check79="extra79" diff --git a/checks/check_sample b/checks/check_sample index 976635617a..024dbd56bf 100644 --- a/checks/check_sample +++ b/checks/check_sample @@ -1,5 +1,5 @@ # CHECK_ID_checkN="N.N" -# CHECK_TITLE_checkN="Description (Not Scored) (Not part of CIS benchmark)" +# CHECK_TITLE_checkN="[checkN] Description (Not Scored) (Not part of CIS benchmark)" # CHECK_SCORED_checkN="NOT_SCORED" # CHECK_ALTERNATE_checkN="extraN" # diff --git a/groups/group1_iam b/groups/group1_iam index 6145bff4b3..aa809806a0 100644 --- a/groups/group1_iam +++ b/groups/group1_iam @@ -1,5 +1,5 @@ GROUP_ID[1]='group1' GROUP_NUMBER[1]='1.0' -GROUP_TITLE[1]='Identity and Access Management ****************************************' +GROUP_TITLE[1]='Identity and Access Management - [group1] **********************' GROUP_RUN_BY_DEFAULT[1]='Y' # run it when execute_all is called GROUP_CHECKS[1]='check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check114,check115,check116,check117,check118,check119,check120,check121,check122,check123,check124' diff --git a/groups/group2_logging b/groups/group2_logging index da10a1d41b..c0ea6c3591 100644 --- a/groups/group2_logging +++ b/groups/group2_logging @@ -1,5 +1,5 @@ GROUP_ID[2]='group2' GROUP_NUMBER[2]='2.0' -GROUP_TITLE[2]='Logging ***************************************************************' +GROUP_TITLE[2]='Logging - [group2] *********************************************' GROUP_RUN_BY_DEFAULT[2]='Y' # run it when execute_all is called GROUP_CHECKS[2]='check21,check22,check23,check24,check25,check26,check27,check28' diff --git a/groups/group3_monitoring b/groups/group3_monitoring index 56356f84ec..61ab3d9c05 100644 --- a/groups/group3_monitoring +++ b/groups/group3_monitoring @@ -1,5 +1,5 @@ GROUP_ID[3]='group3' GROUP_NUMBER[3]='3.0' -GROUP_TITLE[3]='Monitoring ************************************************************' +GROUP_TITLE[3]='Monitoring - [group3] ******************************************' GROUP_RUN_BY_DEFAULT[3]='Y' # run it when execute_all is called GROUP_CHECKS[3]='check31,check32,check33,check34,check35,check36,check37,check38,check39,check310,check311,check312,check313,check314,check315' diff --git a/groups/group4_networking b/groups/group4_networking index b5be3299a8..8a1029d1e4 100644 --- a/groups/group4_networking +++ b/groups/group4_networking @@ -1,5 +1,5 @@ GROUP_ID[4]="group4" GROUP_NUMBER[4]="4.0" -GROUP_TITLE[4]="Networking ************************************************************" +GROUP_TITLE[4]="Networking - [group4] ******************************************" GROUP_RUN_BY_DEFAULT[4]="Y" # run it when execute_all is called GROUP_CHECKS[4]="check41,check42,check43,check44,check45" diff --git a/groups/group5_cislevel1 b/groups/group5_cislevel1 index 277ec060f9..663df5e20c 100644 --- a/groups/group5_cislevel1 +++ b/groups/group5_cislevel1 @@ -1,5 +1,5 @@ GROUP_ID[5]='cislevel1' GROUP_NUMBER[5]='5.0' -GROUP_TITLE[5]='CIS Level 1 **********************************************************' +GROUP_TITLE[5]='CIS Level 1 - [cislevel1] **************************************' GROUP_RUN_BY_DEFAULT[5]='N' # run it when execute_all is called GROUP_CHECKS[5]='check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check115,check116,check117,check118,check119,check120,check122,check123,check124,check21,check23,check24,check25,check26,check31,check32,check33,check34,check35,check38,check312,check313,check314,check315,check41,check42' diff --git a/groups/group6_cislevel2 b/groups/group6_cislevel2 index 3d627e3bde..eeb61521c3 100644 --- a/groups/group6_cislevel2 +++ b/groups/group6_cislevel2 @@ -1,5 +1,5 @@ GROUP_ID[6]='cislevel2' GROUP_NUMBER[6]='6.0' -GROUP_TITLE[6]='CIS Level 2 **********************************************************' +GROUP_TITLE[6]='CIS Level 2 - [cislevel2] **************************************' GROUP_RUN_BY_DEFAULT[6]='N' # run it when execute_all is called GROUP_CHECKS[6]='check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check112,check113,check114,check115,check116,check117,check118,check119,check120,check121,check122,check123,check124,check21,check22,check23,check24,check25,check26,check27,check28,check31,check32,check33,check34,check35,check36,check37,check38,check39,check310,check311,check312,check313,check314,check315,check41,check42,check43,check44,check45' diff --git a/groups/group7_extras b/groups/group7_extras index bddb4c8403..0690022f6d 100644 --- a/groups/group7_extras +++ b/groups/group7_extras @@ -1,5 +1,5 @@ GROUP_ID[7]='extras' GROUP_NUMBER[7]='7.0' -GROUP_TITLE[7]='Extras ****************************************************************' +GROUP_TITLE[7]='Extras - [extras] **********************************************' GROUP_RUN_BY_DEFAULT[7]='Y' # run it when execute_all is called GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723,extra724' diff --git a/groups/group8_forensics b/groups/group8_forensics index 704b31ac3c..1f7e6d68e5 100644 --- a/groups/group8_forensics +++ b/groups/group8_forensics @@ -1,5 +1,5 @@ GROUP_ID[8]='forensics-ready' GROUP_NUMBER[8]='8.0' -GROUP_TITLE[8]='Forensics Readiness ***************************************************' +GROUP_TITLE[8]='Forensics Readiness - [forensics-ready] ************************' GROUP_RUN_BY_DEFAULT[8]='N' # run it when execute_all is called GROUP_CHECKS[8]='check21,check22,check23,check24,check25,check26,check27,check43,extra712,extra713,extra714,extra715,extra717,extra718,extra719,extra720,extra721,extra722' diff --git a/groups/group9_gdpr b/groups/group9_gdpr index 3707fbf70d..9e5b5658cb 100644 --- a/groups/group9_gdpr +++ b/groups/group9_gdpr @@ -1,5 +1,5 @@ GROUP_ID[9]='gdpr' GROUP_NUMBER[9]='8.0' -GROUP_TITLE[9]='GDPR Readiness ***************************************************' +GROUP_TITLE[9]='GDPR Readiness - [gdpr] ****************************************' GROUP_RUN_BY_DEFAULT[9]='N' # run it when execute_all is called GROUP_CHECKS[9]='' diff --git a/groups/groupN_sample b/groups/groupN_sample index a286c9f8e6..e9f44685d5 100644 --- a/groups/groupN_sample +++ b/groups/groupN_sample @@ -1,5 +1,5 @@ -GROUP_ID[9]='my-custom-group' +GROUP_ID[9]='my-custom-group' GROUP_NUMBER[9]='9.0' -GROUP_TITLE[9]='My Custom Group **********************************************' +GROUP_TITLE[9]='My Custom Group - [my-custom-group] ****************************' GROUP_RUN_BY_DEFAULT[9]='N' # run it when execute_all is called GROUP_CHECKS[9]='checkNN,checkMM' From 1da206cb907993ec2349e6ab7c6284e8556ebe96 Mon Sep 17 00:00:00 2001 From: Geoff Webster <1393426+sidewinder12s@users.noreply.github.com> Date: Wed, 4 Apr 2018 21:39:57 -0700 Subject: [PATCH 29/41] Update all CIS document links to AWS version. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0df8ed6c7..aec89d9a04 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ ## Description -Tool based on AWS-CLI commands for AWS account security assessment and hardening, following guidelines of the [CIS Amazon Web Services Foundations Benchmark 1.1 ](https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf) +Tool based on AWS-CLI commands for AWS account security assessment and hardening, following guidelines of the [CIS Amazon Web Services Foundations Benchmark 1.1 ](https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf) ## Features @@ -156,7 +156,7 @@ USAGE: ``` ## Fix every FAIL: - Check your report and fix the issues following all specific guidelines per check in https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf + Check your report and fix the issues following all specific guidelines per check in https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf ## Screenshots From e3e038127ff6cefb15b52e23b4b2acc350500e44 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 9 Apr 2018 15:09:30 -0400 Subject: [PATCH 30/41] license changes for checks --- LICENSE | 364 +------------------------------------ LICENSE-APACHE-2.0 | 201 ++++++++++++++++++++ LICENSE-CC-BY-SA-4.0 | 360 ++++++++++++++++++++++++++++++++++++ README.md | 8 + checks/check11 | 10 + checks/check110 | 10 + checks/check111 | 10 + checks/check112 | 10 + checks/check113 | 10 + checks/check114 | 10 + checks/check115 | 10 + checks/check116 | 10 + checks/check117 | 10 + checks/check118 | 10 + checks/check119 | 12 +- checks/check12 | 10 + checks/check120 | 10 + checks/check121 | 10 + checks/check122 | 10 + checks/check123 | 10 + checks/check124 | 10 + checks/check13 | 10 + checks/check14 | 10 + checks/check15 | 10 + checks/check16 | 12 +- checks/check17 | 10 + checks/check18 | 10 + checks/check19 | 10 + checks/check21 | 10 + checks/check22 | 10 + checks/check23 | 10 + checks/check24 | 10 + checks/check25 | 10 + checks/check26 | 10 + checks/check27 | 10 + checks/check28 | 10 + checks/check31 | 10 + checks/check310 | 10 + checks/check311 | 10 + checks/check312 | 10 + checks/check313 | 10 + checks/check314 | 10 + checks/check315 | 10 + checks/check32 | 10 + checks/check33 | 10 + checks/check34 | 10 + checks/check35 | 10 + checks/check36 | 10 + checks/check37 | 10 + checks/check38 | 10 + checks/check39 | 10 + checks/check41 | 10 + checks/check42 | 10 + checks/check43 | 10 + checks/check44 | 10 + checks/check45 | 10 + checks/check_extra71 | 12 ++ checks/check_extra710 | 12 ++ checks/check_extra711 | 12 ++ checks/check_extra712 | 12 ++ checks/check_extra713 | 12 ++ checks/check_extra714 | 12 ++ checks/check_extra715 | 12 ++ checks/check_extra716 | 12 ++ checks/check_extra717 | 12 ++ checks/check_extra718 | 12 ++ checks/check_extra719 | 12 ++ checks/check_extra72 | 12 ++ checks/check_extra720 | 12 ++ checks/check_extra721 | 12 ++ checks/check_extra722 | 12 ++ checks/check_extra723 | 12 ++ checks/check_extra724 | 12 ++ checks/check_extra725 | 12 ++ checks/check_extra726 | 12 ++ checks/check_extra73 | 12 ++ checks/check_extra74 | 12 ++ checks/check_extra75 | 12 ++ checks/check_extra76 | 12 ++ checks/check_extra77 | 13 ++ checks/check_extra78 | 12 ++ checks/check_extra79 | 12 ++ checks/check_sample | 13 ++ groups/group1_iam | 10 + groups/group2_logging | 10 + groups/group3_monitoring | 10 + groups/group4_networking | 10 + groups/group5_cislevel1 | 10 + groups/group6_cislevel2 | 10 + groups/group7_extras | 13 ++ groups/group8_forensics | 13 ++ groups/group9_gdpr | 13 ++ groups/groupN_sample | 13 ++ include/aws_profile_loader | 14 ++ include/awscli_detector | 13 ++ include/banner | 13 ++ include/colors | 13 ++ include/credentials_report | 13 ++ include/csv_header | 14 ++ include/os_detector | 14 ++ include/outputs | 15 +- include/whoami | 14 ++ prowler | 24 ++- 103 files changed, 1671 insertions(+), 371 deletions(-) create mode 100644 LICENSE-APACHE-2.0 create mode 100644 LICENSE-CC-BY-SA-4.0 diff --git a/LICENSE b/LICENSE index 63f44cc3ac..f764ae6740 100644 --- a/LICENSE +++ b/LICENSE @@ -1,360 +1,6 @@ -Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International -Public License +All CIS based checks in the checks folder are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License. +The link to the license terms can be found at +https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode -By exercising the Licensed Rights (defined below), You accept and agree -to be bound by the terms and conditions of this Creative Commons -Attribution-NonCommercial-ShareAlike 4.0 International Public License -("Public License"). To the extent this Public License may be -interpreted as a contract, You are granted the Licensed Rights in -consideration of Your acceptance of these terms and conditions, and the -Licensor grants You such rights in consideration of benefits the -Licensor receives from making the Licensed Material available under -these terms and conditions. - - -Section 1 -- Definitions. - - a. Adapted Material means material subject to Copyright and Similar - Rights that is derived from or based upon the Licensed Material - and in which the Licensed Material is translated, altered, - arranged, transformed, or otherwise modified in a manner requiring - permission under the Copyright and Similar Rights held by the - Licensor. For purposes of this Public License, where the Licensed - Material is a musical work, performance, or sound recording, - Adapted Material is always produced where the Licensed Material is - synched in timed relation with a moving image. - - b. Adapter's License means the license You apply to Your Copyright - and Similar Rights in Your contributions to Adapted Material in - accordance with the terms and conditions of this Public License. - - c. BY-NC-SA Compatible License means a license listed at - creativecommons.org/compatiblelicenses, approved by Creative - Commons as essentially the equivalent of this Public License. - - d. Copyright and Similar Rights means copyright and/or similar rights - closely related to copyright including, without limitation, - performance, broadcast, sound recording, and Sui Generis Database - Rights, without regard to how the rights are labeled or - categorized. For purposes of this Public License, the rights - specified in Section 2(b)(1)-(2) are not Copyright and Similar - Rights. - - e. Effective Technological Measures means those measures that, in the - absence of proper authority, may not be circumvented under laws - fulfilling obligations under Article 11 of the WIPO Copyright - Treaty adopted on December 20, 1996, and/or similar international - agreements. - - f. Exceptions and Limitations means fair use, fair dealing, and/or - any other exception or limitation to Copyright and Similar Rights - that applies to Your use of the Licensed Material. - - g. License Elements means the license attributes listed in the name - of a Creative Commons Public License. The License Elements of this - Public License are Attribution, NonCommercial, and ShareAlike. - - h. Licensed Material means the artistic or literary work, database, - or other material to which the Licensor applied this Public - License. - - i. Licensed Rights means the rights granted to You subject to the - terms and conditions of this Public License, which are limited to - all Copyright and Similar Rights that apply to Your use of the - Licensed Material and that the Licensor has authority to license. - - j. Licensor means the individual(s) or entity(ies) granting rights - under this Public License. - - k. NonCommercial means not primarily intended for or directed towards - commercial advantage or monetary compensation. For purposes of - this Public License, the exchange of the Licensed Material for - other material subject to Copyright and Similar Rights by digital - file-sharing or similar means is NonCommercial provided there is - no payment of monetary compensation in connection with the - exchange. - - l. Share means to provide material to the public by any means or - process that requires permission under the Licensed Rights, such - as reproduction, public display, public performance, distribution, - dissemination, communication, or importation, and to make material - available to the public including in ways that members of the - public may access the material from a place and at a time - individually chosen by them. - - m. Sui Generis Database Rights means rights other than copyright - resulting from Directive 96/9/EC of the European Parliament and of - the Council of 11 March 1996 on the legal protection of databases, - as amended and/or succeeded, as well as other essentially - equivalent rights anywhere in the world. - - n. You means the individual or entity exercising the Licensed Rights - under this Public License. Your has a corresponding meaning. - - -Section 2 -- Scope. - - a. License grant. - - 1. Subject to the terms and conditions of this Public License, - the Licensor hereby grants You a worldwide, royalty-free, - non-sublicensable, non-exclusive, irrevocable license to - exercise the Licensed Rights in the Licensed Material to: - - a. reproduce and Share the Licensed Material, in whole or - in part, for NonCommercial purposes only; and - - b. produce, reproduce, and Share Adapted Material for - NonCommercial purposes only. - - 2. Exceptions and Limitations. For the avoidance of doubt, where - Exceptions and Limitations apply to Your use, this Public - License does not apply, and You do not need to comply with - its terms and conditions. - - 3. Term. The term of this Public License is specified in Section - 6(a). - - 4. Media and formats; technical modifications allowed. The - Licensor authorizes You to exercise the Licensed Rights in - all media and formats whether now known or hereafter created, - and to make technical modifications necessary to do so. The - Licensor waives and/or agrees not to assert any right or - authority to forbid You from making technical modifications - necessary to exercise the Licensed Rights, including - technical modifications necessary to circumvent Effective - Technological Measures. For purposes of this Public License, - simply making modifications authorized by this Section 2(a) - (4) never produces Adapted Material. - - 5. Downstream recipients. - - a. Offer from the Licensor -- Licensed Material. Every - recipient of the Licensed Material automatically - receives an offer from the Licensor to exercise the - Licensed Rights under the terms and conditions of this - Public License. - - b. Additional offer from the Licensor -- Adapted Material. - Every recipient of Adapted Material from You - automatically receives an offer from the Licensor to - exercise the Licensed Rights in the Adapted Material - under the conditions of the Adapter's License You apply. - - c. No downstream restrictions. You may not offer or impose - any additional or different terms or conditions on, or - apply any Effective Technological Measures to, the - Licensed Material if doing so restricts exercise of the - Licensed Rights by any recipient of the Licensed - Material. - - 6. No endorsement. Nothing in this Public License constitutes or - may be construed as permission to assert or imply that You - are, or that Your use of the Licensed Material is, connected - with, or sponsored, endorsed, or granted official status by, - the Licensor or others designated to receive attribution as - provided in Section 3(a)(1)(A)(i). - - b. Other rights. - - 1. Moral rights, such as the right of integrity, are not - licensed under this Public License, nor are publicity, - privacy, and/or other similar personality rights; however, to - the extent possible, the Licensor waives and/or agrees not to - assert any such rights held by the Licensor to the limited - extent necessary to allow You to exercise the Licensed - Rights, but not otherwise. - - 2. Patent and trademark rights are not licensed under this - Public License. - - 3. To the extent possible, the Licensor waives any right to - collect royalties from You for the exercise of the Licensed - Rights, whether directly or through a collecting society - under any voluntary or waivable statutory or compulsory - licensing scheme. In all other cases the Licensor expressly - reserves any right to collect such royalties, including when - the Licensed Material is used other than for NonCommercial - purposes. - - -Section 3 -- License Conditions. - -Your exercise of the Licensed Rights is expressly made subject to the -following conditions. - - a. Attribution. - - 1. If You Share the Licensed Material (including in modified - form), You must: - - a. retain the following if it is supplied by the Licensor - with the Licensed Material: - - i. identification of the creator(s) of the Licensed - Material and any others designated to receive - attribution, in any reasonable manner requested by - the Licensor (including by pseudonym if - designated); - - ii. a copyright notice; - - iii. a notice that refers to this Public License; - - iv. a notice that refers to the disclaimer of - warranties; - - v. a URI or hyperlink to the Licensed Material to the - extent reasonably practicable; - - b. indicate if You modified the Licensed Material and - retain an indication of any previous modifications; and - - c. indicate the Licensed Material is licensed under this - Public License, and include the text of, or the URI or - hyperlink to, this Public License. - - 2. You may satisfy the conditions in Section 3(a)(1) in any - reasonable manner based on the medium, means, and context in - which You Share the Licensed Material. For example, it may be - reasonable to satisfy the conditions by providing a URI or - hyperlink to a resource that includes the required - information. - 3. If requested by the Licensor, You must remove any of the - information required by Section 3(a)(1)(A) to the extent - reasonably practicable. - - b. ShareAlike. - - In addition to the conditions in Section 3(a), if You Share - Adapted Material You produce, the following conditions also apply. - - 1. The Adapter's License You apply must be a Creative Commons - license with the same License Elements, this version or - later, or a BY-NC-SA Compatible License. - - 2. You must include the text of, or the URI or hyperlink to, the - Adapter's License You apply. You may satisfy this condition - in any reasonable manner based on the medium, means, and - context in which You Share Adapted Material. - - 3. You may not offer or impose any additional or different terms - or conditions on, or apply any Effective Technological - Measures to, Adapted Material that restrict exercise of the - rights granted under the Adapter's License You apply. - - -Section 4 -- Sui Generis Database Rights. - -Where the Licensed Rights include Sui Generis Database Rights that -apply to Your use of the Licensed Material: - - a. for the avoidance of doubt, Section 2(a)(1) grants You the right - to extract, reuse, reproduce, and Share all or a substantial - portion of the contents of the database for NonCommercial purposes - only; - - b. if You include all or a substantial portion of the database - contents in a database in which You have Sui Generis Database - Rights, then the database in which You have Sui Generis Database - Rights (but not its individual contents) is Adapted Material, - including for purposes of Section 3(b); and - - c. You must comply with the conditions in Section 3(a) if You Share - all or a substantial portion of the contents of the database. - -For the avoidance of doubt, this Section 4 supplements and does not -replace Your obligations under this Public License where the Licensed -Rights include other Copyright and Similar Rights. - - -Section 5 -- Disclaimer of Warranties and Limitation of Liability. - - a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE - EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS - AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF - ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, - IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, - WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, - ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT - KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT - ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. - - b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE - TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, - NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, - INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, - COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR - USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR - DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR - IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. - - c. The disclaimer of warranties and limitation of liability provided - above shall be interpreted in a manner that, to the extent - possible, most closely approximates an absolute disclaimer and - waiver of all liability. - - -Section 6 -- Term and Termination. - - a. This Public License applies for the term of the Copyright and - Similar Rights licensed here. However, if You fail to comply with - this Public License, then Your rights under this Public License - terminate automatically. - - b. Where Your right to use the Licensed Material has terminated under - Section 6(a), it reinstates: - - 1. automatically as of the date the violation is cured, provided - it is cured within 30 days of Your discovery of the - violation; or - - 2. upon express reinstatement by the Licensor. - - For the avoidance of doubt, this Section 6(b) does not affect any - right the Licensor may have to seek remedies for Your violations - of this Public License. - - c. For the avoidance of doubt, the Licensor may also offer the - Licensed Material under separate terms or conditions or stop - distributing the Licensed Material at any time; however, doing so - will not terminate this Public License. - - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public - License. - - -Section 7 -- Other Terms and Conditions. - - a. The Licensor shall not be bound by any additional or different - terms or conditions communicated by You unless expressly agreed. - - b. Any arrangements, understandings, or agreements regarding the - Licensed Material not stated herein are separate from and - independent of the terms and conditions of this Public License. - - -Section 8 -- Interpretation. - - a. For the avoidance of doubt, this Public License does not, and - shall not be interpreted to, reduce, limit, restrict, or impose - conditions on any use of the Licensed Material that could lawfully - be made without permission under this Public License. - - b. To the extent possible, if any provision of this Public License is - deemed unenforceable, it shall be automatically reformed to the - minimum extent necessary to make it enforceable. If the provision - cannot be reformed, it shall be severed from this Public License - without affecting the enforceability of the remaining terms and - conditions. - - c. No term or condition of this Public License will be waived and no - failure to comply consented to unless expressly agreed to by the - Licensor. - - d. Nothing in this Public License constitutes or may be interpreted - as a limitation upon, or waiver of, any privileges and immunities - that apply to the Licensor or You, including from the legal - processes of any jurisdiction or authority. \ No newline at end of file +Any other piece of code is licensed as Apache License 2.0 as specified in each file. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 diff --git a/LICENSE-APACHE-2.0 b/LICENSE-APACHE-2.0 new file mode 100644 index 0000000000..cd482d8976 --- /dev/null +++ b/LICENSE-APACHE-2.0 @@ -0,0 +1,201 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all +other entities that control, are controlled by, or are under common +control with that entity. For the purposes of this definition, +"control" means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or +otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or +Object form, made available under the License, as indicated by a +copyright notice that is included in or attached to the work +(an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the purposes +of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, +the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including +the original version of the Work and any modifications or additions +to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner +or by an individual or Legal Entity authorized to submit on behalf of +the copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, +and issue tracking systems that are managed by, or on behalf of, the +Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work, +where such license applies only to those patent claims licensable +by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) +with the Work to which such Contribution(s) was submitted. If You +institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work +or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate +as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You +meet the following conditions: + +(a) You must give any other recipients of the Work or +Derivative Works a copy of this License; and + +(b) You must cause any modified files to carry prominent notices +stating that You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works +that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, +excluding those notices that do not pertain to any part of +the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained +within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one +of the following places: within a NOTICE text file distributed +as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, +within a display generated by the Derivative Works, if and +wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and +do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided +that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and +may provide additional or different license terms and conditions +for use, reproduction, or distribution of Your modifications, or +for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with +the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following +boilerplate notice, with the fields enclosed by brackets "[]" +replaced with your own identifying information. (Don't include +the brackets!) The text should be enclosed in the appropriate +comment syntax for the file format. We also recommend that a +file or class name and description of purpose be included on the +same "printed page" as the copyright notice for easier +identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-CC-BY-SA-4.0 b/LICENSE-CC-BY-SA-4.0 new file mode 100644 index 0000000000..63f44cc3ac --- /dev/null +++ b/LICENSE-CC-BY-SA-4.0 @@ -0,0 +1,360 @@ +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-NC-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution, NonCommercial, and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + m. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + n. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-NC-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. \ No newline at end of file diff --git a/README.md b/README.md index aec89d9a04..a6fc4e9e84 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ - [Add Custom Checks](#add-custom-checks) - [Third Party Integrations](#third-party-integrations) - [Full list of checks and groups](/LIST_OF_CHECKS_AND_GROUPS.md) +- [License](#license) ## Description @@ -428,3 +429,10 @@ In order to add any new check feel free to create a new extra check in the extra Javier Pecete has done an awesome job integrating Prowler with Telegram, you have more details here https://github.com/i4specete/ServerTelegramBot ### Cloud Security Suite The guys of SecurityFTW have added Prowler in their Cloud Security Suite along with other cool security tools https://github.com/SecurityFTW/cs-suite + +## License +All CIS based checks in the checks folder are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License. +The link to the license terms can be found at +https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode +Any other piece of code is licensed as Apache License 2.0 as specified in each file. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 diff --git a/checks/check11 b/checks/check11 index 751b981e70..98a906b0db 100644 --- a/checks/check11 +++ b/checks/check11 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check11="1.1,1.01" CHECK_TITLE_check11="[check11] Avoid the use of the root account (Scored)" CHECK_SCORED_check11="SCORED" diff --git a/checks/check110 b/checks/check110 index 0432aa620e..1ab1fa3beb 100644 --- a/checks/check110 +++ b/checks/check110 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check110="1.10" CHECK_TITLE_check110="[check110] Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" CHECK_SCORED_check110="SCORED" diff --git a/checks/check111 b/checks/check111 index 9ef36c236b..29a015ff29 100644 --- a/checks/check111 +++ b/checks/check111 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check111="1.11" CHECK_TITLE_check111="[check111] Ensure IAM password policy expires passwords within 90 days or less (Scored)" CHECK_SCORED_check111="SCORED" diff --git a/checks/check112 b/checks/check112 index 611559801e..b4bbcb53d5 100644 --- a/checks/check112 +++ b/checks/check112 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check112="1.12" CHECK_TITLE_check112="[check112] Ensure no root account access key exists (Scored)" CHECK_SCORED_check112="SCORED" diff --git a/checks/check113 b/checks/check113 index 5b52c77c94..668bf25bd7 100644 --- a/checks/check113 +++ b/checks/check113 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check113="1.13" CHECK_TITLE_check113="[check113] Ensure MFA is enabled for the root account (Scored)" CHECK_SCORED_check113="SCORED" diff --git a/checks/check114 b/checks/check114 index c6a81a6a5d..3f386543b1 100644 --- a/checks/check114 +++ b/checks/check114 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check114="1.14" CHECK_TITLE_check114="[check114] Ensure hardware MFA is enabled for the root account (Scored)" CHECK_SCORED_check114="SCORED" diff --git a/checks/check115 b/checks/check115 index 41b7891505..08d1089177 100644 --- a/checks/check115 +++ b/checks/check115 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check115="1.15" CHECK_TITLE_check115="[check115] Ensure security questions are registered in the AWS account (Not Scored)" CHECK_SCORED_check115="SCORED" diff --git a/checks/check116 b/checks/check116 index b8dbde0113..6dbbc4c5dc 100644 --- a/checks/check116 +++ b/checks/check116 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check116="1.16" CHECK_TITLE_check116="[check116] Ensure IAM policies are attached only to groups or roles (Scored)" CHECK_SCORED_check116="SCORED" diff --git a/checks/check117 b/checks/check117 index bace657574..4550c1a1d1 100644 --- a/checks/check117 +++ b/checks/check117 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check117="1.17" CHECK_TITLE_check117="[check117] Enable detailed billing (Scored)" CHECK_SCORED_check117="SCORED" diff --git a/checks/check118 b/checks/check118 index abe009ee37..d793c14446 100644 --- a/checks/check118 +++ b/checks/check118 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check118="1.18" CHECK_TITLE_check118="[check118] Ensure IAM Master and IAM Manager roles are active (Scored)" CHECK_SCORED_check118="SCORED" diff --git a/checks/check119 b/checks/check119 index f0ec82e1ba..6593fc30b7 100644 --- a/checks/check119 +++ b/checks/check119 @@ -1,7 +1,17 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check119="1.19" CHECK_TITLE_check119="[check119] Maintain current contact details (Scored)" CHECK_SCORED_check119="SCORED" -CHECK_ALTERNATE_check119="check119" +CHECK_ALTERNATE_check119="check119" check119(){ # "Maintain current contact details (Scored)" diff --git a/checks/check12 b/checks/check12 index 3fd8e24f1f..a96aa30a5a 100644 --- a/checks/check12 +++ b/checks/check12 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check12="1.2,1.02" CHECK_TITLE_check12="[check12] Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" CHECK_SCORED_check12="SCORED" diff --git a/checks/check120 b/checks/check120 index ba15cd21e7..b18bb767ec 100644 --- a/checks/check120 +++ b/checks/check120 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check120="1.20" CHECK_TITLE_check120="[check120] Ensure security contact information is registered (Scored)" CHECK_SCORED_check120="SCORED" diff --git a/checks/check121 b/checks/check121 index 01b4014e45..c70510d910 100644 --- a/checks/check121 +++ b/checks/check121 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check121="1.21" CHECK_TITLE_check121="[check121] Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" CHECK_SCORED_check121="NOT_SCORED" diff --git a/checks/check122 b/checks/check122 index 3c898a162e..67c93c7e35 100644 --- a/checks/check122 +++ b/checks/check122 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check122="1.22" CHECK_TITLE_check122="[check122] Ensure a support role has been created to manage incidents with AWS Support (Scored)" CHECK_SCORED_check122="SCORED" diff --git a/checks/check123 b/checks/check123 index fa60d819d8..db96a7373d 100644 --- a/checks/check123 +++ b/checks/check123 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check123="1.23" CHECK_TITLE_check123="[check123] Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" CHECK_SCORED_check123="NOT_SCORED" diff --git a/checks/check124 b/checks/check124 index f9ca394352..0f99d55d3b 100644 --- a/checks/check124 +++ b/checks/check124 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check124="1.24" CHECK_TITLE_check124="[check124] Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" CHECK_SCORED_check124="SCORED" diff --git a/checks/check13 b/checks/check13 index c52a248005..18b4ed6f69 100644 --- a/checks/check13 +++ b/checks/check13 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check13="1.3,1.03" CHECK_TITLE_check13="[check13] Ensure credentials unused for 90 days or greater are disabled (Scored)" CHECK_SCORED_check13="SCORED" diff --git a/checks/check14 b/checks/check14 index ab1b823c65..1ae4502f1f 100644 --- a/checks/check14 +++ b/checks/check14 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check14="1.4,1.04" CHECK_TITLE_check14="[check14] Ensure access keys are rotated every 90 days or less (Scored)" CHECK_SCORED_check14="SCORED" diff --git a/checks/check15 b/checks/check15 index 998ed69865..afc053ff13 100644 --- a/checks/check15 +++ b/checks/check15 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check15="1.5,1.05" CHECK_TITLE_check15="[check15] Ensure IAM password policy requires at least one uppercase letter (Scored)" CHECK_SCORED_check15="SCORED" diff --git a/checks/check16 b/checks/check16 index 04cb5d8954..b846e03d59 100644 --- a/checks/check16 +++ b/checks/check16 @@ -1,8 +1,18 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check16="1.6,1.06" CHECK_TITLE_check16="[check16] Ensure IAM password policy require at least one lowercase letter (Scored)" CHECK_SCORED_check16="SCORED" CHECK_ALTERNATE_check106="check16" - + check16(){ # "Ensure IAM password policy require at least one lowercase letter (Scored)" COMMAND16=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireLowercaseCharacters' 2> /dev/null) # must be true diff --git a/checks/check17 b/checks/check17 index b4dab41172..8ee31da235 100644 --- a/checks/check17 +++ b/checks/check17 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check17="1.7,1.07" CHECK_TITLE_check17="[check17] Ensure IAM password policy require at least one symbol (Scored)" CHECK_SCORED_check17="SCORED" diff --git a/checks/check18 b/checks/check18 index 4378ea889e..62ebc22c88 100644 --- a/checks/check18 +++ b/checks/check18 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check18="1.8,1.08" CHECK_TITLE_check18="[check18] Ensure IAM password policy require at least one number (Scored)" CHECK_SCORED_check18="SCORED" diff --git a/checks/check19 b/checks/check19 index b367556c2a..57f184607a 100644 --- a/checks/check19 +++ b/checks/check19 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check19="1.9,1.09" CHECK_TITLE_check19="[check19] Ensure IAM password policy requires minimum length of 14 or greater (Scored)" CHECK_SCORED_check19="SCORED" diff --git a/checks/check21 b/checks/check21 index 56bc5fd0ce..82d6c9042d 100644 --- a/checks/check21 +++ b/checks/check21 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check21="2.1,2.01" CHECK_TITLE_check21="[check21] Ensure CloudTrail is enabled in all regions (Scored)" CHECK_SCORED_check21="SCORED" diff --git a/checks/check22 b/checks/check22 index 0506228c0c..3badd579ff 100644 --- a/checks/check22 +++ b/checks/check22 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check22="2.2,2.02" CHECK_TITLE_check22="[check22] Ensure CloudTrail log file validation is enabled (Scored)" CHECK_SCORED_check22="SCORED" diff --git a/checks/check23 b/checks/check23 index f7cea4e7f7..e79a2924f6 100644 --- a/checks/check23 +++ b/checks/check23 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check23="2.3,2.03" CHECK_TITLE_check23="[check23] Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" CHECK_SCORED_check23="SCORED" diff --git a/checks/check24 b/checks/check24 index 84decf74fe..89b2a966d8 100644 --- a/checks/check24 +++ b/checks/check24 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check24="2.4,2.04" CHECK_TITLE_check24="[check24] Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" CHECK_SCORED_check24="SCORED" diff --git a/checks/check25 b/checks/check25 index 2544ef1639..be0ff7cbb8 100644 --- a/checks/check25 +++ b/checks/check25 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check25="2.5,2.05" CHECK_TITLE_check25="[check25] Ensure AWS Config is enabled in all regions (Scored)" CHECK_SCORED_check25="SCORED" diff --git a/checks/check26 b/checks/check26 index dc9d3b399b..7cc86dce29 100644 --- a/checks/check26 +++ b/checks/check26 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check26="2.6,2.06" CHECK_TITLE_check26="[check26] Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" CHECK_SCORED_check26="SCORED" diff --git a/checks/check27 b/checks/check27 index 06036a0d6f..20bd1258f9 100644 --- a/checks/check27 +++ b/checks/check27 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check27="2.7,2.07" CHECK_TITLE_check27="[check27] Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" CHECK_SCORED_check27="SCORED" diff --git a/checks/check28 b/checks/check28 index 3784a8b132..06e93d7524 100644 --- a/checks/check28 +++ b/checks/check28 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check28="2.8,2.08" CHECK_TITLE_check28="[check28] Ensure rotation for customer created CMKs is enabled (Scored)" CHECK_SCORED_check28="SCORED" diff --git a/checks/check31 b/checks/check31 index f3a92e6200..5a2b051212 100644 --- a/checks/check31 +++ b/checks/check31 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check31="3.1,3.01" CHECK_TITLE_check31="[check31] Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" CHECK_SCORED_check31="SCORED" diff --git a/checks/check310 b/checks/check310 index 70c0cf289f..e4e29128ab 100644 --- a/checks/check310 +++ b/checks/check310 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check310="3.10" CHECK_TITLE_check310="[check310] Ensure a log metric filter and alarm exist for security group changes (Scored)" CHECK_SCORED_check310="SCORED" diff --git a/checks/check311 b/checks/check311 index e6744e02a0..8dc05712fc 100644 --- a/checks/check311 +++ b/checks/check311 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check311="3.11" CHECK_TITLE_check311="[check311] Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)" CHECK_SCORED_check311="SCORED" diff --git a/checks/check312 b/checks/check312 index 6c0a070669..f1f29b84c0 100644 --- a/checks/check312 +++ b/checks/check312 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check312="3.12" CHECK_TITLE_check312="[check312] Ensure a log metric filter and alarm exist for changes to network gateways (Scored)" CHECK_SCORED_check312="SCORED" diff --git a/checks/check313 b/checks/check313 index 54ebef55b3..5a9fed6f88 100644 --- a/checks/check313 +++ b/checks/check313 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check313="3.13" CHECK_TITLE_check313="[check313] Ensure a log metric filter and alarm exist for route table changes (Scored)" CHECK_SCORED_check313="SCORED" diff --git a/checks/check314 b/checks/check314 index e78aecb4d1..9ef23dc081 100644 --- a/checks/check314 +++ b/checks/check314 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check314="3.14" CHECK_TITLE_check314="[check314] Ensure a log metric filter and alarm exist for VPC changes (Scored)" CHECK_SCORED_check314="SCORED" diff --git a/checks/check315 b/checks/check315 index df9c8ceb47..cec444cd96 100644 --- a/checks/check315 +++ b/checks/check315 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check315="3.15" CHECK_TITLE_check315="[check315] Ensure appropriate subscribers to each SNS topic (Not Scored)" CHECK_SCORED_check315="SCORED" diff --git a/checks/check32 b/checks/check32 index 35ceeb6d34..d6a17789ed 100644 --- a/checks/check32 +++ b/checks/check32 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check32="3.2,3.02" CHECK_TITLE_check32="[check32] Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)" CHECK_SCORED_check32="SCORED" diff --git a/checks/check33 b/checks/check33 index cb09c9bb50..bec9d695e6 100644 --- a/checks/check33 +++ b/checks/check33 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check33="3.3,3.03" CHECK_TITLE_check33="[check33] Ensure a log metric filter and alarm exist for usage of root account (Scored)" CHECK_SCORED_check33="SCORED" diff --git a/checks/check34 b/checks/check34 index c5a53224f7..57ce435e87 100644 --- a/checks/check34 +++ b/checks/check34 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check34="3.4,3.04" CHECK_TITLE_check34="[check34] Ensure a log metric filter and alarm exist for IAM policy changes (Scored)" CHECK_SCORED_check34="SCORED" diff --git a/checks/check35 b/checks/check35 index a91679abd8..c41aafd4d8 100644 --- a/checks/check35 +++ b/checks/check35 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check35="3.5,3.05" CHECK_TITLE_check35="[check35] Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)" CHECK_SCORED_check35="SCORED" diff --git a/checks/check36 b/checks/check36 index a32dc1029b..8b54cd8797 100644 --- a/checks/check36 +++ b/checks/check36 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check36="3.6,3.06" CHECK_TITLE_check36="[check36] Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)" CHECK_SCORED_check36="SCORED" diff --git a/checks/check37 b/checks/check37 index 36f004812d..fc017174bd 100644 --- a/checks/check37 +++ b/checks/check37 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check37="3.7,3.07" CHECK_TITLE_check37="[check37] Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)" CHECK_SCORED_check37="SCORED" diff --git a/checks/check38 b/checks/check38 index 87783438d2..8d06f323ba 100644 --- a/checks/check38 +++ b/checks/check38 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check38="3.8,3.08" CHECK_TITLE_check38="[check38] Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)" CHECK_SCORED_check38="SCORED" diff --git a/checks/check39 b/checks/check39 index deb7714c3b..3c9b2ba69c 100644 --- a/checks/check39 +++ b/checks/check39 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check39="3.9,3.09" CHECK_TITLE_check39="[check39] Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)" CHECK_SCORED_check39="SCORED" diff --git a/checks/check41 b/checks/check41 index 74d986d7cd..5e7aceafab 100644 --- a/checks/check41 +++ b/checks/check41 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check41="4.1,4.01" CHECK_TITLE_check41="[check41] Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)" CHECK_SCORED_check41="SCORED" diff --git a/checks/check42 b/checks/check42 index 31e9f789ee..d2330f84f4 100644 --- a/checks/check42 +++ b/checks/check42 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check42="4.2,4.02" CHECK_TITLE_check42="[check42] Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)" CHECK_SCORED_check42="SCORED" diff --git a/checks/check43 b/checks/check43 index 257442dbdc..c0223f828b 100644 --- a/checks/check43 +++ b/checks/check43 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check43="4.3,4.03" CHECK_TITLE_check43="[check43] Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" CHECK_SCORED_check43="SCORED" diff --git a/checks/check44 b/checks/check44 index 4b0d347842..d3a5cef5f5 100644 --- a/checks/check44 +++ b/checks/check44 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check44="4.4,4.04" CHECK_TITLE_check44="[check44] Ensure the default security group of every VPC restricts all traffic (Scored)" CHECK_SCORED_check44="SCORED" diff --git a/checks/check45 b/checks/check45 index 4e01e6c958..7bddfa61e2 100644 --- a/checks/check45 +++ b/checks/check45 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + CHECK_ID_check45="4.5,4.05" CHECK_TITLE_check45="[check45] Ensure routing tables for VPC peering are \"least access\" (Not Scored)" CHECK_SCORED_check45="NOT_SCORED" diff --git a/checks/check_extra71 b/checks/check_extra71 index 25e60788e7..fcba890de8 100644 --- a/checks/check_extra71 +++ b/checks/check_extra71 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra71="7.1,7.01" CHECK_TITLE_extra71="[extra71] Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra71="NOT_SCORED" diff --git a/checks/check_extra710 b/checks/check_extra710 index 940324bb8c..957c450267 100644 --- a/checks/check_extra710 +++ b/checks/check_extra710 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra710="7.10" CHECK_TITLE_extra710="[extra710] Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra710="NOT_SCORED" diff --git a/checks/check_extra711 b/checks/check_extra711 index 1e0faa52db..a8e558f00a 100644 --- a/checks/check_extra711 +++ b/checks/check_extra711 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra711="7.11" CHECK_TITLE_extra711="[extra711] Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra711="NOT_SCORED" diff --git a/checks/check_extra712 b/checks/check_extra712 index 86126c9afd..9194dac446 100644 --- a/checks/check_extra712 +++ b/checks/check_extra712 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra712="7.12" CHECK_TITLE_extra712="[extra712] Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra712="NOT_SCORED" diff --git a/checks/check_extra713 b/checks/check_extra713 index 86aecfe4a3..ffd23b0ac1 100644 --- a/checks/check_extra713 +++ b/checks/check_extra713 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra713="7.13" CHECK_TITLE_extra713="[extra713] Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra713="NOT_SCORED" diff --git a/checks/check_extra714 b/checks/check_extra714 index 6c0cf2c5a7..7b13cc447c 100644 --- a/checks/check_extra714 +++ b/checks/check_extra714 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra714="7.14" CHECK_TITLE_extra714="[extra714] Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra714="NOT_SCORED" diff --git a/checks/check_extra715 b/checks/check_extra715 index 88a417152f..b49c718f79 100644 --- a/checks/check_extra715 +++ b/checks/check_extra715 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra715="7.15" CHECK_TITLE_extra715="[extra715] Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra715="NOT_SCORED" diff --git a/checks/check_extra716 b/checks/check_extra716 index 3d85d53cde..fe3e26f146 100644 --- a/checks/check_extra716 +++ b/checks/check_extra716 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra716="7.16" CHECK_TITLE_extra716="[extra716] Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra716="NOT_SCORED" diff --git a/checks/check_extra717 b/checks/check_extra717 index 0c36dda432..d141bd9f7b 100644 --- a/checks/check_extra717 +++ b/checks/check_extra717 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra717="7.17" CHECK_TITLE_extra717="[extra717] Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra717="NOT_SCORED" diff --git a/checks/check_extra718 b/checks/check_extra718 index 927f3d7535..e8b245ab11 100644 --- a/checks/check_extra718 +++ b/checks/check_extra718 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra718="7.18" CHECK_TITLE_extra718="[extra718] Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra718="NOT_SCORED" diff --git a/checks/check_extra719 b/checks/check_extra719 index fddc65fc57..2245d661a9 100644 --- a/checks/check_extra719 +++ b/checks/check_extra719 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra719="7.19" CHECK_TITLE_extra719="[extra719] Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra719="NOT_SCORED" diff --git a/checks/check_extra72 b/checks/check_extra72 index 2523822cda..4575bddda7 100644 --- a/checks/check_extra72 +++ b/checks/check_extra72 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra72="7.2,7.02" CHECK_TITLE_extra72="[extra72] Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra72="NOT_SCORED" diff --git a/checks/check_extra720 b/checks/check_extra720 index af9f63fe22..1e1b1255be 100644 --- a/checks/check_extra720 +++ b/checks/check_extra720 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra720="7.20" CHECK_TITLE_extra720="[extra720] Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra720="NOT_SCORED" diff --git a/checks/check_extra721 b/checks/check_extra721 index 9a9f1b81ca..b8bef0e485 100644 --- a/checks/check_extra721 +++ b/checks/check_extra721 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra721="7.21" CHECK_TITLE_extra721="[extra721] Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra721="NOT_SCORED" diff --git a/checks/check_extra722 b/checks/check_extra722 index b08c5ba6e4..426ab785c0 100644 --- a/checks/check_extra722 +++ b/checks/check_extra722 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra722="7.22" CHECK_TITLE_extra722="[extra722] Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra722="NOT_SCORED" diff --git a/checks/check_extra723 b/checks/check_extra723 index 1c9ef44716..7065508fe4 100644 --- a/checks/check_extra723 +++ b/checks/check_extra723 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra723="7.23" CHECK_TITLE_extra723="[extra723] Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra723="NOT_SCORED" diff --git a/checks/check_extra724 b/checks/check_extra724 index fc3968441a..67a2aa5485 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra724="7.24" CHECK_TITLE_extra724="[extra724] Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra724="NOT_SCORED" diff --git a/checks/check_extra725 b/checks/check_extra725 index d8076b05bc..46333080e5 100644 --- a/checks/check_extra725 +++ b/checks/check_extra725 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. # CHECK_ID_extra725="7.25" # CHECK_TITLE_extra725="[extra725] Check if S3 buckets have Object-level logging enabled (Not Scored) (Not part of CIS benchmark)" # CHECK_SCORED_extra725="NOT_SCORED" diff --git a/checks/check_extra726 b/checks/check_extra726 index 6d77d65bfb..50954b82a5 100644 --- a/checks/check_extra726 +++ b/checks/check_extra726 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. # CHECK_ID_extra726="7.26" # CHECK_TITLE_extra726="[extra726] Check Trusted Advisor for errors and warnings (Not Scored) (Not part of CIS benchmark)" # CHECK_SCORED_extra726="NOT_SCORED" diff --git a/checks/check_extra73 b/checks/check_extra73 index 0d8e3e809b..116ce7e60e 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra73="7.3,7.03" CHECK_TITLE_extra73="[extra73] Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra73="NOT_SCORED" diff --git a/checks/check_extra74 b/checks/check_extra74 index d106d4440d..f8df6e5a94 100644 --- a/checks/check_extra74 +++ b/checks/check_extra74 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra74="7.4,7.04" CHECK_TITLE_extra74="[extra74] Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra74="NOT_SCORED" diff --git a/checks/check_extra75 b/checks/check_extra75 index 20aba2357c..029fb461b3 100644 --- a/checks/check_extra75 +++ b/checks/check_extra75 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra75="7.5,7.05" CHECK_TITLE_extra75="[extra75] Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra75="NOT_SCORED" diff --git a/checks/check_extra76 b/checks/check_extra76 index 18bb4de2e6..bb8e5d53f7 100644 --- a/checks/check_extra76 +++ b/checks/check_extra76 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra76="7.6,7.06" CHECK_TITLE_extra76="[extra75] Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra76="NOT_SCORED" diff --git a/checks/check_extra77 b/checks/check_extra77 index ac726e8e9c..3bf3225173 100644 --- a/checks/check_extra77 +++ b/checks/check_extra77 @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + CHECK_ID_extra77="7.7,7.07" CHECK_TITLE_extra77="[extra77] Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra77="NOT_SCORED" diff --git a/checks/check_extra78 b/checks/check_extra78 index b2ff995494..0b0802cb5f 100644 --- a/checks/check_extra78 +++ b/checks/check_extra78 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra78="7.8,7.08" CHECK_TITLE_extra78="[extra78] Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra78="NOT_SCORED" diff --git a/checks/check_extra79 b/checks/check_extra79 index 45c58a0cc0..d3ee4b1d74 100644 --- a/checks/check_extra79 +++ b/checks/check_extra79 @@ -1,3 +1,15 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. CHECK_ID_extra79="7.9,7.09" CHECK_TITLE_extra79="[extra79] Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra79="NOT_SCORED" diff --git a/checks/check_sample b/checks/check_sample index 024dbd56bf..78c2e29fb1 100644 --- a/checks/check_sample +++ b/checks/check_sample @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + # CHECK_ID_checkN="N.N" # CHECK_TITLE_checkN="[checkN] Description (Not Scored) (Not part of CIS benchmark)" # CHECK_SCORED_checkN="NOT_SCORED" diff --git a/groups/group1_iam b/groups/group1_iam index aa809806a0..006d4c5318 100644 --- a/groups/group1_iam +++ b/groups/group1_iam @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + GROUP_ID[1]='group1' GROUP_NUMBER[1]='1.0' GROUP_TITLE[1]='Identity and Access Management - [group1] **********************' diff --git a/groups/group2_logging b/groups/group2_logging index c0ea6c3591..4b5af93574 100644 --- a/groups/group2_logging +++ b/groups/group2_logging @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + GROUP_ID[2]='group2' GROUP_NUMBER[2]='2.0' GROUP_TITLE[2]='Logging - [group2] *********************************************' diff --git a/groups/group3_monitoring b/groups/group3_monitoring index 61ab3d9c05..6f4263ea16 100644 --- a/groups/group3_monitoring +++ b/groups/group3_monitoring @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + GROUP_ID[3]='group3' GROUP_NUMBER[3]='3.0' GROUP_TITLE[3]='Monitoring - [group3] ******************************************' diff --git a/groups/group4_networking b/groups/group4_networking index 8a1029d1e4..3faf6e0dbc 100644 --- a/groups/group4_networking +++ b/groups/group4_networking @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + GROUP_ID[4]="group4" GROUP_NUMBER[4]="4.0" GROUP_TITLE[4]="Networking - [group4] ******************************************" diff --git a/groups/group5_cislevel1 b/groups/group5_cislevel1 index 663df5e20c..db7413de2c 100644 --- a/groups/group5_cislevel1 +++ b/groups/group5_cislevel1 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + GROUP_ID[5]='cislevel1' GROUP_NUMBER[5]='5.0' GROUP_TITLE[5]='CIS Level 1 - [cislevel1] **************************************' diff --git a/groups/group6_cislevel2 b/groups/group6_cislevel2 index eeb61521c3..b1394b3f2f 100644 --- a/groups/group6_cislevel2 +++ b/groups/group6_cislevel2 @@ -1,3 +1,13 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (c) by Toni de la Fuente +# +# This Prowler check is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. +# +# You should have received a copy of the license along with this +# work. If not, see . + GROUP_ID[6]='cislevel2' GROUP_NUMBER[6]='6.0' GROUP_TITLE[6]='CIS Level 2 - [cislevel2] **************************************' diff --git a/groups/group7_extras b/groups/group7_extras index 0690022f6d..fe8dbf30f3 100644 --- a/groups/group7_extras +++ b/groups/group7_extras @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + GROUP_ID[7]='extras' GROUP_NUMBER[7]='7.0' GROUP_TITLE[7]='Extras - [extras] **********************************************' diff --git a/groups/group8_forensics b/groups/group8_forensics index 1f7e6d68e5..268c7711cf 100644 --- a/groups/group8_forensics +++ b/groups/group8_forensics @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + GROUP_ID[8]='forensics-ready' GROUP_NUMBER[8]='8.0' GROUP_TITLE[8]='Forensics Readiness - [forensics-ready] ************************' diff --git a/groups/group9_gdpr b/groups/group9_gdpr index 9e5b5658cb..774c30a6ca 100644 --- a/groups/group9_gdpr +++ b/groups/group9_gdpr @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + GROUP_ID[9]='gdpr' GROUP_NUMBER[9]='8.0' GROUP_TITLE[9]='GDPR Readiness - [gdpr] ****************************************' diff --git a/groups/groupN_sample b/groups/groupN_sample index e9f44685d5..ceff97025c 100644 --- a/groups/groupN_sample +++ b/groups/groupN_sample @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + GROUP_ID[9]='my-custom-group' GROUP_NUMBER[9]='9.0' GROUP_TITLE[9]='My Custom Group - [my-custom-group] ****************************' diff --git a/include/aws_profile_loader b/include/aws_profile_loader index 4e7ea2a357..3cd2135054 100644 --- a/include/aws_profile_loader +++ b/include/aws_profile_loader @@ -1,3 +1,17 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + + # It checks -p optoin first and use it as profile, if not -p provided then # check environment variables and if not, it checks and loads credentials from # instance profile (metadata server) if runs in an EC2 instance diff --git a/include/awscli_detector b/include/awscli_detector index 6794be3523..40fb03bad8 100644 --- a/include/awscli_detector +++ b/include/awscli_detector @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + # AWS-CLI detector variable AWSCLI=$(which aws) if [ -z "${AWSCLI}" ]; then diff --git a/include/banner b/include/banner index 3e39ed2c12..6e1086b30e 100644 --- a/include/banner +++ b/include/banner @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + prowlerBanner() { if [[ $BANNER != "0" ]]; then echo -e "$CYAN _" diff --git a/include/colors b/include/colors index a8e63f809b..b7b72076b1 100644 --- a/include/colors +++ b/include/colors @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + if [[ $MODE != "mono" && $MODE != "text" && $MODE != "csv" ]]; then echo "" echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, or csv." diff --git a/include/credentials_report b/include/credentials_report index 4a84a3c280..cb51cd4df6 100644 --- a/include/credentials_report +++ b/include/credentials_report @@ -1,3 +1,16 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + # Generate Credential Report genCredReport() { textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT" diff --git a/include/csv_header b/include/csv_header index bad90f37a8..abd1b8c480 100644 --- a/include/csv_header +++ b/include/csv_header @@ -1,3 +1,17 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + + printCsvHeader() { >&2 echo "" >&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM" diff --git a/include/os_detector b/include/os_detector index d36c07ce59..7c4a528a28 100644 --- a/include/os_detector +++ b/include/os_detector @@ -1,3 +1,17 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + + # Functions to manage dates depending on OS if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) diff --git a/include/outputs b/include/outputs index d98ea1277a..ac70ce07d3 100644 --- a/include/outputs +++ b/include/outputs @@ -1,4 +1,17 @@ -## Output formatting functions +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +# Output formatting functions textPass(){ if [[ "$MODE" == "csv" ]]; then if [[ $2 ]]; then diff --git a/include/whoami b/include/whoami index 9f77e4bd5a..eaf98c44d7 100644 --- a/include/whoami +++ b/include/whoami @@ -1,3 +1,17 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + + # Get whoami in AWS, who is the user running this shell script getWhoami(){ ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"') diff --git a/prowler b/prowler index 415c559c2a..c9965f28b7 100755 --- a/prowler +++ b/prowler @@ -1,17 +1,24 @@ #!/usr/bin/env bash -# Prowler is a tool that provides automate auditing and hardening guidance of an AWS account. -# It is based on AWS-CLI commands. It follows guidelines present in the CIS Amazon -# Web Services Foundations Benchmark at: +# Copyright 2018 Toni de la Fuente + +# Prowler is a tool that provides automate auditing and hardening guidance of an +# AWS account. It is based on AWS-CLI commands. It follows some guidelines +# present in the CIS Amazon Web Services Foundations Benchmark at: # https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf -# This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 -# International Public License. The link to the license terms can be found at +# Contact the author at https://blyx.com/contact +# and open issues or ask questions at https://github.com/toniblyx/prowler + + +# All CIS based checks in checks folder are licensed under a Creative Commons +# Attribution-NonCommercial-ShareAlike 4.0 International Public License. +# The link to the license terms can be found at # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode # -# Author: Toni de la Fuente - @ToniBlyx - https://blyx.com/contact - -# http://prowler.cloud +# Any other piece of code is licensed as Apache License 2.0 as specified in +# each file. You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 # Prowler - Iron Maiden # @@ -42,7 +49,6 @@ usage(){ echo " USAGE: `basename $0` [ -p -r -h ] - Options: -p specify your AWS profile to use (i.e.: default) -r specify an AWS region to direct API requests to From 7d510b11b2889acad779297b2a3983af16093e09 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 9 Apr 2018 15:41:55 -0400 Subject: [PATCH 31/41] disable concurrency checks due API limits --- checks/check_extra73 | 118 +++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 37 deletions(-) diff --git a/checks/check_extra73 b/checks/check_extra73 index 116ce7e60e..b666ff3569 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -18,45 +18,89 @@ CHECK_ALTERNATE_check73="extra73" CHECK_ALTERNATE_check703="extra73" extra73(){ + bucket=$1 textInfo "Looking for open S3 Buckets (ACLs and Policies) in all regions... " ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' --profile $PROFILE --region $REGION --output text) for bucket in $ALL_BUCKETS_LIST; do - extra73Thread $bucket & + BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket --profile $PROFILE --region $REGION --output text) + if [[ "None" == $BUCKET_LOCATION ]]; then + BUCKET_LOCATION="us-east-1" + fi + if [[ "EU" == $BUCKET_LOCATION ]]; then + BUCKET_LOCATION="eu-west-1" + fi + # check if AllUsers is in the ACL as Grantee + CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE) + CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL) + # check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only + CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE) + CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL) + # to prevent error NoSuchBucketPolicy first clean the output controlling stderr + TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX) + $AWSCLI s3api get-bucket-policy --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null + # check if the S3 policy has Principal as * + CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*) + if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then + if [[ $CHECK_BUCKET_ALLUSERS_ACL ]];then + textFail "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" + fi + if [[ $CHECK_BUCKET_AUTHUSERS_ACL ]];then + textFail "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" + fi + if [[ $CHECK_BUCKET_ALLUSERS_POLICY ]];then + textFail "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" + fi + else + textPass "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" + fi + rm -fr $TEMP_POLICY_FILE done - wait -} -extra73Thread(){ - bucket=$1 - BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket --profile $PROFILE --region $REGION --output text) - if [[ "None" == $BUCKET_LOCATION ]]; then - BUCKET_LOCATION="us-east-1" - fi - if [[ "EU" == $BUCKET_LOCATION ]]; then - BUCKET_LOCATION="eu-west-1" - fi - # check if AllUsers is in the ACL as Grantee - CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE) - CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL) - # check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only - CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE) - CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL) - # to prevent error NoSuchBucketPolicy first clean the output controlling stderr - TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX) - $AWSCLI s3api get-bucket-policy --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null - # check if the S3 policy has Principal as * - CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*) - if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then - if [[ $CHECK_BUCKET_ALLUSERS_ACL ]];then - textFail "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" - fi - if [[ $CHECK_BUCKET_AUTHUSERS_ACL ]];then - textFail "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" - fi - if [[ $CHECK_BUCKET_ALLUSERS_POLICY ]];then - textFail "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" - fi - else - textPass "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" - fi - rm -fr $TEMP_POLICY_FILE } + +# Then implementation below makes pararel checks but can reach AWS API limits +# and eventually doesn't work as expected + +# extra73(){ +# textTitle "$ID73" "$TITLE73" "NOT_SCORED" "EXTRA" +# textNotice "Looking for open S3 Buckets (ACLs and Policies) in all regions... " +# ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' --profile $PROFILE --region $REGION --output text) +# for bucket in $ALL_BUCKETS_LIST; do +# extra73Thread $bucket & +# done +# wait +# } +# extra73Thread(){ +# bucket=$1 +# BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket --profile $PROFILE --region $REGION --output text) +# if [[ "None" == $BUCKET_LOCATION ]]; then +# BUCKET_LOCATION="us-east-1" +# fi +# if [[ "EU" == $BUCKET_LOCATION ]]; then +# BUCKET_LOCATION="eu-west-1" +# fi +# # check if AllUsers is in the ACL as Grantee +# CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE) +# CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL) +# # check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only +# CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE) +# CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL) +# # to prevent error NoSuchBucketPolicy first clean the output controlling stderr +# TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX) +# $AWSCLI s3api get-bucket-policy --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null +# # check if the S3 policy has Principal as * +# CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*) +# if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then +# if [[ $CHECK_BUCKET_ALLUSERS_ACL ]];then +# textWarn "$BUCKET_LOCATION: $bucket bucket is open to the Internet (Everyone) with permissions: $CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE" "$regx" +# fi +# if [[ $CHECK_BUCKET_AUTHUSERS_ACL ]];then +# textWarn "$BUCKET_LOCATION: $bucket bucket is open to Authenticated users (Any AWS user) with permissions: $CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE" "$regx" +# fi +# if [[ $CHECK_BUCKET_ALLUSERS_POLICY ]];then +# textWarn "$BUCKET_LOCATION: $bucket bucket policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx" +# fi +# else +# textOK "$BUCKET_LOCATION: $bucket bucket is not open" "$regx" +# fi +# rm -fr $TEMP_POLICY_FILE +# } From 168ccffaf4dcdcb9b6d87acfdaf439c4af29e1a0 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 9 Apr 2018 15:55:07 -0400 Subject: [PATCH 32/41] disable concurrency queries due API limits --- checks/check_extra73 | 1 - 1 file changed, 1 deletion(-) diff --git a/checks/check_extra73 b/checks/check_extra73 index b666ff3569..8256915e3a 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -18,7 +18,6 @@ CHECK_ALTERNATE_check73="extra73" CHECK_ALTERNATE_check703="extra73" extra73(){ - bucket=$1 textInfo "Looking for open S3 Buckets (ACLs and Policies) in all regions... " ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' --profile $PROFILE --region $REGION --output text) for bucket in $ALL_BUCKETS_LIST; do From 25cd2202a7b9cafec2bd31994fe6fa2f8a9fbc1b Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 10 Apr 2018 16:17:53 -0400 Subject: [PATCH 33/41] added check extra725 S3 object-level logging --- checks/check_extra725 | 94 ++++++++++++++++++++++--------------------- groups/group9_gdpr | 6 +++ 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/checks/check_extra725 b/checks/check_extra725 index 46333080e5..4b5d426e38 100644 --- a/checks/check_extra725 +++ b/checks/check_extra725 @@ -10,49 +10,51 @@ # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR # CONDITIONS OF ANY KIND, either express or implied. See the License for the # specific language governing permissions and limitations under the License. -# CHECK_ID_extra725="7.25" -# CHECK_TITLE_extra725="[extra725] Check if S3 buckets have Object-level logging enabled (Not Scored) (Not part of CIS benchmark)" -# CHECK_SCORED_extra725="NOT_SCORED" -# CHECK_ALTERNATE_check725="extra725" -# -# aws cloudtrail get-event-selectors --trail-name Default --profile security --region us-east-1 --query "EventSelectors[*].DataResources[?Type == \`AWS::S3::Object\`].Values" --output text |xargs -n1 |cut -d: -f 6|sed 's/\///g' -# -# extra725(){ -# # "Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)" -# for regx in $REGIONS; do -# LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text) -# if [[ $LIST_OF_FUNCTIONS ]]; then -# for lambdafunction in $LIST_OF_FUNCTIONS;do -# LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query trailList[?HomeRegion==\`$regx\`].Name --output text) -# if [[ $LIST_OF_TRAILS ]]; then -# for trail in $LIST_OF_TRAILS; do -# FUNCTION_ENABLED_IN_TRAIL=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $regx --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") -# if [[ $FUNCTION_ENABLED_IN_TRAIL ]]; then -# textPass "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" -# else -# textFail "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" -# fi -# done -# # LIST_OF_MULTIREGION_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\`].Name" --output text) -# # if [[ $LIST_OF_MULTIREGION_TRAILS ]]; then -# # for trail in $LIST_OF_MULTIREGION_TRAILS; do -# # REGION_OF_TRAIL=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\` && Name == \`$trail\` ].HomeRegion" --output text) -# # FUNCTION_ENABLED_IN_THIS_REGION=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $REGION_OF_TRAIL --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$") -# # if [[ $FUNCTION_ENABLED_IN_THIS_REGION ]]; then -# # textPass "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx" -# # else -# # textFail "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx" -# # fi -# # done -# # else -# # textFail "$regx: Lambda function $lambdafunction is not being recorded!" "$regx" -# # fi -# else -# textFail "$regx: Lambda function $lambdafunction is not being recorded no CloudTrail found!" "$regx" -# fi -# done -# else -# textInfo "$regx: No Lambda functions found" "$regx" -# fi -# done -# } + +CHECK_ID_extra725="7.25" +CHECK_TITLE_extra725="[extra725] Check if S3 buckets have Object-level logging enabled in CloudTrail (Not Scored) (Not part of CIS benchmark)" +CHECK_SCORED_extra725="NOT_SCORED" +CHECK_ALTERNATE_check725="extra725" + +# per Object-level logging is not configured at Bucket level but at CloudTrail trail level +extra725(){ + # "Check if S3 buckets have Object-level logging enabled in CloudTrail (Not Scored) (Not part of CIS benchmark)" + textInfo "Looking for S3 Buckets Object-level logging information in all trails... " + + # create a file with a list of all buckets + TEMP_BUCKET_LIST_FILE=$(mktemp -t prowler.bucket-list-XXXXXX) + $AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' $PROFILE_OPT --region $REGION --output text > $TEMP_BUCKET_LIST_FILE + + # now create a list with all trails available and their region + TEMP_TRAILS_LIST_FILE=$(mktemp -t prowler.trails-list-XXXXXX) + for regx in $REGIONS; do + $AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query trailList[?HomeRegion==\`$regx\`].[Name,HomeRegion] --output text >> $TEMP_TRAILS_LIST_FILE + done + if [ ! -s $TEMP_TRAILS_LIST_FILE ]; then + textInfo "$regx: No S3 buckets found" "$regx" + exit + fi + + # look for buckets being logged per trail and create a list with them + TEMP_BUCKETS_LOGGING_LIST_FILE=$(mktemp -t prowler.buckets-logging-list-XXXXXX) + for trail in $(cat $TEMP_TRAILS_LIST_FILE | awk '{ print $1 }'); do + TRAIL_REGION=$(grep ^$trail $TEMP_TRAILS_LIST_FILE | awk '{ print $2 }') + BUCKETS_OBJECT_LOGGING_ENABLED=$($AWSCLI cloudtrail get-event-selectors --trail-name $trail $PROFILE_OPT --region $TRAIL_REGION --query "EventSelectors[*].DataResources[?Type == \`AWS::S3::Object\`].Values" --output text |xargs -n1 |cut -d: -f 6|sed 's/\///g') + echo $BUCKETS_OBJECT_LOGGING_ENABLED |tr " " "\n"|sort >> $TEMP_BUCKETS_LOGGING_LIST_FILE + if [[ $BUCKETS_OBJECT_LOGGING_ENABLED ]]; then + for bucket in $BUCKETS_OBJECT_LOGGING_ENABLED; do + textPass "$regx: S3 bucket $bucket has Object-level logging enabled in trail $trail" "$regx" + done + fi + done + # diff to get the ones that are not in any trail then they are not logging + BUCKETS_NOT_LOGGING=$(diff $TEMP_BUCKETS_LOGGING_LIST_FILE $TEMP_BUCKET_LIST_FILE | sed -n 's/^> //p') + if [[ $BUCKETS_NOT_LOGGING ]]; then + for bucket in $BUCKETS_NOT_LOGGING; do + textFail "$regx: S3 bucket $bucket has Object-level logging disabled" "$regx" + done + fi + # delete all temp files + rm -fr $TEMP_BUCKET_LIST_FILE $TEMP_TRAILS_LIST_FILE $TEMP_BUCKETS_LOGGING_LIST_FILE + +} diff --git a/groups/group9_gdpr b/groups/group9_gdpr index 774c30a6ca..6fe0f0a303 100644 --- a/groups/group9_gdpr +++ b/groups/group9_gdpr @@ -16,3 +16,9 @@ GROUP_NUMBER[9]='8.0' GROUP_TITLE[9]='GDPR Readiness - [gdpr] ****************************************' GROUP_RUN_BY_DEFAULT[9]='N' # run it when execute_all is called GROUP_CHECKS[9]='' + +# Resources: +# https://d1.awsstatic.com/whitepapers/compliance/GDPR_Compliance_on_AWS.pdf +# https://github.com/toniblyx/prowler/issues/189 +# https://www.slideshare.net/AmazonWebServices/sid303-navigating-gdpr-compliance-on-aws +# https://aws.amazon.com/compliance/gdpr-center/ From 473c9b9ce084908e93a87388f8483a1ce8f31e88 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 10 Apr 2018 16:21:08 -0400 Subject: [PATCH 34/41] added extra725 to extras and forensics --- groups/group7_extras | 2 +- groups/group8_forensics | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/groups/group7_extras b/groups/group7_extras index fe8dbf30f3..b404b5baa9 100644 --- a/groups/group7_extras +++ b/groups/group7_extras @@ -15,4 +15,4 @@ GROUP_ID[7]='extras' GROUP_NUMBER[7]='7.0' GROUP_TITLE[7]='Extras - [extras] **********************************************' GROUP_RUN_BY_DEFAULT[7]='Y' # run it when execute_all is called -GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723,extra724' +GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723,extra724,extra725' diff --git a/groups/group8_forensics b/groups/group8_forensics index 268c7711cf..d323056217 100644 --- a/groups/group8_forensics +++ b/groups/group8_forensics @@ -15,4 +15,4 @@ GROUP_ID[8]='forensics-ready' GROUP_NUMBER[8]='8.0' GROUP_TITLE[8]='Forensics Readiness - [forensics-ready] ************************' GROUP_RUN_BY_DEFAULT[8]='N' # run it when execute_all is called -GROUP_CHECKS[8]='check21,check22,check23,check24,check25,check26,check27,check43,extra712,extra713,extra714,extra715,extra717,extra718,extra719,extra720,extra721,extra722' +GROUP_CHECKS[8]='check21,check22,check23,check24,check25,check26,check27,check43,extra712,extra713,extra714,extra715,extra717,extra718,extra719,extra720,extra721,extra722,extra725' From 1b0d09da137b4926fded89cb475e01046f7e6dcc Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 11 Apr 2018 10:01:50 -0400 Subject: [PATCH 35/41] added version variable to banner --- include/banner | 2 +- prowler | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/banner b/include/banner index 6e1086b30e..aadb54e69d 100644 --- a/include/banner +++ b/include/banner @@ -17,7 +17,7 @@ prowlerBanner() { echo -e " _ __ _ __ _____ _| | ___ _ __" echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|" echo -e " | |_) | | | (_) \ V V /| | __/ |" - echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|v2.0" + echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|v$PROWLER_VERSION" echo -e " |_|$NORMAL$BLUE the handy cloud security tool$NORMAL\n" echo -e "$YELLOW Date: $(date)" printColorsCode diff --git a/prowler b/prowler index c9965f28b7..bdaedfbbac 100755 --- a/prowler +++ b/prowler @@ -32,6 +32,7 @@ OPTRED="" OPTNORMAL="" # Set the defaults for these getopts variables +PROWLER_VERSION=2.0-beta1 REGION="us-east-1" FILTERREGION="" MAXITEMS=100 From 4c607bba1cfb30b5bddd7b0acc174fe73ddf4291 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 11 Apr 2018 10:13:43 -0400 Subject: [PATCH 36/41] improved current directoy handler for includes --- prowler | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/prowler b/prowler index bdaedfbbac..18010ae803 100755 --- a/prowler +++ b/prowler @@ -31,8 +31,10 @@ OPTRED="" OPTNORMAL="" -# Set the defaults for these getopts variables +# Set the defaults variables PROWLER_VERSION=2.0-beta1 +PROWLER_DIR=$(dirname "$0") + REGION="us-east-1" FILTERREGION="" MAXITEMS=100 @@ -133,15 +135,15 @@ while getopts ":hlkp:r:c:g:f:m:M:enb" OPTION; do esac done -. include/colors -. include/os_detector -. include/aws_profile_loader -. include/awscli_detector -. include/outputs -. include/csv_header -. include/banner -. include/whoami -. include/credentials_report +. $PROWLER_DIR/include/colors +. $PROWLER_DIR/include/os_detector +. $PROWLER_DIR/include/aws_profile_loader +. $PROWLER_DIR/include/awscli_detector +. $PROWLER_DIR/include/outputs +. $PROWLER_DIR/include/csv_header +. $PROWLER_DIR/include/banner +. $PROWLER_DIR/include/whoami +. $PROWLER_DIR/include/credentials_report # Get a list of all available AWS Regions REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ @@ -151,13 +153,13 @@ REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ --region-names $FILTERREGION) # Load all of the groups of checks inside groups folder named as "groupNumber*" -for group in $(ls groups/group[0-9]*|grep -v groupN_sample); do +for group in $(ls $PROWLER_DIR/groups/group[0-9]*|grep -v groupN_sample); do . "$group" done # Load all of the checks inside checks folder named as "check*" # this includes also extra checks since they are "check_extraNN" -for checks in $(ls checks/check*|grep -v check_sample); do +for checks in $(ls $PROWLER_DIR/checks/check*|grep -v check_sample); do . "$checks" done From 8f86a5319f7a92bf0ea459184e3cdd0049373df8 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 11 Apr 2018 10:14:34 -0400 Subject: [PATCH 37/41] set version label 2.0-beta2 --- prowler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler b/prowler index 18010ae803..d3f9c992eb 100755 --- a/prowler +++ b/prowler @@ -32,7 +32,7 @@ OPTRED="" OPTNORMAL="" # Set the defaults variables -PROWLER_VERSION=2.0-beta1 +PROWLER_VERSION=2.0-beta2 PROWLER_DIR=$(dirname "$0") REGION="us-east-1" From 98a1f4bda01df0c9bc94f63cca1b92dab1d8a322 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Wed, 11 Apr 2018 14:09:55 -0400 Subject: [PATCH 38/41] improved error handling on check111 --- checks/check111 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/checks/check111 b/checks/check111 index 29a015ff29..45973792cb 100644 --- a/checks/check111 +++ b/checks/check111 @@ -11,16 +11,18 @@ CHECK_ID_check111="1.11" CHECK_TITLE_check111="[check111] Ensure IAM password policy expires passwords within 90 days or less (Scored)" CHECK_SCORED_check111="SCORED" -CHECK_ALTERNATE_check111="check111" +CHECK_ALTERNATE_check111="check111" check111(){ # "Ensure IAM password policy expires passwords within 90 days or less (Scored)" - COMMAND111=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g' 2> /dev/null) + COMMAND111=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --query PasswordPolicy.MaxPasswordAge --output text 2> /dev/null) if [[ $COMMAND111 ]];then if [ "$COMMAND111" == "90" ];then textPass "Password Policy includes expiration" + else + textFail "Password expiration is set greater than 90 days" fi else - textFail "Password expiration not set or set greater than 90 days " + textFail "Password expiration is not set" fi } From ada8a225ae6385db97a2ae6cc297fe27ea7e5246 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Mon, 16 Apr 2018 14:09:30 -0400 Subject: [PATCH 39/41] fixed and improved aws profile loader --- include/aws_profile_loader | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/include/aws_profile_loader b/include/aws_profile_loader index 3cd2135054..842fa15575 100644 --- a/include/aws_profile_loader +++ b/include/aws_profile_loader @@ -16,21 +16,19 @@ # check environment variables and if not, it checks and loads credentials from # instance profile (metadata server) if runs in an EC2 instance +INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) + if [[ $PROFILE ]]; then PROFILE_OPT="--profile $PROFILE" -else - # if Prowler runs insinde an AWS instance with IAM instance profile attached - INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) - if [[ $INSTANCE_PROFILE ]]; then +elif [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then + PROFILE="ENV" + PROFILE_OPT="" +elif [[ $INSTANCE_PROFILE ]];then + PROFILE="INSTANCE-PROFILE" AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g') AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') - fi - if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then - PROFILE="ENV" - PROFILE_OPT="" - else +else PROFILE="default" PROFILE_OPT="--profile $PROFILE" - fi fi From 38ad3ca657fd8b80c5a5e9f601f09b6b42349786 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Thu, 19 Apr 2018 09:47:16 -0400 Subject: [PATCH 40/41] region and profile handling improved --- include/aws_profile_loader | 13 +++++++++++++ prowler | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/aws_profile_loader b/include/aws_profile_loader index 842fa15575..c7e9d5eabd 100644 --- a/include/aws_profile_loader +++ b/include/aws_profile_loader @@ -17,6 +17,9 @@ # instance profile (metadata server) if runs in an EC2 instance INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) +if echo "$INSTANCE_PROFILE" | grep -q '404 - Not Found'; then + INSTANCE_PROFILE= +fi if [[ $PROFILE ]]; then PROFILE_OPT="--profile $PROFILE" @@ -32,3 +35,13 @@ else PROFILE="default" PROFILE_OPT="--profile $PROFILE" fi + +# Set default region by aws config, fall back to us-east-1 +REGION_CONFIG=$(aws configure get region) +if [[ $REGION_OPT ]]; then + REGION="$REGION_OPT" +elif [[ $REGION_CONFIG ]]; then + REGION="$REGION_CONFIG" +else + REGION="us-east-1" +fi diff --git a/prowler b/prowler index d3f9c992eb..24d67abffc 100755 --- a/prowler +++ b/prowler @@ -35,7 +35,7 @@ OPTNORMAL="" PROWLER_VERSION=2.0-beta2 PROWLER_DIR=$(dirname "$0") -REGION="us-east-1" +REGION="" FILTERREGION="" MAXITEMS=100 MONOCHROME=0 @@ -92,7 +92,7 @@ while getopts ":hlkp:r:c:g:f:m:M:enb" OPTION; do PROFILE=$OPTARG ;; r ) - REGION=$OPTARG + REGION_OPT=$OPTARG ;; c ) CHECK_ID=$OPTARG From 2362518f13c1a6a275f841c196770d9c92cd6bc3 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Thu, 19 Apr 2018 09:52:31 -0400 Subject: [PATCH 41/41] added -g option to README and fixes --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a6fc4e9e84..c536c09814 100644 --- a/README.md +++ b/README.md @@ -367,11 +367,13 @@ At this moment we have 23 extra checks: - 7.21 (`extra721`) Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) - 7.22 (`extra722`) Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) - 7.23 (`extra723`) Check if RDS Snapshots are public (Not Scored) (Not part of CIS benchmark) +- 7.24 (`extra724`) Check if ACM certificates have Certificate Transparency logging enabled (Not Scored) (Not part of CIS benchmark) +- 7.25 (`extra725`) Check if S3 buckets have Object-level logging enabled in CloudTrail (Not Scored) (Not part of CIS benchmark) To check all extras in one command: ``` -./prowler -c extras +./prowler -g extras ``` or to run just one of the checks: ``` @@ -380,7 +382,7 @@ or to run just one of the checks: ## Forensics Ready Checks -With this group of checks, Prowler looks if each service with logging or audit capabilities has them enabled to ensure all needed evidences are recorded and collected for an eventual digital forensic investigation in case of incident. List of checks part of this group: +With this group of checks, Prowler looks if each service with logging or audit capabilities has them enabled to ensure all needed evidences are recorded and collected for an eventual digital forensic investigation in case of incident. List of checks part of this group (you can also see all groups with `./prowler -l`): - 2.1 Ensure CloudTrail is enabled in all regions (Scored) - 2.2 Ensure CloudTrail log file validation is enabled (Scored) - 2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) @@ -402,7 +404,7 @@ With this group of checks, Prowler looks if each service with logging or audit c The `forensics-ready` group of checks uses existing and extra checks. To get a forensics readiness report, run this command: ``` -./prowler -c forensics-ready +./prowler -g forensics-ready ``` ## Add Custom Checks