diff --git a/README.md b/README.md index e0c5d0e540..7468c8e413 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 f34ebed5f8..09bdcab168 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 6f34b0f275..dabb80dca5 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 ea652b6376..83575d2914 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 f6fa9481d7..a9825ee175 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 481daeefbd..1e034c8d00 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 99391d3350..fff68b726e 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 848bd44072..c52db37e00 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 ad51e34c2e..c20abbf7c1 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 69f897c91a..1264c99edc 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 4217fbf1b2..abd76906e4 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 4dbc7fd0e0..5a0a90d741 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 6e82f10cbc..15bc50f142 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 2983642faa..dd1d4fc51e 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 64032c059f..b909eb7b4c 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 0ae9e6c34b..1c4fdec2c3 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 102897680d..9e0a461635 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 88d144075d..86925defe3 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 aedcba17f7..0aa9c7329b 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 de224521d0..9ee4965b54 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 f344c759ac..fc56ffe7aa 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 412de29141..732b87bd66 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 6e924ae8bd..60aad8ed60 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 591b911ccf..d1a2310338 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 18b13742d7..1646a94f63 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 53d1b6f6ba..feab2c6b3a 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 35185035f1..581878bc33 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 d8d817324f..6bb12698dd 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 83395527a8..8647fd88e6 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 f32b7bfe0e..56fd739279 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 bec0e2341d..adfbca41f0 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 d1f23dc8c1..c49efb2d3b 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 8a8d1329cd..21768a1501 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 77f4b5a3ce..65d50773de 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 b69fc75a2d..e38af0dc26 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 49e1462e3e..b5abde10a0 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 a6a81edc01..0514045c17 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 3a6c9d7d27..de9c387548 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 83779842df..745d38d5a2 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 00c6d7dd65..dd2b94dbe4 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 e4751c79e1..86a55b255c 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 b8b4c6cf7f..929be5b8b4 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 699739d89a..06e0d5576f 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 c0390bc97b..4c6dd4d31b 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 ddc69d3689..c112620c0b 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 3a812a4ae5..a649f15726 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 30fd91319d..00260ebbd2 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 921876205a..a362b0cbe6 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 4599934dad..6c0122ff72 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 a45c116b8e..55ceb9775e 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 8667666bb4..368ad9d49a 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 c259695af4..55216b3d2e 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 717c8680f8..3e9b29ee73 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 60e7156601..251d93a50a 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 a47ecffef5..cb57de8576 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 0acde20574..2268b71979 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 afdb8dd44f..db3aba1db6 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 0bb047416f..74a1893776 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 7331911397..0d361c3cd7 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 f9fa11b9fe..52bcd93d02 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 1bf63cc59f..64fbf0438e 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 ac6ca05499..d464786a65 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 605f7f19b9..e90596b7ac 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 96039eb993..c527c3c8d0 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 bb75085574..2aa08b0f13 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 257a3d8e07..5f4fc99e64 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 5e14e2b5c3..47c41fcb58 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 eb27a9de94..5399822d1c 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 603acbb022..756aa09c83 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 a587a60f6a..86b07197c9 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 53be1c5816..06266cd327 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 0baa1b6e25..744d28a155 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 2fc63a22f1..30c6ec7fa3 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 bebd2bfcaa..02d7f4ecfc 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 cc6ad238bb..0e49b698c6 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 0b5993a710..19082827d6 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 d10a301f96..3e1b6bf2b8 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 bc2b9dc589..c5b59eec70 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 33ff5ecb1c..b12806836e 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 68dbfa92af..f700f1c484 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 d74c760039..5fa0051889 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 f4e54d2cca..20b7b94ab2 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 8d78ab228d..309f75d52b 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 e24326f9c2..4cd22003fa 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 6b7bfb3a59..4bc9edd6fe 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 98a98e634e..b8674e5cec 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 073ca55ff4..79de26e764 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 b9e28b1fb3..027359bfb1 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 50056980b5..9aa711477a 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 3c4a53be6d..0a74e3945f 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 f200762127..a93d01e282 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 1b1d62e367..fd105bfc8d 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 3c8255ea5d..0d623ba8a8 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 650c7e82c5..e64721815f 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 2ba23a5171..44824b933f 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 0b7472e07a..30e8a93960 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 0481f444f8..e0164d7651 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 538fa55b08..69dabb6080 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 0320081a9a..a5ddf6fd27 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 1c402aa563..5f5fe40b45 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 dbd0763291..6b3ff15e0c 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 eac466e72f..ee66c791c3 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 b54cd5ac52..c66974e68c 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 7c839cf378..9ceb949445 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 8b849208a7..8ec26cd41d 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 1bbe4d8a7d..1683d466a1 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 2c10e1dde1..b357c72e06 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 f39de56471..b657bbaa98 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 ecd240c30b..0c9406491f 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 83f3cdd5f2..088be100d1 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 ecd2638529..dbfba0caf4 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 83e2aa6fc3..58042dd36f 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 1ccf541fd1..fa3d8c0c3a 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 42672348cc..8d51168718 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 627bc51a96..02a32868cb 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 9bea1a3db9..ee65225954 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 eadb584ad7..0a694c3585 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 2b19cc7e9b..e4f3662071 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 1c38c7f36f..ab169bee40 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 4c33b1acd0..fa76f6f119 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 cb407538bd..29779d50f3 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 7e22a689bd..59ffba1153 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 e45e5ddc96..d46a63a791 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 54c9d8804e..b041e30c2e 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 0000000000..309c086a20 --- /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 68ac32a43b..e938d143fb 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 6af1477895..40d67a7c57 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 0000000000..b08f527717 --- /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 01eb9a35af..68dce2bc8c 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