diff --git a/README.md b/README.md index 9ee849d6..ff7c40d7 100644 --- a/README.md +++ b/README.md @@ -385,7 +385,11 @@ To use Prowler and Security Hub integration in China regions there is an additio ## CodeBuild deployment -CodeBuild can help you running Prowler and there is a Cloud Formation template that helps you doing that [here](https://github.com/toniblyx/prowler/blob/master/util/codebuild/codebuild-auditor-account-cfn.yaml). +Either to run Prowler once or based on a schedule this template makes it pretty straight forward. This template will create a CodeBuild environment and run Prowler directly leaving all reports in a bucket and creating a report also inside CodeBuild basedon the JUnit output from Prowler. Scheduling can be cron based like `cron(0 22 * * ? *)` or rate based like `rate(5 hours)` since CloudWatch Event rules (or Eventbridge) is used here. + +The Cloud Formation template that helps you doing that is [here](https://github.com/toniblyx/prowler/blob/master/util/codebuild/codebuild-prowler-audit-account-cfn.yaml). + +> This is a simple solution to monitor one account. For multiples accounts see [Multi Account and Continuous Monitoring](util/org-multi-account/README.md). ## Whitelist or allowlist or remove a fail from resources diff --git a/checks/check119 b/checks/check119 index bf37abe9..63557bbe 100644 --- a/checks/check119 +++ b/checks/check119 @@ -25,7 +25,7 @@ check119(){ if [[ $INSTANCE_LIST ]]; then for instance in $INSTANCE_LIST; do STATE_NAME=$(echo $EC2_DATA | jq -r --arg i "$instance" 'select(.InstanceId==$i)|.StateName') - if [[ $STATE_NAME != "terminated" ]]; then + if [[ $STATE_NAME != "terminated" && $STATE_NAME != "shutting-down" ]]; 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 diff --git a/checks/check_extra7114 b/checks/check_extra7114 new file mode 100644 index 00000000..a728c83f --- /dev/null +++ b/checks/check_extra7114 @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +CHECK_ID_extra7114="7.114" +CHECK_TITLE_extra7114="[extra7114] Check if Glue development endpoints have S3 encryption enabled." +CHECK_SCORED_extra7114="NOT_SCORED" +CHECK_TYPE_extra7114="EXTRA" +CHECK_SEVERITY_extra7114="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7114="AwsGlue" +CHECK_ALTERNATE_check7114="extra7114" + +extra7114(){ + for regx in $REGIONS; do + LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json) + if [[ $LIST_EP_SC != '[]' ]]; then + for ep in $(echo "${LIST_EP_SC}"| jq -r '.[] | @base64');do + ENDPOINT_NAME=$(echo $ep | base64 --decode | jq -r '.Name') + ENDPOINT_SC=$(echo $ep | base64 --decode | jq -r '.Security // empty') + if [[ ! -z "$ENDPOINT_SC" ]]; then + ENDPOINT_SC_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${ENDPOINT_SC}" $PROFILE_OPT --region $regx --query 'SecurityConfiguration.EncryptionConfiguration.S3Encryption[0].S3EncryptionMode' --output text) + if [[ "$ENDPOINT_SC_ENCRYPTION" == "DISABLED" ]]; then + textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have S3 encryption enabled!" "$regx" + else + textPass "$regx: Glue development endpoint $ENDPOINT_NAME has S3 encryption enabled" "$regx" + fi + else + textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have security configuration" "$regx" + fi + done + else + textInfo "$regx: There are no Glue development endpoints" "$regx" + fi + done +} + + diff --git a/checks/check_extra7115 b/checks/check_extra7115 new file mode 100644 index 00000000..da606669 --- /dev/null +++ b/checks/check_extra7115 @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +CHECK_ID_extra7115="7.115" +CHECK_TITLE_extra7115="[extra7115] Check if Glue database connection has SSL connection enabled." +CHECK_SCORED_extra7115="NOT_SCORED" +CHECK_TYPE_extra7115="EXTRA" +CHECK_SEVERITY_extra7115="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7115="AwsGlue" +CHECK_ALTERNATE_check7115="extra7115" + +extra7115(){ + for regx in $REGIONS; do + CONNECTION_LIST=$($AWSCLI glue get-connections $PROFILE_OPT --region $regx --output json --query 'ConnectionList[*].{Name:Name,SSL:ConnectionProperties.JDBC_ENFORCE_SSL}') + if [[ $CONNECTION_LIST != '[]' ]]; then + for connection in $(echo "${CONNECTION_LIST}" | jq -r '.[] | @base64'); do + CONNECTION_NAME=$(echo $connection | base64 --decode | jq -r '.Name' ) + CONNECTION_SSL_STATE=$(echo $connection | base64 --decode | jq -r '.SSL') + if [[ "$CONNECTION_SSL_STATE" == "false" ]]; then + textFail "$regx: Glue connection $CONNECTION_NAME has SSL connection disabled" "$regx" + else + textPass "$regx: Glue connection $CONNECTION_NAME has SSL connection enabled" "$regx" + fi + done + else + textInfo "$regx: There are no Glue connections" "$regx" + fi + done +} diff --git a/checks/check_extra7116 b/checks/check_extra7116 new file mode 100644 index 00000000..2dee0295 --- /dev/null +++ b/checks/check_extra7116 @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +CHECK_ID_extra7116="7.116" +CHECK_TITLE_extra7116="[extra7116] Check if Glue data catalog settings have metadata encryption enabled." +CHECK_SCORED_extra7116="NOT_SCORED" +CHECK_TYPE_extra7116="EXTRA" +CHECK_SEVERITY_extra7116="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7116="AwsGlue" +CHECK_ALTERNATE_check7116="extra7116" + +extra7116(){ + for regx in $REGIONS; do + TABLE_LIST=$($AWSCLI glue search-tables --max-results 1 $PROFILE_OPT --region $regx --output text --query 'TableList[*]' ) + if [[ ! -z $TABLE_LIST ]]; then + METADATA_ENCRYPTED=$($AWSCLI glue get-data-catalog-encryption-settings $PROFILE_OPT --region $regx --output text --query "DataCatalogEncryptionSettings.EncryptionAtRest.CatalogEncryptionMode") + if [[ "$METADATA_ENCRYPTED" == "DISABLED" ]]; then + textFail "$regx: Glue data catalog settings have metadata encryption disabled" "$regx" + else + textPass "$regx: Glue data catalog settings have metadata encryption enabled" "$regx" + fi + else + textInfo "$regx: Glue data catalog settings metadata encryption does not apply since there are no tables" "$regx" + fi + done +} diff --git a/checks/check_extra7117 b/checks/check_extra7117 new file mode 100644 index 00000000..686cd729 --- /dev/null +++ b/checks/check_extra7117 @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +CHECK_ID_extra7117="7.117" +CHECK_TITLE_extra7117="[extra7117] Check if Glue data catalog settings have encrypt connection password enabled." +CHECK_SCORED_extra7117="NOT_SCORED" +CHECK_TYPE_extra7117="EXTRA" +CHECK_SEVERITY_extra7117="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7117="AwsGlue" +CHECK_ALTERNATE_check7117="extra7117" + +extra7117(){ + for regx in $REGIONS; do + CONNECTION_LIST=$($AWSCLI glue get-connections $PROFILE_OPT --region $regx --output text --query 'ConnectionList[*]') + if [[ ! -z $CONNECTION_LIST ]]; then + METADATA_ENCRYPTED=$($AWSCLI glue get-data-catalog-encryption-settings $PROFILE_OPT --region $regx --output text --query "DataCatalogEncryptionSettings.ConnectionPasswordEncryption.ReturnConnectionPasswordEncrypted") + if [[ "$METADATA_ENCRYPTED" == "False" ]]; then + textFail "$regx: Glue data catalog connection password is not encrypted" "$regx" + else + textPass "$regx: Glue data catalog connection password is encrypted" "$regx" + fi + else + textInfo "$regx: Glue data catalog connection password encryption does not apply since there are no connections" "$regx" + fi + done +} diff --git a/checks/check_extra7118 b/checks/check_extra7118 new file mode 100644 index 00000000..aa39907f --- /dev/null +++ b/checks/check_extra7118 @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +CHECK_ID_extra7118="7.118" +CHECK_TITLE_extra7118="[extra7118] Check if Glue ETL Jobs have S3 encryption enabled." +CHECK_SCORED_extra7118="NOT_SCORED" +CHECK_TYPE_extra7118="EXTRA" +CHECK_SEVERITY_extra7118="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7118="AwsGlue" +CHECK_ALTERNATE_check7118="extra7118" + +extra7118(){ + for regx in $REGIONS; do + JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration,JobEncryption:DefaultArguments."--encryption-type"}') + if [[ $JOB_LIST != '[]' ]]; then + for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do + JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name') + SECURITY_CONFIGURATION=$(echo $job | base64 --decode | jq -r '.SecurityConfiguration // empty') + JOB_ENCRYPTION=$(echo $job | base64 --decode | jq -r '.JobEncryption // empty') + if [[ ! -z "$SECURITY_CONFIGURATION" ]]; then + S3_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${SECURITY_CONFIGURATION}" $PROFILE_OPT --region $regx --output text --query 'SecurityConfiguration.EncryptionConfiguration.S3Encryption[0].S3EncryptionMode') + if [[ "$S3_ENCRYPTION" == "DISABLED" ]]; then + if [[ ! -z "$JOB_ENCRYPTION" ]]; then + textPass "$regx: Glue job $JOB_NAME does have $JOB_ENCRYPTION for S3 encryption enabled" "$regx" + else + textFail "$regx: Glue job $JOB_NAME does not have S3 encryption enabled" "$regx" + fi + else + textPass "$regx: Glue job $JOB_NAME does have $S3_ENCRYPTION for S3 encryption enabled" "$regx" + fi + elif [[ ! -z "$JOB_ENCRYPTION" ]]; then + textPass "$regx: Glue job $JOB_NAME does have $JOB_ENCRYPTION for S3 encryption enabled" "$regx" + else + textFail "$regx: Glue job $JOB_NAME does not have S3 encryption enabled" "$regx" + fi + done + else + textInfo "$regx: There are no Glue jobs" "$regx" + fi + done +} \ No newline at end of file diff --git a/checks/check_extra7119 b/checks/check_extra7119 new file mode 100644 index 00000000..e8d60488 --- /dev/null +++ b/checks/check_extra7119 @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +CHECK_ID_extra7119="7.119" +CHECK_TITLE_extra7119="[extra7119] Check if Glue development endpoints have CloudWatch logs encryption enabled." +CHECK_SCORED_extra7119="NOT_SCORED" +CHECK_TYPE_extra7119="EXTRA" +CHECK_SEVERITY_extra7119="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7119="AwsGlue" +CHECK_ALTERNATE_check7119="extra7119" + +extra7119(){ + for regx in $REGIONS; do + LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json) + if [[ $LIST_EP_SC != '[]' ]]; then + for ep in $(echo "${LIST_EP_SC}"| jq -r '.[] | @base64');do + ENDPOINT_NAME=$(echo $ep | base64 --decode | jq -r '.Name') + ENDPOINT_SC=$(echo $ep | base64 --decode | jq -r '.Security // empty') + if [[ ! -z "$ENDPOINT_SC" ]]; then + ENDPOINT_SC_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${ENDPOINT_SC}" $PROFILE_OPT --region $regx --query 'SecurityConfiguration.EncryptionConfiguration.CloudWatchEncryption.CloudWatchEncryptionMode' --output text) + if [[ $ENDPOINT_SC_ENCRYPTION == "DISABLED" ]]; then + textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have CloudWatch logs encryption enabled!" "$regx" + else + textPass "$regx: Glue development endpoint $ENDPOINT_NAME has CloudWatch logs encryption enabled" "$regx" + fi + else + textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have security configuration" "$regx" + fi + done + else + textInfo "$regx: There are no Glue development endpoints" "$regx" + fi + done +} diff --git a/checks/check_extra7120 b/checks/check_extra7120 new file mode 100644 index 00000000..69695b7f --- /dev/null +++ b/checks/check_extra7120 @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +CHECK_ID_extra7120="7.120" +CHECK_TITLE_extra7120="[extra7120] Check if Glue ETL Jobs have CloudWatch Logs encryption enabled." +CHECK_SCORED_extra7120="NOT_SCORED" +CHECK_TYPE_extra7120="EXTRA" +CHECK_SEVERITY_extra7120="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7120="AwsGlue" +CHECK_ALTERNATE_check7120="extra7120" + +extra7120(){ + for regx in $REGIONS; do + JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration}') + if [[ $JOB_LIST != '[]' ]]; then + for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do + JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name') + SECURITY_CONFIGURATION=$(echo $job | base64 --decode | jq -r '.SecurityConfiguration // empty') + if [[ ! -z "$SECURITY_CONFIGURATION" ]]; then + CLOUDWATCH_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${SECURITY_CONFIGURATION}" $PROFILE_OPT --region $regx --output text --query 'SecurityConfiguration.EncryptionConfiguration.CloudWatchEncryption.CloudWatchEncryptionMode') + if [[ "$CLOUDWATCH_ENCRYPTION" == "DISABLED" ]]; then + textFail "$regx: Glue job $JOB_NAME does not have CloudWatch Logs encryption enabled" "$regx" + else + textPass "$regx: Glue job $JOB_NAME does have $CLOUDWATCH_ENCRYPTION CloudWatch Logs encryption enabled" "$regx" + fi + else + textFail "$regx: Glue job $JOB_NAME does not have CloudWatch Logs encryption enabled" "$regx" + fi + done + else + textInfo "$regx: There are no Glue jobs" "$regx" + fi + done +} \ No newline at end of file diff --git a/checks/check_extra7121 b/checks/check_extra7121 new file mode 100644 index 00000000..0dd83446 --- /dev/null +++ b/checks/check_extra7121 @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +CHECK_ID_extra7121="7.121" +CHECK_TITLE_extra7121="[extra7121] Check if Glue development endpoints have Job bookmark encryption enabled." +CHECK_SCORED_extra7121="NOT_SCORED" +CHECK_TYPE_extra7121="EXTRA" +CHECK_SEVERITY_extra7121="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7121="AwsGlue" +CHECK_ALTERNATE_check7121="extra7121" + +extra7121(){ + for regx in $REGIONS; do + LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json) + if [[ $LIST_EP_SC != '[]' ]]; then + for ep in $(echo "${LIST_EP_SC}"| jq -r '.[] | @base64');do + ENDPOINT_NAME=$(echo $ep | base64 --decode | jq -r '.Name') + ENDPOINT_SC=$(echo $ep | base64 --decode | jq -r '.Security // empty') + if [[ ! -z "$ENDPOINT_SC" ]]; then + ENDPOINT_SC_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${ENDPOINT_SC}" $PROFILE_OPT --region $regx --query 'SecurityConfiguration.EncryptionConfiguration.JobBookmarksEncryption.JobBookmarksEncryptionMode' --output text) + if [[ "$ENDPOINT_SC_ENCRYPTION" == "DISABLED" ]]; then + textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have Job Bookmark encryption enabled!" "$regx" + else + textPass "$regx: Glue development endpoint $ENDPOINT_NAME has Job Bookmark encryption enabled" "$regx" + fi + else + textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have security configuration" "$regx" + fi + done + else + textInfo "$regx: There are no Glue development endpoints" "$regx" + fi + done +} + + diff --git a/checks/check_extra7122 b/checks/check_extra7122 new file mode 100644 index 00000000..618181c4 --- /dev/null +++ b/checks/check_extra7122 @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +CHECK_ID_extra7122="7.122" +CHECK_TITLE_extra7122="[extra7122] Check if Glue ETL Jobs have Job bookmark encryption enabled." +CHECK_SCORED_extra7122="NOT_SCORED" +CHECK_TYPE_extra7122="EXTRA" +CHECK_SEVERITY_extra7122="Medium" +CHECK_ASFF_RESOURCE_TYPE_extra7122="AwsGlue" +CHECK_ALTERNATE_check7122="extra7122" + +extra7122(){ + for regx in $REGIONS; do + JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration}') + if [[ $JOB_LIST != '[]' ]]; then + for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do + JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name') + SECURITY_CONFIGURATION=$(echo $job | base64 --decode | jq -r '.SecurityConfiguration // empty') + if [[ ! -z "$SECURITY_CONFIGURATION" ]]; then + JOB_BOOKMARK_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${SECURITY_CONFIGURATION}" $PROFILE_OPT --region $regx --output text --query 'SecurityConfiguration.EncryptionConfiguration.JobBookmarksEncryption.JobBookmarksEncryptionMode') + if [[ "$JOB_BOOKMARK_ENCRYPTION" == "DISABLED" ]]; then + textFail "$regx: Glue job $JOB_NAME does not have Job bookmark encryption enabled" "$regx" + else + textPass "$regx: Glue job $JOB_NAME does have $JOB_BOOKMARK_ENCRYPTION for Job bookmark encryption enabled" "$regx" + fi + else + textFail "$regx: Glue job $JOB_NAME does not have Job bookmark encryption enabled" "$regx" + fi + done + else + textInfo "$regx: There are no Glue jobs" "$regx" + fi + done +} \ No newline at end of file diff --git a/groups/group23_ens b/groups/group23_ens new file mode 100644 index 00000000..689e5673 --- /dev/null +++ b/groups/group23_ens @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +GROUP_ID[23]='ens' +GROUP_NUMBER[23]='23.0' +GROUP_TITLE[23]='ENS Esquema Nacional de Seguridad security checks - [ens] *****' +GROUP_RUN_BY_DEFAULT[23]='N' # run it when execute_all is called +GROUP_CHECKS[23]='extra733,check13,check14,check121,extra7100,check120,check116,check12,check14,check13,check21,check25,check35,check24,check31,check36,check32,check33,check34,check22,extra71,check23,check23,check27,check37,extra736,extra737,extra713,check21,check29,extra793,extra792,extra764,extra738,check43,extra74,extra710,extra75,check41,check42,extra749,extra750,extra751,extra752,extra753,extra754,extra755,extra729,extra761,extra740,extra735,extra734,extra728,extra781,extra773,extra744' + +# ENS Control ID for AWS;Prowler checks that apply +# op.acc.1.aws.iam.1;extra733 +# op.acc.1.aws.iam.2;todo +# op.acc.1.aws.iam.3;check13 +# op.acc.1.aws.iam.4;check14 +# op.acc.1.aws.iam.5;check121 +# op.acc.2.aws.iam.1;extra7100 +# op.acc.1.aws.iam.4;check120 +# op.acc.3.aws.iam.1;check116 +# op.acc.4.aws.sys.1;todo ssm session manager +# op.acc.5.aws.iam.1;check12 +# op.acc.5.aws.iam.2;todo +# op.acc.5.aws.iam.3;check14 +# op.acc.5.aws.iam.4;check13 +# op.acc.7.aws.iam.1;check21 +# op.exp.1.aws.cfg.1;check25 +# op.exp.1.aws.sys.1;todo ssm inventory +# op.exp.4.aws.sys.1;todo ssm compliance +# op.exp.8.aws.trail.1;check35 +# op.exp.8.aws.cw.1;check24 +# op.exp.8.aws.trail.2;check31 +# op.exp.8.aws.trail.3;check36 +# op.exp.8.aws.trail.4;check32 +# op.exp.8.aws.trail.5;check33 +# op.exp.8.aws.trail.6;check34 +# op.exp.10.aws.trail.1;check22 +# op.exp.10.aws.trail.2;extra71 +# op.exp.10.aws.trail.3;check23 +# op.exp.10.aws.trail.4;check23 +# op.exp.10.aws.trail.5;check27 +# op.exp.11.aws.kms.1;check37 +# op.exp.11.aws.kms.2;extra736 +# op.exp.11.aws.kms.3;extra737 +# op.mon.1.aws.duty.1;extra713 +# op.mon.1.aws.trail.1;check21 +# op.mon.1.aws.flow.1;check29 +# mp.com.2.aws.elb.1;extra793 +# mp.com.2.aws.elb.2;extra792 +# mp.com.2.aws.s3.1;extra764 +# mp.com.2.aws.front.1;extra738 +# mp.com.4.aws.sg.1;check43 +# mp.com.4.aws.sg.2;extra74 +# mp.com.4.aws.vpc.1;extra710 +# mp.com.4.aws.sg.3;extra75 +# mp.com.4.aws.sg.4;check41 +# mp.com.4.aws.sg.5;check42 +# mp.com.4.aws.sg.6;extra749 +# mp.com.4.aws.sg.7;extra750 +# mp.com.4.aws.sg.8;extra751 +# mp.com.4.aws.sg.9;extra752 +# mp.com.4.aws.sg.10;extra753 +# mp.com.4.aws.sg.11;extra754 +# mp.com.4.aws.sg.12;extra755 +# mp.info.3.aws.dyndb.1;todo +# mp.info.3.aws.ebs.1 ;extra729 +# mp.info.3.aws.ebs.2;extra761 +# mp.info.3.aws.ebs.3;extra740 +# mp.info.3.aws.rds.1;extra735 +# mp.info.3.s3.1;extra734 +# mp.info.3.sns.1;extra728 +# mp.info.3.aws.au.1;extra781 +# mp.s.2.aws.waf.1;extra773 +# mp.s.2.aws.waf.2;extra744 +# mp.s.2.aws.waf.3;todo diff --git a/groups/group24_glue b/groups/group24_glue new file mode 100644 index 00000000..a9b8c313 --- /dev/null +++ b/groups/group24_glue @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +GROUP_ID[24]='glue' +GROUP_NUMBER[24]='24.0' +GROUP_TITLE[24]='Amazon Glue related security checks - [glue] ******************' +GROUP_RUN_BY_DEFAULT[24]='N' # run it when execute_all is called +GROUP_CHECKS[24]='extra7114,extra7115,extra7116,extra7117,extra7118,extra7119,extra7120,extra7121,extra7122' \ No newline at end of file diff --git a/groups/group7_extras b/groups/group7_extras index 041b56df..3326013b 100644 --- a/groups/group7_extras +++ b/groups/group7_extras @@ -15,7 +15,7 @@ GROUP_ID[7]='extras' GROUP_NUMBER[7]='7.0' GROUP_TITLE[7]='Extras - all non CIS specific checks - [extras] ****************' GROUP_RUN_BY_DEFAULT[7]='Y' # run it when execute_all is called -GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723,extra724,extra725,extra726,extra727,extra728,extra729,extra730,extra731,extra732,extra733,extra734,extra735,extra736,extra737,extra738,extra739,extra740,extra741,extra742,extra743,extra744,extra745,extra746,extra747,extra748,extra749,extra750,extra751,extra752,extra753,extra754,extra755,extra756,extra757,extra758,extra761,extra762,extra763,extra764,extra765,extra767,extra768,extra769,extra770,extra771,extra772,extra773,extra774,extra775,extra776,extra777,extra778,extra779,extra780,extra781,extra782,extra783,extra784,extra785,extra786,extra787,extra788,extra791,extra792,extra793,extra794,extra795,extra796,extra797,extra798,extra799,extra7100,extra7101,extra7102,extra7103,extra7104,extra7105,extra7106,extra7107,extra7108,extra7109,extra7110,extra7111,extra7112,extra7113' +GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723,extra724,extra725,extra726,extra727,extra728,extra729,extra730,extra731,extra732,extra733,extra734,extra735,extra736,extra737,extra738,extra739,extra740,extra741,extra742,extra743,extra744,extra745,extra746,extra747,extra748,extra749,extra750,extra751,extra752,extra753,extra754,extra755,extra756,extra757,extra758,extra761,extra762,extra763,extra764,extra765,extra767,extra768,extra769,extra770,extra771,extra772,extra773,extra774,extra775,extra776,extra777,extra778,extra779,extra780,extra781,extra782,extra783,extra784,extra785,extra786,extra787,extra788,extra791,extra792,extra793,extra794,extra795,extra796,extra797,extra798,extra799,extra7100,extra7101,extra7102,extra7103,extra7104,extra7105,extra7106,extra7107,extra7108,extra7109,extra7110,extra7111,extra7112,extra7113,extra7114,extra7115,extra7116,extra7117,extra7118,extra7119,extra7120,extra7121,extra7122' # Extras 759 and 760 (lambda variables and code secrets finder are not included) # to run detect-secrets use `./prowler -g secrets` diff --git a/iam/create_role_to_assume_cfn.yaml b/iam/create_role_to_assume_cfn.yaml index 386224da..0ad1a73b 100644 --- a/iam/create_role_to_assume_cfn.yaml +++ b/iam/create_role_to_assume_cfn.yaml @@ -37,11 +37,13 @@ Resources: Principal: AWS: !Sub ${AuthorisedARN} Action: 'sts:AssumeRole' - ## In case MFA is required uncomment lines below - ## and read https://github.com/toniblyx/prowler#run-prowler-with-mfa-protected-credentials + ## In case MFA is required uncomment lines below and read https://github.com/toniblyx/prowler#run-prowler-with-mfa-protected-credentials # Condition: # Bool: # 'aws:MultiFactorAuthPresent': true + # This is 12h that is maximum allowed, Minimum is 3600 = 1h + # to take advantage of this use -T like in './prowler -A -R ProwlerExecRole -T 43200 -M text,html' + MaxSessionDuration: 43200 ManagedPolicyArns: - 'arn:aws:iam::aws:policy/SecurityAudit' - 'arn:aws:iam::aws:policy/job-function/ViewOnlyAccess' diff --git a/util/codebuild/codebuild-auditor-account-cfn.yaml b/util/codebuild/codebuild-prowler-audit-account-cfn.yaml similarity index 51% rename from util/codebuild/codebuild-auditor-account-cfn.yaml rename to util/codebuild/codebuild-prowler-audit-account-cfn.yaml index 213a2703..1022da6e 100644 --- a/util/codebuild/codebuild-auditor-account-cfn.yaml +++ b/util/codebuild/codebuild-prowler-audit-account-cfn.yaml @@ -1,6 +1,6 @@ --- AWSTemplateFormatVersion: 2010-09-09 -Description: Creates a CodeBuild project to audit the AWS account with Prowler and stores the html report in a S3 bucket / Original author https://github.com/stevecjones +Description: Creates a CodeBuild project to audit an AWS account with Prowler and stores the html report in a S3 bucket. This will run onece at the beginning and on a schedule afterwards. Partial contribution from https://github.com/stevecjones Parameters: ServiceName: Description: 'Specifies the service name used within component naming' @@ -8,30 +8,94 @@ Parameters: Default: 'prowler' LogsRetentionInDays: - Description: 'Specifies the number of days you want to retain CodeBuild run log events in the specified log group. Junit reports are kept for 30 days' + Description: 'Specifies the number of days you want to retain CodeBuild run log events in the specified log group. Junit reports are kept for 30 days, HTML reports in S3 are not deleted' Type: Number Default: 3 - AllowedValues: [1, 3, 5, 7, 14, 30, 60] + AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 180, 365] ProwlerOptions: - Description: 'Options to pass to Prowler command, make sure at least -M junit-xml is used. -r for the region to send API queries, -f to filter only that region, -M output formats, -c for comma separated checks, for all checks do not use -c, for more options see -h' + Description: 'Options to pass to Prowler command, make sure at least -M junit-xml is used for CodeBuild reports. Use -r for the region to send API queries, -f to filter only one region, -M output formats, -c for comma separated checks, for all checks do not use -c or -g, for more options see -h. For a complete assessment use "-M text,junit-xml,html,csv,json", for SecurityHub integration use "-r region -f region -M text,junit-xml,html,csv,json,json-asff -S -q"' Type: String - Default: -r eu-west-1 -f eu-west-1 -M text,junit-xml,html -c check11,check12,check13,check14 + # Prowler command below runs a set of checks, configure it base on your needs, no options will run all regions all checks. + # option -M junit-xml is requirede in order to get the report in CodeBuild. + Default: -r eu-west-1 -f eu-west-1 -M text,junit-xml,html,csv,json -c check11,check12,check13,check14 + + ProwlerScheduler: + Description: The time when Prowler will run in cron format. Default is daily at 22:00h or 10PM 'cron(0 22 * * ? *)', for every 5 hours also works 'rate(5 hours)'. More info here https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html. + Type: String + Default: 'cron(0 22 * * ? *)' Resources: + CodeBuildStartBuild: + Type: 'Custom::CodeBuildStartBuild' + Properties: + Build: !Ref ProwlerCodeBuild + ServiceToken: + 'Fn::GetAtt': + - CodeBuildStartBuildLambda + - Arn + + CodeBuildStartBuildLambdaRole: + Type: 'AWS::IAM::Role' + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: + - 'sts:AssumeRole' + Path: / + ManagedPolicyArns: + - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' + Policies: + - PolicyName: StartBuildInline + PolicyDocument: + Statement: + - Effect: Allow + Action: + - 'codebuild:StartBuild' + Resource: '*' + + CodeBuildStartBuildLambda: + Type: 'AWS::Lambda::Function' + Properties: + Handler: index.lambda_handler + MemorySize: 128 + Role: !Sub ${CodeBuildStartBuildLambdaRole.Arn} + Timeout: 120 + Runtime: python3.6 + Code: + ZipFile: | + import boto3 + import cfnresponse + from botocore.exceptions import ClientError + + def lambda_handler(event,context): + props = event['ResourceProperties'] + codebuil_client = boto3.client('codebuild') + + if (event['RequestType'] == 'Create' or event['RequestType'] == 'Update'): + try: + response = codebuil_client.start_build(projectName=props['Build']) + print(response) + print("Respond: SUCCESS") + cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) + except Exception as ex: + print(ex.response['Error']['Message']) + cfnresponse.send(event, context, cfnresponse.FAILED, ex.response) + ArtifactBucket: Type: AWS::S3::Bucket Properties: Tags: - Key: Name - Value: !Join ['-', ['AP2', 'INF', !Ref 'ServiceName', !Ref 'AWS::AccountId', 'S3', 'Prowler']] - BucketName: !Sub '${ServiceName}-${AWS::Region}-prowler-${AWS::AccountId}' + Value: !Join ['-', [!Ref 'ServiceName', !Ref 'AWS::AccountId', 'S3', 'Prowler', !Ref 'AWS::StackName']] + BucketName: !Sub '${ServiceName}-reports-${AWS::Region}-prowler-${AWS::AccountId}' AccessControl: LogDeliveryWrite VersioningConfiguration: Status: Enabled - # LoggingConfiguration: - # DestinationBucketName: !ImportValue 'ProviderLogBucket' - # LogFilePrefix: !Sub '${ServiceName}-${AWS::Region}-prowler-${AWS::AccountId}/' BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: @@ -69,7 +133,6 @@ Resources: - !Join ['', ['arn:aws:s3:::', !Ref 'ArtifactBucket', '/*']] Sid: DenyUnEncryptedObjectUploads - # Codebuild Project CodeBuildServiceRole: Type: AWS::IAM::Role Metadata: @@ -78,7 +141,7 @@ Resources: - id: W28 reason: "Explicit name is required for this resource to avoid circular dependencies." Properties: - RoleName: prowler-codebuild-role + RoleName: !Sub 'prowler-codebuild-role-${ServiceName}-${AWS::StackName}' Path: '/service-role/' ManagedPolicyArns: - 'arn:aws:iam::aws:policy/job-function/SupportUser' @@ -128,6 +191,14 @@ Resources: - codebuild:BatchPutCodeCoverages Effect: Allow Resource: !Sub 'arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/*' + - PolicyName: SecurityHubBatchImportFindings + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: + - securityhub:BatchImportFindings + Effect: Allow + Resource: !Sub 'arn:aws:securityhub:${AWS::Region}::product/prowler/prowler' - PolicyName: AssumeRole PolicyDocument: Version: '2012-10-17' @@ -144,8 +215,6 @@ Resources: Type: NO_ARTIFACTS Source: Type: NO_SOURCE - # Prowler command below runs a set of checks, configure it base on your needs, no options will run all regions all checks. - # option -M junit-xml is requirede in order to get the report in CodeBuild. BuildSpec: | version: 0.2 phases: @@ -162,13 +231,13 @@ Resources: - git clone https://github.com/toniblyx/prowler build: commands: - - echo "Running Prowler..." + - echo "Running Prowler as ./prowler $PROWLER_OPTIONS" - cd prowler - ./prowler $PROWLER_OPTIONS post_build: commands: - echo "Uploading reports to S3..." - - aws s3 cp --sse AES256 output/*.html s3://$BUCKET_REPORT/ + - aws s3 cp --sse AES256 output/ s3://$BUCKET_REPORT/ --recursive - echo "Done!" reports: prowler: @@ -177,9 +246,11 @@ Resources: base-directory: 'prowler/junit-reports' file-format: JunitXml Environment: - # UILD_GENERAL1_SMALL: Use up to 3 GB memory and 2 vCPUs for builds. - # BUILD_GENERAL1_MEDIUM: Use up to 7 GB memory and 4 vCPUs for builds. - # BUILD_GENERAL1_LARGE: Use up to 15 GB memory and 8 vCPUs for builds. + # AWS CodeBuild free tier includes 100 build minutes of BUILD_GENERAL1_SMALL per month. + # BUILD_GENERAL1_SMALL: Use up to 3 GB memory and 2 vCPUs for builds. $0.005/minute. + # BUILD_GENERAL1_MEDIUM: Use up to 7 GB memory and 4 vCPUs for builds. $0.01/minute. + # BUILD_GENERAL1_LARGE: Use up to 15 GB memory and 8 vCPUs for builds. $0.02/minute. + # BUILD_GENERAL1_2XLARGE: Use up to 144 GB memory and 72 vCPUs for builds. $0.20/minute. ComputeType: "BUILD_GENERAL1_SMALL" Image: "aws/codebuild/amazonlinux2-x86_64-standard:3.0" Type: "LINUX_CONTAINER" @@ -197,7 +268,7 @@ Resources: ProwlerCodeBuildReportGroup: Type: AWS::CodeBuild::ReportGroup Properties: - Name: prowler + Name: !Sub 'prowler-report-group-${ServiceName}-${AWS::StackName}' Type: TEST ExportConfig: ExportConfigType: NO_EXPORT @@ -208,9 +279,50 @@ Resources: LogGroupName: !Sub '/aws/codebuild/${ProwlerCodeBuild}' RetentionInDays: !Ref LogsRetentionInDays + ProwlerSchedule: + Type: "AWS::Events::Rule" + Properties: + Description: > + A schedule for the Lambda function that triggers Prowler in CodeBuild.. + ScheduleExpression: !Ref ProwlerScheduler + State: ENABLED + Targets: + - Arn: !Sub ${ProwlerScheduleLambdaFunction.Arn} + Id: ProwlerSchedule + + ProwlerSchedulePermission: + Type: "AWS::Lambda::Permission" + Properties: + Action: 'lambda:InvokeFunction' + FunctionName: !Sub ${ProwlerScheduleLambdaFunction.Arn} + Principal: 'events.amazonaws.com' + SourceArn: !Sub ${ProwlerSchedule.Arn} + + ProwlerScheduleLambdaFunction: + Type: "AWS::Lambda::Function" + Properties: + Handler: index.lambda_handler + MemorySize: 128 + Role: !Sub ${CodeBuildStartBuildLambdaRole.Arn} + Timeout: 120 + Runtime: python3.6 + Environment: + Variables: + buildName: !Ref ProwlerCodeBuild + Code: + ZipFile: | + import boto3 + import os + + def lambda_handler(event,context): + codebuild_client = boto3.client('codebuild') + print("Running Prowler scheduled!: " + os.environ['buildName']) + project_name = os.environ['buildName'] + response = codebuild_client.start_build(projectName=project_name) + print(response) + print("Respond: SUCCESS") + Outputs: ArtifactBucketName: Description: Artifact Bucket Name - Value: !Ref 'ArtifactBucket' - Export: - Name: !Sub 'ArtifactBucketName-${ServiceName}' \ No newline at end of file + Value: !Ref 'ArtifactBucket' \ No newline at end of file