Merge branch '2.7' into patch-1

This commit is contained in:
Toni de la Fuente authored and GitHub committed 2021-12-13 14:36:10 +01:00
commit 13db49ba64
21 files changed
+471 -76

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is or what is not working as expected
**To Reproduce**
Steps to reproduce the behavior:
1. Command you are running
2. Environment you have, like single account, multi-account, organizations, etc.
3. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots or Logs**
If applicable, add screenshots to help explain your problem.
Add logs (anonymize them first!). Here a command that may help to share a log
`bash -x ./prowler -options > debug.log 2>&1` then attach here `debug.log`
**From where are you running Prowler? (please complete the following information):**
- Resource: [e.g. EC2 instance, Fargate task, Docker container manually, EKS, Cloud9, CodeBuild, workstation, etc.)
- OS: [e.g. Amazon Linux 2, Mac, Alpine, Windows, etc. ]
- AWS-CLI Version [`aws --version`]:
- Prowler Version [`./prowler -V`]:
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+1 -1
View File
@@ -584,7 +584,7 @@ The `gdpr` group of checks uses existing and extra checks. To get a GDPR report,
With this group of checks, Prowler shows result of checks related to the AWS Foundational Technical Review, more information [here](https://apn-checklists.s3.amazonaws.com/foundational/partner-hosted/partner-hosted/CVLHEC5X7.html). The list of checks can be seen in the group file at:
[groups/group25_ftr](groups/group25_ftr)
[groups/group25_ftr](groups/group25_FTR)
The `ftr` group of checks uses existing and extra checks. To get a AWS FTR report, run this command:
+1 -1
View File
@@ -16,7 +16,7 @@ CHECK_SCORED_extra7147="NOT_SCORED"
CHECK_CIS_LEVEL_extra7147="EXTRA"
CHECK_SEVERITY_extra7147="Critical"
CHECK_ASFF_RESOURCE_TYPE_extra7147="AwsGlacierVault"
CHECK_ALTERNATE_check7147="extra7142"
CHECK_ALTERNATE_check7147="extra7147"
CHECK_SERVICENAME_extra7147="glacier"
CHECK_RISK_extra7147='Vaults accessible to everyone could expose sensitive data to bad actors'
CHECK_REMEDIATION_extra7147='Ensure vault policy does not have principle as *'
+42
View File
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2021) 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_extra7160="7.160"
CHECK_TITLE_extra7160="[extra7160] Check if Redshift has automatic upgrades enabled"
CHECK_SCORED_extra7160="NOT_SCORED"
CHECK_CIS_LEVEL_extra7160="EXTRA"
CHECK_SEVERITY_extra7160="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7160="AwsRedshift"
CHECK_ALTERNATE_check7160="extra7160"
CHECK_SERVICENAME_extra7160="redshift"
CHECK_RISK_extra7160='Without automatic version upgrade enabled; a critical Redshift Cluster version can become severly out of date.'
CHECK_REMEDIATION_extra7160='Enabled AutomaticVersionUpgrade on Redshift Cluster'
CHECK_DOC_extra7160='https://docs.aws.amazon.com/redshift/latest/mgmt/managing-cluster-operations.html'
CHECK_CAF_EPIC_extra7160='Infrastructure Security'
extra7160(){
for regx in $REGIONS; do
LIST_OF_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --query 'Clusters[*].ClusterIdentifier' --region $regx --output text)
if [[ $LIST_OF_CLUSTERS ]]; then
for cluster in $LIST_OF_CLUSTERS; do
AUTO_UPGRADE_ENABLED=$($AWSCLI redshift describe-clusters $PROFILE_OPT --cluster-identifier $cluster --query 'Clusters[*].AllowVersionUpgrade' --region $regx --output text)
if [[ $AUTO_UPGRADE_ENABLED == "True" ]]; then
textPass "$regx: $cluster has AllowVersionUpgrade enabled" "$regx" "$cluster"
else
textFail "$regx: $cluster has AllowVersionUpgrade disabled" "$regx" "$cluster"
fi
done
else
textInfo "$regx: No Redshift Clusters found" "$regx"
fi
done
}
+43
View File
@@ -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_extra7161="7.161"
CHECK_TITLE_extra7161="[extra7161] Check if EFS have protects sensative data with encryption at rest"
CHECK_SCORED_extra7161="NOT_SCORED"
CHECK_CIS_LEVEL_extra7161="EXTRA"
CHECK_SEVERITY_extra7161="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7161="AwsEfsFileSystem"
CHECK_ALTERNATE_check7161="extra7161"
CHECK_SERVICENAME_extra7161="efs"
CHECK_RISK_extra7161='EFS should be encrypted at rest to prevent exposure of sensitive data to bad actors'
CHECK_REMEDIATION_extra7161='Ensure that encryption at rest is enabled for EFS file systems. Encryption at rest can only be enabled during the file system creation.'
CHECK_DOC_extra7161='https://docs.aws.amazon.com/efs/latest/ug/encryption-at-rest.html'
CHECK_CAF_EPIC_extra7161='Data Protection'
extra7161(){
# "Check if EFS has encryption at rest enabled (Not Scored) (Proposed requirement for 1.5 CIS benchmark)"
for regx in $REGIONS; do
LIST_OF_EFS_IDS=$($AWSCLI efs describe-file-systems $PROFILE_OPT --region $regx --query 'FileSystems[*].FileSystemId' --output text | xargs -n1)
if [[ $LIST_OF_EFS_IDS ]]; then
for efsId in $LIST_OF_EFS_IDS;do
EFS_ENCRYPTION_CHECK=$($AWSCLI efs $PROFILE_OPT describe-file-systems --region $regx --file-system-id $efsId --output json --query 'FileSystems[*].Encrypted' --output text)
if [[ $EFS_ENCRYPTION_CHECK == "True" ]]; then
textPass "$regx: EFS $efsId has has encryption at rest enabled" "$regx" "$efsId"
else
textFail "$regx: EFS: $efsId does not have encryption at rest enabled" "$regx" "$efsId"
fi
done
else
textInfo "$regx: No EFS found" "$regx"
fi
done
}
+50
View File
@@ -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_extra7162="7.162"
CHECK_TITLE_extra7162="[extra7162] Check if CloudWatch Log Groups have a retention policy of 365 days"
CHECK_SCORED_extra7162="NOT_SCORED"
CHECK_CIS_LEVEL_extra7162="EXTRA"
CHECK_SEVERITY_extra7162="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7162="AwsLogsLogGroup"
CHECK_ALTERNATE_check7162="extra7162"
CHECK_SERVICENAME_extra7162="cloudwatch"
CHECK_RISK_extra7162='If log groups have a low retention policy of less than 365 days, crucial logs and data can be lost'
CHECK_REMEDIATION_extra7162='Add Log Retention policy of 365 days to log groups. This will persist logs and traces for a long time.'
CHECK_DOC_extra7162='https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Logs.html'
CHECK_CAF_EPIC_extra7162='Data Retention'
extra7162() {
# "Check if CloudWatch Log Groups have a retention policy of 365 days"
declare -i LOG_GROUP_RETENTION_PERIOD_DAYS=365
for regx in $REGIONS; do
LIST_OF_365_RETENTION_LOG_GROUPS=$($AWSCLI logs describe-log-groups $PROFILE_OPT --region $regx --query 'logGroups[?retentionInDays=="${LOG_GROUP_RETENTION_PERIOD_DAYS}"].[logGroupName]' --output text)
if [[ $LIST_OF_365_RETENTION_LOG_GROUPS ]]; then
for log in $LIST_OF_365_RETENTION_LOG_GROUPS; do
textPass "$regx: $log Log Group has 365 days retention period!" "$regx" "$log"
done
fi
LIST_OF_NON_365_RETENTION_LOG_GROUPS=$($AWSCLI logs describe-log-groups $PROFILE_OPT --region $regx --query 'logGroups[?retentionInDays!="${LOG_GROUP_RETENTION_PERIOD_DAYS}"].[logGroupName]' --output text)
if [[ $LIST_OF_NON_365_RETENTION_LOG_GROUPS ]]; then
for log in $LIST_OF_NON_365_RETENTION_LOG_GROUPS; do
textFail "$regx: $log Log Group does not have 365 days retention period!" "$regx" "$log"
done
fi
REGION_NO_LOG_GROUP=$($AWSCLI logs describe-log-groups $PROFILE_OPT --region $regx --output text)
if [[ $REGION_NO_LOG_GROUP ]]; then
:
else
textInfo "$regx does not have a Log Group!" "$regx"
fi
done
}
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) 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.
# Remediation:
#
# https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/rotate-secret.html
#
# rotate-secret
# --secret-id <value>
# [--client-request-token <value>]
# [--rotation-lambda-arn <value>]
# [--rotation-rules <value>]
# [--cli-input-json <value>]
# [--generate-cli-skeleton <value>]
CHECK_ID_extra7163="7.163"
CHECK_TITLE_extra7163="[extra7163] Check if Secrets Manager key rotation is enabled"
CHECK_SCORED_extra7163="NOT_SCORED"
CHECK_TYPE_extra7163="EXTRA"
CHECK_SEVERITY_extra7163="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7163="AwsSecretsManagerSecret"
CHECK_ALTERNATE_extra7163="extra7163"
CHECK_SERVICENAME_extra7163="secretsmanager"
CHECK_RISK_extra7163="Rotating secrets minimizes exposure to attacks using stolen keys."
CHECK_REMEDITATION_extra7163="Enable key rotation on Secrets Manager key."
CHECK_DOC_extra7163="https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html"
CHECK_CAF_EPIC_extra7163="Data Protection"
extra7163(){
# "Check if Secrets Manager key rotation is enabled"
for regx in $REGIONS; do
LIST_OF_SECRETS=$($AWSCLI secretsmanager list-secrets $PROFILE_OPT --region $regx --query 'SecretList[*].Name' --output text)
if [[ $LIST_OF_SECRETS ]]; then
for secret in $LIST_OF_SECRETS; do
KEY_ROTATION_ENABLED=$($AWSCLI secretsmanager describe-secret $PROFILE_OPT --region $regx --secret-id $secret --output json | jq '.RotationEnabled')
if [[ $KEY_ROTATION_ENABLED == true ]]; then
textPass "$regx: $secret has key rotation enabled." "$regx" "$secret"
else
textFail "$regx: $secret does not have key rotation enabled." "$regx" "$secret"
fi
done
else
textPass "$regx: No Secrets Manager secrets found." "$regx"
fi
done
}
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) 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.
# Remediation:
#
# https://docs.aws.amazon.com/cli/latest/reference/logs/associate-kms-key.html
# associate-kms-key
# --log-group-name <value>
# --kms-key-id <value>
# [--cli-input-json <value>]
# [--generate-cli-skeleton <value>]
CHECK_ID_extra7164="7.164"
CHECK_TITLE_extra7164="[extra7164] Check if CloudWatch log groups are protected by AWS KMS "
CHECK_SCORED_extra7164="NOT_SCORED"
CHECK_TYPE_extra7164="EXTRA"
CHECK_SEVERITY_extra7164="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7164="Logs"
CHECK_ALTERNATE_extra7164="extra7164"
CHECK_SERVICENAME_extra7164="logs"
CHECK_RISK_extra7164="Using customer managed KMS to encrypt CloudWatch log group provide additional confidentiality and control over the log data"
CHECK_REMEDITATION_extra7164="Associate KMS Key with Cloudwatch log group."
CHECK_DOC_extra7164="https://docs.aws.amazon.com/cli/latest/reference/logs/associate-kms-key.html"
CHECK_CAF_EPIC_extra7164="Data Protection"
extra7164(){
# "Check if Cloudwatch log groups are associated with AWS KMS"
for regx in $REGIONS; do
LIST_OF_LOGGROUPS=$($AWSCLI logs describe-log-groups $PROFILE_OPT --region $regx --output json | jq '.logGroups[]')
if [[ $LIST_OF_LOGGROUPS ]]; then
LIST_OF_LOGGROUPS_WITHOUT_KMS=$(echo "${LIST_OF_LOGGROUPS}" | jq '. | select( has("kmsKeyId") == false )' | jq -r '.logGroupName')
LIST_OF_LOGGROUPS_WITH_KMS=$(echo "${LIST_OF_LOGGROUPS}" | jq '. | select( has("kmsKeyId") == true )' | jq -r '.logGroupName')
if [[ $LIST_OF_LOGGROUPS_WITHOUT_KMS ]]; then
for loggroup in $LIST_OF_LOGGROUPS_WITHOUT_KMS; do
textFail "$regx: ${loggroup} does not have AWS KMS keys associated." "$regx" "${loggroup}"
done
fi
if [[ $LIST_OF_LOGGROUPS_WITH_KMS ]]; then
for loggroup in $LIST_OF_LOGGROUPS_WITH_KMS; do
textPass "$regx: ${loggroup} does have AWS KMS keys associated." "$regx" "${loggroup}"
done
fi
else
textPass "$regx: No Cloudwatch log groups found." "$regx"
fi
done
}
+62
View File
@@ -0,0 +1,62 @@
#!/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.
# Remediation
#
# https://docs.aws.amazon.com/cli/latest/reference/dax/create-cluster.html
#
# create-cluster
# --cluster-name <value>
# --node-type <value>
# --replication-factor <value>
# --iam-role-arn <value>
# --sse-specification Enabled=true
CHECK_ID_extra7165="7.165"
CHECK_TITLE_extra7165="[extra7165] Check if DynamoDB: DAX Clusters are encrypted at rest"
CHECK_SCORED_extra7165="NOT_SCORED"
CHECK_TYPE_extra7165="EXTRA"
CHECK_SEVERITY_extra7165="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7165="AwsDaxCluster"
CHECK_ALTERNATE_check7165="extra7165"
CHECK_SERVICENAME_extra7165="dynamodb"
CHECK_RISK_extra7165="Encryption at rest provides an additional layer of data protection by securing your data from unauthorized access to the underlying storage."
CHECK_REMEDIATION_extra7165="Re-create the cluster to enable encryption at rest if it was not enabled at creation."
CHECK_DOC_extra7165="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionAtRest.html"
CHECK_CAF_EPIC_extra7165="Data Protection"
extra7165(){
# "Check if DynamoDB: DAX Clusters are encrypted at rest"
for regx in $REGIONS; do
LIST_OF_DAX_CLUSTERS=$($AWSCLI dax describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*]' --output json 2>&1)
if [[ "$(echo "$LIST_OF_DAX_CLUSTERS" | grep "Could not connect\|Access Denied" )" ]]; then
textInfo "$regx: DynamoDB: DAX Clusters do not exist in this region." "$regx"
elif [[ $LIST_OF_DAX_CLUSTERS && $LIST_OF_DAX_CLUSTERS != '[]' ]]; then
LIST_OF_CLUSTERS_WITH_ENCRYPTION=$(echo "${LIST_OF_DAX_CLUSTERS}" | jq '.[] | select(.SSEDescription.Status=="ENABLED") | {ClusterName}' | jq -r '.ClusterName')
LIST_OF_CLUSTERS_WITHOUT_ENCRYPTION=$(echo "${LIST_OF_DAX_CLUSTERS}" | jq '.[] | select(.SSEDescription.Status=="DISABLED") | {ClusterName}' | jq -r '.ClusterName')
if [[ $LIST_OF_CLUSTERS_WITHOUT_ENCRYPTION ]]; then
for cluster in $LIST_OF_CLUSTERS_WITHOUT_ENCRYPTION; do
textFail "$regx: ${cluster} does not have encryption at rest enabled." "$regx" "${cluster}"
done
fi
if [[ $LIST_OF_CLUSTERS_WITH_ENCRYPTION ]]; then
for cluster in $LIST_OF_CLUSTERS_WITH_ENCRYPTION; do
textPass "$regx: ${cluster} has encryption at rest enabled." "$regx" "${cluster}"
done
fi
else
textInfo "$regx: No DynamoDB: DAX Clusters found." "$regx"
fi
done
}
+5 -1
View File
@@ -31,7 +31,11 @@ extra760(){
fi
for regx in $REGIONS; do
LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text)
LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text 2>&1)
if [[ $(echo "$LIST_OF_FUNCTIONS" | grep AccessDenied) ]]; then
textFail "$regx: Access Denied trying to list Lambda functions" "$regx" "$lambdafunction"
continue
fi
if [[ $LIST_OF_FUNCTIONS ]]; then
for lambdafunction in $LIST_OF_FUNCTIONS;do
LAMBDA_FUNCTION_FOLDER="$SECRETS_TEMP_FOLDER/extra760-$lambdafunction-$regx"
+2 -2
View File
@@ -34,9 +34,9 @@ extra763(){
continue
fi
if [[ $(echo "$BUCKET_VERSIONING_ENABLED" | grep "^Enabled$") ]]; then
textPass "Bucket $bucket has versioning enabled" "us-east-1" "$bucket"
textPass "Bucket $bucket has versioning enabled" "$REGION" "$bucket"
else
textFail "Bucket $bucket has versioning disabled!" "us-east-1" "$bucket"
textFail "Bucket $bucket has versioning disabled!" "$REGION" "$bucket"
fi
done
else
+2 -2
View File
@@ -37,7 +37,7 @@ extra792(){
ELBSECURECIPHERS=("Protocol-TLSv1.2" "Protocol-TLSv1.1" "Protocol-TLSv1" "ECDHE-ECDSA-AES128-GCM-SHA256" "ECDHE-RSA-AES128-GCM-SHA256" "ECDHE-ECDSA-AES128-SHA256" "ECDHE-RSA-AES128-SHA256" "ECDHE-ECDSA-AES128-SHA" "ECDHE-RSA-AES128-SHA" "ECDHE-ECDSA-AES256-GCM-SHA384" "ECDHE-RSA-AES256-GCM-SHA384" "ECDHE-ECDSA-AES256-SHA384" "ECDHE-RSA-AES256-SHA384" "ECDHE-RSA-AES256-SHA" "ECDHE-ECDSA-AES256-SHA" "AES128-GCM-SHA256" "AES128-SHA256" "AES128-SHA" "AES256-GCM-SHA384" "AES256-SHA256" "AES256-SHA" "Server-Defined-Cipher-Order")
for elb in $LIST_OF_ELBS; do
ELB_LISTENERS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --load-balancer-name $elb --query "LoadBalancerDescriptions[0]")
ELB_LISTENERS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --load-balancer-name $elb --query "LoadBalancerDescriptions[0]" --output json)
ELB_PROTOCOLS=$(echo $ELB_LISTENERS | jq -r '.ListenerDescriptions[].Listener.Protocol')
if [[ $(echo $ELB_PROTOCOLS | grep HTTPS) || $(echo $ELB_PROTOCOLS | grep SSL) ]]; then
@@ -90,7 +90,7 @@ extra792(){
elbname=$elbarn
fi
ELBV2_LISTENERS=$($AWSCLI elbv2 describe-listeners $PROFILE_OPT --region $regx --load-balancer-arn $elbarn --query "Listeners[*]")
ELBV2_LISTENERS=$($AWSCLI elbv2 describe-listeners $PROFILE_OPT --region $regx --load-balancer-arn $elbarn --query "Listeners[*]" --output json)
ELBV2_PROTOCOLS=$(echo $ELBV2_LISTENERS | jq -r '.[].Protocol')
+2 -2
View File
@@ -14,8 +14,8 @@
GROUP_ID[25]='ftr'
GROUP_NUMBER[25]='25.0'
GROUP_TITLE[25]='Amazon FTR related security checks - [ftr] ******************'
GROUP_RUN_BY_DEFAULT[9]='N' # run it when execute_all is called
GROUP_CHECKS[9]='check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check111,check112,check113,check117,check118,check122,check21,check22,extra759,extra760,extra768,extra775,extra797,extra7141,extra73'
GROUP_RUN_BY_DEFAULT[25]='N' # run it when execute_all is called
GROUP_CHECKS[25]='check11,check12,check13,check14,check15,check16,check17,check18,check19,check110,check111,check111,check112,check113,check117,check118,check122,check21,check22,extra759,extra760,extra768,extra775,extra797,extra7141,extra73'
# Checks from AWS FTR https://apn-checklists.s3.amazonaws.com/foundational/partner-hosted/partner-hosted/CVLHEC5X7.html
# 1.1 [check11] Avoid the use of the root account - iam [High]
+2 -2
View File
@@ -15,9 +15,9 @@ 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,extra738,extra739,extra740,extra741,extra742,extra743,extra744,extra745,extra746,extra747,extra748,extra749,extra750,extra751,extra752,extra753,extra754,extra755,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,extra7123,extra7124,extra7125,extra7126,extra7127,extra7128,extra7129,extra7130,extra7131,extra7132,extra7133,extra7134,extra7135,extra7136,extra7137,extra7138,extra7139,extra7140,extra7141,extra7142,extra7143,extra7144,extra7145,extra7146,extra7147,extra7148,extra7149,extra7150,extra7151,extra7152,extra7153,extra7154,extra7155,extra7156,extra7157,extra7158,extra7159'
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,extra738,extra739,extra740,extra741,extra742,extra743,extra744,extra745,extra746,extra747,extra748,extra749,extra750,extra751,extra752,extra753,extra754,extra755,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,extra7123,extra7124,extra7125,extra7126,extra7127,extra7128,extra7129,extra7130,extra7131,extra7132,extra7133,extra7134,extra7135,extra7136,extra7137,extra7138,extra7139,extra7140,extra7141,extra7142,extra7143,extra7144,extra7145,extra7146,extra7147,extra7148,extra7149,extra7150,extra7151,extra7152,extra7153,extra7154,extra7155,extra7156,extra7157,extra7158,extra7159,extra7160,extra7161,extra7162,extra7163,extra7164,extra7165'
# Extras 759 and 760 (lambda variables and code secrets finder are not included)
# Extras 759 and 760 (lambda variables and code secrets finder are not included)
# to run detect-secrets use `./prowler -g secrets`
# Extras 789 and 790 VPC trust boundaries are not included by default in Extras
+39 -45
View File
@@ -11,9 +11,10 @@
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
# both variables are mandatory to be set together
assume_role(){
if [[ -z $ROLE_TO_ASSUME ]]; then
PROFILE_OPT=$PROFILE_OPT_BAK
# Both variables are mandatory to be set together
if [[ -z $ROLE_TO_ASSUME || -z $ACCOUNT_TO_ASSUME ]]; then
echo "$OPTRED ERROR!$OPTNORMAL - Both Account ID (-A) and IAM Role to assume (-R) must be set"
exit 1
fi
@@ -28,6 +29,7 @@ assume_role(){
# temporary file where to store credentials
TEMP_STS_ASSUMED_FILE=$(mktemp -t prowler.sts_assumed-XXXXXX)
TEMP_STS_ASSUMED_ERROR=$(mktemp -t prowler.sts_assumed-XXXXXX)
# check if role arn or role name
if [[ $ROLE_TO_ASSUME == arn:* ]]; then
@@ -36,57 +38,49 @@ assume_role(){
PROWLER_ROLE=arn:${AWS_PARTITION}:iam::$ACCOUNT_TO_ASSUME:role/$ROLE_TO_ASSUME
fi
#Check if external ID has bee provided if so execute with external ID if not ignore
if [[ -z $ROLE_EXTERNAL_ID ]]; then
# assume role command
$AWSCLI $PROFILE_OPT sts assume-role --role-arn $PROWLER_ROLE \
--role-session-name ProwlerAssessmentSession \
--region $REGION_FOR_STS \
--duration-seconds $SESSION_DURATION_TO_ASSUME > $TEMP_STS_ASSUMED_FILE 2>&1
else
$AWSCLI $PROFILE_OPT sts assume-role --role-arn $PROWLER_ROLE \
--role-session-name ProwlerAssessmentSession \
--duration-seconds $SESSION_DURATION_TO_ASSUME \
--region $REGION_FOR_STS \
--external-id $ROLE_EXTERNAL_ID > $TEMP_STS_ASSUMED_FILE 2>&1
fi
if [[ $(grep AccessDenied $TEMP_STS_ASSUMED_FILE) ]]; then
textFail "Access Denied assuming role $PROWLER_ROLE"
EXITCODE=1
exit $EXITCODE
elif [[ "$(grep MaxSessionDuration $TEMP_STS_ASSUMED_FILE)" ]]; then
textFail "The requested DurationSeconds exceeds the MaxSessionDuration set for the role ${PROWLER_ROLE}"
EXITCODE=1
exit $EXITCODE
# Check if external ID has bee provided if so execute with external ID if not ignore
ROLE_EXTERNAL_ID_OPTION=""
if [[ -n "${ROLE_EXTERNAL_ID}" ]]; then
ROLE_EXTERNAL_ID_OPTION="--external-id ${ROLE_EXTERNAL_ID}"
fi
# assume role command
#$AWSCLI $PROFILE_OPT sts assume-role --role-arn arn:${AWS_PARTITION}:iam::$ACCOUNT_TO_ASSUME:role/$ROLE_TO_ASSUME \
# --role-session-name ProwlerAssessmentSession \
# --duration-seconds $SESSION_DURATION_TO_ASSUME > $TEMP_STS_ASSUMED_FILE
# if previous command fails exit with the given error from aws-cli
# this is likely to be due to session duration limit of 1h in case
# of assume role chaining:
# "The requested DurationSeconds exceeds the 1 hour session limit
# for roles assumed by role chaining."
# https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html
if [[ $? != 0 ]];then
exit 1
# Assume role
if ! $AWSCLI $PROFILE_OPT sts assume-role --role-arn $PROWLER_ROLE \
--role-session-name ProwlerAssessmentSession \
--duration-seconds $SESSION_DURATION_TO_ASSUME \
--region $REGION_FOR_STS \
"${ROLE_EXTERNAL_ID_OPTION}" > $TEMP_STS_ASSUMED_FILE 2>"${TEMP_STS_ASSUMED_ERROR}"
then
STS_ERROR="$(cat ${TEMP_STS_ASSUMED_ERROR} | tr '\n' ' ')"
textFail "${STS_ERROR}"
EXITCODE=1
exit $EXITCODE
fi
echo FILE WITH TEMP CREDS: $TEMP_STS_ASSUMED_FILE
# The profile shouldn't be used for CLI
PROFILE=""
PROFILE_OPT=""
PROFILE_OPT=""
# Set AWS environment variables with assumed role credentials
AWS_ACCESS_KEY_ID=$(jq -r '.Credentials.AccessKeyId' "${TEMP_STS_ASSUMED_FILE}")
export AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY=$(jq -r '.Credentials.SecretAccessKey' "${TEMP_STS_ASSUMED_FILE}")
export AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN=$(jq -r '.Credentials.SessionToken' "${TEMP_STS_ASSUMED_FILE}")
export AWS_SESSION_TOKEN
AWS_SESSION_EXPIRATION=$(jq -r '.Credentials.Expiration | sub("\\+00:00";"Z") | fromdateiso8601' "${TEMP_STS_ASSUMED_FILE}")
export AWS_SESSION_EXPIRATION
echo TEMP AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
echo TEMP AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
echo TEMP AWS_SESSION_TOKEN: $AWS_SESSION_TOKEN
echo EXPIRATION EPOCH TIME: $AWS_SESSION_EXPIRATION
# set env variables with assumed role credentials
export AWS_ACCESS_KEY_ID=$(cat $TEMP_STS_ASSUMED_FILE | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(cat $TEMP_STS_ASSUMED_FILE | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(cat $TEMP_STS_ASSUMED_FILE | jq -r '.Credentials.SessionToken')
export AWS_SESSION_EXPIRATION=$(cat $TEMP_STS_ASSUMED_FILE | jq -r '.Credentials.Expiration | sub("\\+00:00";"Z") | fromdateiso8601')
cleanSTSAssumeFile
}
cleanSTSAssumeFile() {
rm -fr "${TEMP_STS_ASSUMED_FILE}"
}
rm -fr "${TEMP_STS_ASSUMED_ERROR}"
}
+2 -1
View File
@@ -45,7 +45,8 @@ else
PROFILE="default"
PROFILE_OPT="--profile $PROFILE"
fi
# Backing up $PROFILE_OPT needed to renew assume_role
PROFILE_OPT_BAK=$PROFILE_OPT
# Set default region by aws config, fall back to us-east-1
REGION_CONFIG=$(aws configure get region)
if [[ $REGION_OPT ]]; then
+28 -9
View File
@@ -42,29 +42,48 @@ checkSecurityHubCompatibility(){
resolveSecurityHubPreviousFails(){
# Move previous check findings RecordState to ARCHIVED (as prowler didn't re-detect them)
SH_TEMP_FOLDER="$PROWLER_DIR/SH-$ACCOUNT_NUM"
if [[ ! -d $SH_TEMP_FOLDER ]]; then
# this folder is deleted once the security hub update is completed
mkdir "$SH_TEMP_FOLDER"
fi
for regx in $REGIONS; do
REGION_FOLDER="$SH_TEMP_FOLDER/$regx"
if [[ ! -d $REGION_FOLDER ]]; then
mkdir "$REGION_FOLDER"
fi
local check="$1"
NEW_TIMESTAMP=$(get_iso8601_timestamp)
FILTER="{\"GeneratorId\":[{\"Value\": \"prowler-$check\",\"Comparison\":\"EQUALS\"}],\"RecordState\":[{\"Value\": \"ACTIVE\",\"Comparison\":\"EQUALS\"}],\"AwsAccountId\":[{\"Value\": \"$ACCOUNT_NUM\",\"Comparison\":\"EQUALS\"}]}"
NEW_FINDING_IDS=$(echo -n "${SECURITYHUB_NEW_FINDINGS_IDS[@]}" | jq -cRs 'split(" ")')
SECURITY_HUB_PREVIOUS_FINDINGS=$($AWSCLI securityhub --region "$regx" $PROFILE_OPT get-findings --filters "${FILTER}" | jq -c --argjson ids "$NEW_FINDING_IDS" --arg updated_at $NEW_TIMESTAMP '[ .Findings[] | select( .Id| first(select($ids[] == .)) // false | not) | .RecordState = "ARCHIVED" | .UpdatedAt = $updated_at ]')
NEW_FINDING_FILE="$REGION_FOLDER/findings.json"
NEW_FINDING_IDS=$(echo -n "${SECURITYHUB_NEW_FINDINGS_IDS[@]}" | jq -cRs 'split(" ")' > $NEW_FINDING_FILE)
EXISTING_FILE="$REGION_FOLDER/existing.json"
EXISTING_FINDINGS=$($AWSCLI securityhub --region "$regx" $PROFILE_OPT get-findings --filters "${FILTER}" > $EXISTING_FILE)
SECURITY_HUB_PREVIOUS_FINDINGS=$(for id in $(comm -23 <(jq '[.Findings[].Id] | sort | .[]' $EXISTING_FILE) <(jq '[.[]] | sort | .[]' $NEW_FINDING_FILE));
do
jq --arg updated_at $NEW_TIMESTAMP '.Findings[] | select(.Id == '"$id"') | .RecordState = "ARCHIVED" | .UpdatedAt = $updated_at ' < $EXISTING_FILE
done | jq -s '.')
if [[ $SECURITY_HUB_PREVIOUS_FINDINGS != "[]" ]]; then
FINDINGS_COUNT=$(echo $SECURITY_HUB_PREVIOUS_FINDINGS | jq '. | length')
for i in `seq 0 100 $FINDINGS_COUNT`;
for i in $(seq 0 50 $FINDINGS_COUNT);
do
BATCH_FINDINGS=$(echo $SECURITY_HUB_PREVIOUS_FINDINGS | jq -c '.['"$i:$i+100"']')
BATCH_IMPORT_RESULT=$($AWSCLI securityhub --region "$regx" $PROFILE_OPT batch-import-findings --findings "${BATCH_FINDINGS}")
if [[ -z "${BATCH_IMPORT_RESULT}" ]] || jq -e '.FailedCount >= 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"
BATCH_FINDINGS=$(echo $SECURITY_HUB_PREVIOUS_FINDINGS | jq -c '.['"$i:$i+50"']')
BATCH_FINDINGS_COUNT=$(echo $BATCH_FINDINGS | jq '. | length')
if [ "$BATCH_FINDINGS_COUNT" -gt 0 ]; then
BATCH_IMPORT_RESULT=$($AWSCLI securityhub --region "$regx" $PROFILE_OPT batch-import-findings --findings "${BATCH_FINDINGS}")
if [[ -z "${BATCH_IMPORT_RESULT}" ]] || jq -e '.FailedCount >= 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
fi
done
fi
done
rm -rf "$SH_TEMP_FOLDER"
}
sendToSecurityHub(){
+15 -9
View File
@@ -32,7 +32,7 @@ OPTRED=""
OPTNORMAL=""
# Set the defaults variables
PROWLER_VERSION=2.6.1-15November2021
PROWLER_VERSION=2.7.0-1December2021
PROWLER_DIR=$(dirname "$0")
REGION=""
@@ -97,7 +97,7 @@ USAGE:
(i.e.: 123456789012)
-R role name or role arn to assume in the account, requires -A and -T
(i.e.: ProwlerRole)
-T session duration given to that role credentials in seconds, default 1h (3600) recommended 12h, requires -R and -T
-T session duration given to that role credentials in seconds, default 1h (3600) recommended 12h, optional with -R and -A
(i.e.: 43200)
-I External ID to be used when assuming roles (not mandatory), requires -A and -R
-w whitelist file. See whitelist_sample.txt for reference and format
@@ -135,6 +135,7 @@ while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:F:zZ:" OPTION; do
;;
p )
PROFILE=$OPTARG
AWS_PROFILE=$OPTARG
;;
r )
REGION_OPT=$OPTARG
@@ -338,6 +339,7 @@ TOTAL_CHECKS=($(echo "${TOTAL_CHECKS[*]}" | tr ' ' '\n' | awk '!seen[$0]++' | so
get_regions() {
# Get list of regions based on include/whoami
REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' --output text $PROFILE_OPT --region $REGION_FOR_STS --region-names $FILTERREGION 2>&1)
echo $REGIONS
ret=$?
if [[ $ret -ne 0 ]]; then
echo "$OPTRED Access Denied trying to describe regions! Review permissions as described here: https://github.com/toniblyx/prowler/#requirements-and-installation $OPTNORMAL"
@@ -392,13 +394,15 @@ show_group_title() {
# Function to execute the check
execute_check() {
if [[ $ACCOUNT_TO_ASSUME ]]; then
if [[ -n "${ACCOUNT_TO_ASSUME}" || -n "${ROLE_TO_ASSUME}" ]]; then
# Following logic looks for time remaining in the session and review it
# if it is less than 600 seconds, 10 minutes.
CURRENT_TIMESTAMP=$(date -u "+%s")
SESSION_TIME_REMAINING=$(expr $AWS_SESSION_EXPIRATION - $CURRENT_TIMESTAMP)
MINIMUM_REMAINING_TIME_ALLOWED="600"
if [[ $MINIMUM_REMAINING_TIME_ALLOWED > $SESSION_TIME_REMAINING ]]; then
echo SESSION TIME REMAINING IN SECONDS: $SESSION_TIME_REMAINING
MINIMUM_REMAINING_TIME_ALLOWED=600
if (( $MINIMUM_REMAINING_TIME_ALLOWED > $SESSION_TIME_REMAINING )); then
echo LESS THAN 10 MIN LEFT: RE-ASSUMING...
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
@@ -497,7 +501,7 @@ execute_check() {
fi
else
textFail "ERROR! Use a valid check name (i.e. check41 or extra71)";
textFail "Check ${CHECK_ID} does not exist. Use a valid check name (i.e. check41 or extra71)";
exit $EXITCODE
fi
fi
@@ -565,7 +569,7 @@ show_all_titles() {
fi
done
else
textFail "Use a valid check group ID i.e.: group1, extras, forensics-ready, etc."
textFail "Group ${GROUP_ID_READ} does not exist. Use a valid check group ID i.e.: group1, extras, forensics-ready, etc."
show_all_group_titles
exit $EXITCODE
fi
@@ -639,12 +643,14 @@ fi
# Gather account data / test aws cli connectivity
getWhoami
if [[ $ACCOUNT_TO_ASSUME ]]; then
if [[ -n "${ACCOUNT_TO_ASSUME}" || -n "${ROLE_TO_ASSUME}" ]]; then
assume_role
fi
# List regions
echo REGIONS_init
get_regions
echo REGIONS_end
# Execute group of checks if called with -g
if [[ $GROUP_ID_READ ]];then
@@ -659,7 +665,7 @@ if [[ $GROUP_ID_READ ]];then
copyToS3
exit $EXITCODE
else
textFail "Use a valid check group ID i.e.: group1, extras, forensics-ready, etc."
textFail "Group ${GROUP_ID_READ} does not exist. Use a valid check group ID i.e.: group1, extras, forensics-ready, etc."
show_all_group_titles
exit $EXITCODE
fi
@@ -123,8 +123,12 @@ Resources:
runtime-versions:
python: 3.8
commands:
- echo "Updating yum..."
- echo "Updating yum ..."
- yum -y update
- echo "Updating pip ..."
- python -m pip install --upgrade pip
- echo "Installing requirements ..."
- pip install "git+https://github.com/ibm/detect-secrets.git@master#egg=detect-secrets"
build:
commands:
- echo "Running Prowler with script"
@@ -83,6 +83,7 @@ Resources:
- dax:ListTables
- ds:ListAuthorizedApplications
- ds:DescribeRoles
- ec2:GetEbsEncryptionByDefault
- ecr:Describe*
- lambda:GetAccountSettings
- lambda:GetFunctionConfiguration