diff --git a/README.md b/README.md index e0c5d0e5..7468c8e4 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX pip install awscli ansi2html detect-secrets ``` - AWS-CLI can be also installed it using "brew", "apt", "yum" or manually from , but `ansi2html` and `detect-secrets` has to be installed using `pip`. You will need to install `jq` to get more accuracy in some checks. + AWS-CLI can be also installed it using "brew", "apt", "yum" or manually from , but `ansi2html` and `detect-secrets` has to be installed using `pip`. You will need to install `jq` to get more accuracy in some checks. - Make sure jq is installed (example below with "apt" but use a valid package manager for your OS): ```sh @@ -81,7 +81,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX ```sh aws configure ``` - or + or ```sh export AWS_ACCESS_KEY_ID="ASXXXXXXX" export AWS_SECRET_ACCESS_KEY="XXXXXXXXX" @@ -94,7 +94,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX arn:aws:iam::aws:policy/SecurityAudit ``` - > Additional permissions needed: to make sure Prowler can scan all services included in the group *Extras*, make sure you attach also the custom policy [prowler-additions-policy.json](https://github.com/toniblyx/prowler/blob/master/iam/prowler-additions-policy.json) to the role you are using. + > Additional permissions needed: to make sure Prowler can scan all services included in the group *Extras*, make sure you attach also the custom policy [prowler-additions-policy.json](https://github.com/toniblyx/prowler/blob/master/iam/prowler-additions-policy.json) to the role you are using. If you want Prowler to send findings to [AWS Security Hub](https://aws.amazon.com/security-hub), make sure you also attach the custom policy [prowler-security-hub.json](https://github.com/toniblyx/prowler/blob/master/iam/prowler-security-hub.json). ## Usage @@ -107,7 +107,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX Use `-l` to list all available checks and group of checks (sections) If you want to avoid installing dependences run it using Docker: - + ```sh docker run -ti --rm --name prowler --env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY --env AWS_SESSION_TOKEN toniblyx/prowler:latest ``` @@ -127,7 +127,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX ```sh docker run -ti --rm --name prowler --env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY --env AWS_SESSION_TOKEN toniblyx/prowler:latest "-c check310" ``` - + or multiple checks separated by comma: ```sh ./prowler -c check310,check722 @@ -185,6 +185,14 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX ./prowler -M mono | aws s3 cp - s3://bucket-name/prowler-report.txt ``` +1. If you want Prowler to submit findings to [AWS Security Hub](https://aws.amazon.com/security-hub): + + ```sh + ./prowler -M json-asff -S + ``` + + > Note that Security Hub must be enabled for the active region. It can be enabled by calling `aws securityhub enable-security-hub` + 1. To perform an assessment based on CIS Profile Definitions you can use cislevel1 or cislevel2 with `-g` flag, more information about this [here, page 8](https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf): ```sh @@ -228,6 +236,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX -b do not print Prowler banner -V show version number & exit -s show scoring report + -S send check output to AWS Security Hub - only valid when the output mode is json-asff (i.e. "-M json-asff -S") -x specify external directory with custom checks (i.e. /my/own/checks, files must start by check) -q suppress info messages and passing test output -A account id for the account where to assume a role, requires -R and -T @@ -241,17 +250,17 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX ## Advanced Usage -### Assume Role: +### Assume Role: Prowler uses the AWS CLI underneath so it uses the same authentication methods. However, there are few ways to run Prowler against multiple accounts using IAM Assume Role feature depending on eachg use case. You can just set up your custom profile inside `~/.aws/config` with all needed information about the role to assume then call it with `./prowler -p your-custom-profile`. Additionally you can use `-A 123456789012` and `-R RemoteRoleToAssume` and Prowler will get those temporary credentials using `aws sts assume-role`, set them up as environment variables and run against that given account. ``` -./prowler -A 123456789012 -R ProwlerRole +./prowler -A 123456789012 -R ProwlerRole ``` > *NOTE 1 about Session Duration*: By default it gets credentials valid for 1 hour (3600 seconds). Depending on the mount of checks you run and the size of your infrastructure, Prowler may require more than 1 hour to finish. Use option `-T ` to allow up to 12h (43200 seconds). To allow more than 1h you need to modify *"Maximum CLI/API session duration"* for that particular role, read more [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session). -> *NOTE 2 about Session Duration*: Bear in mind that if you are using roles assumed by role chaining there is a hard limit of 1 hour so consider not using role chaining if possible, read more about that, in foot note 1 below the table [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html). +> *NOTE 2 about Session Duration*: Bear in mind that if you are using roles assumed by role chaining there is a hard limit of 1 hour so consider not using role chaining if possible, read more about that, in foot note 1 below the table [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html). For example, if you want to get only the fails in CSV format from all checks regarding RDS without banner from the AWS Account 123456789012 assuming the role RemoteRoleToAssume and set a fixed session duration of 1h: @@ -322,7 +331,7 @@ Some new and specific checks require Prowler to inherit more permissions than Se [iam/prowler-additions-policy.json](iam/prowler-additions-policy.json) -> Note: Action `ec2:get*` is included in "ProwlerReadOnlyPolicy" policy above, that includes `get-password-data`, type `aws ec2 get-password-data help` to better understand its implications. +> Note: Action `ec2:get*` is included in "ProwlerReadOnlyPolicy" policy above, that includes `get-password-data`, type `aws ec2 get-password-data help` to better understand its implications. ### Bootstrap Script @@ -371,7 +380,7 @@ or to run just one of the checks: or to run multiple extras in one go: -```sh +```sh ./prowler -c extraNumber,extraNumber ``` @@ -441,7 +450,7 @@ In order to add any new check feel free to create a new extra check in the extra ## Third Party Integrations -### AWS Security Hub +### AWS Security Hub There is a blog post about that integration in the AWS Security blog here diff --git a/checks/check11 b/checks/check11 index f34ebed5..09bdcab1 100644 --- a/checks/check11 +++ b/checks/check11 @@ -12,6 +12,7 @@ CHECK_ID_check11="1.1,1.01" CHECK_TITLE_check11="[check11] Avoid the use of the root account (Scored)" CHECK_SCORED_check11="SCORED" CHECK_TYPE_check11="LEVEL1" +CHECK_ASFF_TYPE_check11="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check101="check11" check11(){ diff --git a/checks/check110 b/checks/check110 index 6f34b0f2..dabb80dc 100644 --- a/checks/check110 +++ b/checks/check110 @@ -12,6 +12,7 @@ CHECK_ID_check110="1.10" CHECK_TITLE_check110="[check110] Ensure IAM password policy prevents password reuse: 24 or greater (Scored)" CHECK_SCORED_check110="SCORED" CHECK_TYPE_check110="LEVEL1" +CHECK_ASFF_TYPE_check110="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check110="check110" check110(){ diff --git a/checks/check111 b/checks/check111 index ea652b63..83575d29 100644 --- a/checks/check111 +++ b/checks/check111 @@ -12,6 +12,7 @@ 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_TYPE_check111="LEVEL1" +CHECK_ASFF_TYPE_check111="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check111="check111" check111(){ diff --git a/checks/check112 b/checks/check112 index f6fa9481..a9825ee1 100644 --- a/checks/check112 +++ b/checks/check112 @@ -12,6 +12,7 @@ CHECK_ID_check112="1.12" CHECK_TITLE_check112="[check112] Ensure no root account access key exists (Scored)" CHECK_SCORED_check112="SCORED" CHECK_TYPE_check112="LEVEL1" +CHECK_ASFF_TYPE_check112="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check112="check112" check112(){ @@ -22,11 +23,11 @@ check112(){ if [ "$ROOTKEY1" == "false" ];then textPass "No access key 1 found for root" else - textFail "Found access key 1 for root " + textFail "Found access key 1 for root" fi if [ "$ROOTKEY2" == "false" ];then textPass "No access key 2 found for root" else - textFail "Found access key 2 for root " + textFail "Found access key 2 for root" fi } diff --git a/checks/check113 b/checks/check113 index 481daeef..1e034c8d 100644 --- a/checks/check113 +++ b/checks/check113 @@ -12,6 +12,7 @@ CHECK_ID_check113="1.13" CHECK_TITLE_check113="[check113] Ensure MFA is enabled for the root account (Scored)" CHECK_SCORED_check113="SCORED" CHECK_TYPE_check113="LEVEL1" +CHECK_ASFF_TYPE_check113="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check113="check113" check113(){ @@ -20,6 +21,6 @@ check113(){ if [ "$COMMAND113" == "1" ]; then textPass "Virtual MFA is enabled for root" else - textFail "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 99391d33..fff68b72 100644 --- a/checks/check114 +++ b/checks/check114 @@ -12,6 +12,7 @@ CHECK_ID_check114="1.14" CHECK_TITLE_check114="[check114] Ensure hardware MFA is enabled for the root account (Scored)" CHECK_SCORED_check114="SCORED" CHECK_TYPE_check114="LEVEL2" +CHECK_ASFF_TYPE_check114="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check114="check114" check114(){ @@ -22,9 +23,9 @@ check114(){ if [[ "$COMMAND114" ]]; then textFail "Only Virtual MFA is enabled for root" else - textPass "Hardware MFA is enabled for root " + textPass "Hardware MFA is enabled for root" fi else - textFail "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 848bd440..c52db37e 100644 --- a/checks/check115 +++ b/checks/check115 @@ -12,6 +12,7 @@ CHECK_ID_check115="1.15" CHECK_TITLE_check115="[check115] Ensure security questions are registered in the AWS account (Not Scored)" CHECK_SCORED_check115="NOT_SCORED" CHECK_TYPE_check115="LEVEL1" +CHECK_ASFF_TYPE_check115="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check115="check115" check115(){ diff --git a/checks/check116 b/checks/check116 index ad51e34c..c20abbf7 100644 --- a/checks/check116 +++ b/checks/check116 @@ -12,6 +12,8 @@ CHECK_ID_check116="1.16" CHECK_TITLE_check116="[check116] Ensure IAM policies are attached only to groups or roles (Scored)" CHECK_SCORED_check116="SCORED" CHECK_TYPE_check116="LEVEL1" +CHECK_ASFF_TYPE_check116="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check116="AwsIamUser" CHECK_ALTERNATE_check116="check116" check116(){ @@ -21,16 +23,16 @@ 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 - textFail "$user has managed policy directly attached " + textFail "$user has managed policy directly attached" C116_NUM_USERS=$(expr $C116_NUM_USERS + 1) fi USER_POLICY=$($AWSCLI iam list-user-policies --output text $PROFILE_OPT --region $REGION --user-name $user) if [[ $USER_POLICY ]]; then - textFail "$user has inline policy directly attached " + textFail "$user has inline policy directly attached" C116_NUM_USERS=$(expr $C116_NUM_USERS + 1) fi done if [[ $C116_NUM_USERS -eq 0 ]]; then - textPass "No policies attached to users." + textPass "No policies attached to users" fi } diff --git a/checks/check117 b/checks/check117 index 69f897c9..1264c99e 100644 --- a/checks/check117 +++ b/checks/check117 @@ -12,6 +12,7 @@ CHECK_ID_check117="1.17" CHECK_TITLE_check117="[check117] Maintain current contact details (Not Scored)" CHECK_SCORED_check117="NOT_SCORED" CHECK_TYPE_check117="LEVEL1" +CHECK_ASFF_TYPE_check117="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check117="check117" check117(){ diff --git a/checks/check118 b/checks/check118 index 4217fbf1..abd76906 100644 --- a/checks/check118 +++ b/checks/check118 @@ -12,6 +12,7 @@ CHECK_ID_check118="1.18" CHECK_TITLE_check118="[check118] Ensure security contact information is registered (Not Scored)" CHECK_SCORED_check118="NOT_SCORED" CHECK_TYPE_check118="LEVEL1" +CHECK_ASFF_TYPE_check118="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check118="check118" check118(){ diff --git a/checks/check119 b/checks/check119 index 4dbc7fd0..5a0a90d7 100644 --- a/checks/check119 +++ b/checks/check119 @@ -12,6 +12,8 @@ CHECK_ID_check119="1.19" CHECK_TITLE_check119="[check119] Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)" CHECK_SCORED_check119="NOT_SCORED" CHECK_TYPE_check119="LEVEL2" +CHECK_ASFF_TYPE_check119="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check119="AwsEc2Instance" CHECK_ALTERNATE_check119="check119" check119(){ @@ -25,9 +27,9 @@ check119(){ if [[ $STATE_NAME != "terminated" ]]; then PROFILEARN=$(echo $EC2_DATA | jq -r --arg i "$instance" 'select(.InstanceId==$i)|.ProfileArn') if [[ $PROFILEARN == "null" ]]; then - textFail "$regx: Instance $instance not associated with an instance role." $regx + textFail "$regx: Instance $instance not associated with an instance role" $regx else - textPass "$regx: Instance $instance associated with role ${PROFILEARN##*/}." $regx + textPass "$regx: Instance $instance associated with role ${PROFILEARN##*/}" $regx fi fi done diff --git a/checks/check12 b/checks/check12 index 6e82f10c..15bc50f1 100644 --- a/checks/check12 +++ b/checks/check12 @@ -12,6 +12,8 @@ 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" CHECK_TYPE_check12="LEVEL1" +CHECK_ASFF_TYPE_check12="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check12="AwsIamUser" CHECK_ALTERNATE_check102="check12" check12(){ diff --git a/checks/check120 b/checks/check120 index 2983642f..dd1d4fc5 100644 --- a/checks/check120 +++ b/checks/check120 @@ -12,6 +12,8 @@ CHECK_ID_check120="1.20" CHECK_TITLE_check120="[check120] Ensure a support role has been created to manage incidents with AWS Support (Scored)" CHECK_SCORED_check120="SCORED" CHECK_TYPE_check120="LEVEL1" +CHECK_ASFF_TYPE_check120="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check120="AwsIamRole" CHECK_ALTERNATE_check120="check120" check120(){ @@ -28,7 +30,7 @@ check120(){ # textInfo "User $user has support access via $policyarn" # done else - textFail "Support Policy not applied to any Role " + textFail "Support Policy not applied to any Role" fi done else diff --git a/checks/check121 b/checks/check121 index 64032c05..b909eb7b 100644 --- a/checks/check121 +++ b/checks/check121 @@ -12,6 +12,8 @@ CHECK_ID_check121="1.21" CHECK_TITLE_check121="[check121] Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)" CHECK_SCORED_check121="NOT_SCORED" CHECK_TYPE_check121="LEVEL1" +CHECK_ASFF_TYPE_check121="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check121="AwsIamUser" CHECK_ALTERNATE_check121="check121" check121(){ diff --git a/checks/check122 b/checks/check122 index 0ae9e6c3..1c4fdec2 100644 --- a/checks/check122 +++ b/checks/check122 @@ -12,6 +12,8 @@ CHECK_ID_check122="1.22" CHECK_TITLE_check122="[check122] Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)" CHECK_SCORED_check122="SCORED" CHECK_TYPE_check122="LEVEL1" +CHECK_ASFF_TYPE_check122="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check122="AwsIamPolicy" CHECK_ALTERNATE_check122="check122" check122(){ diff --git a/checks/check13 b/checks/check13 index 10289768..9e0a4616 100644 --- a/checks/check13 +++ b/checks/check13 @@ -12,6 +12,8 @@ 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" CHECK_TYPE_check13="LEVEL1" +CHECK_ASFF_TYPE_check13="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check13="AwsIamUser" CHECK_ALTERNATE_check103="check13" check13(){ diff --git a/checks/check14 b/checks/check14 index 88d14407..86925def 100644 --- a/checks/check14 +++ b/checks/check14 @@ -12,6 +12,8 @@ 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" CHECK_TYPE_check14="LEVEL1" +CHECK_ASFF_TYPE_check14="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check14="AwsIamUser" CHECK_ALTERNATE_check104="check14" check14(){ @@ -28,15 +30,15 @@ check14(){ HOWOLDER=$(how_older_from_today $DATEROTATED1) if [ $HOWOLDER -gt "90" ];then - textFail " $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 - textPass "No users with access key 1 older than 90 days." + textPass "No users with access key 1 older than 90 days" fi else - textPass "No users with access key 1." + textPass "No users with access key 1" fi if [[ $LIST_OF_USERS_WITH_ACCESS_KEY2 ]]; then @@ -46,14 +48,14 @@ check14(){ DATEROTATED2=$(cat $TEMP_REPORT_FILE | grep -v user_creation_time | grep "^${user},"| awk -F, '{ print $15 }' | grep -v "N/A" | awk -F"T" '{ print $1 }') HOWOLDER=$(how_older_from_today $DATEROTATED2) if [ $HOWOLDER -gt "90" ];then - textFail " $user has not rotated access key2 in over 90 days. " + textFail " $user has not rotated access key2 in over 90 days" C14_NUM_USERS2=$(expr $C14_NUM_USERS2 + 1) fi done if [[ $C14_NUM_USERS2 -eq 0 ]]; then - textPass "No users with access key 2 older than 90 days." + textPass "No users with access key 2 older than 90 days" fi else - textPass "No users with access key 2." + textPass "No users with access key 2" fi } diff --git a/checks/check15 b/checks/check15 index aedcba17..0aa9c732 100644 --- a/checks/check15 +++ b/checks/check15 @@ -12,6 +12,7 @@ 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" CHECK_TYPE_check15="LEVEL1" +CHECK_ASFF_TYPE_check15="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check105="check15" check15(){ diff --git a/checks/check16 b/checks/check16 index de224521..9ee4965b 100644 --- a/checks/check16 +++ b/checks/check16 @@ -12,6 +12,7 @@ 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_TYPE_check16="LEVEL1" +CHECK_ASFF_TYPE_check16="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check106="check16" check16(){ diff --git a/checks/check17 b/checks/check17 index f344c759..fc56ffe7 100644 --- a/checks/check17 +++ b/checks/check17 @@ -12,6 +12,7 @@ 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" CHECK_TYPE_check17="LEVEL1" +CHECK_ASFF_TYPE_check17="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check107="check17" check17(){ diff --git a/checks/check18 b/checks/check18 index 412de291..732b87bd 100644 --- a/checks/check18 +++ b/checks/check18 @@ -12,6 +12,7 @@ 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" CHECK_TYPE_check18="LEVEL1" +CHECK_ASFF_TYPE_check18="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check108="check18" check18(){ diff --git a/checks/check19 b/checks/check19 index 6e924ae8..60aad8ed 100644 --- a/checks/check19 +++ b/checks/check19 @@ -12,6 +12,7 @@ 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" CHECK_TYPE_check19="LEVEL1" +CHECK_ASFF_TYPE_check19="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check109="check19" check19(){ diff --git a/checks/check21 b/checks/check21 index 591b911c..d1a23103 100644 --- a/checks/check21 +++ b/checks/check21 @@ -12,6 +12,8 @@ CHECK_ID_check21="2.1,2.01" CHECK_TITLE_check21="[check21] Ensure CloudTrail is enabled in all regions (Scored)" CHECK_SCORED_check21="SCORED" CHECK_TYPE_check21="LEVEL1" +CHECK_ASFF_TYPE_check21="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check21="AwsCloudTrailTrail" CHECK_ALTERNATE_check201="check21" check21(){ @@ -27,7 +29,7 @@ check21(){ MULTIREGION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].IsMultiRegionTrail' --output text --trail-name-list $trail) ISLOGGING_STATUS=$($AWSCLI cloudtrail get-trail-status $PROFILE_OPT --region $regx --name $trail --query ['IsLogging'] --output text) INCLUDEMANAGEMENTEVENTS_STATUS=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --region $regx --trail-name $trail --query EventSelectors[*].IncludeManagementEvents --output text) - READWRITETYPE_STATUS=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --region $regx --trail-name $trail --query EventSelectors[*].ReadWriteType --output text) + READWRITETYPE_STATUS=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --region $regx --trail-name $trail --query EventSelectors[*].ReadWriteType --output text) if [[ "$MULTIREGION_TRAIL_STATUS" == "True" ]] && [[ "$ISLOGGING_STATUS" == "True" ]] && [[ "$INCLUDEMANAGEMENTEVENTS_STATUS" == *"True"* ]] && [[ "$READWRITETYPE_STATUS" == *"All"* ]];then textPass "$trail trail in $regx is enabled for all regions" result='True' diff --git a/checks/check22 b/checks/check22 index 18b13742..1646a94f 100644 --- a/checks/check22 +++ b/checks/check22 @@ -12,11 +12,13 @@ CHECK_ID_check22="2.2,2.02" CHECK_TITLE_check22="[check22] Ensure CloudTrail log file validation is enabled (Scored)" CHECK_SCORED_check22="SCORED" CHECK_TYPE_check22="LEVEL2" +CHECK_ASFF_TYPE_check22="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check22="AwsCloudTrailTrail" CHECK_ALTERNATE_check202="check22" check22(){ # "Ensure CloudTrail log file validation is enabled (Scored)" - + for regx in $REGIONS; do LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].Name' --output text --no-include-shadow-trails) if [[ $LIST_OF_TRAILS ]];then diff --git a/checks/check23 b/checks/check23 index 53d1b6f6..feab2c6b 100644 --- a/checks/check23 +++ b/checks/check23 @@ -12,6 +12,8 @@ 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" CHECK_TYPE_check23="LEVEL1" +CHECK_ASFF_TYPE_check23="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check23="AwsS3Bucket" CHECK_ALTERNATE_check203="check23" check23(){ diff --git a/checks/check24 b/checks/check24 index 35185035..581878bc 100644 --- a/checks/check24 +++ b/checks/check24 @@ -12,6 +12,8 @@ CHECK_ID_check24="2.4,2.04" CHECK_TITLE_check24="[check24] Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" CHECK_SCORED_check24="SCORED" CHECK_TYPE_check24="LEVEL1" +CHECK_ASFF_TYPE_check24="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check24="AwsCloudTrailTrail" CHECK_ALTERNATE_check204="check24" check24(){ diff --git a/checks/check25 b/checks/check25 index d8d81732..6bb12698 100644 --- a/checks/check25 +++ b/checks/check25 @@ -12,6 +12,7 @@ CHECK_ID_check25="2.5,2.05" CHECK_TITLE_check25="[check25] Ensure AWS Config is enabled in all regions (Scored)" CHECK_SCORED_check25="SCORED" CHECK_TYPE_check25="LEVEL1" +CHECK_ASFF_TYPE_check25="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" CHECK_ALTERNATE_check205="check25" check25(){ diff --git a/checks/check26 b/checks/check26 index 83395527..8647fd88 100644 --- a/checks/check26 +++ b/checks/check26 @@ -12,6 +12,8 @@ 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" CHECK_TYPE_check26="LEVEL1" +CHECK_ASFF_TYPE_check26="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check26="AwsS3Bucket" CHECK_ALTERNATE_check206="check26" check26(){ diff --git a/checks/check27 b/checks/check27 index f32b7bfe..56fd7392 100644 --- a/checks/check27 +++ b/checks/check27 @@ -12,6 +12,8 @@ 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" CHECK_TYPE_check27="LEVEL2" +CHECK_ASFF_TYPE_check27="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check27="AwsCloudTrailTrail" CHECK_ALTERNATE_check207="check27" check27(){ diff --git a/checks/check28 b/checks/check28 index bec0e234..adfbca41 100644 --- a/checks/check28 +++ b/checks/check28 @@ -12,6 +12,8 @@ CHECK_ID_check28="2.8,2.08" CHECK_TITLE_check28="[check28] Ensure rotation for customer created CMKs is enabled (Scored)" CHECK_SCORED_check28="SCORED" CHECK_TYPE_check28="LEVEL2" +CHECK_ASFF_TYPE_check28="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check28="AwsKmsKey" CHECK_ALTERNATE_check208="check28" check28(){ @@ -27,7 +29,7 @@ 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 - textPass "$regx: Key $key in Region $regx Customer Uploaded Key Material." "$regx" + textPass "$regx: 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 diff --git a/checks/check29 b/checks/check29 index d1f23dc8..c49efb2d 100644 --- a/checks/check29 +++ b/checks/check29 @@ -12,10 +12,12 @@ CHECK_ID_check29="2.9,2.09" CHECK_TITLE_check29="[check29] Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" CHECK_SCORED_check29="SCORED" CHECK_TYPE_check29="LEVEL2" +CHECK_ASFF_TYPE_check29="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check29="AwsEc2Vpc" CHECK_ALTERNATE_check209="check29" check29(){ - # "Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" + # "Ensure VPC Flow Logging is Enabled in all VPCs (Scored)" for regx in $REGIONS; do AVAILABLE_VPC=$($AWSCLI ec2 describe-vpcs $PROFILE_OPT --region $regx --query 'Vpcs[?State==`available`].VpcId' --output text) for vpcx in $AVAILABLE_VPC; do @@ -26,7 +28,7 @@ check29(){ done else textFail "VPC $vpcx: No VPCFlowLog has been found in Region $regx" "$regx" - fi + fi done done } diff --git a/checks/check31 b/checks/check31 index 8a8d1329..21768a15 100644 --- a/checks/check31 +++ b/checks/check31 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check31="LEVEL1" +CHECK_ASFF_TYPE_check31="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check31="AwsCloudTrailTrail" CHECK_ALTERNATE_check301="check31" check31(){ diff --git a/checks/check310 b/checks/check310 index 77f4b5a3..65d50773 100644 --- a/checks/check310 +++ b/checks/check310 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check310="LEVEL2" +CHECK_ASFF_TYPE_check310="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check310="AwsCloudTrailTrail" CHECK_ALTERNATE_check310="check310" check310(){ diff --git a/checks/check311 b/checks/check311 index b69fc75a..e38af0dc 100644 --- a/checks/check311 +++ b/checks/check311 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check311="LEVEL2" +CHECK_ASFF_TYPE_check311="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check311="AwsCloudTrailTrail" CHECK_ALTERNATE_check311="check311" check311(){ diff --git a/checks/check312 b/checks/check312 index 49e1462e..b5abde10 100644 --- a/checks/check312 +++ b/checks/check312 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check312="LEVEL1" +CHECK_ASFF_TYPE_check312="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check312="AwsCloudTrailTrail" CHECK_ALTERNATE_check312="check312" check312(){ diff --git a/checks/check313 b/checks/check313 index a6a81edc..0514045c 100644 --- a/checks/check313 +++ b/checks/check313 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check313="LEVEL1" +CHECK_ASFF_TYPE_check313="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check313="AwsCloudTrailTrail" CHECK_ALTERNATE_check313="check313" check313(){ diff --git a/checks/check314 b/checks/check314 index 3a6c9d7d..de9c3875 100644 --- a/checks/check314 +++ b/checks/check314 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check314="LEVEL1" +CHECK_ASFF_TYPE_check314="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check314="AwsCloudTrailTrail" CHECK_ALTERNATE_check314="check314" check314(){ diff --git a/checks/check32 b/checks/check32 index 83779842..745d38d5 100644 --- a/checks/check32 +++ b/checks/check32 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check32="LEVEL1" +CHECK_ASFF_TYPE_check32="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check32="AwsCloudTrailTrail" CHECK_ALTERNATE_check302="check32" check32(){ diff --git a/checks/check33 b/checks/check33 index 00c6d7dd..dd2b94db 100644 --- a/checks/check33 +++ b/checks/check33 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check33="LEVEL1" +CHECK_ASFF_TYPE_check33="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check33="AwsCloudTrailTrail" CHECK_ALTERNATE_check303="check33" check33(){ diff --git a/checks/check34 b/checks/check34 index e4751c79..86a55b25 100644 --- a/checks/check34 +++ b/checks/check34 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check34="LEVEL1" +CHECK_ASFF_TYPE_check34="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check34="AwsCloudTrailTrail" CHECK_ALTERNATE_check304="check34" check34(){ diff --git a/checks/check35 b/checks/check35 index b8b4c6cf..929be5b8 100644 --- a/checks/check35 +++ b/checks/check35 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check35="LEVEL1" +CHECK_ASFF_TYPE_check35="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check35="AwsCloudTrailTrail" CHECK_ALTERNATE_check305="check35" check35(){ diff --git a/checks/check36 b/checks/check36 index 699739d8..06e0d557 100644 --- a/checks/check36 +++ b/checks/check36 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check36="LEVEL2" +CHECK_ASFF_TYPE_check36="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check36="AwsCloudTrailTrail" CHECK_ALTERNATE_check306="check36" check36(){ diff --git a/checks/check37 b/checks/check37 index c0390bc9..4c6dd4d3 100644 --- a/checks/check37 +++ b/checks/check37 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check37="LEVEL2" +CHECK_ASFF_TYPE_check37="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check37="AwsCloudTrailTrail" CHECK_ALTERNATE_check307="check37" check37(){ diff --git a/checks/check38 b/checks/check38 index ddc69d36..c112620c 100644 --- a/checks/check38 +++ b/checks/check38 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check38="LEVEL1" +CHECK_ASFF_TYPE_check38="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check38="AwsCloudTrailTrail" CHECK_ALTERNATE_check308="check38" check38(){ diff --git a/checks/check39 b/checks/check39 index 3a812a4a..a649f157 100644 --- a/checks/check39 +++ b/checks/check39 @@ -37,6 +37,8 @@ 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" CHECK_TYPE_check39="LEVEL2" +CHECK_ASFF_TYPE_check39="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check39="AwsCloudTrailTrail" CHECK_ALTERNATE_check309="check39" check39(){ diff --git a/checks/check41 b/checks/check41 index 30fd9131..00260ebb 100644 --- a/checks/check41 +++ b/checks/check41 @@ -12,6 +12,8 @@ CHECK_ID_check41="4.1,4.01" CHECK_TITLE_check41="[check41] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to port 22 (Scored)" CHECK_SCORED_check41="SCORED" CHECK_TYPE_check41="LEVEL2" +CHECK_ASFF_TYPE_check41="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check41="AwsEc2SecurityGroup" CHECK_ALTERNATE_check401="check41" check41(){ diff --git a/checks/check42 b/checks/check42 index 92187620..a362b0cb 100644 --- a/checks/check42 +++ b/checks/check42 @@ -12,6 +12,8 @@ CHECK_ID_check42="4.2,4.02" CHECK_TITLE_check42="[check42] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to port 3389 (Scored)" CHECK_SCORED_check42="SCORED" CHECK_TYPE_check42="LEVEL2" +CHECK_ASFF_TYPE_check42="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check42="AwsEc2SecurityGroup" CHECK_ALTERNATE_check402="check42" check42(){ diff --git a/checks/check43 b/checks/check43 index 4599934d..6c0122ff 100644 --- a/checks/check43 +++ b/checks/check43 @@ -12,6 +12,8 @@ CHECK_ID_check43="4.3,4.03" CHECK_TITLE_check43="[check43] Ensure the default security group of every VPC restricts all traffic (Scored)" CHECK_SCORED_check43="SCORED" CHECK_TYPE_check43="LEVEL2" +CHECK_ASFF_TYPE_check43="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check43="AwsEc2SecurityGroup" CHECK_ALTERNATE_check403="check43" check43(){ diff --git a/checks/check44 b/checks/check44 index a45c116b..55ceb977 100644 --- a/checks/check44 +++ b/checks/check44 @@ -12,6 +12,8 @@ CHECK_ID_check44="4.4,4.04" CHECK_TITLE_check44="[check44] Ensure routing tables for VPC peering are \"least access\" (Not Scored)" CHECK_SCORED_check44="NOT_SCORED" CHECK_TYPE_check44="LEVEL2" +CHECK_ASFF_TYPE_check44="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" +CHECK_ASFF_RESOURCE_TYPE_check44="AwsEc2Vpc" CHECK_ALTERNATE_check404="check44" check44(){ diff --git a/checks/check_extra71 b/checks/check_extra71 index 8667666b..368ad9d4 100644 --- a/checks/check_extra71 +++ b/checks/check_extra71 @@ -14,6 +14,7 @@ CHECK_ID_extra71="7.1,7.01" CHECK_TITLE_extra71="[extra71] Ensure users of groups with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra71="NOT_SCORED" CHECK_TYPE_extra71="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra71="AwsIamUser" CHECK_ALTERNATE_extra701="extra71" CHECK_ALTERNATE_check71="extra71" CHECK_ALTERNATE_check701="extra71" diff --git a/checks/check_extra710 b/checks/check_extra710 index c259695a..55216b3d 100644 --- a/checks/check_extra710 +++ b/checks/check_extra710 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra710="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra710="AwsEc2Instance" CHECK_ALTERNATE_check710="extra710" extra710(){ diff --git a/checks/check_extra711 b/checks/check_extra711 index 717c8680..3e9b29ee 100644 --- a/checks/check_extra711 +++ b/checks/check_extra711 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra711="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra711="AwsRedshiftCluster" CHECK_ALTERNATE_check711="extra711" extra711(){ diff --git a/checks/check_extra712 b/checks/check_extra712 index 60e71566..251d93a5 100644 --- a/checks/check_extra712 +++ b/checks/check_extra712 @@ -22,7 +22,7 @@ extra712(){ 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 - textPass "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 textFail "No Macie related IAM roles found. It is most likely not to be enabled" fi diff --git a/checks/check_extra714 b/checks/check_extra714 index a47ecffe..cb57de85 100644 --- a/checks/check_extra714 +++ b/checks/check_extra714 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra714="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra714="AwsCloudFrontDistribution" CHECK_ALTERNATE_check714="extra714" extra714(){ diff --git a/checks/check_extra715 b/checks/check_extra715 index 0acde205..2268b719 100644 --- a/checks/check_extra715 +++ b/checks/check_extra715 @@ -14,6 +14,7 @@ CHECK_ID_extra715="7.15" CHECK_TITLE_extra715="[extra715] Check if Amazon Elasticsearch Service (ES) domains have logging enabled" CHECK_SCORED_extra715="NOT_SCORED" CHECK_TYPE_extra715="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra715="AwsElasticsearchDomain" CHECK_ALTERNATE_check715="extra715" extra715(){ diff --git a/checks/check_extra716 b/checks/check_extra716 index afdb8dd4..db3aba1d 100644 --- a/checks/check_extra716 +++ b/checks/check_extra716 @@ -14,6 +14,7 @@ CHECK_ID_extra716="7.16" CHECK_TITLE_extra716="[extra716] Check if Amazon Elasticsearch Service (ES) domains are set as Public and have cross account access " CHECK_SCORED_extra716="NOT_SCORED" CHECK_TYPE_extra716="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra716="AwsElasticsearchDomain" CHECK_ALTERNATE_check716="extra716" extra716(){ @@ -32,8 +33,8 @@ extra716(){ # If the endpoint starts with "vpc-" it is in a VPC then it is fine. if [[ "$ES_DOMAIN_ENDPOINT" =~ ^vpc-* ]];then ES_DOMAIN_VPC=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.VPCOptions.VPCId' --output text) - textInfo "$regx: Amazon ES domain $domain is in VPC $ES_DOMAIN_VPC run extra779 to make sure it is not exposed using custom proxy" "$regx" - else + textInfo "$regx: Amazon ES domain $domain is in VPC $ES_DOMAIN_VPC run extra779 to make sure it is not exposed using custom proxy" "$regx" + else $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_ES_DOMAIN_POLICY_OPEN=$(cat $TEMP_POLICY_FILE | jq -r '. | .Statement[] | select(.Effect == "Allow" and (((.Principal|type == "object") and .Principal.AWS == "*") or ((.Principal|type == "string") and .Principal == "*")) and select(has("Condition") | not))') CHECK_ES_DOMAIN_POLICY_HAS_CONDITION=$(cat $TEMP_POLICY_FILE | jq -r '. | .Statement[] | select(.Effect == "Allow" and (((.Principal|type == "object") and .Principal.AWS == "*") or ((.Principal|type == "string") and .Principal == "*")) and select(has("Condition")))' ) @@ -44,30 +45,30 @@ extra716(){ CONDITION_HAS_PRIVATE_IP=$(echo $condition_ip | grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)') if [[ $CONDITION_HAS_PRIVATE_IP ]];then CONDITION_HAS_PRIVATE_IP_ARRAY+=($condition_ip) - fi + fi CONDITION_HAS_PUBLIC_IP=$(echo $condition_ip | grep -vE '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|0\.0\.0\.0|\*)') if [[ $CONDITION_HAS_PUBLIC_IP ]];then CONDITION_HAS_PUBLIC_IP_ARRAY+=($condition_ip) fi CONDITION_HAS_ZERO_NET=$(echo $condition_ip | grep -E '^(0\.0\.0\.0|\*)') CONDITION_HAS_STAR=$(echo $condition_ip | grep -E '^\*') - done + done CHECK_ES_DOMAIN_POLICY_CONDITION_PRIVATE_IP=${CONDITION_HAS_PRIVATE_IP_ARRAY[@]} CHECK_ES_DOMAIN_POLICY_CONDITION_PUBLIC_IP=${CONDITION_HAS_PUBLIC_IP_ARRAY[@]} CHECK_ES_DOMAIN_POLICY_CONDITION_ZERO=$CONDITION_HAS_ZERO_NET CHECK_ES_DOMAIN_POLICY_CONDITION_STAR=$CONDITION_HAS_STAR - fi + fi if [[ $CHECK_ES_DOMAIN_POLICY_OPEN || $CHECK_ES_DOMAIN_POLICY_CONDITION_ZERO || $CHECK_ES_DOMAIN_POLICY_CONDITION_STAR || ${CHECK_ES_DOMAIN_POLICY_CONDITION_PUBLIC_IP[@]} ]];then #Prowler will check to read indices or kibaba status if no conditions, condition IP is *, 0.0.0.0/0, 0.0.0.0/8 or any public IP. if [[ $TEST_ES_AUTHENTICATION ]];then # check for REST API on port 443 CHECH_ES_HTTPS=$(curl -m 2 -s -w "%{http_code}" -o /dev/null -X GET "https://$ES_DOMAIN_ENDPOINT/_cat/indices") httpStatus $CHECH_ES_HTTPS - if [[ $CHECH_ES_HTTPS -eq "200" ]];then + if [[ $CHECH_ES_HTTPS -eq "200" ]];then textFail "$regx: Amazon ES domain $domain policy allows Anonymous access and ES service endpoint $ES_DOMAIN_ENDPOINT responded $SERVER_RESPONSE" "$regx" else textInfo "$regx: Amazon ES domain $domain policy allows Anonymous access but ES service endpoint $ES_DOMAIN_ENDPOINT responded $SERVER_RESPONSE" "$regx" - fi + fi # check for Kibana on port 443 CHECH_KIBANA_HTTPS=$(curl -m 2 -s -w "%{http_code}" -o /dev/null -X GET "https://$ES_DOMAIN_ENDPOINT/_plugin/kibana/api/status") httpStatus $CHECH_KIBANA_HTTPS @@ -75,27 +76,27 @@ extra716(){ textFail "$regx: Amazon ES domain $domain policy allows Anonymous access and Kibana service endpoint $ES_DOMAIN_ENDPOINT responded $SERVER_RESPONSE" "$regx" else textInfo "$regx: Amazon ES domain $domain policy allows Anonymous access but Kibana service endpoint $ES_DOMAIN_ENDPOINT responded $SERVER_RESPONSE" "$regx" - fi - else - if [[ $CHECK_ES_DOMAIN_POLICY_OPEN ]];then + fi + else + if [[ $CHECK_ES_DOMAIN_POLICY_OPEN ]];then textFail "$regx: Amazon ES domain $domain policy allows access (Principal: \"*\") AUTH NOT TESTED" "$regx" - fi - if [[ $CHECK_ES_DOMAIN_POLICY_HAS_CONDITION && $CHECK_ES_DOMAIN_POLICY_CONDITION_ZERO ]];then + fi + if [[ $CHECK_ES_DOMAIN_POLICY_HAS_CONDITION && $CHECK_ES_DOMAIN_POLICY_CONDITION_ZERO ]];then textFail "$regx: Amazon ES domain $domain policy allows access (Principal: \"*\" and network 0.0.0.0) AUTH NOT TESTED" "$regx" - fi - if [[ $CHECK_ES_DOMAIN_POLICY_HAS_CONDITION && $CHECK_ES_DOMAIN_POLICY_CONDITION_STAR ]];then + fi + if [[ $CHECK_ES_DOMAIN_POLICY_HAS_CONDITION && $CHECK_ES_DOMAIN_POLICY_CONDITION_STAR ]];then textFail "$regx: Amazon ES domain $domain policy allows access (Principal: \"*\" and network \"*\") AUTH NOT TESTED" "$regx" fi - if [[ $CHECK_ES_DOMAIN_POLICY_HAS_CONDITION && ${CHECK_ES_DOMAIN_POLICY_CONDITION_PUBLIC_IP[@]} ]];then + if [[ $CHECK_ES_DOMAIN_POLICY_HAS_CONDITION && ${CHECK_ES_DOMAIN_POLICY_CONDITION_PUBLIC_IP[@]} ]];then textFail "$regx: Amazon ES domain $domain policy allows access (Principal: \"*\" and Public IP or Network $(echo ${CONDITION_HAS_PUBLIC_IP_ARRAY[@]})) AUTH NOT TESTED" "$regx" fi - fi + fi else if [[ $CHECK_ES_DOMAIN_POLICY_HAS_CONDITION && ${CHECK_ES_DOMAIN_POLICY_CONDITION_PRIVATE_IP[@]} ]];then textInfo "$regx: Amazon ES domain $domain policy allows access from a Private IP or CIDR RFC1918 $(echo ${CONDITION_HAS_PRIVATE_IP_ARRAY[@]})" "$regx" - else - textPass "$regx: Amazon ES domain $domain does not allow Anonymous cross account access" "$regx" - fi + else + textPass "$regx: Amazon ES domain $domain does not allow Anonymous cross account access" "$regx" + fi fi rm -f $TEMP_POLICY_FILE fi @@ -104,4 +105,4 @@ extra716(){ textInfo "$regx: No Amazon ES domain found" "$regx" fi done -} +} diff --git a/checks/check_extra717 b/checks/check_extra717 index 0bb04741..74a18937 100644 --- a/checks/check_extra717 +++ b/checks/check_extra717 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra717="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra717="AwsElbLoadBalancer" CHECK_ALTERNATE_check717="extra717" extra717(){ diff --git a/checks/check_extra718 b/checks/check_extra718 index 73319113..0d361c3c 100644 --- a/checks/check_extra718 +++ b/checks/check_extra718 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra718="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra718="AwsS3Bucket" CHECK_ALTERNATE_check718="extra718" extra718(){ diff --git a/checks/check_extra72 b/checks/check_extra72 index f9fa11b9..52bcd93d 100644 --- a/checks/check_extra72 +++ b/checks/check_extra72 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra72="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra72="AwsEc2Snapshot" CHECK_ALTERNATE_extra702="extra72" CHECK_ALTERNATE_check72="extra72" CHECK_ALTERNATE_check702="extra72" diff --git a/checks/check_extra720 b/checks/check_extra720 index 1bf63cc5..64fbf043 100644 --- a/checks/check_extra720 +++ b/checks/check_extra720 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra720="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra720="AwsLambdaFunction" CHECK_ALTERNATE_check720="extra720" extra720(){ diff --git a/checks/check_extra721 b/checks/check_extra721 index ac6ca054..d464786a 100644 --- a/checks/check_extra721 +++ b/checks/check_extra721 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra721="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra721="AwsRedshiftCluster" CHECK_ALTERNATE_check721="extra721" extra721(){ diff --git a/checks/check_extra722 b/checks/check_extra722 index 605f7f19..e90596b7 100644 --- a/checks/check_extra722 +++ b/checks/check_extra722 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra722="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra722="AwsApiGatewayRestApi" CHECK_ALTERNATE_check722="extra722" extra722(){ diff --git a/checks/check_extra723 b/checks/check_extra723 index 96039eb9..c527c3c8 100644 --- a/checks/check_extra723 +++ b/checks/check_extra723 @@ -14,6 +14,7 @@ CHECK_ID_extra723="7.23" CHECK_TITLE_extra723="[extra723] Check if RDS Snapshots and Cluster Snapshots are public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra723="NOT_SCORED" CHECK_TYPE_extra723="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra723="AwsRdsDbSnapshot" CHECK_ALTERNATE_check723="extra723" extra723(){ diff --git a/checks/check_extra724 b/checks/check_extra724 index bb750855..2aa08b0f 100644 --- a/checks/check_extra724 +++ b/checks/check_extra724 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra724="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra724="AwsCertificateManagerCertificate" CHECK_ALTERNATE_check724="extra724" extra724(){ diff --git a/checks/check_extra725 b/checks/check_extra725 index 257a3d8e..5f4fc99e 100644 --- a/checks/check_extra725 +++ b/checks/check_extra725 @@ -15,6 +15,7 @@ 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_TYPE_extra725="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra725="AwsS3Bucket" CHECK_ALTERNATE_check725="extra725" # per Object-level logging is not configured at Bucket level but at CloudTrail trail level diff --git a/checks/check_extra727 b/checks/check_extra727 index 5e14e2b5..47c41fcb 100644 --- a/checks/check_extra727 +++ b/checks/check_extra727 @@ -15,6 +15,7 @@ CHECK_ID_extra727="7.27" CHECK_TITLE_extra727="[extra727] Check if SQS queues have policy set as Public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra727="NOT_SCORED" CHECK_TYPE_extra727="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra727="AwsSqsQueue" CHECK_ALTERNATE_check727="extra727" extra727(){ diff --git a/checks/check_extra728 b/checks/check_extra728 index eb27a9de..5399822d 100644 --- a/checks/check_extra728 +++ b/checks/check_extra728 @@ -15,6 +15,7 @@ CHECK_ID_extra728="7.28" CHECK_TITLE_extra728="[extra728] Check if SQS queues have Server Side Encryption enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra728="NOT_SCORED" CHECK_TYPE_extra728="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra728="AwsSqsQueue" CHECK_ALTERNATE_check728="extra728" extra728(){ diff --git a/checks/check_extra729 b/checks/check_extra729 index 603acbb0..756aa09c 100644 --- a/checks/check_extra729 +++ b/checks/check_extra729 @@ -15,6 +15,7 @@ CHECK_ID_extra729="7.29" CHECK_TITLE_extra729="[extra729] Ensure there are no EBS Volumes unencrypted (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra729="NOT_SCORED" CHECK_TYPE_extra729="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra729="AwsEc2Volume" CHECK_ALTERNATE_check729="extra729" extra729(){ diff --git a/checks/check_extra73 b/checks/check_extra73 index a587a60f..86b07197 100644 --- a/checks/check_extra73 +++ b/checks/check_extra73 @@ -15,6 +15,7 @@ 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" CHECK_TYPE_extra73="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra73="AwsS3Bucket" CHECK_ALTERNATE_extra703="extra73" CHECK_ALTERNATE_check73="extra73" CHECK_ALTERNATE_check703="extra73" diff --git a/checks/check_extra730 b/checks/check_extra730 index 53be1c58..06266cd3 100644 --- a/checks/check_extra730 +++ b/checks/check_extra730 @@ -17,6 +17,7 @@ CHECK_ID_extra730="7.30" CHECK_TITLE_extra730="[extra730] Check if ACM Certificates are about to expire in $DAYS_TO_EXPIRE_THRESHOLD days or less (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra730="NOT_SCORED" CHECK_TYPE_extra730="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra730="AwsCertificateManagerCertificate" CHECK_ALTERNATE_check730="extra730" extra730(){ diff --git a/checks/check_extra731 b/checks/check_extra731 index 0baa1b6e..744d28a1 100644 --- a/checks/check_extra731 +++ b/checks/check_extra731 @@ -15,6 +15,7 @@ CHECK_ID_extra731="7.31" CHECK_TITLE_extra731="[extra731] Check if SNS topics have policy set as Public (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra731="NOT_SCORED" CHECK_TYPE_extra731="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra731="AwsSnsTopic" CHECK_ALTERNATE_check731="extra731" extra731(){ diff --git a/checks/check_extra732 b/checks/check_extra732 index 2fc63a22..30c6ec7f 100644 --- a/checks/check_extra732 +++ b/checks/check_extra732 @@ -15,6 +15,7 @@ CHECK_ID_extra732="7.32" CHECK_TITLE_extra732="[extra732] Check if Geo restrictions are enabled in CloudFront distributions (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra732="NOT_SCORED" CHECK_TYPE_extra732="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra732="AwsCloudFrontDistribution" CHECK_ALTERNATE_check732="extra732" extra732(){ diff --git a/checks/check_extra734 b/checks/check_extra734 index bebd2bfc..02d7f4ec 100644 --- a/checks/check_extra734 +++ b/checks/check_extra734 @@ -14,6 +14,7 @@ CHECK_ID_extra734="7.34" CHECK_TITLE_extra734="[extra734] Check if S3 buckets have default encryption (SSE) enabled or use a bucket policy to enforce it (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra734="NOT_SCORED" CHECK_TYPE_extra734="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra734="AwsS3Bucket" CHECK_ALTERNATE_check734="extra734" extra734(){ diff --git a/checks/check_extra735 b/checks/check_extra735 index cc6ad238..0e49b698 100644 --- a/checks/check_extra735 +++ b/checks/check_extra735 @@ -14,6 +14,7 @@ CHECK_ID_extra735="7.35" CHECK_TITLE_extra735="[extra735] Check if RDS instances storage is encrypted (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra735="NOT_SCORED" CHECK_TYPE_extra735="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra735="AwsRdsDbInstance" CHECK_ALTERNATE_check735="extra735" extra735(){ diff --git a/checks/check_extra736 b/checks/check_extra736 index 0b5993a7..19082827 100644 --- a/checks/check_extra736 +++ b/checks/check_extra736 @@ -14,6 +14,7 @@ CHECK_ID_extra736="7.36" CHECK_TITLE_extra736="[extra736] Check exposed KMS keys (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra736="NOT_SCORED" CHECK_TYPE_extra736="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra736="AwsKmsKey" CHECK_ALTERNATE_check736="extra736" extra736(){ diff --git a/checks/check_extra737 b/checks/check_extra737 index d10a301f..3e1b6bf2 100644 --- a/checks/check_extra737 +++ b/checks/check_extra737 @@ -14,6 +14,7 @@ CHECK_ID_extra737="7.37" CHECK_TITLE_extra737="[extra737] Check KMS keys with key rotation disabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra737="NOT_SCORED" CHECK_TYPE_extra737="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra737="AwsKmsKey" CHECK_ALTERNATE_check737="extra737" extra737(){ diff --git a/checks/check_extra738 b/checks/check_extra738 index bc2b9dc5..c5b59eec 100644 --- a/checks/check_extra738 +++ b/checks/check_extra738 @@ -14,6 +14,7 @@ CHECK_ID_extra738="7.38" CHECK_TITLE_extra738="[extra738] Check if CloudFront distributions are set to HTTPS (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra738="NOT_SCORED" CHECK_TYPE_extra738="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra738="AwsCloudFrontDistribution" CHECK_ALTERNATE_check738="extra738" extra738(){ diff --git a/checks/check_extra739 b/checks/check_extra739 index 33ff5ecb..b1280683 100644 --- a/checks/check_extra739 +++ b/checks/check_extra739 @@ -14,6 +14,7 @@ CHECK_ID_extra739="7.39" CHECK_TITLE_extra739="[extra739] Check if RDS instances have backup enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra739="NOT_SCORED" CHECK_TYPE_extra739="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra739="AwsRdsDbInstance" CHECK_ALTERNATE_check739="extra739" extra739(){ @@ -21,12 +22,12 @@ extra739(){ LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].DBInstanceIdentifier' --output text) if [[ $LIST_OF_RDS_INSTANCES ]];then for rdsinstance in $LIST_OF_RDS_INSTANCES; do - # if retention is 0 then is disabled + # if retention is 0 then is disabled BACKUP_RETENTION=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --db-instance-identifier $rdsinstance --query 'DBInstances[*].BackupRetentionPeriod' --output text) if [[ $BACKUP_RETENTION == "0" ]]; then textFail "$regx: RDS instance $rdsinstance has not backup enabled!" "$regx" else - textPass "$regx: RDS instance $rdsinstance has backup enabled with retention period $BACKUP_RETENTION days " "$regx" + textPass "$regx: RDS instance $rdsinstance has backup enabled with retention period $BACKUP_RETENTION days" "$regx" fi done else diff --git a/checks/check_extra74 b/checks/check_extra74 index 68dbfa92..f700f1c4 100644 --- a/checks/check_extra74 +++ b/checks/check_extra74 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra74="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra74="AwsEc2SecurityGroup" CHECK_ALTERNATE_extra704="extra74" CHECK_ALTERNATE_check74="extra74" CHECK_ALTERNATE_check704="extra74" diff --git a/checks/check_extra740 b/checks/check_extra740 index d74c7600..5fa00518 100644 --- a/checks/check_extra740 +++ b/checks/check_extra740 @@ -14,6 +14,7 @@ CHECK_ID_extra740="7.40" CHECK_TITLE_extra740="[extra740] Check if EBS snapshots are encrypted (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra740="NOT_SCORED" CHECK_TYPE_extra740="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra740="AwsEc2Snapshot" CHECK_ALTERNATE_check740="extra740" extra740(){ @@ -30,7 +31,7 @@ extra740(){ fi done else - textInfo "$regx: No EBS Snapshots found" "$regx" + textInfo "$regx: No EBS Snapshots found" "$regx" fi done } diff --git a/checks/check_extra741 b/checks/check_extra741 index f4e54d2c..20b7b94a 100644 --- a/checks/check_extra741 +++ b/checks/check_extra741 @@ -14,14 +14,15 @@ CHECK_ID_extra741="7.41" CHECK_TITLE_extra741="[extra741] Find secrets in EC2 User Data (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra741="NOT_SCORED" CHECK_TYPE_extra741="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra741="AwsEc2Instance" CHECK_ALTERNATE_check741="extra741" extra741(){ SECRETS_TEMP_FOLDER="$PROWLER_DIR/secrets-$ACCOUNT_NUM" - if [[ ! -d $SECRETS_TEMP_FOLDER ]]; then + if [[ ! -d $SECRETS_TEMP_FOLDER ]]; then # this folder is deleted once this check is finished mkdir $SECRETS_TEMP_FOLDER - fi + fi textInfo "Looking for secrets in EC2 User Data in instances across all regions... (max 100 instances per region use -m to increase it) " for regx in $REGIONS; do @@ -56,7 +57,7 @@ extra741(){ textFail "$regx: Potential secret found in $instance" "$regx" fi fi - else + else textPass "$regx: No secrets found in $instance User Data or it is empty" "$regx" fi done diff --git a/checks/check_extra742 b/checks/check_extra742 index 8d78ab22..309f75d5 100644 --- a/checks/check_extra742 +++ b/checks/check_extra742 @@ -14,11 +14,12 @@ CHECK_ID_extra742="7.42" CHECK_TITLE_extra742="[extra742] Find secrets in CloudFormation outputs (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra742="NOT_SCORED" CHECK_TYPE_extra742="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra742="AwsCloudFormationStack" CHECK_ALTERNATE_check742="extra742" extra742(){ SECRETS_TEMP_FOLDER="$PROWLER_DIR/secrets-$ACCOUNT_NUM" - if [[ ! -d $SECRETS_TEMP_FOLDER ]]; then + if [[ ! -d $SECRETS_TEMP_FOLDER ]]; then # this folder is deleted once this check is finished mkdir $SECRETS_TEMP_FOLDER fi diff --git a/checks/check_extra743 b/checks/check_extra743 index e24326f9..4cd22003 100644 --- a/checks/check_extra743 +++ b/checks/check_extra743 @@ -14,6 +14,7 @@ CHECK_ID_extra743="7.43" CHECK_TITLE_extra743="[extra743] Check if API Gateway has client certificate enabled to access your backend endpoint (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra743="NOT_SCORED" CHECK_TYPE_extra743="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra743="AwsApiGatewayRestApi" CHECK_ALTERNATE_check743="extra743" extra743(){ @@ -23,15 +24,15 @@ extra743(){ for api in $LIST_OF_REST_APIS; do API_GW_NAME=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query "items[?id==\`$api\`].name" --output text) LIST_OF_STAGES=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-stages --rest-api-id $api --query 'item[*].stageName' --output text) - if [[ $LIST_OF_STAGES ]]; then + if [[ $LIST_OF_STAGES ]]; then for stage in $LIST_OF_STAGES; do CHECK_CERTIFICATE=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-stages --rest-api-id $api --query "item[?stageName==\`$stage\`].clientCertificateId" --output text) if [[ $CHECK_CERTIFICATE ]]; then textPass "$regx: API Gateway $API_GW_NAME ID $api in $stage has client certificate enabled" "$regx" - else + else textFail "$regx: API Gateway $API_GW_NAME ID $api in $stage has not client certificate enabled" "$regx" - fi - done + fi + done fi done else diff --git a/checks/check_extra744 b/checks/check_extra744 index 6b7bfb3a..4bc9edd6 100644 --- a/checks/check_extra744 +++ b/checks/check_extra744 @@ -14,6 +14,7 @@ CHECK_ID_extra744="7.44" CHECK_TITLE_extra744="[extra744] Check if API Gateway has a WAF ACL attached (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra744="NOT_SCORED" CHECK_TYPE_extra744="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra744="AwsApiGatewayRestApi" CHECK_ALTERNATE_check744="extra744" extra744(){ @@ -23,15 +24,15 @@ extra744(){ for api in $LIST_OF_REST_APIS; do API_GW_NAME=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query "items[?id==\`$api\`].name" --output text) LIST_OF_STAGES=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-stages --rest-api-id $api --query 'item[*].stageName' --output text) - if [[ $LIST_OF_STAGES ]]; then + if [[ $LIST_OF_STAGES ]]; then for stage in $LIST_OF_STAGES; do CHECK_WAFACL=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-stages --rest-api-id $api --query "item[?stageName==\`$stage\`].webAclArn" --output text) if [[ $CHECK_WAFACL ]]; then textPass "$regx: API Gateway $API_GW_NAME ID $api in $stage has $CHECK_WAFACL WAF ACL attached" "$regx" - else + else textFail "$regx: API Gateway $API_GW_NAME ID $api in $stage has not WAF ACL attached" "$regx" - fi - done + fi + done fi done else diff --git a/checks/check_extra745 b/checks/check_extra745 index 98a98e63..b8674e5c 100644 --- a/checks/check_extra745 +++ b/checks/check_extra745 @@ -14,6 +14,7 @@ CHECK_ID_extra745="7.45" CHECK_TITLE_extra745="[extra745] Check if API Gateway endpoint is public or private (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra745="NOT_SCORED" CHECK_TYPE_extra745="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra745="AwsApiGatewayRestApi" CHECK_ALTERNATE_check745="extra745" extra745(){ @@ -23,7 +24,7 @@ extra745(){ for api in $LIST_OF_REST_APIS; do API_GW_NAME=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query "items[?id==\`$api\`].name" --output text) ENDPOINT_CONFIG_TYPE=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-api --rest-api-id $api --query endpointConfiguration.types --output text) - if [[ $ENDPOINT_CONFIG_TYPE ]]; then + if [[ $ENDPOINT_CONFIG_TYPE ]]; then case $ENDPOINT_CONFIG_TYPE in PRIVATE ) textPass "$regx: API Gateway $API_GW_NAME ID $api is set as $ENDPOINT_CONFIG_TYPE" "$regx" diff --git a/checks/check_extra746 b/checks/check_extra746 index 073ca55f..79de26e7 100644 --- a/checks/check_extra746 +++ b/checks/check_extra746 @@ -14,6 +14,7 @@ CHECK_ID_extra746="7.46" CHECK_TITLE_extra746="[extra746] Check if API Gateway has configured authorizers (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra746="NOT_SCORED" CHECK_TYPE_extra746="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra746="AwsApiGatewayRestApi" CHECK_ALTERNATE_check746="extra746" extra746(){ @@ -23,7 +24,7 @@ extra746(){ for api in $LIST_OF_REST_APIS; do API_GW_NAME=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query "items[?id==\`$api\`].name" --output text) AUTHORIZER_CONFIGURED=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-authorizers --rest-api-id $api --query items[*].type --output text) - if [[ $AUTHORIZER_CONFIGURED ]]; then + if [[ $AUTHORIZER_CONFIGURED ]]; then textPass "$regx: API Gateway $API_GW_NAME ID $api has authorizer configured" "$regx" else textFail "$regx: API Gateway $API_GW_NAME ID $api has not authorizer configured" "$regx" diff --git a/checks/check_extra747 b/checks/check_extra747 index b9e28b1f..027359bf 100644 --- a/checks/check_extra747 +++ b/checks/check_extra747 @@ -14,6 +14,7 @@ CHECK_ID_extra747="7.47" CHECK_TITLE_extra747="[extra747] Check if RDS instances is integrated with CloudWatch Logs (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra747="NOT_SCORED" CHECK_TYPE_extra747="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra747="AwsRdsDbInstance" CHECK_ALTERNATE_check747="extra747" extra747(){ @@ -21,7 +22,7 @@ extra747(){ LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].DBInstanceIdentifier' --output text) if [[ $LIST_OF_RDS_INSTANCES ]];then for rdsinstance in $LIST_OF_RDS_INSTANCES; do - # if retention is 0 then is disabled + # if retention is 0 then is disabled ENABLED_CLOUDWATCHLOGS_EXPORTS=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --db-instance-identifier $rdsinstance --query 'DBInstances[*].EnabledCloudwatchLogsExports' --output text) if [[ $ENABLED_CLOUDWATCHLOGS_EXPORTS ]]; then textPass "$regx: RDS instance $rdsinstance is shipping $ENABLED_CLOUDWATCHLOGS_EXPORTS to CloudWatch Logs" "$regx" diff --git a/checks/check_extra748 b/checks/check_extra748 index 50056980..9aa71147 100644 --- a/checks/check_extra748 +++ b/checks/check_extra748 @@ -14,6 +14,7 @@ CHECK_ID_extra748="7.48" CHECK_TITLE_extra748="[extra748] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to any port (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra748="NOT_SCORED" CHECK_TYPE_extra748="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra748="AwsEc2SecurityGroup" CHECK_ALTERNATE_check748="extra748" extra748(){ diff --git a/checks/check_extra749 b/checks/check_extra749 index 3c4a53be..0a74e394 100644 --- a/checks/check_extra749 +++ b/checks/check_extra749 @@ -14,6 +14,7 @@ CHECK_ID_extra749="7.49" CHECK_TITLE_extra749="[extra749] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to Oracle ports 1521 or 2483 (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra749="NOT_SCORED" CHECK_TYPE_extra749="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra749="AwsEc2SecurityGroup" CHECK_ALTERNATE_check749="extra749" extra749(){ diff --git a/checks/check_extra75 b/checks/check_extra75 index f2007621..a93d01e2 100644 --- a/checks/check_extra75 +++ b/checks/check_extra75 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra75="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra75="AwsEc2SecurityGroup" CHECK_ALTERNATE_extra705="extra75" CHECK_ALTERNATE_check75="extra75" CHECK_ALTERNATE_check705="extra75" diff --git a/checks/check_extra750 b/checks/check_extra750 index 1b1d62e3..fd105bfc 100644 --- a/checks/check_extra750 +++ b/checks/check_extra750 @@ -14,6 +14,7 @@ CHECK_ID_extra750="7.50" CHECK_TITLE_extra750="[extra750] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to MySQL port 3306 (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra750="NOT_SCORED" CHECK_TYPE_extra750="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra750="AwsEc2SecurityGroup" CHECK_ALTERNATE_check750="extra750" extra750(){ diff --git a/checks/check_extra751 b/checks/check_extra751 index 3c8255ea..0d623ba8 100644 --- a/checks/check_extra751 +++ b/checks/check_extra751 @@ -14,6 +14,7 @@ CHECK_ID_extra751="7.51" CHECK_TITLE_extra751="[extra751] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to Postgres port 5432 (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra751="NOT_SCORED" CHECK_TYPE_extra751="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra751="AwsEc2SecurityGroup" CHECK_ALTERNATE_check751="extra751" extra751(){ diff --git a/checks/check_extra752 b/checks/check_extra752 index 650c7e82..e6472181 100644 --- a/checks/check_extra752 +++ b/checks/check_extra752 @@ -14,6 +14,7 @@ CHECK_ID_extra752="7.52" CHECK_TITLE_extra752="[extra752] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to Redis port 6379 (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra752="NOT_SCORED" CHECK_TYPE_extra752="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra752="AwsEc2SecurityGroup" CHECK_ALTERNATE_check752="extra752" extra752(){ diff --git a/checks/check_extra753 b/checks/check_extra753 index 2ba23a51..44824b93 100644 --- a/checks/check_extra753 +++ b/checks/check_extra753 @@ -14,6 +14,7 @@ CHECK_ID_extra753="7.53" CHECK_TITLE_extra753="[extra753] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to MongoDB ports 27017 and 27018 (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra753="NOT_SCORED" CHECK_TYPE_extra753="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra753="AwsEc2SecurityGroup" CHECK_ALTERNATE_check753="extra753" extra753(){ diff --git a/checks/check_extra754 b/checks/check_extra754 index 0b7472e0..30e8a939 100644 --- a/checks/check_extra754 +++ b/checks/check_extra754 @@ -14,6 +14,7 @@ CHECK_ID_extra754="7.54" CHECK_TITLE_extra754="[extra754] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to Cassandra ports 7199 or 9160 or 8888 (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra754="NOT_SCORED" CHECK_TYPE_extra754="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra754="AwsEc2SecurityGroup" CHECK_ALTERNATE_check754="extra754" extra754(){ diff --git a/checks/check_extra755 b/checks/check_extra755 index 0481f444..e0164d76 100644 --- a/checks/check_extra755 +++ b/checks/check_extra755 @@ -14,6 +14,7 @@ CHECK_ID_extra755="7.55" CHECK_TITLE_extra755="[extra755] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to Memcached port 11211 (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra755="NOT_SCORED" CHECK_TYPE_extra755="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra755="AwsEc2SecurityGroup" CHECK_ALTERNATE_check755="extra755" extra755(){ diff --git a/checks/check_extra756 b/checks/check_extra756 index 538fa55b..69dabb60 100644 --- a/checks/check_extra756 +++ b/checks/check_extra756 @@ -14,6 +14,7 @@ CHECK_ID_extra756="7.56" CHECK_TITLE_extra756="[extra756] Check if Redshift cluster is Public Accessible (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra756="NOT_SCORED" CHECK_TYPE_extra756="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra756="AwsRedshiftCluster" CHECK_ALTERNATE_check756="extra756" extra756(){ @@ -22,10 +23,10 @@ extra756(){ if [[ $LIST_OF_RS_CLUSTERS ]];then for cluster in $LIST_OF_RS_CLUSTERS; do IS_PUBLICLY_ACCESSIBLE=$($AWSCLI $PROFILE_OPT redshift describe-clusters --region $regx --cluster-identifier $cluster --query Clusters[*].PubliclyAccessible --output text|grep True) - if [[ $IS_PUBLICLY_ACCESSIBLE ]]; then - textFail "$regx: Redshift cluster $cluster is publicly accessible" "$regx" + if [[ $IS_PUBLICLY_ACCESSIBLE ]]; then + textFail "$regx: Redshift cluster $cluster is publicly accessible" "$regx" else - textPass "$regx: Redshift cluster $cluster is not publicly accessible" "$regx" + textPass "$regx: Redshift cluster $cluster is not publicly accessible" "$regx" fi done else diff --git a/checks/check_extra757 b/checks/check_extra757 index 0320081a..a5ddf6fd 100644 --- a/checks/check_extra757 +++ b/checks/check_extra757 @@ -14,6 +14,7 @@ CHECK_ID_extra757="7.57" CHECK_TITLE_extra757="[extra757] Check EC2 Instances older than 6 months (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra757="NOT_SCORED" CHECK_TYPE_extra757="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra757="AwsEc2Instance" CHECK_ALTERNATE_check757="extra757" extra757(){ diff --git a/checks/check_extra758 b/checks/check_extra758 index 1c402aa5..5f5fe40b 100644 --- a/checks/check_extra758 +++ b/checks/check_extra758 @@ -14,6 +14,7 @@ CHECK_ID_extra758="7.58" CHECK_TITLE_extra758="[extra758] Check EC2 Instances older than 12 months (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra758="NOT_SCORED" CHECK_TYPE_extra758="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra758="AwsEc2Instance" CHECK_ALTERNATE_check758="extra758" extra758(){ diff --git a/checks/check_extra759 b/checks/check_extra759 index dbd07632..6b3ff15e 100644 --- a/checks/check_extra759 +++ b/checks/check_extra759 @@ -14,14 +14,15 @@ CHECK_ID_extra759="7.59" CHECK_TITLE_extra759="[extra759] Find secrets in Lambda functions variables (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra759="NOT_SCORED" CHECK_TYPE_extra759="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra759="AwsLambdaFunction" CHECK_ALTERNATE_check759="extra759" extra759(){ SECRETS_TEMP_FOLDER="$PROWLER_DIR/secrets-$ACCOUNT_NUM" - if [[ ! -d $SECRETS_TEMP_FOLDER ]]; then + if [[ ! -d $SECRETS_TEMP_FOLDER ]]; then # this folder is deleted once this check is finished mkdir $SECRETS_TEMP_FOLDER - fi + fi textInfo "Looking for secrets in Lambda variables across all regions... " for regx in $REGIONS; do diff --git a/checks/check_extra760 b/checks/check_extra760 index eac466e7..ee66c791 100644 --- a/checks/check_extra760 +++ b/checks/check_extra760 @@ -14,11 +14,12 @@ CHECK_ID_extra760="7.60" CHECK_TITLE_extra760="[extra760] Find secrets in Lambda functions code (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra760="NOT_SCORED" CHECK_TYPE_extra760="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra760="AwsLambdaFunction" CHECK_ALTERNATE_check760="extra760" extra760(){ SECRETS_TEMP_FOLDER="$PROWLER_DIR/secrets-$ACCOUNT_NUM" - if [[ ! -d $SECRETS_TEMP_FOLDER ]]; then + if [[ ! -d $SECRETS_TEMP_FOLDER ]]; then # this folder is deleted once this check is finished mkdir $SECRETS_TEMP_FOLDER fi diff --git a/checks/check_extra762 b/checks/check_extra762 index b54cd5ac..c66974e6 100644 --- a/checks/check_extra762 +++ b/checks/check_extra762 @@ -14,6 +14,7 @@ CHECK_ID_extra762="7.62" CHECK_TITLE_extra762="[extra762] Find obsolete Lambda runtimes (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra762="NOT_SCORED" CHECK_TYPE_extra762="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra762="AwsLambdaFunction" CHECK_ALTERNATE_check762="extra762" extra762(){ diff --git a/checks/check_extra763 b/checks/check_extra763 index 7c839cf3..9ceb9494 100644 --- a/checks/check_extra763 +++ b/checks/check_extra763 @@ -14,6 +14,7 @@ CHECK_ID_extra763="7.63" CHECK_TITLE_extra763="[extra763] Check if S3 buckets have object versioning enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra763="NOT_SCORED" CHECK_TYPE_extra763="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra763="AwsS3Bucket" CHECK_ALTERNATE_check763="extra763" extra763(){ @@ -28,7 +29,7 @@ extra763(){ fi if [[ $(echo "$BUCKET_VERSIONING_ENABLED" | grep "^Enabled$") ]]; then textPass "Bucket $bucket has versioning enabled" - else + else textFail "Bucket $bucket has versioning disabled!" fi done diff --git a/checks/check_extra764 b/checks/check_extra764 index 8b849208..8ec26cd4 100644 --- a/checks/check_extra764 +++ b/checks/check_extra764 @@ -14,6 +14,7 @@ CHECK_ID_extra764="7.64" CHECK_TITLE_extra764="[extra764] Check if S3 buckets have secure transport policy (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra764="NOT_SCORED" CHECK_TYPE_extra764="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra764="AwsS3Bucket" CHECK_ALTERNATE_check764="extra764" extra764(){ diff --git a/checks/check_extra767 b/checks/check_extra767 index 1bbe4d8a..1683d466 100644 --- a/checks/check_extra767 +++ b/checks/check_extra767 @@ -14,6 +14,7 @@ CHECK_ID_extra767="7.67" CHECK_TITLE_extra767="[extra767] Check if CloudFront distributions have Field Level Encryption enabled (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra767="NOT_SCORED" CHECK_TYPE_extra767="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra767="AwsCloudFrontDistribution" CHECK_ALTERNATE_check767="extra767" extra767(){ @@ -23,7 +24,7 @@ extra767(){ CHECK_FLE=$($AWSCLI cloudfront get-distribution --id $dist --query Distribution.DistributionConfig.DefaultCacheBehavior.FieldLevelEncryptionId $PROFILE_OPT --output text) if [[ $CHECK_FLE ]]; then textPass "CloudFront distribution $dist has Field Level Encryption enabled" "$regx" - else + else textFail "CloudFront distribution $dist has Field Level Encryption disabled!" "$regx" fi done diff --git a/checks/check_extra768 b/checks/check_extra768 index 2c10e1dd..b357c72e 100644 --- a/checks/check_extra768 +++ b/checks/check_extra768 @@ -14,6 +14,7 @@ CHECK_ID_extra768="7.68" CHECK_TITLE_extra768="[extra768] Find secrets in ECS task definitions variables (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra768="NOT_SCORED" CHECK_TYPE_extra768="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra768="AwsEcsTaskDefinition" CHECK_ALTERNATE_check768="extra768" extra768(){ diff --git a/checks/check_extra770 b/checks/check_extra770 index f39de564..b657bbaa 100644 --- a/checks/check_extra770 +++ b/checks/check_extra770 @@ -14,6 +14,7 @@ CHECK_ID_extra770="7.70" CHECK_TITLE_extra770="[extra770] Check for internet facing EC2 instances with Instance Profiles attached (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra770="NOT_SCORED" CHECK_TYPE_extra770="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra770="AwsEc2Instance" CHECK_ALTERNATE_check770="extra770" extra770(){ diff --git a/checks/check_extra771 b/checks/check_extra771 index ecd240c3..0c940649 100644 --- a/checks/check_extra771 +++ b/checks/check_extra771 @@ -14,6 +14,7 @@ CHECK_ID_extra771="7.71" CHECK_TITLE_extra771="[extra771] Check if S3 buckets have policies which allow WRITE access (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra771="NOT_SCORED" CHECK_TYPE_extra771="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra771="AwsS3Bucket" CHECK_ALTERNATE_check771="extra771" extra771(){ diff --git a/checks/check_extra772 b/checks/check_extra772 index 83f3cdd5..088be100 100644 --- a/checks/check_extra772 +++ b/checks/check_extra772 @@ -14,6 +14,7 @@ CHECK_ID_extra772="7.72" CHECK_TITLE_extra772="[extra772] Check if elastic IPs are unused (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra772="NOT_SCORED" CHECK_TYPE_extra772="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra772="AwsEc2Eip" CHECK_ALTERNATE_check772="extra772" extra772(){ diff --git a/checks/check_extra773 b/checks/check_extra773 index ecd26385..dbfba0ca 100644 --- a/checks/check_extra773 +++ b/checks/check_extra773 @@ -14,6 +14,7 @@ CHECK_ID_extra773="7.73" CHECK_TITLE_extra773="[extra773] Check if CloudFront distributions are using WAF (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra773="NOT_SCORED" CHECK_TYPE_extra773="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra773="AwsCloudFrontDistribution" CHECK_ALTERNATE_check773="extra773" extra773(){ diff --git a/checks/check_extra774 b/checks/check_extra774 index 83e2aa6f..58042dd3 100644 --- a/checks/check_extra774 +++ b/checks/check_extra774 @@ -14,6 +14,7 @@ CHECK_ID_extra774="7.74" CHECK_TITLE_extra774="[extra774] Check if user have unused console login" CHECK_SCORED_extra774="NOT_SCORED" CHECK_TYPE_extra774="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra774="AwsIamUser" CHECK_ALTERNATE_check774="extra774" extra774(){ diff --git a/checks/check_extra777 b/checks/check_extra777 index 1ccf541f..fa3d8c0c 100644 --- a/checks/check_extra777 +++ b/checks/check_extra777 @@ -12,12 +12,13 @@ # specific language governing permissions and limitations under the License. # Current VPC Limit is 120 rules (60 inbound and 60 outbound) -# Reference: https://docs.aws.amazon.com/vpc/latest/userguide/amazon-vpc-limits.html +# Reference: https://docs.aws.amazon.com/vpc/latest/userguide/amazon-vpc-limits.html CHECK_ID_extra777="7.77" CHECK_TITLE_extra777="[extra777] Find VPC security groups with many ingress or egress rules (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra777="NOT_SCORED" CHECK_TYPE_extra777="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra777="AwsEc2SecurityGroup" CHECK_ALTERNATE_check777="extra777" extra777(){ @@ -31,7 +32,7 @@ extra777(){ --query 'SecurityGroups[*].GroupId' \ --output text | xargs ) - + for SECURITY_GROUP in ${SECURITY_GROUP_IDS}; do INGRESS_TOTAL=$(${AWSCLI} ec2 describe-security-groups \ @@ -51,8 +52,8 @@ extra777(){ ) if [[ (${INGRESS_TOTAL} -ge ${THRESHOLD}) || (${EGRESS_TOTAL} -ge ${THRESHOLD}) ]]; then - textFail "${regx}: ${SECURITY_GROUP} has ${INGRESS_TOTAL} inbound rules and ${EGRESS_TOTAL} outbound rules." "${regx}" + textFail "${regx}: ${SECURITY_GROUP} has ${INGRESS_TOTAL} inbound rules and ${EGRESS_TOTAL} outbound rules" "${regx}" fi done done -} \ No newline at end of file +} diff --git a/checks/check_extra778 b/checks/check_extra778 index 42672348..8d511687 100644 --- a/checks/check_extra778 +++ b/checks/check_extra778 @@ -15,6 +15,7 @@ CHECK_ID_extra778="7.78" CHECK_TITLE_extra778="[extra778] Find VPC security groups with wide-open public IPv4 CIDR ranges (non-RFC1918) (Not Scored) (Not part of CIS benchmark)" CHECK_SCORED_extra778="NOT_SCORED" CHECK_TYPE_extra778="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra778="AwsEc2SecurityGroup" CHECK_ALTERNATE_check778="extra778" extra778(){ @@ -27,7 +28,7 @@ extra778(){ local DIRECTION=$2 local DIRECTION_FILTER="" local REGION=$3 - + case ${DIRECTION} in "inbound") DIRECTION_FILTER="IpPermissions" @@ -44,14 +45,14 @@ extra778(){ --region ${REGION} \ --output text | xargs ) - + for CIDR_IP in ${CIDR_IP_LIST}; do if [[ ! ${CIDR_IP} =~ ${RFC1918_REGEX} ]]; then CIDR=$(echo ${CIDR_IP} | cut -d"/" -f2 | xargs) # Edge case "0.0.0.0/0" for RDP and SSH are checked already by check41 and check42 if [[ ${CIDR} < ${CIDR_THRESHOLD} && 0 < ${CIDR} ]]; then - textFail "${REGION}: ${SECURITY_GROUP} has potential wide-open non-RFC1918 address ${CIDR_IP} in ${DIRECTION} rule." "${REGION}" + textFail "${REGION}: ${SECURITY_GROUP} has potential wide-open non-RFC1918 address ${CIDR_IP} in ${DIRECTION} rule" "${REGION}" fi fi done @@ -69,4 +70,4 @@ extra778(){ check_cidr "${SECURITY_GROUP}" "outbound" "${regx}" done done -} \ No newline at end of file +} diff --git a/checks/check_extra779 b/checks/check_extra779 index 627bc51a..02a32868 100644 --- a/checks/check_extra779 +++ b/checks/check_extra779 @@ -12,8 +12,9 @@ # specific language governing permissions and limitations under the License. CHECK_ID_extra779="7.79" CHECK_TITLE_extra779="[extra779] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to Elasticsearch/Kibana ports" -CHECK_SCORED_extra779="NOT_SCORED" +CHECK_SCORED_extra779="NOT_SCORED" CHECK_TYPE_extra779="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra779="AwsEc2SecurityGroup" CHECK_ALTERNATE_check779="extra779" extra779(){ @@ -38,30 +39,30 @@ extra779(){ $AWSCLI $PROFILE_OPT --region $regx ec2 describe-instances --filters Name=instance.group-id,Values=$sg --query 'Reservations[*].Instances[*].[InstanceId,PublicIpAddress]' --output text > $TEMP_EXTRA779_FILE # in case of exposed instances it does access checks if [[ -s "$TEMP_EXTRA779_FILE" ]];then - while read instance eip ; do + while read instance eip ; do if [[ $TEST_ES_AUTHENTICATION ]];then - if [[ "$eip" != "None" ]];then + if [[ "$eip" != "None" ]];then # check for Elasticsearch on port $ES_API_PORT, rest API HTTP. CHECH_HTTP_ES_API=$(curl -m 2 -s -w "%{http_code}" -o /dev/null -X GET "http://$eip:$ES_API_PORT/_cat/indices") httpStatus $CHECH_HTTP_ES_API - if [[ $CHECH_HTTP_ES_API -eq "200" ]];then + if [[ $CHECH_HTTP_ES_API -eq "200" ]];then textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch port $ES_API_PORT response $SERVER_RESPONSE" "$regx" else textInfo "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch port $ES_API_PORT response $SERVER_RESPONSE" "$regx" - fi + fi # check for port $ES_DATA_PORT TCP, this is the communication port, not: - # test_tcp_connectivity is in include/os_detector + # test_tcp_connectivity is in include/os_detector # syntax is 'test_tcp_connectivity $HOST $PORT $TIMEOUT' (in seconds) CHECH_HTTP_ES_DATA=$(test_tcp_connectivity $eip $ES_DATA_PORT 2) - # Using HTTP error codes here as well to reuse httpStatus function + # Using HTTP error codes here as well to reuse httpStatus function # codes for better handling, so 200 is open and 000 is not responding httpStatus $CHECH_HTTP_ES_DATA if [[ $CHECH_HTTP_ES_DATA -eq "200" ]];then textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch port $ES_DATA_PORT response $SERVER_RESPONSE" "$regx" else textInfo "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch port $ES_DATA_PORT response $SERVER_RESPONSE" "$regx" - fi + fi # check for Kibana on port $ES_KIBANA_PORT CHECH_HTTP_ES_KIBANA=$(curl -m 2 -s -w "%{http_code}" -o /dev/null -X GET "http://$eip:$ES_KIBANA_PORT/api/status") @@ -70,25 +71,25 @@ extra779(){ textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Kibana on port $ES_KIBANA_PORT response $SERVER_RESPONSE" "$regx" else textInfo "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Kibana on port $ES_KIBANA_PORT response $SERVER_RESPONSE" "$regx" - fi - fi + fi + fi else - if [[ "$eip" == "None" ]];then + if [[ "$eip" == "None" ]];then textInfo "$regx: Found instance $instance with private IP on Security Group: $sg" "$regx" - else + else textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg open to 0.0.0.0/0 on for Elasticsearch/Kibana ports $ES_API_PORT/$ES_DATA_PORT/$ES_KIBANA_PORT" "$regx" - fi - fi - if [[ "$eip" == "None" ]];then + fi + fi + if [[ "$eip" == "None" ]];then textInfo "$regx: Found instance $instance with private IP on Security Group: $sg" "$regx" fi # done < <(cat $TEMP_EXTRA779_FILE | grep -v None$) done < <(cat $TEMP_EXTRA779_FILE) - # while read instance eip ; do + # while read instance eip ; do # textInfo "$regx: Found instance $instance with private IP on Security Group: $sg" "$regx" # done < <(cat $TEMP_EXTRA779_FILE | grep None$) - fi - rm -rf $TEMP_EXTRA779_FILE + fi + rm -rf $TEMP_EXTRA779_FILE #textFail "$regx: Found Security Group: $sg open to 0.0.0.0/0 on for Elasticsearch ports" "$regx" done else diff --git a/checks/check_extra78 b/checks/check_extra78 index 9bea1a3d..ee652259 100644 --- a/checks/check_extra78 +++ b/checks/check_extra78 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra78="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra78="AwsRdsDbInstance" CHECK_ALTERNATE_extra708="extra78" CHECK_ALTERNATE_check78="extra78" CHECK_ALTERNATE_check708="extra78" diff --git a/checks/check_extra780 b/checks/check_extra780 index eadb584a..0a694c35 100644 --- a/checks/check_extra780 +++ b/checks/check_extra780 @@ -14,6 +14,7 @@ CHECK_ID_extra780="7.80" CHECK_TITLE_extra780="[extra780] Check if Amazon Elasticsearch Service (ES) domains has Amazon Cognito authentication for Kibana enabled" CHECK_SCORED_extra780="NOT_SCORED" CHECK_TYPE_extra780="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra780="AwsElasticsearchDomain" CHECK_ALTERNATE_check780="extra780" extra780(){ @@ -24,7 +25,7 @@ extra780(){ CHECK_IF_COGNITO_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.CognitoOptions.Enabled' --output text|grep -i true) if [[ $CHECK_IF_COGNITO_ENABLED ]];then textPass "$regx: Amazon ES domain $domain has Amazon Cognito authentication for Kibana enabled" "$regx" - else + else textFail "$regx: Amazon ES domain $domain does not have Amazon Cognito authentication for Kibana enabled" "$regx" fi done diff --git a/checks/check_extra781 b/checks/check_extra781 index 2b19cc7e..e4f36620 100644 --- a/checks/check_extra781 +++ b/checks/check_extra781 @@ -14,6 +14,7 @@ CHECK_ID_extra781="7.81" CHECK_TITLE_extra781="[extra781] Check if Amazon Elasticsearch Service (ES) domains has encryption at-rest enabled" CHECK_SCORED_extra781="NOT_SCORED" CHECK_TYPE_extra781="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra781="AwsElasticsearchDomain" CHECK_ALTERNATE_check781="extra781" extra781(){ @@ -24,7 +25,7 @@ extra781(){ CHECK_IF_ENCREST_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.EncryptionAtRestOptions.Enabled' --output text|grep -i true) if [[ $CHECK_IF_ENCREST_ENABLED ]];then textPass "$regx: Amazon ES domain $domain has encryption at-rest enabled" "$regx" - else + else textFail "$regx: Amazon ES domain $domain does not have encryption at-rest enabled" "$regx" fi done diff --git a/checks/check_extra782 b/checks/check_extra782 index 1c38c7f3..ab169bee 100644 --- a/checks/check_extra782 +++ b/checks/check_extra782 @@ -14,6 +14,7 @@ CHECK_ID_extra782="7.82" CHECK_TITLE_extra782="[extra782] Check if Amazon Elasticsearch Service (ES) domains has node-to-node encryption enabled" CHECK_SCORED_extra782="NOT_SCORED" CHECK_TYPE_extra782="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra782="AwsElasticsearchDomain" CHECK_ALTERNATE_check782="extra782" extra782(){ @@ -24,7 +25,7 @@ extra782(){ CHECK_IF_NODETOENCR_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.NodeToNodeEncryptionOptions.Enabled' --output text|grep -i true) if [[ $CHECK_IF_NODETOENCR_ENABLED ]];then textPass "$regx: Amazon ES domain $domain has node-to-node encryption enabled" "$regx" - else + else textFail "$regx: Amazon ES domain $domain does not have node-to-node encryption enabled" "$regx" fi done diff --git a/checks/check_extra783 b/checks/check_extra783 index 4c33b1ac..fa76f6f1 100644 --- a/checks/check_extra783 +++ b/checks/check_extra783 @@ -14,6 +14,7 @@ CHECK_ID_extra783="7.83" CHECK_TITLE_extra783="[extra783] Check if Amazon Elasticsearch Service (ES) domains has enforce HTTPS enabled" CHECK_SCORED_extra783="NOT_SCORED" CHECK_TYPE_extra783="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra783="AwsElasticsearchDomain" CHECK_ALTERNATE_check783="extra783" extra783(){ @@ -24,7 +25,7 @@ extra783(){ CHECK_IF_ENFORCEHTTPS_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.DomainEndpointOptions.EnforceHTTPS' --output text|grep -i true) if [[ $CHECK_IF_ENFORCEHTTPS_ENABLED ]];then textPass "$regx: Amazon ES domain $domain has enforce HTTPS enabled" "$regx" - else + else textFail "$regx: Amazon ES domain $domain does not have enforce HTTPS enabled" "$regx" fi done diff --git a/checks/check_extra784 b/checks/check_extra784 index cb407538..29779d50 100644 --- a/checks/check_extra784 +++ b/checks/check_extra784 @@ -14,6 +14,7 @@ CHECK_ID_extra784="7.84" CHECK_TITLE_extra784="[extra784] Check if Amazon Elasticsearch Service (ES) domains internal user database enabled" CHECK_SCORED_extra784="NOT_SCORED" CHECK_TYPE_extra784="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra784="AwsElasticsearchDomain" CHECK_ALTERNATE_check784="extra784" extra784(){ @@ -24,7 +25,7 @@ extra784(){ CHECK_IF_INTERNALDB_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.AdvancedSecurityOptions.InternalUserDatabaseEnabled' --output text|grep -i true) if [[ $CHECK_IF_INTERNALDB_ENABLED ]];then textPass "$regx: Amazon ES domain $domain has internal user database enabled" "$regx" - else + else textFail "$regx: Amazon ES domain $domain does not have internal user database enabled" "$regx" fi done diff --git a/checks/check_extra785 b/checks/check_extra785 index 7e22a689..59ffba11 100644 --- a/checks/check_extra785 +++ b/checks/check_extra785 @@ -14,12 +14,13 @@ CHECK_ID_extra785="7.85" CHECK_TITLE_extra785="[extra785] Check if Amazon Elasticsearch Service (ES) domains have updates available" CHECK_SCORED_extra785="NOT_SCORED" CHECK_TYPE_extra785="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra785="AwsElasticsearchDomain" CHECK_ALTERNATE_check785="extra785" -# NOTE! +# NOTE! # API does not properly shows if an update is available while it is a new version available # that can be done using the Console but not the API, not sure if it is a bug -# I have to investigate further +# I have to investigate further extra785(){ for regx in $REGIONS; do @@ -29,8 +30,8 @@ extra785(){ CHECK_IF_UPDATE_AVAILABLE_AND_VERSION=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.[ServiceSoftwareOptions.UpdateAvailable,ElasticsearchVersion]' --output text) while read update_status es_version;do if [[ $update_status != "False" ]];then - textInfo "$regx: Amazon ES domain $domain v$es_version has updates available " "$regx" - else + textInfo "$regx: Amazon ES domain $domain v$es_version has updates available" "$regx" + else textPass "$regx: Amazon ES domain $domain v$es_version does not have have updates available" "$regx" fi done < <(echo $CHECK_IF_UPDATE_AVAILABLE_AND_VERSION) diff --git a/checks/check_extra79 b/checks/check_extra79 index e45e5ddc..d46a63a7 100644 --- a/checks/check_extra79 +++ b/checks/check_extra79 @@ -14,6 +14,7 @@ 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" CHECK_TYPE_extra79="EXTRA" +CHECK_ASFF_RESOURCE_TYPE_extra79="AwsElbLoadBalancer" CHECK_ALTERNATE_extra709="extra79" CHECK_ALTERNATE_check79="extra79" CHECK_ALTERNATE_check709="extra79" diff --git a/checks/check_sample b/checks/check_sample index 54c9d880..b041e30c 100644 --- a/checks/check_sample +++ b/checks/check_sample @@ -15,7 +15,7 @@ # # here URL to the relevand/official documentation # -# here commands or steps to fix it if avalable, like: +# here commands or steps to fix it if avalable, like: # aws logs put-metric-filter \ # --region us-east-1 \ # --log-group-name CloudTrail/MyCloudTrailLG \ @@ -28,6 +28,7 @@ # CHECK_TITLE_checkN="[checkN] Description (Not Scored) (Not part of CIS benchmark)" # CHECK_SCORED_checkN="NOT_SCORED" # CHECK_TYPE_checkN="EXTRA" +# CHECK_ASFF_RESOURCE_TYPE_checkN="AwsAccount" # Choose appropriate value from https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format.html#asff-resources # CHECK_ALTERNATE_checkN="extraN" # # extraN(){ diff --git a/iam/prowler-security-hub.json b/iam/prowler-security-hub.json new file mode 100644 index 00000000..309c086a --- /dev/null +++ b/iam/prowler-security-hub.json @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "securityhub:BatchImportFindings" + ], + "Effect": "Allow", + "Resource": "*" + } + ] +} diff --git a/include/colors b/include/colors index 68ac32a4..e938d143 100644 --- a/include/colors +++ b/include/colors @@ -11,9 +11,9 @@ # 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" && "$MODE" != "json" && "$MODE" != "json-asff" && "$MODE" != "securityhub" ]]; then +if [[ "$MODE" != "mono" && "$MODE" != "text" && "$MODE" != "csv" && "$MODE" != "json" && "$MODE" != "json-asff" ]]; then echo "" - echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json, json-asff or securityhub." + echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json or json-asff." usage EXITCODE=1 exit $EXITCODE diff --git a/include/outputs b/include/outputs index 6af14778..40d67a7c 100644 --- a/include/outputs +++ b/include/outputs @@ -18,7 +18,7 @@ textPass(){ fi PASS_COUNTER=$((PASS_COUNTER+1)) - if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" || "$MODE" == "securityhub" ]]; then + if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then if [[ $2 ]]; then REPREGION=$2 else @@ -29,10 +29,11 @@ textPass(){ elif [[ "$MODE" == "json" ]]; then generateJsonOutput "$1" "Pass" elif [[ "$MODE" == "json-asff" ]]; then - generateJsonAsffOutput "$1" "PASSED" "INFORMATIONAL" - elif [[ "$MODE" == "securityhub" ]]; then - printf " $OK PASS!$NORMAL %s... " "$1" - aws securityhub batch-import-findings --findings "$(generateJsonAsffOutput "$1" "PASSED" "INFORMATIONAL")" | jq -M -r 'if .SuccessCount == 1 then "Successfully submitted finding" else "Failed to upload finding" end' + JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "PASSED" "INFORMATIONAL") + echo "${JSON_ASFF_OUTPUT}" + if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then + sendToSecurityHub "${JSON_ASFF_OUTPUT}" + fi fi else echo " $OK PASS!$NORMAL $1" @@ -54,11 +55,6 @@ textInfo(){ echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" elif [[ "$MODE" == "json" ]]; then generateJsonOutput "$1" "Info" - elif [[ "$MODE" == "json-asff" ]]; then - generateJsonAsffOutput "$1" "NOT_AVAILABLE" "LOW" - elif [[ "$MODE" == "securityhub" ]]; then - printf " $NOTICE INFO! %s... $NORMAL" "$1" - aws securityhub batch-import-findings --findings "$(generateJsonAsffOutput "$1" "NOT_AVAILABLE" "LOW")" | jq -M -r 'if .SuccessCount == 1 then "Successfully submitted finding" else "Failed to upload finding" end' fi else echo " $NOTICE INFO! $1 $NORMAL" @@ -68,7 +64,7 @@ textInfo(){ textFail(){ FAIL_COUNTER=$((FAIL_COUNTER+1)) EXITCODE=3 - if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" || "$MODE" == "securityhub" ]]; then + if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then if [[ $2 ]]; then REPREGION=$2 else @@ -79,10 +75,11 @@ textFail(){ elif [[ "$MODE" == "json" ]]; then generateJsonOutput "$1" "Fail" elif [[ "$MODE" == "json-asff" ]]; then - generateJsonAsffOutput "$1" "FAILED" "HIGH" - elif [[ "$MODE" == "securityhub" ]]; then - printf " $BAD FAIL! %s... $NORMAL" "$1" - aws securityhub batch-import-findings --findings "$(generateJsonAsffOutput "$1" "FAILED" "HIGH")" | jq -M -r 'if .SuccessCount == 1 then "Successfully submitted finding" else "Failed to upload finding" end' + JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "FAILED" "HIGH") + echo "${JSON_ASFF_OUTPUT}" + if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then + sendToSecurityHub "${JSON_ASFF_OUTPUT}" + fi fi else echo " $BAD FAIL! $1 $NORMAL" @@ -178,6 +175,8 @@ generateJsonAsffOutput(){ --arg SCORED "$ITEM_SCORED" \ --arg ITEM_LEVEL "$ITEM_LEVEL" \ --arg TITLE_ID "$TITLE_ID" \ + --arg TYPE "$ASFF_TYPE" \ + --arg RESOURCE_TYPE "$ASFF_RESOURCE_TYPE" \ --arg REPREGION "$REPREGION" \ --arg TIMESTAMP $(date -u +"%Y-%m-%dT%H:%M:%SZ") \ --arg PROWLER_VERSION "$PROWLER_VERSION" \ @@ -192,7 +191,7 @@ generateJsonAsffOutput(){ "GeneratorId": "prowler-\($PROWLER_VERSION)", "AwsAccountId": $ACCOUNT_NUM, "Types": [ - "Software and Configuration Checks" + $TYPE ], "FirstObservedAt": $TIMESTAMP, "UpdatedAt": $TIMESTAMP, @@ -204,8 +203,8 @@ generateJsonAsffOutput(){ "Description": $MESSAGE, "Resources": [ { - "Type": "AwsAccount", - "Id": "AWS: : : :Account:\($ACCOUNT_NUM)", + "Type": $RESOURCE_TYPE, + "Id": "AWS::::Account:\($ACCOUNT_NUM)", "Partition": "aws", "Region": $REPREGION } diff --git a/include/securityhub_integration b/include/securityhub_integration new file mode 100644 index 00000000..b08f5277 --- /dev/null +++ b/include/securityhub_integration @@ -0,0 +1,37 @@ +#!/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. + +# Checks that the correct mode (json-asff) has been specified if wanting to send check output to AWS Security Hub +# and that Security Hub is enabled in the chosen region +checkSecurityHubCompatibility(){ + if [[ "${MODE}" != "json-asff" ]]; then + echo -e "\n$RED ERROR!$NORMAL Output can only be sent to Security Hub when the output mode is json-asff, i.e. -M json-asff -S\n" + EXITCODE=1 + exit $EXITCODE + fi + SECURITY_HUB_ENABLED=$($AWSCLI securityhub --region $REGION $PROFILE_OPT describe-hub) + if [[ -z "${SECURITY_HUB_ENABLED}" ]]; then + echo -e "\n$RED ERROR!$NORMAL Security Hub is not enabled in $REGION. Enable it by calling '$AWSCLI securityhub --region $REGION $PROFILE_OPT enable-security-hub'\n" + EXITCODE=1 + exit $EXITCODE + fi +} + +sendToSecurityHub(){ + BATCH_IMPORT_RESULT=$($AWSCLI securityhub --region $REGION $PROFILE_OPT batch-import-findings --findings "$1") + # A successful CLI response is: {"SuccessCount": 1,"FailedFindings": [],"FailedCount": 0} + # Therefore, check that SuccessCount is indeed 1 + if [[ -z "${BATCH_IMPORT_RESULT}" ]] || ! jq -e '.SuccessCount == 1' <<< "${BATCH_IMPORT_RESULT}" > /dev/null 2>&1; then + echo -e "\n$RED ERROR!$NORMAL Failed to send check output to AWS Security Hub\n" + fi +} diff --git a/prowler b/prowler index 01eb9a35..68dce2bc 100755 --- a/prowler +++ b/prowler @@ -44,6 +44,7 @@ QUIET=0 SEP=',' KEEPCREDREPORT=0 EXITCODE=0 +SEND_TO_SECURITY_HUB=0 SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) TITLE_ID="" TITLE_TEXT="CALLER ERROR - UNSET TITLE" @@ -64,7 +65,7 @@ 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 (default), mono, json, json-asff, securityhub, csv (separator is ","; data is on stdout; progress on stderr) + -M output mode: text (default), mono, json, json-asff, 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) @@ -75,6 +76,7 @@ USAGE: -b do not print Prowler banner -V show version number & exit -s show scoring report + -S send check output to AWS Security Hub - only valid when the output mode is json-asff (i.e. "-M json-asff -S") -x specify external directory with custom checks (i.e. /my/own/checks, files must start by "check") -q suppress info messages and passing test output -A account id for the account where to assume a role, requires -R and -T @@ -88,7 +90,7 @@ USAGE: exit } -while getopts ":hlLkqp:r:c:g:f:m:M:E:enbVsx:A:R:T:" OPTION; do +while getopts ":hlLkqp:r:c:g:f:m:M:E:enbVsSx:A:R:T:" OPTION; do case $OPTION in h ) usage @@ -145,6 +147,9 @@ while getopts ":hlLkqp:r:c:g:f:m:M:E:enbVsx:A:R:T:" OPTION; do s ) SCORING=1 ;; + S ) + SEND_TO_SECURITY_HUB=1 + ;; x ) EXTERNAL_CHECKS_PATH=$OPTARG ;; @@ -195,6 +200,7 @@ trap "{ rm -f /tmp/prowler*.policy.*; }" EXIT . $PROWLER_DIR/include/check3x . $PROWLER_DIR/include/assume_role . $PROWLER_DIR/include/connection_tests +. $PROWLER_DIR/include/securityhub_integration # Get a list of all available AWS Regions REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ @@ -245,6 +251,14 @@ execute_check() { # for example, we might have been passed 1.01 which is another name for 1.1 local alternate_name_var=CHECK_ALTERNATE_$1 local alternate_name=${!alternate_name_var} + # See if this check defines an ASFF Type, if so, use this, falling back to a sane default + # For a list of Types, see: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format.html#securityhub-findings-format-type-taxonomy + local asff_type_var=CHECK_ASFF_TYPE_$1 + ASFF_TYPE="${!asff_type_var:-Software and Configuration Checks}" + # See if this check defines an ASFF Resource Type, if so, use this, falling back to a sane default + # For a list of Resource Types, see: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format.html#asff-resources + local asff_resource_type_var=CHECK_ASFF_RESOURCE_TYPE_$1 + ASFF_RESOURCE_TYPE="${!asff_resource_type_var:-AwsAccount}" # Generate the credential report, only if it is group1 related which checks we # run so that the checks can safely assume it's available if [ ${alternate_name} ];then @@ -396,10 +410,14 @@ if [[ $PRINTGROUPSONLY == "1" ]]; then fi # Check that jq is installed for JSON outputs -if [[ "$MODE" == "json" || "$MODE" == "json-asff" || "$MODE" == "securityhub" ]]; then +if [[ "$MODE" == "json" || "$MODE" == "json-asff" ]]; then . $PROWLER_DIR/include/jq_detector fi +if [[ "$SEND_TO_SECURITY_HUB" -eq 1 ]]; then + checkSecurityHubCompatibility +fi + # Gather account data / test aws cli connectivity getWhoami