diff --git a/.dockerignore b/.dockerignore
index 58992691..3a5374b0 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,4 +1,5 @@
.git/
+.github/
# Ignore output directories
output/
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..ead43c3a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,50 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: "[Bug]: "
+labels: ["bug", "triage"]
+assignees: ''
+
+---
+
+
+
+**What happened?**
+A clear and concise description of what the bug is or what is not working as expected
+
+
+**How to reproduce it**
+Steps to reproduce the behavior:
+1. What command are you 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.
+Also, you can 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`]:
+ - Shell and version:
+ - Others:
+
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..11fc491e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -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.
diff --git a/README.md b/README.md
index 5cb8afde..a655774f 100644
--- a/README.md
+++ b/README.md
@@ -66,7 +66,7 @@ Read more about [CIS Amazon Web Services Foundations Benchmark v1.2.0 - 05-23-20
With Prowler you can:
- Get a direct colorful or monochrome report
-- A HTML, CSV, JUNIT, JSON or JSON ASFF format report
+- A HTML, CSV, JUNIT, JSON or JSON ASFF (Security Hub) format report
- Send findings directly to Security Hub
- Run specific checks and groups or create your own
- Check multiple AWS accounts in parallel or sequentially
@@ -79,39 +79,47 @@ You can run Prowler from your workstation, an EC2 instance, Fargate or any other

## Requirements and Installation
-Prowler has been written in bash using AWS-CLI and it works in Linux and OSX.
+Prowler has been written in bash using AWS-CLI underneath and it works in Linux, Mac OS or Windows with cygwin or virtualization. Also requires `jq` and `detect-secrets` to work properly.
-- Make sure the latest version of AWS-CLI is installed on your workstation (it works with either v1 or v2), and other components needed, with Python pip already installed:
+- Make sure the latest version of AWS-CLI is installed. It works with either v1 or v2, however _latest v2 is recommended if using new regions since they require STS v2 token_, and other components needed, with Python pip already installed.
- ```sh
- pip install awscli
+- For Amazon Linux (`yum` based Linux distributions and AWS CLI v2):
+ ```
+ sudo yum update -y
+ sudo yum remove -y awscli
+ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
+ unzip awscliv2.zip
+ sudo ./aws/install
+ sudo yum install -y python3 jq git
+ sudo pip3 install detect-secrets==1.0.3
+ git clone https://github.com/toniblyx/prowler
+ ```
+- For Ubuntu Linux (`apt` based Linux distributions and AWS CLI v2):
+ ```
+ sudo apt update
+ sudo apt install python3 python3-pip jq git zip
+ pip install detect-secrets==1.0.3
+ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
+ unzip awscliv2.zip
+ sudo ./aws/install
+ git clone https://github.com/toniblyx/prowler
```
- > NOTE: detect-secrets Yelp version is no longer supported the one from IBM is mantained now. Use the one mentioned below or the specific Yelp version 1.0.3 to make sure it works as expected (`pip install detect-secrets==1.0.3`):
+ > NOTE: detect-secrets Yelp version is no longer supported, the one from IBM is mantained now. Use the one mentioned below or the specific Yelp version 1.0.3 to make sure it works as expected (`pip install detect-secrets==1.0.3`):
```sh
pip install "git+https://github.com/ibm/detect-secrets.git@master#egg=detect-secrets"
```
- AWS-CLI can be also installed it using "brew", "apt", "yum" or manually from , but `detect-secrets` has to be installed using `pip` or `pip3`. You will need to install `jq` to get the most from Prowler.
+ AWS-CLI can be also installed it using other methods, refer to official documentation for more details: , but `detect-secrets` has to be installed using `pip` or `pip3`.
-- Make sure jq is installed: examples below with "apt" for Debian alike and "yum" for RedHat alike distros (like Amazon Linux):
+- Once Prowler repository is cloned, get into the folder and you can run it:
```sh
- sudo apt install jq
- ```
-
- ```sh
- sudo yum install jq
- ```
-
-- Previous steps, from your workstation:
-
- ```sh
- git clone https://github.com/toniblyx/prowler
cd prowler
+ ./prowler
```
-- Since Prowler users AWS CLI under the hood, you can follow any authentication method as described [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-precedence). Make sure you have properly configured your AWS-CLI with a valid Access Key and Region or declare AWS variables properly (or intance profile):
+- Since Prowler users AWS CLI under the hood, you can follow any authentication method as described [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-precedence). Make sure you have properly configured your AWS-CLI with a valid Access Key and Region or declare AWS variables properly (or instance profile/role):
```sh
aws configure
@@ -150,6 +158,11 @@ Prowler has been written in bash using AWS-CLI and it works in Linux and OSX.
docker run -ti --rm --name prowler --env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY --env AWS_SESSION_TOKEN toniblyx/prowler:latest
```
+ In case you want to get reports created by Prowler use docker volume option like in the example below:
+ ```sh
+ docker run -ti --rm -v /your/local/output:/prowler/output --name prowler --env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY --env AWS_SESSION_TOKEN toniblyx/prowler:latest -g hipaa -M csv,json,html
+ ```
+
1. For custom AWS-CLI profile and region, use the following: (it will use your custom profile and run checks over all regions when needed):
```sh
@@ -216,7 +229,7 @@ Prowler has two parameters related to regions: `-r` that is used query AWS servi
-- Sample screenshot of the Quicksight dashboard, see [https://quicksight-security-dashboard.workshop.aws](quicksight-security-dashboard.workshop.aws/):
+- Sample screenshot of the Quicksight dashboard, see [quicksight-security-dashboard.workshop.aws](https://quicksight-security-dashboard.workshop.aws/):
@@ -584,7 +597,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:
diff --git a/checks/check119 b/checks/check119
index c1ebe209..141a36c2 100644
--- a/checks/check119
+++ b/checks/check119
@@ -27,9 +27,14 @@ CHECK_CAF_EPIC_check119='IAM'
check119(){
for regx in $REGIONS; do
- EC2_DATA=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[].Instances[].[InstanceId, IamInstanceProfile.Arn, State.Name]' --output json)
- EC2_DATA=$(echo $EC2_DATA | jq '.[]|{InstanceId: .[0], ProfileArn: .[1], StateName: .[2]}')
- INSTANCE_LIST=$(echo $EC2_DATA | jq -r '.InstanceId')
+ EC2_DATA=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[].Instances[].[InstanceId, IamInstanceProfile.Arn, State.Name]' --output json 2>&1)
+ if [[ $(echo "$EC2_DATA" | grep UnauthorizedOperation) ]]; then
+ textInfo "$regx: Unauthorized Operation error trying to describe instances" "$regx"
+ continue
+ else
+ EC2_DATA=$(echo $EC2_DATA | jq '.[]|{InstanceId: .[0], ProfileArn: .[1], StateName: .[2]}')
+ INSTANCE_LIST=$(echo $EC2_DATA | jq -r '.InstanceId')
+ fi
if [[ $INSTANCE_LIST ]]; then
for instance in $INSTANCE_LIST; do
STATE_NAME=$(echo $EC2_DATA | jq -r --arg i "$instance" 'select(.InstanceId==$i)|.StateName')
diff --git a/checks/check122 b/checks/check122
index 81ea3e61..db1c68c6 100644
--- a/checks/check122
+++ b/checks/check122
@@ -42,9 +42,9 @@ check122(){
textFail "$REGION: Policy $policy allows \"*:*\"" "$REGION" "$policy"
done
else
- textPass "$REGION: No custom policy found that allow full \"*:*\" administrative privileges" "$REGION" "$policy"
+ textPass "$REGION: No custom policy found that allow full \"*:*\" administrative privileges" "$REGION"
fi
else
- textPass "$REGION: No custom policies found" "$REGION" "$policy"
+ textPass "$REGION: No custom policies found" "$REGION"
fi
}
diff --git a/checks/check21 b/checks/check21
index 968f6c19..d34ed292 100644
--- a/checks/check21
+++ b/checks/check21
@@ -32,7 +32,7 @@ check21(){
for regx in $REGIONS; do
TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',')
if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe trails" "$regx" "$trail"
+ textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail"
continue
fi
if [[ $TRAILS_AND_REGIONS ]]; then
diff --git a/checks/check22 b/checks/check22
index cca1a8da..98488b2b 100644
--- a/checks/check22
+++ b/checks/check22
@@ -32,7 +32,7 @@ check22(){
for regx in $REGIONS; do
TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',')
if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe trails" "$regx" "$trail"
+ textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail"
continue
fi
if [[ $TRAILS_AND_REGIONS ]]; then
diff --git a/checks/check23 b/checks/check23
index 48b9bf44..f8c5fde0 100644
--- a/checks/check23
+++ b/checks/check23
@@ -32,7 +32,7 @@ check23(){
for regx in $REGIONS; do
TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',')
if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe trails" "$regx" "$trail"
+ textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail"
continue
fi
if [[ $TRAILS_AND_REGIONS ]]; then
@@ -63,7 +63,7 @@ check23(){
#
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $regx --bucket $CLOUDTRAILBUCKET --output text 2>&1)
if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then
- textFail "Trail $trail in $TRAIL_REGION Access Denied getting bucket location for $CLOUDTRAILBUCKET"
+ textInfo "Trail $trail in $TRAIL_REGION Access Denied getting bucket location for $CLOUDTRAILBUCKET"
continue
fi
if [[ $BUCKET_LOCATION == "None" ]]; then
diff --git a/checks/check24 b/checks/check24
index 68cabd67..9a04d0ae 100644
--- a/checks/check24
+++ b/checks/check24
@@ -32,7 +32,7 @@ check24(){
for regx in $REGIONS; do
TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',')
if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe trails" "$regx" "$trail"
+ textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail"
continue
fi
if [[ $TRAILS_AND_REGIONS ]]; then
diff --git a/checks/check25 b/checks/check25
index 752235fc..a1062259 100644
--- a/checks/check25
+++ b/checks/check25
@@ -31,7 +31,7 @@ check25(){
CHECK_AWSCONFIG_RECORDING=$($AWSCLI configservice describe-configuration-recorder-status $PROFILE_OPT --region $regx --query 'ConfigurationRecordersStatus[*].recording' --output text 2>&1)
CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice describe-configuration-recorder-status $PROFILE_OPT --region $regx --query 'ConfigurationRecordersStatus[*].lastStatus' --output text 2>&1)
if [[ $(echo "$CHECK_AWSCONFIG_STATUS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe configuration recorder status" "$regx" "recorder"
+ textInfo "$regx: Access Denied trying to describe configuration recorder status" "$regx" "recorder"
continue
fi
if [[ $CHECK_AWSCONFIG_RECORDING == "True" ]]; then
diff --git a/checks/check26 b/checks/check26
index 166fbea5..405e6800 100644
--- a/checks/check26
+++ b/checks/check26
@@ -31,7 +31,7 @@ check26(){
for regx in $REGIONS; do
TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',')
if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe trails" "$regx" "$trail"
+ textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail"
continue
fi
if [[ $TRAILS_AND_REGIONS ]]; then
@@ -62,7 +62,7 @@ check26(){
#
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $regx --bucket $CLOUDTRAILBUCKET --output text 2>&1)
if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then
- textFail "$regx: Trail $trail Access Denied getting bucket location for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail"
+ textInfo "$regx: Trail $trail Access Denied getting bucket location for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail"
continue
fi
if [[ $BUCKET_LOCATION == "None" ]]; then
diff --git a/checks/check27 b/checks/check27
index c5304c74..166b1a07 100644
--- a/checks/check27
+++ b/checks/check27
@@ -32,7 +32,7 @@ check27(){
for regx in $REGIONS; do
TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',')
if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe trails" "$regx" "$trail"
+ textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail"
continue
fi
if [[ $TRAILS_AND_REGIONS ]]; then
diff --git a/checks/check28 b/checks/check28
index 1008a36d..2770d0a6 100644
--- a/checks/check28
+++ b/checks/check28
@@ -30,7 +30,7 @@ check28(){
for regx in $REGIONS; do
CHECK_KMS_KEYLIST=$($AWSCLI kms list-keys $PROFILE_OPT --region $regx --output text --query 'Keys[*].KeyId' --output text 2>&1)
if [[ $(echo "$CHECK_KMS_KEYLIST" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to list keys" "$regx" "$key"
+ textInfo "$regx: Access Denied trying to list keys" "$regx" "$key"
continue
fi
if [[ $CHECK_KMS_KEYLIST ]]; then
@@ -38,7 +38,7 @@ check28(){
for key in $CHECK_KMS_KEYLIST; do
KMSDETAILS=$($AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --query 'KeyMetadata.{key:KeyId,man:KeyManager,origin:Origin,spec:CustomerMasterKeySpec,state:KeyState}' --output text 2>&1 | grep SYMMETRIC)
if [[ $(echo "$KMSDETAILS" | grep AccessDenied) ]]; then
- textFail "$regx: Key $key Access Denied describing key" "$regx" "$key"
+ textInfo "$regx: Access Denied describing key $key" "$regx" "$key"
continue
fi
@@ -60,7 +60,7 @@ check28(){
else
CHECK_KMS_KEY_ROTATION=$($AWSCLI kms get-key-rotation-status --key-id $key $PROFILE_OPT --region $regx --output text 2>&1)
if [[ $(echo "$CHECK_KMS_KEY_ROTATION" | grep AccessDenied) ]]; then
- textFail "$regx: Key $key Access Denied getting key rotation status" "$regx" "$key"
+ textInfo "$regx: Access Denied getting key rotation status for $key " "$regx" "$key"
continue
fi
if [[ "$CHECK_KMS_KEY_ROTATION" == "True" ]];then
diff --git a/checks/check29 b/checks/check29
index dc9f37b4..035fc345 100644
--- a/checks/check29
+++ b/checks/check29
@@ -30,14 +30,14 @@ check29(){
# "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 2>&1)
- if [[ $(echo "$AVAILABLE_VPC" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe VPCs" "$regx" "$vpcx"
+ if [[ $(echo "$AVAILABLE_VPC" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe VPCs" "$regx" "$vpcx"
continue
fi
for vpcx in $AVAILABLE_VPC; do
CHECK_FL=$($AWSCLI ec2 describe-flow-logs $PROFILE_OPT --region $regx --filter Name="resource-id",Values="${vpcx}" --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].FlowLogId' --output text 2>&1)
- if [[ $(echo "$CHECK_FL" | grep AccessDenied) ]]; then
- textFail "$regx: VPC $vpcx Access Denied trying to describe flow logs" "$regx" "$vpcx"
+ if [[ $(echo "$CHECK_FL" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe flow logs in VPC $vpcx" "$regx" "$vpcx"
continue
fi
if [[ $CHECK_FL ]]; then
diff --git a/checks/check41 b/checks/check41
index f8af5e9b..33e87109 100644
--- a/checks/check41
+++ b/checks/check41
@@ -29,7 +29,11 @@ CHECK_CAF_EPIC_check41='Infrastructure Security'
check41(){
# "Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to port 22 (Scored)"
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`22` && ToPort>=`22`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`22` && ToPort>=`22`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0" "$regx" "$SG"
diff --git a/checks/check42 b/checks/check42
index cf4b3cf2..71c67838 100644
--- a/checks/check42
+++ b/checks/check42
@@ -29,7 +29,11 @@ CHECK_CAF_EPIC_check42='Infrastructure Security'
check42(){
# "Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to port 3389 (Scored)"
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`3389` && ToPort>=`3389`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`3389` && ToPort>=`3389`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0" "$regx" "$SG"
diff --git a/checks/check43 b/checks/check43
index c3a57e12..8e2f004c 100644
--- a/checks/check43
+++ b/checks/check43
@@ -29,7 +29,11 @@ CHECK_CAF_EPIC_check43='Infrastructure Security'
check43(){
# "Ensure the default security group of every VPC restricts all traffic (Scored)"
for regx in $REGIONS; do
- CHECK_SGDEFAULT_IDS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters Name=group-name,Values='default' --query 'SecurityGroups[*].GroupId[]' --output text)
+ CHECK_SGDEFAULT_IDS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters Name=group-name,Values='default' --query 'SecurityGroups[*].GroupId[]' --output text 2>&1)
+ if [[ $(echo "$CHECK_SGDEFAULT_IDS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
for CHECK_SGDEFAULT_ID in $CHECK_SGDEFAULT_IDS; do
CHECK_SGDEFAULT_ID_OPEN=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --group-ids $CHECK_SGDEFAULT_ID --query 'SecurityGroups[*].{IpPermissions:IpPermissions,IpPermissionsEgress:IpPermissionsEgress,GroupId:GroupId}' --output text |egrep '\s0.0.0.0|\:\:\/0')
if [[ $CHECK_SGDEFAULT_ID_OPEN ]];then
diff --git a/checks/check44 b/checks/check44
index e6b8aee9..158e5c32 100644
--- a/checks/check44
+++ b/checks/check44
@@ -28,7 +28,11 @@ CHECK_CAF_EPIC_check44='Infrastructure Security'
check44(){
# "Ensure routing tables for VPC peering are \"least access\" (Not Scored)"
for regx in $REGIONS; do
- LIST_OF_VPCS_PEERING_CONNECTIONS=$($AWSCLI ec2 describe-vpc-peering-connections --output text $PROFILE_OPT --region $regx --query 'VpcPeeringConnections[*].VpcPeeringConnectionId'| sort | paste -s -d" " -)
+ LIST_OF_VPCS_PEERING_CONNECTIONS=$($AWSCLI ec2 describe-vpc-peering-connections --output text $PROFILE_OPT --region $regx --query 'VpcPeeringConnections[*].VpcPeeringConnectionId' 2>&1| sort | paste -s -d" " - )
+ if [[ $(echo "$LIST_OF_VPCS_PEERING_CONNECTIONS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe vpc peering connections" "$regx"
+ continue
+ fi
if [[ $LIST_OF_VPCS_PEERING_CONNECTIONS ]];then
textInfo "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS - review routing tables" "$regx" "$LIST_OF_VPCS_PEERING_CONNECTIONS"
#LIST_OF_VPCS=$($AWSCLI ec2 describe-vpcs $PROFILE_OPT --region $regx --query 'Vpcs[*].VpcId' --output text)
diff --git a/checks/check45 b/checks/check45
index c9a461e9..cc95207d 100644
--- a/checks/check45
+++ b/checks/check45
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_check45='Infrastructure Security'
check45(){
for regx in $REGIONS; do
- NACL_LIST=$($AWSCLI ec2 describe-network-acls --query 'NetworkAcls[?Entries[?(((!PortRange) || (PortRange.From<=`22` && PortRange.To>=`22`)) && ((CidrBlock == `0.0.0.0/0`) && (Egress == `false`) && (RuleAction == `allow`)))]].{NetworkAclId:NetworkAclId}' $PROFILE_OPT --region $regx --output text)
+ NACL_LIST=$($AWSCLI ec2 describe-network-acls --query 'NetworkAcls[?Entries[?(((!PortRange) || (PortRange.From<=`22` && PortRange.To>=`22`)) && ((CidrBlock == `0.0.0.0/0`) && (Egress == `false`) && (RuleAction == `allow`)))]].{NetworkAclId:NetworkAclId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$NACL_LIST" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe vpc network acls" "$regx"
+ continue
+ fi
if [[ $NACL_LIST ]];then
for NACL in $NACL_LIST;do
textInfo "$regx: Found Network ACL: $NACL open to 0.0.0.0/0 for SSH port 22" "$regx" "$NACL"
diff --git a/checks/check46 b/checks/check46
index 72395991..9bcfccd5 100644
--- a/checks/check46
+++ b/checks/check46
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_check46='Infrastructure Security'
check46(){
for regx in $REGIONS; do
- NACL_LIST=$($AWSCLI ec2 describe-network-acls --query 'NetworkAcls[?Entries[?(((!PortRange) || (PortRange.From<=`3389` && PortRange.To>=`3389`)) && ((CidrBlock == `0.0.0.0/0`) && (Egress == `false`) && (RuleAction == `allow`)))]].{NetworkAclId:NetworkAclId}' $PROFILE_OPT --region $regx --output text)
+ NACL_LIST=$($AWSCLI ec2 describe-network-acls --query 'NetworkAcls[?Entries[?(((!PortRange) || (PortRange.From<=`3389` && PortRange.To>=`3389`)) && ((CidrBlock == `0.0.0.0/0`) && (Egress == `false`) && (RuleAction == `allow`)))]].{NetworkAclId:NetworkAclId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$NACL_LIST" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe vpc network acls" "$regx"
+ continue
+ fi
if [[ $NACL_LIST ]];then
for NACL in $NACL_LIST;do
textInfo "$regx: Found Network ACL: $NACL open to 0.0.0.0/0 for Microsoft RDP port 3389" "$regx" "$NACL"
diff --git a/checks/check_extra710 b/checks/check_extra710
index ffd3b035..22bcd7ab 100644
--- a/checks/check_extra710
+++ b/checks/check_extra710
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_extra710='Infrastructure Security'
extra710(){
# "Check for internet facing EC2 Instances "
for regx in $REGIONS; do
- LIST_OF_PUBLIC_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]' --output text)
+ LIST_OF_PUBLIC_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?PublicIpAddress].[InstanceId,PublicIpAddress]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_PUBLIC_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe instances" "$regx"
+ continue
+ fi
if [[ $LIST_OF_PUBLIC_INSTANCES ]];then
while read -r instance;do
INSTANCE_ID=$(echo $instance | awk '{ print $1; }')
diff --git a/checks/check_extra7101 b/checks/check_extra7101
index a4fd714c..2efe711a 100644
--- a/checks/check_extra7101
+++ b/checks/check_extra7101
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7101='Logging and Monitoring'
extra7101(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
AUDIT_LOGS_ENABLED=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.LogPublishingOptions.Options.AUDIT_LOGS.Enabled --output text |grep -v ^None|grep -v ^False)
diff --git a/checks/check_extra7102 b/checks/check_extra7102
index f16c3908..f70492c7 100644
--- a/checks/check_extra7102
+++ b/checks/check_extra7102
@@ -36,7 +36,11 @@ extra7102(){
textInfo "[extra7102] Requires a Shodan API key to work. Use -N "
else
for regx in $REGIONS; do
- LIST_OF_EIP=$($AWSCLI $PROFILE_OPT --region $regx ec2 describe-network-interfaces --query 'NetworkInterfaces[*].Association.PublicIp' --output text)
+ LIST_OF_EIP=$($AWSCLI $PROFILE_OPT --region $regx ec2 describe-network-interfaces --query 'NetworkInterfaces[*].Association.PublicIp' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_EIP" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe network interfaces" "$regx"
+ continue
+ fi
if [[ $LIST_OF_EIP ]]; then
for ip in $LIST_OF_EIP;do
SHODAN_QUERY=$(curl -ks https://api.shodan.io/shodan/host/$ip?key=$SHODAN_API_KEY)
diff --git a/checks/check_extra7103 b/checks/check_extra7103
index 12ace203..97713f20 100644
--- a/checks/check_extra7103
+++ b/checks/check_extra7103
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7103='IAM'
extra7103(){
for regx in ${REGIONS}; do
- LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text)
+ LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list notebook instances" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_INSTANCES ]];then
for nb_instance in $LIST_SM_NB_INSTANCES; do
SM_NB_ROOTACCESS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-notebook-instance --notebook-instance-name $nb_instance --query 'RootAccess' --output text)
diff --git a/checks/check_extra7104 b/checks/check_extra7104
index 7697ad50..c1a44d44 100644
--- a/checks/check_extra7104
+++ b/checks/check_extra7104
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7104='Infrastructure Security'
extra7104(){
for regx in ${REGIONS}; do
- LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text)
+ LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list notebook instances" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_INSTANCES ]];then
for nb_instance in $LIST_SM_NB_INSTANCES; do
SM_NB_SUBNETID=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-notebook-instance --notebook-instance-name $nb_instance --query 'SubnetId' --output text)
diff --git a/checks/check_extra7105 b/checks/check_extra7105
index 1b2d2c89..5ba8d94d 100644
--- a/checks/check_extra7105
+++ b/checks/check_extra7105
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7105='Infrastructure Security'
extra7105(){
for regx in ${REGIONS}; do
- LIST_SM_NB_MODELS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-models --query 'Models[*].ModelName' --output text)
+ LIST_SM_NB_MODELS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-models --query 'Models[*].ModelName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_MODELS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list models" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_MODELS ]];then
for nb_model_name in $LIST_SM_NB_MODELS; do
SM_NB_NETWORKISOLATION=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-model --model-name $nb_model_name --query 'EnableNetworkIsolation' --output text)
diff --git a/checks/check_extra7106 b/checks/check_extra7106
index af09f269..9863edf7 100644
--- a/checks/check_extra7106
+++ b/checks/check_extra7106
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7106='Infrastructure Security'
extra7106(){
for regx in ${REGIONS}; do
- LIST_SM_NB_MODELS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-models --query 'Models[*].ModelName' --output text)
+ LIST_SM_NB_MODELS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-models --query 'Models[*].ModelName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_MODELS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list models" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_MODELS ]];then
for nb_model_name in $LIST_SM_NB_MODELS; do
SM_NB_VPCCONFIG=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-model --model-name $nb_model_name --query 'VpcConfig.Subnets' --output text)
diff --git a/checks/check_extra7107 b/checks/check_extra7107
index e5536e87..1a94873b 100644
--- a/checks/check_extra7107
+++ b/checks/check_extra7107
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7107='Data Protection'
extra7107(){
for regx in ${REGIONS}; do
- LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text)
+ LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_JOBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list training jobs" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_JOBS ]];then
for nb_job_name in $LIST_SM_NB_JOBS; do
SM_NB_INTERCONTAINERENCRYPTION=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-training-job --training-job-name $nb_job_name --query 'EnableInterContainerTrafficEncryption' --output text)
diff --git a/checks/check_extra7108 b/checks/check_extra7108
index 2956afe8..183cd302 100644
--- a/checks/check_extra7108
+++ b/checks/check_extra7108
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7108='Data Protection'
extra7108(){
for regx in ${REGIONS}; do
- LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text)
+ LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_JOBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list training jobs" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_JOBS ]];then
for nb_job_name in $LIST_SM_NB_JOBS; do
SM_JOB_KMSENCRYPTION=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-training-job --training-job-name $nb_job_name --query 'ResourceConfig.VolumeKmsKeyId' --output text)
diff --git a/checks/check_extra7109 b/checks/check_extra7109
index 90d036e0..8775ee74 100644
--- a/checks/check_extra7109
+++ b/checks/check_extra7109
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7109='Infrastructure Security'
extra7109(){
for regx in ${REGIONS}; do
- LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text)
+ LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_JOBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list training jobs" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_JOBS ]];then
for nb_job_name in $LIST_SM_NB_JOBS; do
SM_NB_NETWORKISOLATION=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-training-job --training-job-name $nb_job_name --query 'EnableNetworkIsolation' --output text)
diff --git a/checks/check_extra711 b/checks/check_extra711
index a7c7b798..2b8335d9 100644
--- a/checks/check_extra711
+++ b/checks/check_extra711
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra711='Data Protection'
extra711(){
# "Check for Publicly Accessible Redshift Clusters "
for regx in $REGIONS; do
- LIST_OF_PUBLIC_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[?PubliclyAccessible == `true`].[ClusterIdentifier,Endpoint.Address]' --output text)
+ LIST_OF_PUBLIC_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[?PubliclyAccessible == `true`].[ClusterIdentifier,Endpoint.Address]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_PUBLIC_REDSHIFT_CLUSTERS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe clusters" "$regx"
+ continue
+ fi
if [[ $LIST_OF_PUBLIC_REDSHIFT_CLUSTERS ]];then
while read -r cluster;do
CLUSTER_ID=$(echo $cluster | awk '{ print $1; }')
diff --git a/checks/check_extra7110 b/checks/check_extra7110
index 448e2308..151d35cf 100644
--- a/checks/check_extra7110
+++ b/checks/check_extra7110
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7110='Infrastructure Security'
extra7110(){
for regx in ${REGIONS}; do
- LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text)
+ LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_JOBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list training jobs" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_JOBS ]];then
for nb_job_name in $LIST_SM_NB_JOBS; do
SM_NB_SUBNETS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-training-job --training-job-name $nb_job_name --query 'VpcConfig.Subnets' --output text)
diff --git a/checks/check_extra7111 b/checks/check_extra7111
index a6669a09..936931fd 100644
--- a/checks/check_extra7111
+++ b/checks/check_extra7111
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7111='Infrastructure Security'
extra7111(){
for regx in ${REGIONS}; do
- LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text)
+ LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list notebook instances" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_INSTANCES ]];then
for nb_instance in $LIST_SM_NB_INSTANCES; do
SM_NB_DIRECTINET=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-notebook-instance --notebook-instance-name $nb_instance --query 'DirectInternetAccess' --output text)
diff --git a/checks/check_extra7112 b/checks/check_extra7112
index e031065d..c3143cb7 100644
--- a/checks/check_extra7112
+++ b/checks/check_extra7112
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7112='Data Protection'
extra7112(){
for regx in ${REGIONS}; do
- LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text)
+ LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text 2>&1)
+ if [[ $(echo "$LIST_SM_NB_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list notebook instances" "$regx"
+ continue
+ fi
if [[ $LIST_SM_NB_INSTANCES ]];then
for nb_instance in $LIST_SM_NB_INSTANCES; do
SM_NB_KMSKEY=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-notebook-instance --notebook-instance-name $nb_instance --query 'KmsKeyId' --output text)
diff --git a/checks/check_extra7113 b/checks/check_extra7113
index 4afcfdc3..e8e61201 100644
--- a/checks/check_extra7113
+++ b/checks/check_extra7113
@@ -37,7 +37,11 @@ CHECK_CAF_EPIC_extra7113='Data Protection'
extra7113(){
for regx in $REGIONS; do
- LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query "DBInstances[?Engine != 'docdb'].DBInstanceIdentifier" --output text)
+ LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query "DBInstances[?Engine != 'docdb'].DBInstanceIdentifier" --output text 2>&1)
+ if [[ $(echo "$LIST_OF_RDS_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe DB instances" "$regx"
+ continue
+ fi
if [[ $LIST_OF_RDS_INSTANCES ]];then
for rdsinstance in $LIST_OF_RDS_INSTANCES; do
IS_DELETIONPROTECTION=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --db-instance-identifier $rdsinstance --query 'DBInstances[*].DeletionProtection' --output text)
diff --git a/checks/check_extra7114 b/checks/check_extra7114
index 91a640bb..9179e63f 100644
--- a/checks/check_extra7114
+++ b/checks/check_extra7114
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7114='Data Protection'
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)
+ LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json 2>&1)
+ if [[ $(echo "$LIST_EP_SC" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get dev endpoints" "$regx"
+ continue
+ fi
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')
diff --git a/checks/check_extra7115 b/checks/check_extra7115
index e09e6590..8abca268 100644
--- a/checks/check_extra7115
+++ b/checks/check_extra7115
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7115='Data Protection'
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}')
+ CONNECTION_LIST=$($AWSCLI glue get-connections $PROFILE_OPT --region $regx --output json --query 'ConnectionList[*].{Name:Name,SSL:ConnectionProperties.JDBC_ENFORCE_SSL}' 2>&1)
+ if [[ $(echo "$CONNECTION_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get connections" "$regx"
+ continue
+ fi
if [[ $CONNECTION_LIST != '[]' ]]; then
for connection in $(echo "${CONNECTION_LIST}" | jq -r '.[] | @base64'); do
CONNECTION_NAME=$(echo $connection | base64 --decode | jq -r '.Name' )
diff --git a/checks/check_extra7116 b/checks/check_extra7116
index d18ab6f2..4aad3ecb 100644
--- a/checks/check_extra7116
+++ b/checks/check_extra7116
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7116='Data Protection'
extra7116(){
for regx in $REGIONS; do
- TABLE_LIST=$($AWSCLI glue search-tables --max-results 1 $PROFILE_OPT --region $regx --output text --query 'TableList[*]' )
+ TABLE_LIST=$($AWSCLI glue search-tables --max-results 1 $PROFILE_OPT --region $regx --output text --query 'TableList[*]' 2>&1)
+ if [[ $(echo "$TABLE_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to search tables" "$regx"
+ continue
+ fi
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
diff --git a/checks/check_extra7117 b/checks/check_extra7117
index 6091a71c..c390fcac 100644
--- a/checks/check_extra7117
+++ b/checks/check_extra7117
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7117='Data Protection'
extra7117(){
for regx in $REGIONS; do
- CONNECTION_LIST=$($AWSCLI glue get-connections $PROFILE_OPT --region $regx --output text --query 'ConnectionList[*]')
+ CONNECTION_LIST=$($AWSCLI glue get-connections $PROFILE_OPT --region $regx --output text --query 'ConnectionList[*]' 2>&1)
+ if [[ $(echo "$CONNECTION_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get connections" "$regx"
+ continue
+ fi
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
diff --git a/checks/check_extra7118 b/checks/check_extra7118
index 0b70fcab..53303c08 100644
--- a/checks/check_extra7118
+++ b/checks/check_extra7118
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7118='Data Protection'
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"}')
+ JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration,JobEncryption:DefaultArguments."--encryption-type"}' 2>&1)
+ if [[ $(echo "$JOB_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get jobs" "$regx"
+ continue
+ fi
if [[ $JOB_LIST != '[]' ]]; then
for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do
JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name')
diff --git a/checks/check_extra7119 b/checks/check_extra7119
index a3ca4a10..06270736 100644
--- a/checks/check_extra7119
+++ b/checks/check_extra7119
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7119='Logging and Monitoring'
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)
+ LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json 2>&1)
+ if [[ $(echo "$LIST_EP_SC" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get dev endpoints" "$regx"
+ continue
+ fi
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')
diff --git a/checks/check_extra7120 b/checks/check_extra7120
index 93907c93..018067c5 100644
--- a/checks/check_extra7120
+++ b/checks/check_extra7120
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7120='Logging and Monitoring'
extra7120(){
for regx in $REGIONS; do
- JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration}')
+ JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration}' 2>&1)
+ if [[ $(echo "$JOB_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get jobs" "$regx"
+ continue
+ fi
if [[ $JOB_LIST != '[]' ]]; then
for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do
JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name')
diff --git a/checks/check_extra7121 b/checks/check_extra7121
index 13259770..bdc041d1 100644
--- a/checks/check_extra7121
+++ b/checks/check_extra7121
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7121='Data Protection'
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)
+ LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json 2>&1)
+ if [[ $(echo "$LIST_EP_SC" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get dev endpoints" "$regx"
+ continue
+ fi
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')
diff --git a/checks/check_extra7122 b/checks/check_extra7122
index 9f50bb71..6c91dfca 100644
--- a/checks/check_extra7122
+++ b/checks/check_extra7122
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7122='Data Protection'
extra7122(){
for regx in $REGIONS; do
- JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration}')
+ JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration}' 2>&1)
+ if [[ $(echo "$JOB_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get jobs" "$regx"
+ continue
+ fi
if [[ $JOB_LIST != '[]' ]]; then
for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do
JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name')
diff --git a/checks/check_extra7124 b/checks/check_extra7124
index 7a7e8b1f..72b1e1c1 100644
--- a/checks/check_extra7124
+++ b/checks/check_extra7124
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_extra7124='Infrastructure Security'
extra7124(){
for regx in $REGIONS; do
# Filters running instances only
- LIST_EC2_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --query 'Reservations[*].Instances[*].[InstanceId]' --filters Name=instance-state-name,Values=running --region $regx --output text)
+ LIST_EC2_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --query 'Reservations[*].Instances[*].[InstanceId]' --filters Name=instance-state-name,Values=running --region $regx --output text 2>&1)
+ if [[ $(echo "$LIST_EC2_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe instances" "$regx"
+ continue
+ fi
if [[ $LIST_EC2_INSTANCES ]]; then
LIST_SSM_MANAGED_INSTANCES=$($AWSCLI ssm describe-instance-information $PROFILE_OPT --query "InstanceInformationList[].InstanceId" --region $regx | jq -r '.[]')
LIST_EC2_UNMANAGED=$(echo ${LIST_SSM_MANAGED_INSTANCES[@]} ${LIST_EC2_INSTANCES[@]} | tr ' ' '\n' | sort | uniq -u)
diff --git a/checks/check_extra7127 b/checks/check_extra7127
index 9c12009a..34650167 100644
--- a/checks/check_extra7127
+++ b/checks/check_extra7127
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_extra7127='Infrastructure Security'
extra7127(){
for regx in $REGIONS; do
- NON_COMPLIANT_SSM_MANAGED_INSTANCES=$($AWSCLI ssm list-resource-compliance-summaries $PROFILE_OPT --region $regx --filters Key=Status,Values=NON_COMPLIANT --query ResourceComplianceSummaryItems[].ResourceId --output text)
+ NON_COMPLIANT_SSM_MANAGED_INSTANCES=$($AWSCLI ssm list-resource-compliance-summaries $PROFILE_OPT --region $regx --filters Key=Status,Values=NON_COMPLIANT --query ResourceComplianceSummaryItems[].ResourceId --output text 2>&1)
+ if [[ $(echo "$NON_COMPLIANT_SSM_MANAGED_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list resource compliance summaries" "$regx"
+ continue
+ fi
COMPLIANT_SSM_MANAGED_INSTANCES=$($AWSCLI ssm list-resource-compliance-summaries $PROFILE_OPT --region $regx --filters Key=Status,Values=COMPLIANT --query ResourceComplianceSummaryItems[].ResourceId --output text)
if [[ $NON_COMPLIANT_SSM_MANAGED_INSTANCES || $COMPLIANT_SSM_MANAGED_INSTANCES ]]; then
if [[ $NON_COMPLIANT_SSM_MANAGED_INSTANCES ]]; then
diff --git a/checks/check_extra7128 b/checks/check_extra7128
index f9ad2cda..61c7f6e3 100644
--- a/checks/check_extra7128
+++ b/checks/check_extra7128
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7128='Data Protection'
extra7128(){
for regx in $REGIONS; do
- DDB_TABLES_LIST=$($AWSCLI dynamodb list-tables $PROFILE_OPT --region $regx --output text --query TableNames)
+ DDB_TABLES_LIST=$($AWSCLI dynamodb list-tables $PROFILE_OPT --region $regx --output text --query TableNames 2>&1)
+ if [[ $(echo "$DDB_TABLES_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list tables" "$regx"
+ continue
+ fi
if [[ $DDB_TABLES_LIST ]]; then
for table in $DDB_TABLES_LIST; do
DDB_TABLE_WITH_KMS=$($AWSCLI dynamodb describe-table --table-name $table $PROFILE_OPT --region $regx --query Table.SSEDescription.SSEType --output text)
diff --git a/checks/check_extra7129 b/checks/check_extra7129
index caa6fefa..29031a6c 100644
--- a/checks/check_extra7129
+++ b/checks/check_extra7129
@@ -29,7 +29,11 @@ PARALLEL_REGIONS="50"
extra7129(){
for regx in $REGIONS; do
# (
- LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Scheme == `internet-facing` && Type == `application`].[LoadBalancerName]' --output text)
+ LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Scheme == `internet-facing` && Type == `application`].[LoadBalancerName]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_ELBSV2" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
LIST_OF_WAFV2_WEBACL_ARN=$($AWSCLI wafv2 list-web-acls $PROFILE_OPT --region=$regx --scope=REGIONAL --query WebACLs[*].ARN --output text)
LIST_OF_WAFV1_WEBACL_WEBACLID=$($AWSCLI waf-regional list-web-acls $PROFILE_OPT --region $regx --query WebACLs[*].[WebACLId] --output text)
diff --git a/checks/check_extra713 b/checks/check_extra713
index 01f96d58..17b56827 100644
--- a/checks/check_extra713
+++ b/checks/check_extra713
@@ -44,7 +44,7 @@ extra713(){
fi
else
# if list-detectors return any error
- textInfo "$regx: GuardDuty not checked" "$regx"
+ textInfo "$regx: GuardDuty not checked or Access Denied trying to get detector" "$regx"
fi
done
}
\ No newline at end of file
diff --git a/checks/check_extra7130 b/checks/check_extra7130
index f1641516..0980eea9 100644
--- a/checks/check_extra7130
+++ b/checks/check_extra7130
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7130='Data Protection'
extra7130(){
for regx in $REGIONS; do
- LIST_SNS=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --query 'Topics[*].TopicArn' --output text)
+ LIST_SNS=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --query 'Topics[*].TopicArn' --output text 2>&1)
+ if [[ $(echo "$LIST_SNS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list topics" "$regx"
+ continue
+ fi
if [[ $LIST_SNS ]];then
for topic in $LIST_SNS; do
SHORT_TOPIC=$(echo $topic | awk -F ":" '{print $NF}')
diff --git a/checks/check_extra7131 b/checks/check_extra7131
index dbd22bd9..af4bc429 100644
--- a/checks/check_extra7131
+++ b/checks/check_extra7131
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7131='Infrastructure Security'
extra7131(){
for regx in $REGIONS; do
# LIST_OF_RDS_PUBLIC_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[?PubliclyAccessible==`true` && DBInstanceStatus==`"available"`].[DBInstanceIdentifier,Endpoint.Address]' --output text)
- LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].[DBInstanceIdentifier,AutoMinorVersionUpgrade]' --output text)
+ LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].[DBInstanceIdentifier,AutoMinorVersionUpgrade]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_RDS_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe DB instances" "$regx"
+ continue
+ fi
if [[ $LIST_OF_RDS_INSTANCES ]];then
while read -r rds_instance;do
RDS_NAME=$(echo $rds_instance | awk '{ print $1; }')
diff --git a/checks/check_extra7132 b/checks/check_extra7132
index 4d3af561..a2bbba74 100644
--- a/checks/check_extra7132
+++ b/checks/check_extra7132
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7132='Logging and Monitoring'
extra7132(){
for regx in $REGIONS; do
- RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query "DBInstances[?Engine != 'docdb'].DBInstanceIdentifier" --output text)
+ RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query "DBInstances[?Engine != 'docdb'].DBInstanceIdentifier" --output text 2>&1)
+ if [[ $(echo "$RDS_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe DB instances" "$regx"
+ continue
+ fi
if [[ $RDS_INSTANCES ]];then
for rdsinstance in ${RDS_INSTANCES}; do
RDS_NAME="$rdsinstance"
diff --git a/checks/check_extra7133 b/checks/check_extra7133
index ee20f261..eae0f3a0 100644
--- a/checks/check_extra7133
+++ b/checks/check_extra7133
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7133='Data Protection'
extra7133(){
for regx in $REGIONS; do
- RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query "DBInstances[?Engine != 'docdb'].DBInstanceIdentifier" --output text)
+ RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query "DBInstances[?Engine != 'docdb'].DBInstanceIdentifier" --output text 2>&1)
+ if [[ $(echo "$RDS_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe DB instances" "$regx"
+ continue
+ fi
if [[ $RDS_INSTANCES ]];then
for rdsinstance in ${RDS_INSTANCES}; do
RDS_NAME="$rdsinstance"
diff --git a/checks/check_extra7134 b/checks/check_extra7134
index 14f2b957..4919262f 100644
--- a/checks/check_extra7134
+++ b/checks/check_extra7134
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7134='Infrastructure Security'
extra7134(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`20` && ToPort==`21`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`20` && ToPort==`21`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for FTP ports" "$regx" "$SG"
diff --git a/checks/check_extra7135 b/checks/check_extra7135
index 2788b54e..74c9cb74 100644
--- a/checks/check_extra7135
+++ b/checks/check_extra7135
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7135='Infrastructure Security'
extra7135(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`9092` && ToPort==`9092`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`9092` && ToPort==`9092`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for Kafka ports" "$regx" "$SG"
diff --git a/checks/check_extra7136 b/checks/check_extra7136
index b7779b6f..3646a827 100644
--- a/checks/check_extra7136
+++ b/checks/check_extra7136
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7136='Infrastructure Security'
extra7136(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`23` && ToPort==`23`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`23` && ToPort==`23`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for Telnet ports" "$regx" "$SG"
diff --git a/checks/check_extra7137 b/checks/check_extra7137
index 5759927e..00afed61 100644
--- a/checks/check_extra7137
+++ b/checks/check_extra7137
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7137='Infrastructure Security'
extra7137(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`1433` && ToPort==`1434`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`1433` && ToPort==`1434`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for Microsoft SQL Server ports" "$regx" "$SG"
diff --git a/checks/check_extra7138 b/checks/check_extra7138
index f164aa62..14b05ebb 100644
--- a/checks/check_extra7138
+++ b/checks/check_extra7138
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7138='Infrastructure Security'
extra7138(){
for regx in $REGIONS; do
- NACL_LIST=$($AWSCLI ec2 describe-network-acls --query 'NetworkAcls[?Entries[?((!PortRange) && (CidrBlock == `0.0.0.0/0`) && (Egress == `false`) && (RuleAction == `allow`))]].{NetworkAclId:NetworkAclId}' $PROFILE_OPT --region $regx --output text)
+ NACL_LIST=$($AWSCLI ec2 describe-network-acls --query 'NetworkAcls[?Entries[?((!PortRange) && (CidrBlock == `0.0.0.0/0`) && (Egress == `false`) && (RuleAction == `allow`))]].{NetworkAclId:NetworkAclId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$NACL_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe network acls" "$regx"
+ continue
+ fi
if [[ $NACL_LIST ]];then
for NACL in $NACL_LIST;do
textInfo "$regx: Found Network ACL: $NACL open to 0.0.0.0/0 for any port" "$regx" "$NACL"
diff --git a/checks/check_extra7139 b/checks/check_extra7139
index 094037ee..4268c26f 100644
--- a/checks/check_extra7139
+++ b/checks/check_extra7139
@@ -25,7 +25,11 @@ extra7139(){
for regx in $REGIONS; do
DETECTORS_LIST=""
- DETECTORS_LIST=$($AWSCLI guardduty list-detectors --query DetectorIds $PROFILE_OPT --region $regx --output text)
+ DETECTORS_LIST=$($AWSCLI guardduty list-detectors --query DetectorIds $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$DETECTORS_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list detectors" "$regx"
+ continue
+ fi
if [[ $DETECTORS_LIST ]];then
for DETECTOR in $DETECTORS_LIST;do
FINDINGS_COUNT=""
diff --git a/checks/check_extra714 b/checks/check_extra714
index 40d2c679..9408fa6d 100644
--- a/checks/check_extra714
+++ b/checks/check_extra714
@@ -28,8 +28,9 @@ extra714(){
LIST_OF_DISTRIBUTIONS=$($AWSCLI cloudfront list-distributions $PROFILE_OPT --query 'DistributionList.Items[].Id' --output text | grep -v "^None")
if [[ $LIST_OF_DISTRIBUTIONS ]]; then
for dist in $LIST_OF_DISTRIBUTIONS; do
- LOG_ENABLED=$($AWSCLI cloudfront get-distribution $PROFILE_OPT --id "$dist" --query 'Distribution.DistributionConfig.Logging.Enabled' | grep true)
- if [[ $LOG_ENABLED ]]; then
+ LOG_ENABLED=$($AWSCLI cloudfront get-distribution $PROFILE_OPT --id "$dist" --query 'Distribution.DistributionConfig.Logging.Enabled' --output text | grep True)
+ LOG_ENABLED_REALTIME=$($AWSCLI cloudfront get-distribution $PROFILE_OPT --id "$dist" --query 'Distribution.DistributionConfig.DefaultCacheBehavior.RealtimeLogConfigArn' --output text | grep -i arn)
+ if [[ $LOG_ENABLED || $LOG_ENABLED_REALTIME ]]; then
textPass "$REGION: CloudFront distribution $dist has logging enabled" "$REGION" "$dist"
else
textFail "$REGION: CloudFront distribution $dist has logging disabled" "$REGION" "$dist"
diff --git a/checks/check_extra7140 b/checks/check_extra7140
index 42f93e72..3cab4570 100644
--- a/checks/check_extra7140
+++ b/checks/check_extra7140
@@ -24,7 +24,11 @@ CHECK_CAF_EPIC_extra7140='Data Protection'
extra7140(){
for regx in $REGIONS; do
- SSM_DOCS=$($AWSCLI $PROFILE_OPT --region $regx ssm list-documents --filters Key=Owner,Values=Self --query DocumentIdentifiers[].Name --output text)
+ SSM_DOCS=$($AWSCLI $PROFILE_OPT --region $regx ssm list-documents --filters Key=Owner,Values=Self --query DocumentIdentifiers[].Name --output text 2>&1)
+ if [[ $(echo "$SSM_DOCS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list documents" "$regx"
+ continue
+ fi
if [[ $SSM_DOCS ]];then
for ssmdoc in $SSM_DOCS; do
SSM_DOC_SHARED_ALL=$($AWSCLI $PROFILE_OPT --region $regx ssm describe-document-permission --name "$ssmdoc" --permission-type "Share" --query AccountIds[] --output text | grep all)
diff --git a/checks/check_extra7141 b/checks/check_extra7141
index 3b828cdd..1768b4fc 100644
--- a/checks/check_extra7141
+++ b/checks/check_extra7141
@@ -31,7 +31,11 @@ extra7141(){
fi
for regx in $REGIONS; do
- SSM_DOCS=$($AWSCLI $PROFILE_OPT --region $regx ssm list-documents --filters Key=Owner,Values=Self --query DocumentIdentifiers[].Name --output text)
+ SSM_DOCS=$($AWSCLI $PROFILE_OPT --region $regx ssm list-documents --filters Key=Owner,Values=Self --query DocumentIdentifiers[].Name --output text 2>&1)
+ if [[ $(echo "$SSM_DOCS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list documents" "$regx"
+ continue
+ fi
if [[ $SSM_DOCS ]];then
for ssmdoc in $SSM_DOCS; do
SSM_DOC_FILE="$SECRETS_TEMP_FOLDER/extra7141-$ssmdoc-$regx-content.txt"
diff --git a/checks/check_extra7142 b/checks/check_extra7142
index 9900d46d..ded331ec 100644
--- a/checks/check_extra7142
+++ b/checks/check_extra7142
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_extra7142='Data Protection'
extra7142(){
for regx in $REGIONS; do
- LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Type == `application`].[LoadBalancerArn]' --output text)
+ LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Type == `application`].[LoadBalancerArn]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_ELBSV2" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
if [[ $LIST_OF_ELBSV2 ]];then
for alb in $LIST_OF_ELBSV2;do
CHECK_IF_DROP_INVALID_HEADER_FIELDS=$($AWSCLI elbv2 describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-arn $alb --query 'Attributes[6]' --output text|grep -i true)
diff --git a/checks/check_extra7143 b/checks/check_extra7143
index 7d3ee0eb..abf1d81f 100644
--- a/checks/check_extra7143
+++ b/checks/check_extra7143
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7143='Data Protection'
extra7143(){
# "Check if EFS have policies which allow access to everyone (Not Scored) (Not part of 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)
+ LIST_OF_EFS_IDS=$($AWSCLI efs describe-file-systems $PROFILE_OPT --region $regx --query FileSystems[*].FileSystemId --output text 2>&1|xargs -n1 )
+ if [[ $(echo "$LIST_OF_EFS_IDS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe file systems" "$regx"
+ continue
+ fi
if [[ $LIST_OF_EFS_IDS ]]; then
for efsId in $LIST_OF_EFS_IDS;do
EFS_POLICY_STATEMENTS=$($AWSCLI efs $PROFILE_OPT describe-file-system-policy --region $regx --file-system-id $efsId --output json --query Policy 2>&1)
diff --git a/checks/check_extra7145 b/checks/check_extra7145
index 8ef77601..c62b7c61 100644
--- a/checks/check_extra7145
+++ b/checks/check_extra7145
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7145='IAM'
extra7145(){
# "Check if lambda functions have policies which allow access to every aws account (Not Scored) (Not part of CIS benchmark)"
for regx in $REGIONS; do
- LIST_OF_LAMBDA_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text)
+ LIST_OF_LAMBDA_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text 2>&1)
+ if [[ $(echo "$LIST_OF_LAMBDA_FUNCTIONS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list functions" "$regx"
+ continue
+ fi
if [[ $LIST_OF_LAMBDA_FUNCTIONS ]]; then
for lambdaFunction in $LIST_OF_LAMBDA_FUNCTIONS;do
FUNCTION_POLICY_STATEMENTS=$($AWSCLI lambda $PROFILE_OPT get-policy --region $regx --function-name $lambdaFunction --output json --query Policy 2>&1)
diff --git a/checks/check_extra7146 b/checks/check_extra7146
index 78e56683..2c4682a8 100644
--- a/checks/check_extra7146
+++ b/checks/check_extra7146
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7146='Infrastructure Security'
extra7146(){
# "Check if there is any unassigned elastic ip (Not Scored) (Not part of CIS benchmark)"
for regx in $REGIONS; do
- ELASTIC_IP_ADDRESSES=$($AWSCLI ec2 describe-addresses $PROFILE_OPT --region $regx --query Addresses --output json)
+ ELASTIC_IP_ADDRESSES=$($AWSCLI ec2 describe-addresses $PROFILE_OPT --region $regx --query Addresses --output json 2>&1)
+ if [[ $(echo "$ELASTIC_IP_ADDRESSES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe addresses" "$regx"
+ continue
+ fi
if [[ $ELASTIC_IP_ADDRESSES != [] ]]; then
LIST_OF_ASSOCIATED_IPS=$(echo $ELASTIC_IP_ADDRESSES | jq -r '.[] | select(.AssociationId!=null) | .PublicIp')
LIST_OF_UNASSOCIATED_IPS=$(echo $ELASTIC_IP_ADDRESSES | jq -r '.[] | select(.AssociationId==null) | .PublicIp')
diff --git a/checks/check_extra7147 b/checks/check_extra7147
index 4e8c16e3..ef9ee88b 100644
--- a/checks/check_extra7147
+++ b/checks/check_extra7147
@@ -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 *'
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7147='Data Protection'
extra7147(){
for regx in $REGIONS; do
- LIST_OF_VAULTS=$($AWSCLI glacier list-vaults $PROFILE_OPT --region $regx --account-id $ACCOUNT_NUM --query VaultList[*].VaultName --output text|xargs -n1)
+ LIST_OF_VAULTS=$($AWSCLI glacier list-vaults $PROFILE_OPT --region $regx --account-id $ACCOUNT_NUM --query VaultList[*].VaultName --output text 2>&1|xargs -n1)
+ if [[ $(echo "$LIST_OF_VAULTS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list vaults" "$regx"
+ continue
+ fi
if [[ $LIST_OF_VAULTS ]]; then
for vault in $LIST_OF_VAULTS;do
VAULT_POLICY_STATEMENTS=$($AWSCLI glacier $PROFILE_OPT get-vault-access-policy --region $regx --account-id $ACCOUNT_NUM --vault-name $vault --output json --query policy.Policy 2>&1)
diff --git a/checks/check_extra7148 b/checks/check_extra7148
index c69805b5..4f035a88 100644
--- a/checks/check_extra7148
+++ b/checks/check_extra7148
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7148='Data Protection'
extra7148() {
for regx in $REGIONS; do
- LIST_OF_EFS_SYSTEMS=$($AWSCLI efs describe-file-systems $PROFILE_OPT --region $regx --query 'FileSystems[*].FileSystemId' --output text)
+ LIST_OF_EFS_SYSTEMS=$($AWSCLI efs describe-file-systems $PROFILE_OPT --region $regx --query 'FileSystems[*].FileSystemId' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_EFS_SYSTEMS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe file systems" "$regx"
+ continue
+ fi
if [[ $LIST_OF_EFS_SYSTEMS ]]; then
for filesystem in $LIST_OF_EFS_SYSTEMS; do
# if retention is 0 then is disabled
diff --git a/checks/check_extra7149 b/checks/check_extra7149
index 259947d8..2fd07c6c 100644
--- a/checks/check_extra7149
+++ b/checks/check_extra7149
@@ -26,12 +26,16 @@ CHECK_CAF_EPIC_extra7149='Data Protection'
extra7149() {
# "Check if Redshift cluster has audit logging enabled "
for regx in $REGIONS; do
- LIST_OF_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*].ClusterIdentifier' --output text)
+ LIST_OF_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*].ClusterIdentifier' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_REDSHIFT_CLUSTERS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe clusters" "$regx"
+ continue
+ fi
if [[ $LIST_OF_REDSHIFT_CLUSTERS ]]; then
for redshiftcluster in $LIST_OF_REDSHIFT_CLUSTERS; do
REDSHIFT_SNAPSHOT_ENABLED=$($AWSCLI redshift describe-cluster-snapshots $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --snapshot-type automated)
if [[ $REDSHIFT_SNAPSHOT_ENABLED ]]; then
- textPass "$regx: Redshift cluster $redshiftcluster has automated snapshots $REDSHIFT_SNAPSHOT_ENABLED" "$regx" "$redshiftcluster"
+ textPass "$regx: Redshift cluster $redshiftcluster has automated snapshots." "$regx" "$redshiftcluster"
else
textFail "$regx: Redshift cluster $redshiftcluster has automated snapshots disabled!" "$regx" "$redshiftcluster"
fi
diff --git a/checks/check_extra715 b/checks/check_extra715
index b5ccdb0e..20d03ac7 100644
--- a/checks/check_extra715
+++ b/checks/check_extra715
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra715='Logging and Monitoring'
extra715(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
SEARCH_SLOWLOG_ENABLED=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.LogPublishingOptions.Options.SEARCH_SLOW_LOGS.Enabled --output text |grep -v ^None|grep -v ^False)
diff --git a/checks/check_extra7150 b/checks/check_extra7150
index 673a3da8..c9f945a6 100644
--- a/checks/check_extra7150
+++ b/checks/check_extra7150
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra7150='Data Protection'
extra7150(){
# "Check if Elastic Load Balancers have delete protection enabled."
for regx in $REGIONS; do
- LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text|xargs -n1)
+ LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text 2>&1|xargs -n1 )
+ if [[ $(echo "$LIST_OF_ELBSV2" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
if [[ $LIST_OF_ELBSV2 ]]; then
for elb in $LIST_OF_ELBSV2; do
CHECK_DELETION_PROTECTION_ENABLED=$($AWSCLI elbv2 describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-arn $elb --query Attributes[*] --output text|grep "deletion_protection.enabled"|grep true )
diff --git a/checks/check_extra7151 b/checks/check_extra7151
index a17a3673..bb95ce1a 100644
--- a/checks/check_extra7151
+++ b/checks/check_extra7151
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_extra7151='Data Protection'
extra7151(){
# "Check if DynamoDB tables point-in-time recovery (PITR) is enabled"
for regx in $REGIONS; do
- LIST_OF_DYNAMODB_TABLES=$($AWSCLI dynamodb list-tables $PROFILE_OPT --region $regx --query 'TableNames[*]' --output text)
+ LIST_OF_DYNAMODB_TABLES=$($AWSCLI dynamodb list-tables $PROFILE_OPT --region $regx --query 'TableNames[*]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DYNAMODB_TABLES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list tables" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DYNAMODB_TABLES ]]; then
for dynamodb_table in $LIST_OF_DYNAMODB_TABLES; do
POINT_IN_TIME_RECOVERY_ENABLED=$($AWSCLI dynamodb describe-continuous-backups $PROFILE_OPT --region $regx --table-name $dynamodb_table | jq '.[].PointInTimeRecoveryDescription | select(.PointInTimeRecoveryStatus=="ENABLED") | .PointInTimeRecoveryStatus')
diff --git a/checks/check_extra7152 b/checks/check_extra7152
index e205de31..136a332e 100644
--- a/checks/check_extra7152
+++ b/checks/check_extra7152
@@ -23,31 +23,32 @@
# --tech-privacy
CHECK_ID_extra7152="7.152"
-CHECK_TITLE_extra7152="[extra7152] Enable Privacy Protection for for a Route53 Domain"
+CHECK_TITLE_extra7152="[extra7152] Enable Privacy Protection for for a Route53 Domain (us-east-1 only)"
CHECK_SCORED_extra7152="NOT_SCORED"
CHECK_CIS_LEVEL_extra7152="EXTRA"
CHECK_SEVERITY_extra7152="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7152="AwsRoute53Domain"
CHECK_ALTERNATE_check7152="extra7152"
CHECK_SERVICENAME_extra7152="route53"
-CHECK_RISK_extra7152='Without privacy protection enabled, ones personal information is published to the public WHOIS database'
+CHECK_RISK_extra7152='Without privacy protection enabled; ones personal information is published to the public WHOIS database'
CHECK_REMEDIATION_extra7152='Ensure default Privacy is enabled'
CHECK_DOC_extra7152='https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-privacy-protection.html'
CHECK_CAF_EPIC_extra7152='Data Protection'
extra7152(){
- echo "Route53 is a global service, looking for domains in US-EAST-1"
+ # Route53 is a global service, looking for domains in US-EAST-1
+ # this is also valid for GovCloud https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/setting-up-route53.html
DOMAIN_NAMES=$($AWSCLI route53domains list-domains $PROFILE_OPT --region us-east-1 --query 'Domains[*].DomainName' --output text )
if [[ $DOMAIN_NAMES ]];then
for domain_name in $DOMAIN_NAMES;do
DOMAIN_DETAIL=$($AWSCLI route53domains get-domain-detail $PROFILE_OPT --region us-east-1 --query 'AdminPrivacy' --domain-name $domain_name)
if [[ $DOMAIN_DETAIL == false ]]; then
- textFail "$regx: Contact information public for: $domain_name" "$regx" "$domain_name"
+ textFail "us-east-1: Contact information public for: $domain_name" "us-east-1" "$domain_name"
else
- textPass "$regx: All contact information is private for: $domain_name" "$regx" "$domain_name"
+ textPass "us-east-1: All contact information is private for: $domain_name" "us-east-1" "$domain_name"
fi
done
else
- textPass "$regx: No Domain Names found" "$regx"
+ textInfo "us-east-1: No Domain Names found" "us-east-1"
fi
}
diff --git a/checks/check_extra7153 b/checks/check_extra7153
index eee485c5..e7f31b2b 100644
--- a/checks/check_extra7153
+++ b/checks/check_extra7153
@@ -20,32 +20,33 @@
CHECK_ID_extra7153="7.153"
-CHECK_TITLE_extra7153="[extra7153] Enable Transfer Lock for a Route53 Domain"
+CHECK_TITLE_extra7153="[extra7153] Enable Transfer Lock for a Route53 Domain (us-east-1 only)"
CHECK_SCORED_extra7153="NOT_SCORED"
CHECK_CIS_LEVEL_extra7153="EXTRA"
CHECK_SEVERITY_extra7153="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7153="AwsRoute53Domain"
CHECK_ALTERNATE_check7153="extra7153"
CHECK_SERVICENAME_extra7153="route53"
-CHECK_RISK_extra7153='Without transfer lock enabled, a domain name could be incorrectly moved to a new registrar'
+CHECK_RISK_extra7153='Without transfer lock enabled; a domain name could be incorrectly moved to a new registrar'
CHECK_REMEDIATION_extra7153='Ensure transfer lock is enabled'
CHECK_DOC_extra7153='https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-lock.html'
CHECK_CAF_EPIC_extra7153='Data Protection'
extra7153(){
# Route53 is a global service, looking for domains in US-EAST-1
+ # this is also valid for GovCloud https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/setting-up-route53.html
DOMAIN_NAMES=$($AWSCLI route53domains list-domains $PROFILE_OPT --region us-east-1 --query 'Domains[*].DomainName' --output text )
if [[ $DOMAIN_NAMES ]];then
for domain_name in $DOMAIN_NAMES;do
DOMAIN_DETAIL=$($AWSCLI route53domains get-domain-detail $PROFILE_OPT --region us-east-1 --query 'StatusList' --domain-name $domain_name)
HAS_TRANSFER_LOCK=$( grep -o 'clientTransferProhibited' <<< $DOMAIN_DETAIL)
if [[ $HAS_TRANSFER_LOCK ]]; then
- textPass "$regx: clientTransferProhibited found for: $domain_name" "$regx" "$domain_name"
+ textPass "us-east-1: clientTransferProhibited found for: $domain_name" "us-east-1" "$domain_name"
else
- textFail "$regx: clientTransferProhibited not found for: $domain_name" "$regx" "$domain_name"
+ textFail "us-east-1: clientTransferProhibited not found for: $domain_name" "us-east-1" "$domain_name"
fi
done
else
- textPass "$regx: No Domain Names found" "$regx"
+ textInfo "us-east-1: No Domain Names found" "us-east-1"
fi
}
diff --git a/checks/check_extra7154 b/checks/check_extra7154
index 8ea2efe6..7d4dcc42 100644
--- a/checks/check_extra7154
+++ b/checks/check_extra7154
@@ -34,7 +34,11 @@ CHECK_CAF_EPIC_extra7154='Infrastructure Protection'
extra7154() {
for regx in $REGIONS; do
- CFN_STACKS=$($AWSCLI cloudformation describe-stacks $PROFILE_OPT --region $regx --output json)
+ CFN_STACKS=$($AWSCLI cloudformation describe-stacks $PROFILE_OPT --region $regx --output json 2>&1)
+ if [[ $(echo "$CFN_STACKS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe stacks" "$regx"
+ continue
+ fi
LIST_OF_CFN_STACKS=$(echo $CFN_STACKS | jq -r '.Stacks[].StackName')
if [[ $LIST_OF_CFN_STACKS ]];then
for stack in $LIST_OF_CFN_STACKS; do
diff --git a/checks/check_extra7155 b/checks/check_extra7155
index 7c663886..e593a805 100644
--- a/checks/check_extra7155
+++ b/checks/check_extra7155
@@ -33,7 +33,11 @@ CHECK_CAF_EPIC_extra7155='Data Protection'
extra7155() {
for regx in $REGIONS; do
- LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Type == `application`].[LoadBalancerArn]' --output text)
+ LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Type == `application`].[LoadBalancerArn]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_ELBSV2" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
if [[ $LIST_OF_ELBSV2 ]];then
for alb in $LIST_OF_ELBSV2;do
CHECK_DESYNC_MITIGATION_MODE=$($AWSCLI elbv2 describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-arn $alb --query 'Attributes[8]' --output json | jq -r '.Value')
diff --git a/checks/check_extra7156 b/checks/check_extra7156
index 529c0616..7c8de499 100644
--- a/checks/check_extra7156
+++ b/checks/check_extra7156
@@ -28,7 +28,11 @@ extra7156(){
# "Check if API Gateway V2 has Access Logging enabled "
for regx in $REGIONS; do
- LIST_OF_API_GW=$($AWSCLI apigatewayv2 get-apis $PROFILE_OPT --region $regx --query Items[*].ApiId --output text)
+ LIST_OF_API_GW=$($AWSCLI apigatewayv2 get-apis $PROFILE_OPT --region $regx --query Items[*].ApiId --output text 2>&1)
+ if [[ $(echo "$LIST_OF_API_GW" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get APIs" "$regx"
+ continue
+ fi
if [[ $LIST_OF_API_GW ]];then
for apigwid in $LIST_OF_API_GW;do
API_GW_NAME=$($AWSCLI apigatewayv2 get-apis $PROFILE_OPT --region $regx --query "Items[?ApiId==\`$apigwid\`].Name" --output text)
@@ -37,9 +41,9 @@ extra7156(){
for stagename in $CHECK_STAGES_NAME;do
CHECK_STAGE_METHOD_LOGGING=$($AWSCLI apigatewayv2 get-stages $PROFILE_OPT --region $regx --api-id $apigwid --query "Items[?StageName == \`$stagename\` ].AccessLogSettings.DestinationArn" --output text)
if [[ $CHECK_STAGE_METHOD_LOGGING ]];then
- textPass "$regx: API Gateway V2 $API_GW_NAME ID: $apigwid, stage: $stagename, has access logging enabled to $CHECK_STAGE_METHOD_LOGGING" "$regx" "$API_GW_NAME"
+ textPass "$regx: API Gateway V2 $API_GW_NAME ID: $apigwid with stage: $stagename has access logging enabled to $CHECK_STAGE_METHOD_LOGGING" "$regx" "$API_GW_NAME"
else
- textFail "$regx: API Gateway V2 $API_GW_NAME ID: $apigwid, stage: $stagename, has access logging disabled" "$regx" "$API_GW_NAME"
+ textFail "$regx: API Gateway V2 $API_GW_NAME ID: $apigwid with stage: $stagename has access logging disabled" "$regx" "$API_GW_NAME"
fi
done
else
diff --git a/checks/check_extra7157 b/checks/check_extra7157
index ec62f4a8..755435c5 100644
--- a/checks/check_extra7157
+++ b/checks/check_extra7157
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7157='IAM'
extra7157(){
for regx in $REGIONS; do
- LIST_OF_API_GW=$($AWSCLI apigatewayv2 get-apis $PROFILE_OPT --region $regx --query "Items[*].ApiId" --output text)
+ LIST_OF_API_GW=$($AWSCLI apigatewayv2 get-apis $PROFILE_OPT --region $regx --query "Items[*].ApiId" --output text 2>&1)
+ if [[ $(echo "$LIST_OF_API_GW" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get APIs" "$regx"
+ continue
+ fi
if [[ $LIST_OF_API_GW ]];then
for api in $LIST_OF_API_GW; do
API_GW_NAME=$($AWSCLI apigatewayv2 get-apis $PROFILE_OPT --region $regx --query "Items[?ApiId==\`$api\`].Name" --output text)
diff --git a/checks/check_extra7158 b/checks/check_extra7158
index 3aaf74ec..ee1bad9f 100644
--- a/checks/check_extra7158
+++ b/checks/check_extra7158
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7158='Data Protection'
extra7158(){
for regx in $REGIONS; do
- LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers --query 'LoadBalancers[*].LoadBalancerArn' $PROFILE_OPT --region $regx --output text)
+ LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers --query 'LoadBalancers[*].LoadBalancerArn' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$LIST_OF_ELBSV2" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
if [[ $LIST_OF_ELBSV2 ]]; then
for elb in $LIST_OF_ELBSV2; do
LIST_OF_LISTENERS=$($AWSCLI elbv2 describe-listeners $PROFILE_OPT --region $regx --load-balancer-arn $elb --query 'Listeners[*]' --output text)
diff --git a/checks/check_extra7159 b/checks/check_extra7159
index 58437519..ddbe5452 100644
--- a/checks/check_extra7159
+++ b/checks/check_extra7159
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra7159='Data Protection'
extra7159(){
for regx in $REGIONS; do
- LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers --query 'LoadBalancerDescriptions[*].LoadBalancerName' $PROFILE_OPT --region $regx --output text)
+ LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers --query 'LoadBalancerDescriptions[*].LoadBalancerName' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$LIST_OF_ELBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
if [[ $LIST_OF_ELBS ]]; then
for elb in $LIST_OF_ELBS; do
LIST_OF_LISTENERS=$($AWSCLI elb describe-load-balancers --load-balancer-name $elb --query 'LoadBalancerDescriptions[*].ListenerDescriptions' $PROFILE_OPT --region $regx --output text)
diff --git a/checks/check_extra716 b/checks/check_extra716
index 87980aea..0bac7f7f 100644
--- a/checks/check_extra716
+++ b/checks/check_extra716
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra716='Infrastructure Security'
extra716(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.policy.XXXXXXXXXX)
diff --git a/checks/check_extra7160 b/checks/check_extra7160
new file mode 100644
index 00000000..066fa66b
--- /dev/null
+++ b/checks/check_extra7160
@@ -0,0 +1,46 @@
+#!/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 2>&1)
+ if [[ $(echo "$LIST_OF_CLUSTERS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe clusters" "$regx"
+ continue
+ fi
+ 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
+}
\ No newline at end of file
diff --git a/checks/check_extra7161 b/checks/check_extra7161
new file mode 100644
index 00000000..0fbe0021
--- /dev/null
+++ b/checks/check_extra7161
@@ -0,0 +1,47 @@
+#!/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 2>&1| xargs -n1 )
+ if [[ $(echo "$LIST_OF_EFS_IDS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe file systems" "$regx"
+ continue
+ fi
+ 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
+}
diff --git a/checks/check_extra7162 b/checks/check_extra7162
new file mode 100644
index 00000000..b0d17eac
--- /dev/null
+++ b/checks/check_extra7162
@@ -0,0 +1,54 @@
+#!/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 2>&1)
+ if [[ $(echo "$LIST_OF_365_RETENTION_LOG_GROUPS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe log groups" "$regx"
+ continue
+ fi
+ 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
+}
diff --git a/checks/check_extra7163 b/checks/check_extra7163
new file mode 100644
index 00000000..6d5b45d8
--- /dev/null
+++ b/checks/check_extra7163
@@ -0,0 +1,61 @@
+#!/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
+# [--client-request-token ]
+# [--rotation-lambda-arn ]
+# [--rotation-rules ]
+# [--cli-input-json ]
+# [--generate-cli-skeleton ]
+
+
+CHECK_ID_extra7163="7.163"
+CHECK_TITLE_extra7163="[extra7163] Check if Secrets Manager key rotation is enabled"
+CHECK_SCORED_extra7163="NOT_SCORED"
+CHECK_CIS_LEVEL_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 2>&1)
+ if [[ $(echo "$LIST_OF_SECRETS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list secrets" "$regx"
+ continue
+ fi
+ 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
+}
diff --git a/checks/check_extra7164 b/checks/check_extra7164
new file mode 100644
index 00000000..9c9a8198
--- /dev/null
+++ b/checks/check_extra7164
@@ -0,0 +1,61 @@
+#!/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
+# --kms-key-id
+# [--cli-input-json ]
+# [--generate-cli-skeleton ]
+
+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_CIS_LEVEL_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 2>&1 )
+ if [[ $(echo "$LIST_OF_LOGGROUPS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe log groups" "$regx"
+ continue
+ fi
+ if [[ $LIST_OF_LOGGROUPS ]]; then
+ LIST_OF_LOGGROUPS_WITHOUT_KMS=$(echo "${LIST_OF_LOGGROUPS}" | jq '.logGroups[]' | jq '. | select( has("kmsKeyId") == false )' | jq -r '.logGroupName')
+ LIST_OF_LOGGROUPS_WITH_KMS=$(echo "${LIST_OF_LOGGROUPS}" | jq '.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
+}
diff --git a/checks/check_extra7165 b/checks/check_extra7165
new file mode 100644
index 00000000..95f990a5
--- /dev/null
+++ b/checks/check_extra7165
@@ -0,0 +1,68 @@
+#!/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
+# --node-type
+# --replication-factor
+# --iam-role-arn
+# --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_CIS_LEVEL_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 -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe clusters" "$regx"
+ continue
+ fi
+ if [[ $(echo "$LIST_OF_DAX_CLUSTERS" | grep -E 'Could not connect') ]]; then
+ textInfo "$regx: Service not available in this region" "$regx"
+ continue
+ fi
+ if [[ $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
+}
\ No newline at end of file
diff --git a/checks/check_extra7166 b/checks/check_extra7166
new file mode 100644
index 00000000..4a8430f5
--- /dev/null
+++ b/checks/check_extra7166
@@ -0,0 +1,50 @@
+#!/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.
+
+CHECK_ID_extra7166="7.166"
+CHECK_TITLE_extra7166="[extra7166] Check if Elastic IP addresses with associations are protected by AWS Shield Advanced"
+CHECK_SCORED_extra7166="NOT_SCORED"
+CHECK_CIS_LEVEL_extra7166="EXTRA"
+CHECK_SEVERITY_extra7166="Medium"
+CHECK_ASFF_RESOURCE_TYPE_extra7166="AwsEc2Eip"
+CHECK_ALTERNATE_check7166="extra7166"
+CHECK_SERVICENAME_extra7166="shield"
+CHECK_RISK_extra7166='AWS Shield Advanced provides expanded DDoS attack protection for your resources'
+CHECK_REMEDIATION_extra7166='Add as a protected resource in AWS Shield Advanced.'
+CHECK_DOC_extra7166='https://docs.aws.amazon.com/waf/latest/developerguide/configure-new-protection.html'
+CHECK_CAF_EPIC_extra7166='Infrastructure security'
+
+extra7166() {
+ if [[ "$($AWSCLI $PROFILE_OPT shield get-subscription-state --output text)" == "ACTIVE" ]]; then
+ CALLER_IDENTITY=$($AWSCLI sts get-caller-identity $PROFILE_OPT --query Arn)
+ PARTITION=$(echo $CALLER_IDENTITY | cut -d: -f2)
+ ACCOUNT_ID=$(echo $CALLER_IDENTITY | cut -d: -f5)
+ for regx in $REGIONS; do
+ LIST_OF_ELASTIC_IPS_WITH_ASSOCIATIONS=$($AWSCLI ec2 describe-addresses $PROFILE_OPT --region $regx --query 'Addresses[?AssociationId].AllocationId' --output text)
+ if [[ $LIST_OF_ELASTIC_IPS_WITH_ASSOCIATIONS ]]; then
+ for elastic_ip in $LIST_OF_ELASTIC_IPS_WITH_ASSOCIATIONS; do
+ EIP_ARN="arn:${PARTITION}:ec2:${regx}:${ACCOUNT_ID}:eip-allocation/${elastic_ip}"
+ if $AWSCLI $PROFILE_OPT shield describe-protection --resource-arn $EIP_ARN >/dev/null 2>&1; then
+ textPass "$regx: EIP $elastic_ip is protected by AWS Shield Advanced" "$regx" "$elastic_ip"
+ else
+ textFail "$regx: EIP $elastic_ip is not protected by AWS Shield Advanced" "$regx" "$elastic_ip"
+ fi
+ done
+ else
+ textInfo "$regx: no elastic IP addresses with assocations found" "$regx"
+ fi
+ done
+ else
+ textInfo "No AWS Shield Advanced subscription found. Skipping check."
+ fi
+}
diff --git a/checks/check_extra7167 b/checks/check_extra7167
new file mode 100644
index 00000000..18ce6209
--- /dev/null
+++ b/checks/check_extra7167
@@ -0,0 +1,46 @@
+#!/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.
+
+CHECK_ID_extra7167="7.167"
+CHECK_TITLE_extra7167="[extra7167] Check if Cloudfront distributions are protected by AWS Shield Advanced"
+CHECK_SCORED_extra7167="NOT_SCORED"
+CHECK_CIS_LEVEL_extra7167="EXTRA"
+CHECK_SEVERITY_extra7167="Medium"
+CHECK_ASFF_RESOURCE_TYPE_extra7167="AwsCloudFrontDistribution"
+CHECK_ALTERNATE_check7167="extra7167"
+CHECK_SERVICENAME_extra7167="shield"
+CHECK_RISK_extra7167='AWS Shield Advanced provides expanded DDoS attack protection for your resources'
+CHECK_REMEDIATION_extra7167='Add as a protected resource in AWS Shield Advanced.'
+CHECK_DOC_extra7167='https://docs.aws.amazon.com/waf/latest/developerguide/configure-new-protection.html'
+CHECK_CAF_EPIC_extra7167='Infrastructure security'
+
+extra7167() {
+ if [[ "$($AWSCLI $PROFILE_OPT shield get-subscription-state --output text)" == "ACTIVE" ]]; then
+ LIST_OF_CLOUDFRONT_DISTRIBUTIONS=$($AWSCLI cloudfront list-distributions $PROFILE_OPT --query 'DistributionList.Items[*].[Id,ARN]' --output text)
+ if [[ $LIST_OF_CLOUDFRONT_DISTRIBUTIONS ]]; then
+ while read -r distribution; do
+ DISTRIBUTION_ID=$(echo $distribution | awk '{ print $1; }')
+ DISTRIBUTION_ARN=$(echo $distribution | awk '{ print $2; }')
+ if $AWSCLI $PROFILE_OPT shield describe-protection --resource-arn $DISTRIBUTION_ARN >/dev/null 2>&1; then
+ textPass "$REGION: Cloudfront distribution $DISTRIBUTION_ID is protected by AWS Shield Advanced" "$REGION" "$DISTRIBUTION_ID"
+ else
+ textFail "$REGION: Cloudfront distribution $DISTRIBUTION_ID is not protected by AWS Shield Advanced" "$REGION" "$DISTRIBUTION_ID"
+ fi
+ done <<<"$LIST_OF_CLOUDFRONT_DISTRIBUTIONS"
+ else
+ textInfo "$REGION: no Cloudfront distributions found" "$REGION"
+ fi
+ else
+ textInfo "No AWS Shield Advanced subscription found. Skipping check."
+ fi
+}
diff --git a/checks/check_extra7168 b/checks/check_extra7168
new file mode 100644
index 00000000..e2f2514d
--- /dev/null
+++ b/checks/check_extra7168
@@ -0,0 +1,49 @@
+#!/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.
+
+CHECK_ID_extra7168="7.168"
+CHECK_TITLE_extra7168="[extra7168] Check if Route53 hosted zones are protected by AWS Shield Advanced"
+CHECK_SCORED_extra7168="NOT_SCORED"
+CHECK_CIS_LEVEL_extra7168="EXTRA"
+CHECK_SEVERITY_extra7168="Medium"
+CHECK_ASFF_RESOURCE_TYPE_extra7168="AwsRoute53Domain"
+CHECK_ALTERNATE_check7168="extra7168"
+CHECK_SERVICENAME_extra7168="shield"
+CHECK_RISK_extra7168='AWS Shield Advanced provides expanded DDoS attack protection for your resources'
+CHECK_REMEDIATION_extra7168='Add as a protected resource in AWS Shield Advanced.'
+CHECK_DOC_extra7168='https://docs.aws.amazon.com/waf/latest/developerguide/configure-new-protection.html'
+CHECK_CAF_EPIC_extra7168='Infrastructure security'
+
+extra7168() {
+ if [[ "$($AWSCLI $PROFILE_OPT shield get-subscription-state --output text)" == "ACTIVE" ]]; then
+ CALLER_IDENTITY=$($AWSCLI sts get-caller-identity $PROFILE_OPT --query Arn)
+ PARTITION=$(echo $CALLER_IDENTITY | cut -d: -f2)
+ LIST_OF_ROUTE53_HOSTED_ZONES=$($AWSCLI route53 list-hosted-zones $PROFILE_OPT --query 'HostedZones[*].[Id,Name]' --output text)
+ if [[ $LIST_OF_ROUTE53_HOSTED_ZONES ]]; then
+ while read -r hosted_zone; do
+ HOSTED_ZONE_ID=$(echo $hosted_zone | awk '{ print $1; }')
+ HOSTED_ZONE_NAME=$(echo $hosted_zone | awk '{ print $2; }')
+ HOSTED_ZONE_ARN="arn:${PARTITION}:route53:::${HOSTED_ZONE_ID:1}"
+ if $AWSCLI $PROFILE_OPT shield describe-protection --resource-arn $HOSTED_ZONE_ARN >/dev/null 2>&1; then
+ textPass "$REGION: Route53 Hosted Zone $HOSTED_ZONE_NAME is protected by AWS Shield Advanced" "$REGION" "$HOSTED_ZONE_NAME"
+ else
+ textFail "$REGION: Route53 Hosted Zone $HOSTED_ZONE_NAME is not protected by AWS Shield Advanced" "$REGION" "$HOSTED_ZONE_NAME"
+ fi
+ done <<<"$LIST_OF_ROUTE53_HOSTED_ZONES"
+ else
+ textInfo "$REGION: no Route53 hosted zones found" "$REGION"
+ fi
+ else
+ textInfo "No AWS Shield Advanced subscription found. Skipping check."
+ fi
+}
diff --git a/checks/check_extra7169 b/checks/check_extra7169
new file mode 100644
index 00000000..573c0415
--- /dev/null
+++ b/checks/check_extra7169
@@ -0,0 +1,46 @@
+#!/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.
+
+CHECK_ID_extra7169="7.169"
+CHECK_TITLE_extra7169="[extra7169] Check if global accelerators are protected by AWS Shield Advanced"
+CHECK_SCORED_extra7169="NOT_SCORED"
+CHECK_CIS_LEVEL_extra7169="EXTRA"
+CHECK_SEVERITY_extra7169="Medium"
+CHECK_ASFF_RESOURCE_TYPE_extra7169="AwsGlobalAccelerator"
+CHECK_ALTERNATE_check7169="extra7169"
+CHECK_SERVICENAME_extra7169="shield"
+CHECK_RISK_extra7169='AWS Shield Advanced provides expanded DDoS attack protection for your resources'
+CHECK_REMEDIATION_extra7169='Add as a protected resource in AWS Shield Advanced.'
+CHECK_DOC_extra7169='https://docs.aws.amazon.com/waf/latest/developerguide/configure-new-protection.html'
+CHECK_CAF_EPIC_extra7169='Infrastructure security'
+
+extra7169() {
+ if [[ "$($AWSCLI $PROFILE_OPT shield get-subscription-state --output text)" == "ACTIVE" ]]; then
+ LIST_OF_GLOBAL_ACCELERATORS=$($AWSCLI globalaccelerator list-accelerators --region us-west-2 $PROFILE_OPT --query 'Accelerators[?Enabled].[Name,AcceleratorArn]' --output text)
+ if [[ $LIST_OF_GLOBAL_ACCELERATORS ]]; then
+ while read -r accelerator; do
+ ACCELERATOR_NAME=$(echo $accelerator | awk '{ print $1; }')
+ ACCELERATOR_ARN=$(echo $accelerator | awk '{ print $2; }')
+ if $AWSCLI $PROFILE_OPT shield describe-protection --resource-arn $ACCELERATOR_ARN >/dev/null 2>&1; then
+ textPass "$REGION: Global Accelerator $ACCELERATOR_NAME is protected by AWS Shield Advanced" "$REGION" "$ACCELERATOR_NAME"
+ else
+ textFail "$REGION: Global Accelerator $ACCELERATOR_NAME is not protected by AWS Shield Advanced" "$REGION" "$ACCELERATOR_NAME"
+ fi
+ done <<<"$LIST_OF_GLOBAL_ACCELERATORS"
+ else
+ textInfo "$REGION: no global accelerators found" "$REGION"
+ fi
+ else
+ textInfo "No AWS Shield Advanced subscription found. Skipping check."
+ fi
+}
diff --git a/checks/check_extra717 b/checks/check_extra717
index aa42a36e..4be331cd 100644
--- a/checks/check_extra717
+++ b/checks/check_extra717
@@ -26,12 +26,20 @@ CHECK_CAF_EPIC_extra717='Logging and Monitoring'
extra717(){
# "Check if Elastic Load Balancers have logging enabled "
for regx in $REGIONS; do
- LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text|xargs -n1)
- LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text|xargs -n1)
+ LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text 2>&1 |xargs -n1)
+ if [[ $(echo "$LIST_OF_ELBS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to list load balancers v1" "$regx"
+ continue
+ fi
+ LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text 2>&1 |xargs -n1)
+ if [[ $(echo "$LIST_OF_ELBSV2" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to list load balancers v2" "$regx"
+ continue
+ fi
if [[ $LIST_OF_ELBS || $LIST_OF_ELBSV2 ]]; then
if [[ $LIST_OF_ELBS ]]; then
for elb in $LIST_OF_ELBS; do
- CHECK_ELBS_LOG_ENABLED=$($AWSCLI elb describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-name $elb --query 'LoadBalancerAttributes.AccessLog.Enabled'|grep "^true")
+ CHECK_ELBS_LOG_ENABLED=$($AWSCLI elb describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-name $elb --query 'LoadBalancerAttributes.AccessLog.Enabled' |grep "^true")
if [[ $CHECK_ELBS_LOG_ENABLED ]]; then
textPass "$regx: $elb has access logs to S3 configured" "$regx" "$elb"
else
@@ -41,7 +49,7 @@ extra717(){
fi
if [[ $LIST_OF_ELBSV2 ]]; then
for elbarn in $LIST_OF_ELBSV2; do
- CHECK_ELBSV2_LOG_ENABLED=$($AWSCLI elbv2 describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-arn $elbarn --query Attributes[*] --output text|grep "^access_logs.s3.enabled"|cut -f2|grep true)
+ CHECK_ELBSV2_LOG_ENABLED=$($AWSCLI elbv2 describe-load-balancer-attributes $PROFILE_OPT --region $regx --load-balancer-arn $elbarn --query Attributes[*] --output text |grep "^access_logs.s3.enabled"|cut -f2|grep true)
ELBV2_NAME=$(echo $elbarn|cut -d\/ -f3)
if [[ $CHECK_ELBSV2_LOG_ENABLED ]]; then
textPass "$regx: $ELBV2_NAME has access logs to S3 configured" "$regx" "$elb"
diff --git a/checks/check_extra7170 b/checks/check_extra7170
new file mode 100644
index 00000000..f8675a5c
--- /dev/null
+++ b/checks/check_extra7170
@@ -0,0 +1,48 @@
+#!/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.
+
+CHECK_ID_extra7170="7.170"
+CHECK_TITLE_extra7170="[extra7170] Check if internet-facing application load balancers are protected by AWS Shield Advanced"
+CHECK_SCORED_extra7170="NOT_SCORED"
+CHECK_CIS_LEVEL_extra7170="EXTRA"
+CHECK_SEVERITY_extra7170="Medium"
+CHECK_ASFF_RESOURCE_TYPE_extra7170="AwsElasticLoadBalancingV2LoadBalancer"
+CHECK_ALTERNATE_check7170="extra7170"
+CHECK_SERVICENAME_extra7170="shield"
+CHECK_RISK_extra7170='AWS Shield Advanced provides expanded DDoS attack protection for your resources'
+CHECK_REMEDIATION_extra7170='Add as a protected resource in AWS Shield Advanced.'
+CHECK_DOC_extra7170='https://docs.aws.amazon.com/waf/latest/developerguide/configure-new-protection.html'
+CHECK_CAF_EPIC_extra7170='Infrastructure security'
+
+extra7170() {
+ if [[ "$($AWSCLI $PROFILE_OPT shield get-subscription-state --output text)" == "ACTIVE" ]]; then
+ for regx in $REGIONS; do
+ LIST_OF_APPLICATION_LOAD_BALANCERS=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Type == `application` && Scheme == `internet-facing`].[LoadBalancerName,LoadBalancerArn]' --output text)
+ if [[ $LIST_OF_APPLICATION_LOAD_BALANCERS ]]; then
+ while read -r alb; do
+ ALB_NAME=$(echo $alb | awk '{ print $1; }')
+ ALB_ARN=$(echo $alb | awk '{ print $2; }')
+ if $AWSCLI $PROFILE_OPT shield describe-protection --resource-arn $ALB_ARN >/dev/null 2>&1; then
+ textPass "$regx: ALB $ALB_NAME is protected by AWS Shield Advanced" "$regx" "$ALB_NAME"
+ else
+ textFail "$regx: ALB $ALB_NAME is not protected by AWS Shield Advanced" "$regx" "$ALB_NAME"
+ fi
+ done <<<"$LIST_OF_APPLICATION_LOAD_BALANCERS"
+ else
+ textInfo "$regx: no application load balancers found" "$regx"
+ fi
+ done
+ else
+ textInfo "No AWS Shield Advanced subscription found. Skipping check."
+ fi
+}
diff --git a/checks/check_extra7171 b/checks/check_extra7171
new file mode 100644
index 00000000..61834e58
--- /dev/null
+++ b/checks/check_extra7171
@@ -0,0 +1,50 @@
+#!/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.
+
+CHECK_ID_extra7171="7.171"
+CHECK_TITLE_extra7171="[extra7171] Check if classic load balancers are protected by AWS Shield Advanced"
+CHECK_SCORED_extra7171="NOT_SCORED"
+CHECK_CIS_LEVEL_extra7171="EXTRA"
+CHECK_SEVERITY_extra7171="Medium"
+CHECK_ASFF_RESOURCE_TYPE_extra7171="AwsElasticLoadBalancingLoadBalancer"
+CHECK_ALTERNATE_check7171="extra7171"
+CHECK_SERVICENAME_extra7171="shield"
+CHECK_RISK_extra7171='AWS Shield Advanced provides expanded DDoS attack protection for your resources'
+CHECK_REMEDIATION_extra7171='Add as a protected resource in AWS Shield Advanced.'
+CHECK_DOC_extra7171='https://docs.aws.amazon.com/waf/latest/developerguide/configure-new-protection.html'
+CHECK_CAF_EPIC_extra7171='Infrastructure security'
+
+extra7171() {
+ if [[ "$($AWSCLI $PROFILE_OPT shield get-subscription-state --output text)" == "ACTIVE" ]]; then
+ CALLER_IDENTITY=$($AWSCLI sts get-caller-identity $PROFILE_OPT --query Arn)
+ PARTITION=$(echo $CALLER_IDENTITY | cut -d: -f2)
+ ACCOUNT_ID=$(echo $CALLER_IDENTITY | cut -d: -f5)
+ for regx in $REGIONS; do
+ LIST_OF_CLASSIC_LOAD_BALANCERS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[?Scheme == `internet-facing`].[LoadBalancerName]' --output text |grep -v '^None$')
+ if [[ $LIST_OF_CLASSIC_LOAD_BALANCERS ]]; then
+ for elb in $LIST_OF_CLASSIC_LOAD_BALANCERS; do
+ ELB_ARN="arn:${PARTITION}:elasticloadbalancing:${regx}:${ACCOUNT_ID}:loadbalancer/${elb}"
+ if $AWSCLI $PROFILE_OPT shield describe-protection --resource-arn $ELB_ARN >/dev/null 2>&1; then
+ textPass "$regx: ELB $elb is protected by AWS Shield Advanced" "$regx" "$elb"
+ else
+ textFail "$regx: ELB $elb is not protected by AWS Shield Advanced" "$regx" "$elb"
+ fi
+ done
+ else
+ textInfo "$regx: no classic load balancers found" "$regx"
+ fi
+ done
+ else
+ textInfo "No AWS Shield Advanced subscription found. Skipping check."
+ fi
+}
diff --git a/checks/check_extra718 b/checks/check_extra718
index c747e1c8..775d7958 100644
--- a/checks/check_extra718
+++ b/checks/check_extra718
@@ -30,7 +30,7 @@ extra718(){
for bucket in $LIST_OF_BUCKETS;do
BUCKET_SERVER_LOG_ENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --query [LoggingEnabled] --output text 2>&1)
if [[ $(echo "$BUCKET_SERVER_LOG_ENABLED" | grep AccessDenied) ]]; then
- textFail "$REGION: Access Denied Trying to Get Bucket Logging for $bucket" "$REGION" "$bucket"
+ textInfo "$REGION: Access Denied Trying to Get Bucket Logging for $bucket" "$REGION" "$bucket"
continue
fi
if [[ $(echo "$BUCKET_SERVER_LOG_ENABLED" | grep "^None$") ]]; then
diff --git a/checks/check_extra72 b/checks/check_extra72
index 019bfb26..36ba6ed4 100644
--- a/checks/check_extra72
+++ b/checks/check_extra72
@@ -28,7 +28,11 @@ CHECK_CAF_EPIC_extra72='Data Protection'
extra72(){
# "Ensure there are no EBS Snapshots set as Public "
for regx in $REGIONS; do
- LIST_OF_EBS_SNAPSHOTS=$($AWSCLI ec2 describe-snapshots $PROFILE_OPT --region $regx --owner-ids $ACCOUNT_NUM --output text --query 'Snapshots[*].{ID:SnapshotId}' --max-items $MAXITEMS | grep -v None 2> /dev/null)
+ LIST_OF_EBS_SNAPSHOTS=$($AWSCLI ec2 describe-snapshots $PROFILE_OPT --region $regx --owner-ids $ACCOUNT_NUM --output text --query 'Snapshots[*].{ID:SnapshotId}' --max-items $MAXITEMS 2>&1 | grep -v None )
+ if [[ $(echo "$LIST_OF_EBS_SNAPSHOTS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe snapshot" "$regx"
+ continue
+ fi
for snapshot in $LIST_OF_EBS_SNAPSHOTS; do
SNAPSHOT_IS_PUBLIC=$($AWSCLI ec2 describe-snapshot-attribute $PROFILE_OPT --region $regx --output text --snapshot-id $snapshot --attribute createVolumePermission --query "CreateVolumePermissions[?Group=='all']")
if [[ $SNAPSHOT_IS_PUBLIC ]];then
diff --git a/checks/check_extra720 b/checks/check_extra720
index 7f035229..c8af3fca 100644
--- a/checks/check_extra720
+++ b/checks/check_extra720
@@ -28,13 +28,13 @@ extra720(){
for regx in $REGIONS; do
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 functions" "$regx"
+ textInfo "$regx: Access Denied trying to list functions" "$regx"
continue
fi
if [[ $LIST_OF_FUNCTIONS ]]; then
LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].TrailARN' --output text 2>&1)
if [[ $(echo "$LIST_OF_TRAILS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied trying to describe trails" "$regx"
+ textInfo "$regx: Access Denied trying to describe trails" "$regx"
continue
fi
for lambdafunction in $LIST_OF_FUNCTIONS; do
diff --git a/checks/check_extra721 b/checks/check_extra721
index 7d63b0ee..4d4116ff 100644
--- a/checks/check_extra721
+++ b/checks/check_extra721
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra721='Logging and Monitoring'
extra721(){
# "Check if Redshift cluster has audit logging enabled "
for regx in $REGIONS; do
- LIST_OF_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*].ClusterIdentifier' --output text)
+ LIST_OF_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*].ClusterIdentifier' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_REDSHIFT_CLUSTERS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe clusters" "$regx"
+ continue
+ fi
if [[ $LIST_OF_REDSHIFT_CLUSTERS ]]; then
for redshiftcluster in $LIST_OF_REDSHIFT_CLUSTERS;do
REDSHIFT_LOG_ENABLED=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query LoggingEnabled --output text | grep True)
diff --git a/checks/check_extra722 b/checks/check_extra722
index 3def51c4..ab992174 100644
--- a/checks/check_extra722
+++ b/checks/check_extra722
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra722='Logging and Monitoring'
extra722(){
# "Check if API Gateway has logging enabled "
for regx in $REGIONS; do
- LIST_OF_API_GW=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query items[*].id --output text)
+ LIST_OF_API_GW=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query items[*].id --output text 2>&1)
+ if [[ $(echo "$LIST_OF_API_GW" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to get rest APIs" "$regx"
+ continue
+ fi
if [[ $LIST_OF_API_GW ]];then
for apigwid in $LIST_OF_API_GW;do
API_GW_NAME=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query "items[?id==\`$apigwid\`].name" --output text)
diff --git a/checks/check_extra723 b/checks/check_extra723
index 94833c23..7f4aee3f 100644
--- a/checks/check_extra723
+++ b/checks/check_extra723
@@ -27,7 +27,11 @@ extra723(){
# "Check if RDS Snapshots are public "
for regx in $REGIONS; do
# RDS snapshots
- LIST_OF_RDS_SNAPSHOTS=$($AWSCLI rds describe-db-snapshots $PROFILE_OPT --region $regx --query DBSnapshots[*].DBSnapshotIdentifier --output text)
+ LIST_OF_RDS_SNAPSHOTS=$($AWSCLI rds describe-db-snapshots $PROFILE_OPT --region $regx --query DBSnapshots[*].DBSnapshotIdentifier --output text 2>&1)
+ if [[ $(echo "$LIST_OF_RDS_SNAPSHOTS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe db snapshots" "$regx"
+ continue
+ fi
if [[ $LIST_OF_RDS_SNAPSHOTS ]]; then
for rdssnapshot in $LIST_OF_RDS_SNAPSHOTS;do
SNAPSHOT_IS_PUBLIC=$($AWSCLI rds describe-db-snapshot-attributes $PROFILE_OPT --region $regx --db-snapshot-identifier $rdssnapshot --query DBSnapshotAttributesResult.DBSnapshotAttributes[*] --output text|grep ^ATTRIBUTEVALUES|cut -f2|grep all)
diff --git a/checks/check_extra725 b/checks/check_extra725
index 3f1edcf3..6424d083 100644
--- a/checks/check_extra725
+++ b/checks/check_extra725
@@ -29,12 +29,12 @@ extra725(){
# "Check if S3 buckets have Object-level logging enabled in CloudTrail "
LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --region $REGION --query 'Buckets[*].{Name:Name}' --output text 2>&1)
if [[ $(echo "$LIST_OF_BUCKETS" | grep AccessDenied) ]]; then
- textFail "$REGION: Access Denied trying to list buckets"
+ textInfo "$REGION: Access Denied trying to list buckets"
return
fi
LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[].TrailARN' --output text 2>&1)
if [[ $(echo "$LIST_OF_TRAILS" | grep AccessDenied) ]]; then
- textFail "$REGION: Access Denied trying to describe trails"
+ textInfo "$REGION: Access Denied trying to describe trails"
return
fi
if [[ $LIST_OF_BUCKETS ]]; then
diff --git a/checks/check_extra726 b/checks/check_extra726
index ac61aaea..c9273cb9 100644
--- a/checks/check_extra726
+++ b/checks/check_extra726
@@ -31,6 +31,10 @@ extra726(){
textInfo "$REGION: Trusted Advisor requires AWS Premium Support Subscription" "$REGION"
return
fi
+ if [[ $(echo "$TA_CHECKS_ID" | grep "Could not connect") ]]; then
+ textInfo "$REGION: Trusted Advisor not available in this region" "$REGION"
+ return
+ fi
for checkid in $TA_CHECKS_ID; do
TA_CHECKS_NAME=$($AWSCLI support describe-trusted-advisor-checks --language en $PROFILE_OPT --region $REGION --query "checks[?id==\`$checkid\`].{name:name}[*]" --output text)
@@ -38,19 +42,19 @@ extra726(){
# Possible results - https://docs.aws.amazon.com/cli/latest/reference/support/describe-trusted-advisor-check-result.html
case "$QUERY_TA_CHECK_RESULT" in
"ok")
- textPass "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in ok state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
+ textPass "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
;;
"error")
- textFail "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in error state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
+ textFail "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
;;
"warning")
- textInfo "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in warning state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
+ textInfo "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
;;
"not_available")
- textInfo "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in not_available state $QUERY_TA_CHECK_RESULT" "u$REGION" "$TA_CHECKS_NAME"
+ textInfo "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
;;
"*")
- textFail "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in unknown state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
+ textFail "$REGION: Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_TA_CHECK_RESULT" "$REGION" "$TA_CHECKS_NAME"
;;
esac
done
diff --git a/checks/check_extra727 b/checks/check_extra727
index 86f5dfbd..c6b9a792 100644
--- a/checks/check_extra727
+++ b/checks/check_extra727
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra727='Infrastructure Security'
extra727(){
for regx in $REGIONS; do
- LIST_SQS=$($AWSCLI sqs list-queues $PROFILE_OPT --region $regx --query QueueUrls --output text |grep -v ^None)
+ LIST_SQS=$($AWSCLI sqs list-queues $PROFILE_OPT --region $regx --query QueueUrls --output text 2>&1|grep -v ^None )
+ if [[ $(echo "$LIST_SQS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to list queues" "$regx"
+ continue
+ fi
if [[ $LIST_SQS ]]; then
for queue in $LIST_SQS; do
SQS_POLICY=$($AWSCLI sqs get-queue-attributes --queue-url $queue $PROFILE_OPT --region $regx --attribute-names All --query Attributes.Policy)
@@ -39,7 +43,7 @@ extra727(){
if [[ $SQS_POLICY_ALLOW_ALL_WITHOUT_CONDITION ]]; then
SQS_POLICY_ALLOW_ALL_WITHOUT_CONDITION_DETAILS=$(echo $SQS_POLICY_ALLOW_ALL_WITHOUT_CONDITION \
| jq '"[Principal: " + (.Principal|tostring) + " Action: " + (.Action|tostring) + "]"' )
- textFail "$regx: SQS $queue queue policy with public access: $SQS_POLICY_ALLOW_ALL_WITHOUT_CONDITION_DETAILS" "$regx" "$queue"
+ textFail "$regx: SQS $queue queue policy with public access" "$regx" "$queue"
else
textInfo "$regx: SQS $queue queue policy with public access but has a Condition" "$regx" "$queue"
fi
diff --git a/checks/check_extra728 b/checks/check_extra728
index 10ad0e0c..ada64c0f 100644
--- a/checks/check_extra728
+++ b/checks/check_extra728
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_extra728='Data Protection'
extra728(){
for regx in $REGIONS; do
- LIST_SQS=$($AWSCLI sqs list-queues $PROFILE_OPT --region $regx --query QueueUrls --output text |grep -v ^None)
+ LIST_SQS=$($AWSCLI sqs list-queues $PROFILE_OPT --region $regx --query QueueUrls --output text 2>&1|grep -v ^None )
+ if [[ $(echo "$LIST_SQS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to list queues" "$regx"
+ continue
+ fi
if [[ $LIST_SQS ]]; then
for queue in $LIST_SQS; do
# check if the policy has KmsMasterKeyId therefore SSE enabled
diff --git a/checks/check_extra729 b/checks/check_extra729
index 5a839e5e..ca5d5433 100644
--- a/checks/check_extra729
+++ b/checks/check_extra729
@@ -28,7 +28,11 @@ CHECK_CAF_EPIC_extra729='Data Protection'
extra729(){
# "Ensure there are no EBS Volumes unencrypted "
for regx in $REGIONS; do
- LIST_OF_EBS_NON_ENC_VOLUMES=$($AWSCLI ec2 describe-volumes $PROFILE_OPT --region $regx --query 'Volumes[?Encrypted==`false`].VolumeId' --output text)
+ LIST_OF_EBS_NON_ENC_VOLUMES=$($AWSCLI ec2 describe-volumes $PROFILE_OPT --region $regx --query 'Volumes[?Encrypted==`false`].VolumeId' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_EBS_NON_ENC_VOLUMES" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe volumes" "$regx"
+ continue
+ fi
if [[ $LIST_OF_EBS_NON_ENC_VOLUMES ]];then
for volume in $LIST_OF_EBS_NON_ENC_VOLUMES; do
textFail "$regx: $volume is not encrypted!" "$regx" "$volume"
diff --git a/checks/check_extra73 b/checks/check_extra73
index 6bb99f69..621ab43e 100644
--- a/checks/check_extra73
+++ b/checks/check_extra73
@@ -48,7 +48,7 @@ extra73(){
#
ACCOUNT_PUBLIC_ACCESS_BLOCK=$($AWSCLI s3control get-public-access-block $PROFILE_OPT --region $REGION --account-id $ACCOUNT_NUM --output json 2>&1)
if [[ $(echo "$ACCOUNT_PUBLIC_ACCESS_BLOCK" | grep AccessDenied) ]]; then
- textFail "$REGION: Access Denied getting PublicAccessBlock configuration for AWS account" "$REGION" "$bucket"
+ textInfo "$REGION: Access Denied getting PublicAccessBlock configuration for AWS account" "$REGION" "$bucket"
return
fi
if [[ $(echo "$ACCOUNT_PUBLIC_ACCESS_BLOCK" | grep NoSuchPublicAccessBlockConfiguration) ]]; then
@@ -68,7 +68,7 @@ extra73(){
#
ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' $PROFILE_OPT --output text 2>&1)
if [[ $(echo "$ALL_BUCKETS_LIST" | grep AccessDenied) ]]; then
- textFail "$REGION: Access Denied Trying to List Buckets" "$REGION" "$bucket"
+ textInfo "$REGION: Access Denied Trying to List Buckets" "$REGION" "$bucket"
return
fi
if [[ "$ALL_BUCKETS_LIST" == "" ]]; then
@@ -85,7 +85,7 @@ extra73(){
#
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $REGION --bucket $bucket --output text 2>&1)
if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then
- textFail "$REGION: Access Denied Trying to Get Bucket Location for $bucket" "$REGION" "$bucket"
+ textInfo "$REGION: Access Denied Trying to Get Bucket Location for $bucket" "$REGION" "$bucket"
continue
fi
if [[ $BUCKET_LOCATION == "None" ]]; then
@@ -99,7 +99,7 @@ extra73(){
#
BUCKET_PUBLIC_ACCESS_BLOCK=$($AWSCLI s3api get-public-access-block $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --output json 2>&1)
if [[ $(echo "$BUCKET_PUBLIC_ACCESS_BLOCK" | grep AccessDenied) ]]; then
- textFail "$BUCKET_LOCATION: Access Denied Trying to Get Public Access Block for $bucket" "$BUCKET_LOCATION" "$bucket"
+ textInfo "$BUCKET_LOCATION: Access Denied Trying to Get Public Access Block for $bucket" "$BUCKET_LOCATION" "$bucket"
continue
fi
if [[ $(echo "$BUCKET_PUBLIC_ACCESS_BLOCK" | grep NoSuchPublicAccessBlockConfiguration) ]]; then
@@ -119,7 +119,7 @@ extra73(){
#
BUCKET_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --output json 2>&1)
if [[ $(echo "$BUCKET_ACL" | grep AccessDenied) ]]; then
- textFail "$BUCKET_LOCATION: Access Denied Trying to Get Bucket Acl for $bucket" "$BUCKET_LOCATION" "$bucket"
+ textInfo "$BUCKET_LOCATION: Access Denied Trying to Get Bucket Acl for $bucket" "$BUCKET_LOCATION" "$bucket"
continue
fi
@@ -140,7 +140,7 @@ extra73(){
#
BUCKET_POLICY_STATUS=$($AWSCLI s3api get-bucket-policy-status $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query PolicyStatus.IsPublic --output text 2>&1)
if [[ $(echo "$BUCKET_POLICY_STATUS" | grep AccessDenied) ]]; then
- textFail "$BUCKET_LOCATION: Access Denied Trying to Get Bucket Policy Status for $bucket" "$BUCKET_LOCATION" "$bucket"
+ textInfo "$BUCKET_LOCATION: Access Denied Trying to Get Bucket Policy Status for $bucket" "$BUCKET_LOCATION" "$bucket"
continue
fi
if [[ $(echo "$BUCKET_POLICY_STATUS" | grep NoSuchBucketPolicy) ]]; then
diff --git a/checks/check_extra731 b/checks/check_extra731
index a22d8492..fabb05eb 100644
--- a/checks/check_extra731
+++ b/checks/check_extra731
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra731='Infrastructure Security'
extra731(){
for regx in $REGIONS; do
- LIST_SNS=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --query Topics --output text |grep -v ^None)
+ LIST_SNS=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --query Topics --output text 2>&1|grep -v ^None )
+ if [[ $(echo "$LIST_SNS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list topics" "$regx"
+ continue
+ fi
if [[ $LIST_SNS ]]; then
for topic in $LIST_SNS; do
SHORT_TOPIC=$(echo $topic| cut -d: -f6)
@@ -39,7 +43,7 @@ extra731(){
if [[ $SNS_POLICY_ALLOW_ALL_WITHOUT_CONDITION ]]; then
SNS_POLICY_ALLOW_ALL_WITHOUT_CONDITION_DETAILS=$(echo $SNS_POLICY_ALLOW_ALL_WITHOUT_CONDITION \
| jq '"[Principal: " + (.Principal|tostring) + " Action: " + (.Action|tostring) + "]"' )
- textFail "$regx: SNS topic $SHORT_TOPIC's policy with public access: $SNS_POLICY_ALLOW_ALL_WITHOUT_CONDITION_DETAILS" "$regx" "$SHORT_TOPIC"
+ textFail "$regx: SNS topic $SHORT_TOPIC's policy with public access" "$regx" "$SHORT_TOPIC"
else
textPass "$regx: SNS topic $SHORT_TOPIC's policy with public access but has a Condition" "$regx" "$SHORT_TOPIC"
fi
diff --git a/checks/check_extra734 b/checks/check_extra734
index 08646604..d9cacfe5 100644
--- a/checks/check_extra734
+++ b/checks/check_extra734
@@ -30,7 +30,7 @@ extra734(){
for bucket in $LIST_OF_BUCKETS;do
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $REGION --bucket $bucket --output text 2>&1)
if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then
- textFail "$BUCKET_LOCATION Access Denied Trying to Get Bucket Location for $bucket" "$BUCKET_LOCATION" "$bucket"
+ textInfo "$BUCKET_LOCATION: Access Denied Trying to Get Bucket Location for $bucket" "$BUCKET_LOCATION" "$bucket"
continue
fi
if [[ $BUCKET_LOCATION == "None" ]]; then
@@ -46,7 +46,7 @@ extra734(){
# query to get if has encryption enabled or not
RESULT=$($AWSCLI s3api get-bucket-encryption $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query ServerSideEncryptionConfiguration.Rules[].ApplyServerSideEncryptionByDefault[].SSEAlgorithm --output text 2>&1)
if [[ $(echo "$RESULT" | grep AccessDenied) ]]; then
- textFail "$BUCKET_LOCATION: Access Denied Trying to Get Encryption for $bucket" "$BUCKET_LOCATION" "$bucket"
+ textInfo "$BUCKET_LOCATION: Access Denied Trying to Get Encryption for $bucket" "$BUCKET_LOCATION" "$bucket"
continue
fi
@@ -61,7 +61,7 @@ extra734(){
# get bucket policy
$AWSCLI s3api get-bucket-policy $PROFILE_OPT --bucket $bucket --region $BUCKET_LOCATION --output text --query Policy > $TEMP_SSE_POLICY_FILE 2>&1
if [[ $(grep AccessDenied $TEMP_SSE_POLICY_FILE) ]]; then
- textFail "$BUCKET_LOCATION: Access Denied Trying to Get Bucket Policy for $bucket" "$BUCKET_LOCATION" "$bucket"
+ textInfo "$BUCKET_LOCATION: Access Denied Trying to Get Bucket Policy for $bucket" "$BUCKET_LOCATION" "$bucket"
rm -f $TEMP_SSE_POLICY_FILE
continue
fi
diff --git a/checks/check_extra735 b/checks/check_extra735
index 6b86cc52..1ce59e60 100644
--- a/checks/check_extra735
+++ b/checks/check_extra735
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra735='Data Protection'
extra735(){
for regx in $REGIONS; do
- LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].DBInstanceIdentifier' --output text)
+ LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].DBInstanceIdentifier' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_RDS_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe DB instances" "$regx"
+ continue
+ fi
if [[ $LIST_OF_RDS_INSTANCES ]];then
for rdsinstance in $LIST_OF_RDS_INSTANCES; do
IS_ENCRYPTED=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --db-instance-identifier $rdsinstance --query 'DBInstances[*].StorageEncrypted' --output text)
diff --git a/checks/check_extra739 b/checks/check_extra739
index 2f998df0..06a67723 100644
--- a/checks/check_extra739
+++ b/checks/check_extra739
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra739='Data Protection'
extra739(){
for regx in $REGIONS; do
- LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].DBInstanceIdentifier' --output text)
+ LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].DBInstanceIdentifier' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_RDS_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe DB instances" "$regx"
+ continue
+ fi
if [[ $LIST_OF_RDS_INSTANCES ]];then
for rdsinstance in $LIST_OF_RDS_INSTANCES; do
# if retention is 0 then is disabled
diff --git a/checks/check_extra74 b/checks/check_extra74
index 2c57b776..50ed2aa8 100644
--- a/checks/check_extra74
+++ b/checks/check_extra74
@@ -29,7 +29,11 @@ CHECK_CAF_EPIC_extra74='Infrastructure Security'
extra74(){
# "Ensure there are no Security Groups without ingress filtering being used "
for regx in $REGIONS; do
- LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS)
+ LIST_OF_SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" --query "SecurityGroups[].[GroupId]" --output text --max-items $MAXITEMS 2>&1)
+ if [[ $(echo "$LIST_OF_SECURITYGROUPS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
for SG_ID in $LIST_OF_SECURITYGROUPS; do
SG_NO_INGRESS_FILTER=$($AWSCLI ec2 describe-network-interfaces $PROFILE_OPT --region $regx --filters "Name=group-id,Values=$SG_ID" --query "length(NetworkInterfaces)" --output text)
if [[ $SG_NO_INGRESS_FILTER -ne 0 ]];then
diff --git a/checks/check_extra740 b/checks/check_extra740
index d939a305..9b388512 100644
--- a/checks/check_extra740
+++ b/checks/check_extra740
@@ -31,12 +31,21 @@ extra740(){
for regx in ${REGIONS}; do
UNENCRYPTED_SNAPSHOTS=$(${AWSCLI} ec2 describe-snapshots ${PROFILE_OPT} \
--region ${regx} --owner-ids ${ACCOUNT_NUM} --output text \
- --query 'Snapshots[?Encrypted==`false`]|[*].{Id:SnapshotId}' \
- | grep -v None 2> /dev/null)
+ --query 'Snapshots[?Encrypted==`false`]|[*].{Id:SnapshotId}' 2>&1 \
+ | grep -v None )
+ if [[ $(echo "$UNENCRYPTED_SNAPSHOTS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe snapshots" "$regx"
+ continue
+ fi
+
ENCRYPTED_SNAPSHOTS=$(${AWSCLI} ec2 describe-snapshots ${PROFILE_OPT} \
--region ${regx} --owner-ids ${ACCOUNT_NUM} --output text \
- --query 'Snapshots[?Encrypted==`true`]|[*].{Id:SnapshotId}' \
- | grep -v None 2> /dev/null)
+ --query 'Snapshots[?Encrypted==`true`]|[*].{Id:SnapshotId}' 2>&1 \
+ | grep -v None )
+ if [[ $(echo "$ENCRYPTED_SNAPSHOTS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe snapshots" "$regx"
+ continue
+ fi
typeset -i unencrypted
typeset -i encrypted
unencrypted=0
diff --git a/checks/check_extra741 b/checks/check_extra741
index 8a7d87e4..5f34a871 100644
--- a/checks/check_extra741
+++ b/checks/check_extra741
@@ -31,7 +31,11 @@ extra741(){
fi
for regx in $REGIONS; do
- LIST_OF_EC2_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query Reservations[*].Instances[*].InstanceId --output text --max-items $MAXITEMS | grep -v None)
+ LIST_OF_EC2_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query Reservations[*].Instances[*].InstanceId --output text --max-items $MAXITEMS 2>&1| grep -v None)
+ if [[ $(echo "$LIST_OF_EC2_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe instances" "$regx"
+ continue
+ fi
if [[ $LIST_OF_EC2_INSTANCES ]];then
for instance in $LIST_OF_EC2_INSTANCES; do
EC2_USERDATA_FILE="$SECRETS_TEMP_FOLDER/extra741-$instance-userData.decoded"
diff --git a/checks/check_extra742 b/checks/check_extra742
index 6933c1af..edeaaa9c 100644
--- a/checks/check_extra742
+++ b/checks/check_extra742
@@ -31,7 +31,11 @@ extra742(){
fi
for regx in $REGIONS; do
- CFN_STACKS=$($AWSCLI cloudformation describe-stacks $PROFILE_OPT --region $regx --output json)
+ CFN_STACKS=$($AWSCLI cloudformation describe-stacks $PROFILE_OPT --region $regx --output json 2>&1)
+ if [[ $(echo "$CFN_STACKS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe stacks" "$regx"
+ continue
+ fi
LIST_OF_CFN_STACKS=$(echo $CFN_STACKS | jq -r '.Stacks[].StackName')
if [[ $LIST_OF_CFN_STACKS ]];then
for stack in $LIST_OF_CFN_STACKS; do
diff --git a/checks/check_extra743 b/checks/check_extra743
index b7112cf9..abc15f09 100644
--- a/checks/check_extra743
+++ b/checks/check_extra743
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra743='Data Protection'
extra743(){
for regx in $REGIONS; do
- LIST_OF_REST_APIS=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-apis --query 'items[*].id' --output text)
+ LIST_OF_REST_APIS=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-apis --query 'items[*].id' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_REST_APIS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get rest APIs" "$regx"
+ continue
+ fi
if [[ $LIST_OF_REST_APIS ]];then
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)
diff --git a/checks/check_extra744 b/checks/check_extra744
index a8672c94..e7dcd10e 100644
--- a/checks/check_extra744
+++ b/checks/check_extra744
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra744='Infrastructure Security'
extra744(){
for regx in $REGIONS; do
- LIST_OF_REST_APIS=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-apis --query 'items[*].id' --output text)
+ LIST_OF_REST_APIS=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-apis --query 'items[*].id' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_REST_APIS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get rest APIs" "$regx"
+ continue
+ fi
if [[ $LIST_OF_REST_APIS ]];then
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)
diff --git a/checks/check_extra745 b/checks/check_extra745
index 37cb6b17..f6e6fe8b 100644
--- a/checks/check_extra745
+++ b/checks/check_extra745
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra745='Infrastructure Security'
extra745(){
for regx in $REGIONS; do
- LIST_OF_REST_APIS=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-apis --query 'items[*].id' --output text)
+ LIST_OF_REST_APIS=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-apis --query 'items[*].id' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_REST_APIS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get rest APIs" "$regx"
+ continue
+ fi
if [[ $LIST_OF_REST_APIS ]];then
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)
diff --git a/checks/check_extra746 b/checks/check_extra746
index e2ff570a..d5b6512b 100644
--- a/checks/check_extra746
+++ b/checks/check_extra746
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra746='IAM'
extra746(){
for regx in $REGIONS; do
- LIST_OF_REST_APIS=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-apis --query 'items[*].id' --output text)
+ LIST_OF_REST_APIS=$($AWSCLI $PROFILE_OPT --region $regx apigateway get-rest-apis --query 'items[*].id' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_REST_APIS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get rest APIs" "$regx"
+ continue
+ fi
if [[ $LIST_OF_REST_APIS ]];then
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)
diff --git a/checks/check_extra747 b/checks/check_extra747
index 80cedad3..ade2b32f 100644
--- a/checks/check_extra747
+++ b/checks/check_extra747
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra747='Logging and Monitoring'
extra747(){
for regx in $REGIONS; do
- LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].DBInstanceIdentifier' --output text)
+ LIST_OF_RDS_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[*].DBInstanceIdentifier' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_RDS_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to get rest APIs" "$regx"
+ continue
+ fi
if [[ $LIST_OF_RDS_INSTANCES ]];then
for rdsinstance in $LIST_OF_RDS_INSTANCES; do
# if retention is 0 then is disabled
diff --git a/checks/check_extra748 b/checks/check_extra748
index 49c10e76..f9a62174 100644
--- a/checks/check_extra748
+++ b/checks/check_extra748
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra748='Infrastructure Security'
extra748(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`0` && ToPort==`65535`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort==`0` && ToPort==`65535`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0" "$regx" "$SG"
diff --git a/checks/check_extra749 b/checks/check_extra749
index 28dbaf46..4f2ee184 100644
--- a/checks/check_extra749
+++ b/checks/check_extra749
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra749='Infrastructure Security'
extra749(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || ((FromPort<=`1521` && ToPort>=`1521`)||(FromPort<=`2483` && ToPort>=`2483`))) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || ((FromPort<=`1521` && ToPort>=`1521`)||(FromPort<=`2483` && ToPort>=`2483`))) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for Oracle ports" "$regx" "$SG"
diff --git a/checks/check_extra75 b/checks/check_extra75
index 8d24a414..d4abe391 100644
--- a/checks/check_extra75
+++ b/checks/check_extra75
@@ -29,12 +29,15 @@ CHECK_CAF_EPIC_extra75='Infrastructure Security'
extra75(){
# "Ensure there are no Security Groups not being used "
for regx in $REGIONS; do
- SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --max-items $MAXITEMS --output json | jq '.SecurityGroups|map({(.GroupId): (.GroupName)})|add')
- if [[ $SECURITYGROUPS == "null" ]];
- then
+ SECURITYGROUPS=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --max-items $MAXITEMS --output json 2>&1 )
+ if [[ $(echo "$SECURITYGROUPS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
+ if [[ $SECURITYGROUPS == "null" ]]; then
continue
fi
- LIST_OF_SECURITYGROUPS=$(echo $SECURITYGROUPS|jq -r 'to_entries|sort_by(.key)|.[]|.key')
+ LIST_OF_SECURITYGROUPS=$(echo $SECURITYGROUPS | jq '.SecurityGroups|map({(.GroupId): (.GroupName)})|add' |jq -r 'to_entries|sort_by(.key)|.[]|.key')
for SG_ID in $LIST_OF_SECURITYGROUPS; do
SG_NOT_USED=$($AWSCLI ec2 describe-network-interfaces $PROFILE_OPT --region $regx --filters "Name=group-id,Values=$SG_ID" --query "length(NetworkInterfaces)" --output text)
# Default security groups can not be deleted, so draw attention to them
diff --git a/checks/check_extra750 b/checks/check_extra750
index 1f0f30c5..14e1f003 100644
--- a/checks/check_extra750
+++ b/checks/check_extra750
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra750='Infrastructure Security'
extra750(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`3306` && ToPort>=`3306`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`3306` && ToPort>=`3306`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for MySQL port" "$regx" "$SG"
diff --git a/checks/check_extra751 b/checks/check_extra751
index 2b31dd91..4eec1a02 100644
--- a/checks/check_extra751
+++ b/checks/check_extra751
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra751='Infrastructure Security'
extra751(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`5432` && ToPort>=`5432`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`5432` && ToPort>=`5432`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for Postgres port" "$regx" "$SG"
diff --git a/checks/check_extra752 b/checks/check_extra752
index d60d32f2..4b74116a 100644
--- a/checks/check_extra752
+++ b/checks/check_extra752
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra752='Infrastructure Security'
extra752(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`6379` && ToPort>=`6379`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`6379` && ToPort>=`6379`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for Redis port" "$regx" "$SG"
diff --git a/checks/check_extra753 b/checks/check_extra753
index bd11d24b..8ee93c6b 100644
--- a/checks/check_extra753
+++ b/checks/check_extra753
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra753='Infrastructure Security'
extra753(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || ((FromPort<=`27017` && ToPort>=`27017`) || (FromPort<=`27018` && ToPort>=`27018`))) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || ((FromPort<=`27017` && ToPort>=`27017`) || (FromPort<=`27018` && ToPort>=`27018`))) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for MongoDB ports" "$regx" "$SG"
diff --git a/checks/check_extra754 b/checks/check_extra754
index a2252297..ef89bcf8 100644
--- a/checks/check_extra754
+++ b/checks/check_extra754
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra754='Infrastructure Security'
extra754(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || ((FromPort<=`7199` && ToPort>=`7199`) || (FromPort<=`9160` && ToPort>=`9160`)|| (FromPort<=`8888` && ToPort>=`8888`))) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || ((FromPort<=`7199` && ToPort>=`7199`) || (FromPort<=`9160` && ToPort>=`9160`)|| (FromPort<=`8888` && ToPort>=`8888`))) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for Cassandra ports" "$regx" "$SG"
diff --git a/checks/check_extra755 b/checks/check_extra755
index 53ab014b..a766b033 100644
--- a/checks/check_extra755
+++ b/checks/check_extra755
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra755='Infrastructure Security'
extra755(){
for regx in $REGIONS; do
- SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`11211` && ToPort>=`11211`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
+ SG_LIST=$($AWSCLI ec2 describe-security-groups --query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`11211` && ToPort>=`11211`)) && (contains(IpRanges[].CidrIp, `0.0.0.0/0`) || contains(Ipv6Ranges[].CidrIpv6, `::/0`))]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
if [[ $SG_LIST ]];then
for SG in $SG_LIST;do
textFail "$regx: Found Security Group: $SG open to 0.0.0.0/0 for Memcached port" "$regx" "$SG"
diff --git a/checks/check_extra757 b/checks/check_extra757
index dc603afe..55dc81b5 100644
--- a/checks/check_extra757
+++ b/checks/check_extra757
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra757='Infrastructure Security'
extra757(){
OLDAGE="$(get_date_previous_than_months 6)"
for regx in $REGIONS; do
- EC2_RUNNING="$($AWSCLI ec2 describe-instances --query "Reservations[*].Instances[*].[InstanceId]" $PROFILE_OPT --region $regx --output text)"
+ EC2_RUNNING=$($AWSCLI ec2 describe-instances --query "Reservations[*].Instances[*].[InstanceId]" $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$EC2_RUNNING" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe instances" "$regx"
+ continue
+ fi
if [[ $EC2_RUNNING ]]; then
INSTACES_OLD_THAN_AGE=$($AWSCLI ec2 describe-instances --query "Reservations[].Instances[?LaunchTime<='$OLDAGE'][].{id: InstanceId, launched: LaunchTime}" $PROFILE_OPT --region $regx --output text)
if [[ $INSTACES_OLD_THAN_AGE ]]; then
diff --git a/checks/check_extra758 b/checks/check_extra758
index 63129eb3..dd07a60a 100644
--- a/checks/check_extra758
+++ b/checks/check_extra758
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra758='Infrastructure Security'
extra758(){
OLDAGE="$(get_date_previous_than_months 12)"
for regx in $REGIONS; do
- EC2_RUNNING="$($AWSCLI ec2 describe-instances --query "Reservations[*].Instances[*].[InstanceId]" $PROFILE_OPT --region $regx --output text)"
+ EC2_RUNNING=$($AWSCLI ec2 describe-instances --query "Reservations[*].Instances[*].[InstanceId]" $PROFILE_OPT --region $regx --output text 2>&1)
+ if [[ $(echo "$EC2_RUNNING" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe instances" "$regx"
+ continue
+ fi
if [[ $EC2_RUNNING ]]; then
INSTACES_OLD_THAN_AGE=$($AWSCLI ec2 describe-instances --query "Reservations[].Instances[?LaunchTime<='$OLDAGE'][].{id: InstanceId, launched: LaunchTime}" $PROFILE_OPT --region $regx --output text)
if [[ $INSTACES_OLD_THAN_AGE ]]; then
diff --git a/checks/check_extra759 b/checks/check_extra759
index 533f0445..d804095b 100644
--- a/checks/check_extra759
+++ b/checks/check_extra759
@@ -31,7 +31,11 @@ extra759(){
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 -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list functions" "$regx"
+ continue
+ fi
if [[ $LIST_OF_FUNCTIONS ]]; then
for lambdafunction in $LIST_OF_FUNCTIONS;do
LAMBDA_FUNCTION_VARIABLES_FILE="$SECRETS_TEMP_FOLDER/extra759-$lambdafunction-$regx-variables.txt"
diff --git a/checks/check_extra76 b/checks/check_extra76
index 3a5d7e54..e606b322 100644
--- a/checks/check_extra76
+++ b/checks/check_extra76
@@ -27,7 +27,11 @@ CHECK_CAF_EPIC_extra76='Infrastructure Security'
extra76(){
# "Ensure there are no EC2 AMIs set as Public "
for regx in $REGIONS; do
- LIST_OF_PUBLIC_AMIS=$($AWSCLI ec2 describe-images --owners self $PROFILE_OPT --region $regx --filters "Name=is-public,Values=true" --query 'Images[*].{ID:ImageId}' --output text)
+ LIST_OF_PUBLIC_AMIS=$($AWSCLI ec2 describe-images --owners self $PROFILE_OPT --region $regx --filters "Name=is-public,Values=true" --query 'Images[*].{ID:ImageId}' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_PUBLIC_AMIS" | grep -E 'AccessDenied|UnauthorizedOperation') ]]; then
+ textInfo "$regx: Access Denied trying to describe images" "$regx"
+ continue
+ fi
if [[ $LIST_OF_PUBLIC_AMIS ]];then
for ami in $LIST_OF_PUBLIC_AMIS; do
textFail "$regx: $ami is currently Public!" "$regx" "$ami"
diff --git a/checks/check_extra760 b/checks/check_extra760
index 143ab96e..1d031603 100644
--- a/checks/check_extra760
+++ b/checks/check_extra760
@@ -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
+ textInfo "$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"
diff --git a/checks/check_extra761 b/checks/check_extra761
index 7189b473..1e1d2211 100644
--- a/checks/check_extra761
+++ b/checks/check_extra761
@@ -25,16 +25,16 @@ CHECK_CAF_EPIC_extra761='Data Protection'
extra761(){
for regx in $REGIONS; do
- EBS_DEFAULT_ENCRYPTION=$($AWSCLI ec2 get-ebs-encryption-by-default $PROFILE_OPT --region $regx --query 'EbsEncryptionByDefault' 2>&1)
+ EBS_DEFAULT_ENCRYPTION=$($AWSCLI ec2 get-ebs-encryption-by-default $PROFILE_OPT --region $regx --query 'EbsEncryptionByDefault' --output text 2>&1)
if [[ $(echo "$EBS_DEFAULT_ENCRYPTION" | grep "argument operation: Invalid choice") ]]; then
- textFail "$regx: Newer aws cli needed for get-ebs-encryption-by-default" "$regx"
+ textInfo "$regx: Newer aws cli needed for get-ebs-encryption-by-default" "$regx"
continue
fi
if [[ $(echo "$EBS_DEFAULT_ENCRYPTION" | grep UnauthorizedOperation) ]]; then
- textFail "$regx: Prowler needs ec2:GetEbsEncryptionByDefault permission for this check" "$regx"
+ textInfo "$regx: Prowler needs ec2:GetEbsEncryptionByDefault permission for this check" "$regx"
continue
fi
- if [[ $EBS_DEFAULT_ENCRYPTION == "true" ]];then
+ if [[ $EBS_DEFAULT_ENCRYPTION == "True" ]];then
textPass "$regx: EBS Default Encryption is activated" "$regx"
else
textFail "$regx: EBS Default Encryption is not activated" "$regx"
diff --git a/checks/check_extra762 b/checks/check_extra762
index 28f6c2ab..dfa41438 100644
--- a/checks/check_extra762
+++ b/checks/check_extra762
@@ -18,7 +18,7 @@ CHECK_SEVERITY_extra762="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra762="AwsLambdaFunction"
CHECK_ALTERNATE_check762="extra762"
CHECK_SERVICENAME_extra762="lambda"
-CHECK_RISK_extra762=' If you have functions running on a runtime that will be deprecated in the next 60 days; Lambda notifies you by email that you should prepare by migrating your function to a supported runtime. In some cases; such as security issues that require a backwards-incompatible update; or software that does not support a long-term support (LTS) schedule; advance notice might not be possible. After a runtime is deprecated; Lambda might retire it completely at any time by disabling invocation. Deprecated runtimes are not eligible for security updates or technical support.'
+CHECK_RISK_extra762='If you have functions running on a runtime that will be deprecated in the next 60 days; Lambda notifies you by email that you should prepare by migrating your function to a supported runtime. In some cases; such as security issues that require a backwards-incompatible update; or software that does not support a long-term support (LTS) schedule; advance notice might not be possible. After a runtime is deprecated; Lambda might retire it completely at any time by disabling invocation. Deprecated runtimes are not eligible for security updates or technical support.'
CHECK_REMEDIATION_extra762='Test new runtimes as they are made available. Implement them in production as soon as possible.'
CHECK_DOC_extra762='https://docs.aws.amazon.com/lambda/latest/dg/runtime-support-policy.html'
CHECK_CAF_EPIC_extra762='Infrastructure Security'
@@ -30,7 +30,11 @@ extra762(){
OBSOLETE='%(nodejs4.3|nodejs4.3-edge|nodejs6.10|nodejs8.10|dotnetcore1.0|dotnetcore2.0)'
for regx in $REGIONS; do
- LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --output text --query 'Functions[*].{R:Runtime,N:FunctionName}' | tr "\t" "%")
+ LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --output text --query 'Functions[*].{R:Runtime,N:FunctionName}' 2>&1| tr "\t" "%" )
+ if [[ $(echo "$LIST_OF_FUNCTIONS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list functions" "$regx"
+ continue
+ fi
if [[ $LIST_OF_FUNCTIONS ]]; then
for lambdafunction in $LIST_OF_FUNCTIONS;do
fname=$(echo "$lambdafunction" | cut -d'%' -f1)
diff --git a/checks/check_extra763 b/checks/check_extra763
index 6cbf5b28..1c44c740 100644
--- a/checks/check_extra763
+++ b/checks/check_extra763
@@ -30,13 +30,13 @@ extra763(){
for bucket in $LIST_OF_BUCKETS;do
BUCKET_VERSIONING_ENABLED=$($AWSCLI s3api get-bucket-versioning --bucket $bucket $PROFILE_OPT --query Status --output text 2>&1)
if [[ $(echo "$BUCKET_VERSIONING_ENABLED" | grep AccessDenied) ]]; then
- textFail "Access Denied Trying to Get Bucket Versioning for $bucket"
+ textInfo "Access Denied Trying to Get Bucket Versioning for $bucket"
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
diff --git a/checks/check_extra764 b/checks/check_extra764
index ab84e553..e3b3a46a 100644
--- a/checks/check_extra764
+++ b/checks/check_extra764
@@ -32,7 +32,7 @@ extra764(){
TEMP_STP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX)
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $REGION --bucket $bucket --output text 2>&1)
if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then
- textFail "Access Denied Trying to Get Bucket Location for $bucket"
+ textInfo "Access Denied Trying to Get Bucket Location for $bucket"
continue
fi
if [[ $BUCKET_LOCATION == "None" ]]; then
@@ -44,7 +44,7 @@ extra764(){
# get bucket policy
$AWSCLI s3api get-bucket-policy $PROFILE_OPT --bucket $bucket --output text --query Policy --region $BUCKET_LOCATION > $TEMP_STP_POLICY_FILE 2>&1
if [[ $(grep AccessDenied $TEMP_STP_POLICY_FILE) ]]; then
- textFail "Access Denied Trying to Get Bucket Policy for $bucket"
+ textInfo "Access Denied Trying to Get Bucket Policy for $bucket"
rm -f $TEMP_STP_POLICY_FILE
continue
fi
diff --git a/checks/check_extra765 b/checks/check_extra765
index 34d417cd..91ac7883 100644
--- a/checks/check_extra765
+++ b/checks/check_extra765
@@ -36,7 +36,7 @@ extra765(){
for region in $REGIONS; do
LIST_ECR_REPOS=$($AWSCLI ecr describe-repositories $PROFILE_OPT --region $region --query "repositories[*].[repositoryName]" --output text 2>&1)
if [[ $(echo "$LIST_ECR_REPOS" | grep AccessDenied) ]]; then
- textFail "Access Denied Trying to describe ECR repositories"
+ textInfo "$region: Access Denied Trying to describe ECR repositories"
continue
fi
if [[ ! -z "$LIST_ECR_REPOS" ]]; then
@@ -50,7 +50,7 @@ extra765(){
textFail "$region: ECR repository $repo has scan on push disabled!" "$region" "$repo"
;;
"None")
- textInfo "$region: ECR repository $repo has no scanOnPush status, newer awscli needed" "$region" "$repo"
+ textInfo "$region: ECR repository $repo has no scanOnPush status: newer awscli needed" "$region" "$repo"
;;
"*")
textInfo "$region: ECR repository $repo has unknown scanOnPush status \"$SCAN_ENABLED\"" "$region" "$repo"
diff --git a/checks/check_extra768 b/checks/check_extra768
index 5e59c7b8..713530f5 100644
--- a/checks/check_extra768
+++ b/checks/check_extra768
@@ -30,9 +30,13 @@ extra768(){
fi
for regx in $REGIONS; do
# Get a list of all task definition families first:
- FAMILIES=$($AWSCLI ecs list-task-definition-families $PROFILE_OPT --region $regx --status ACTIVE | jq -r .families[])
- if [[ $FAMILIES ]]; then
- for FAMILY in $FAMILIES;do
+ FAMILIES=$($AWSCLI ecs list-task-definition-families $PROFILE_OPT --region $regx --status ACTIVE 2>&1 )
+ if [[ $(echo "$FAMILIES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list task definition families" "$regx"
+ continue
+ fi
+ if [[ $(echo $FAMILIES | jq -r .families[]) ]]; then
+ for FAMILY in $(echo $FAMILIES | jq -r .families[]);do
# Get the full task definition arn:
TASK_DEFINITION_TEMP=$($AWSCLI ecs list-task-definitions $PROFILE_OPT --region $regx --family-prefix $FAMILY --sort DESC --max-items 1 | jq -r .taskDefinitionArns[0])
# We only care about the task definition name:
diff --git a/checks/check_extra769 b/checks/check_extra769
index 6127c646..48c37e53 100644
--- a/checks/check_extra769
+++ b/checks/check_extra769
@@ -27,11 +27,11 @@ extra769(){
for regx in $REGIONS; do
LIST_OF_ACCESS_ANALYZERS=$($AWSCLI accessanalyzer list-analyzers $PROFILE_OPT --region $regx --query analyzers[*].arn --output text 2>&1)
if [[ $(echo "$LIST_OF_ACCESS_ANALYZERS" | grep -i "argument command: Invalid choice") ]]; then
- textInfo "$regx: list-analyzers not supported, newer awscli needed" "$regx"
+ textInfo "$regx: list-analyzers not supported: newer awscli needed" "$regx"
continue
fi
if [[ $(echo "$LIST_OF_ACCESS_ANALYZERS" | grep -i "AccessDeniedException") ]]; then
- textFail "$regx: Access Denied trying to list-analyzers" "$regx"
+ textInfo "$regx: Access Denied trying to list-analyzers" "$regx"
continue
fi
if [[ $LIST_OF_ACCESS_ANALYZERS ]]; then
diff --git a/checks/check_extra77 b/checks/check_extra77
index fcbbd977..4971d243 100644
--- a/checks/check_extra77
+++ b/checks/check_extra77
@@ -30,11 +30,11 @@ extra77(){
for regx in $REGIONS; do
LIST_ECR_REPOS=$($AWSCLI ecr describe-repositories $PROFILE_OPT --region $regx --query "repositories[*].[repositoryName]" --output text 2>&1)
if [[ $(echo "$LIST_ECR_REPOS" | grep AccessDenied) ]]; then
- textFail "$regx: Access Denied Trying to describe ECR repositories" "$regx" "$repo"
+ textInfo "$regx: Access Denied Trying to describe ECR repositories" "$regx" "$repo"
continue
fi
if [[ $(echo "$LIST_ECR_REPOS" | grep SubscriptionRequiredException) ]]; then
- textFail "$regx: Subscription Required Exception trying to describe ECR repositories" "$regx" "$repo"
+ textInfo "$regx: Subscription Required Exception trying to describe ECR repositories" "$regx" "$repo"
continue
fi
if [[ ! -z "$LIST_ECR_REPOS" ]]; then
@@ -42,7 +42,7 @@ extra77(){
TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-ecr-repo.policy.XXXXXXXXXX)
$AWSCLI ecr get-repository-policy $PROFILE_OPT --region $regx --repository-name $repo --query "policyText" --output text > $TEMP_POLICY_FILE 2>&1
if [[ $(grep AccessDenied $TEMP_POLICY_FILE) ]]; then
- textFail "$regx: $repo Access Denied for get-repository-policy" "$regx" "$repo"
+ textInfo "$regx: Access Denied to get repository policy for repo $repo" "$regx" "$repo"
rm -f $TEMP_POLICY_FILE
continue
fi
diff --git a/checks/check_extra770 b/checks/check_extra770
index e2c3abf7..6975c22f 100644
--- a/checks/check_extra770
+++ b/checks/check_extra770
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra770='Infrastructure Security'
extra770(){
# "Check for internet facing EC2 Instances "
for regx in $REGIONS; do
- LIST_OF_PUBLIC_INSTANCES_WITH_INSTANCE_PROFILES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?((IamInstanceProfile!=`null` && PublicIpAddress!=`null`))].[InstanceId,PublicIpAddress,IamInstanceProfile.Arn]' --output text)
+ LIST_OF_PUBLIC_INSTANCES_WITH_INSTANCE_PROFILES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx --query 'Reservations[*].Instances[?((IamInstanceProfile!=`null` && PublicIpAddress!=`null`))].[InstanceId,PublicIpAddress,IamInstanceProfile.Arn]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_PUBLIC_INSTANCES_WITH_INSTANCE_PROFILES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe instances" "$regx"
+ continue
+ fi
if [[ $LIST_OF_PUBLIC_INSTANCES_WITH_INSTANCE_PROFILES ]];then
while read -r instance;do
INSTANCE_ID=$(echo $instance | awk '{ print $1; }')
diff --git a/checks/check_extra772 b/checks/check_extra772
index c56a7c32..560cc1ad 100644
--- a/checks/check_extra772
+++ b/checks/check_extra772
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra772='Infrastructure Security'
extra772(){
for region in $REGIONS; do
- EIP_DUMP=$($AWSCLI ec2 describe-addresses ${PROFILE_OPT} --region $region --output json)
+ EIP_DUMP=$($AWSCLI ec2 describe-addresses ${PROFILE_OPT} --region $region --output json 2>&1)
+ if [[ $(echo "$EIP_DUMP" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe addresses" "$regx"
+ continue
+ fi
EIP_LIST=$(echo $EIP_DUMP | jq -r '.Addresses[].AllocationId')
if [[ $EIP_LIST ]]; then
for eip in $EIP_LIST; do
diff --git a/checks/check_extra775 b/checks/check_extra775
index bc47823f..7b6f5f53 100644
--- a/checks/check_extra775
+++ b/checks/check_extra775
@@ -30,7 +30,11 @@ extra775(){
fi
for regx in $REGIONS; do
- LIST_OF_EC2_AUTOSCALING=$($AWSCLI autoscaling describe-launch-configurations $PROFILE_OPT --region $regx --query LaunchConfigurations[*].LaunchConfigurationName --output text --max-items $MAXITEMS | grep -v None)
+ LIST_OF_EC2_AUTOSCALING=$($AWSCLI autoscaling describe-launch-configurations $PROFILE_OPT --region $regx --query LaunchConfigurations[*].LaunchConfigurationName --output text --max-items $MAXITEMS 2>&1 | grep -v None )
+ if [[ $(echo "$LIST_OF_EC2_AUTOSCALING" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe launch configurations" "$regx"
+ continue
+ fi
if [[ $LIST_OF_EC2_AUTOSCALING ]];then
for autoscaling_configuration in $LIST_OF_EC2_AUTOSCALING; do
EC2_AUTOSCALING_USERDATA_FILE="$SECRETS_TEMP_FOLDER/extra775-$autoscaling_configuration-userData.decoded"
diff --git a/checks/check_extra776 b/checks/check_extra776
index 9212d084..36fc793d 100644
--- a/checks/check_extra776
+++ b/checks/check_extra776
@@ -42,7 +42,7 @@ extra776(){
for region in $REGIONS; do
LIST_ECR_REPOS=$($AWSCLI ecr describe-repositories $PROFILE_OPT --region $region --query "repositories[*].[repositoryName]" --output text 2>&1)
if [[ $(echo "$LIST_ECR_REPOS" | grep AccessDenied) ]]; then
- textFail "Access Denied Trying to describe ECR repositories"
+ textInfo "$region: Access Denied trying to describe ECR repositories"
continue
fi
if [[ ! -z "$LIST_ECR_REPOS" ]]; then
diff --git a/checks/check_extra777 b/checks/check_extra777
index 4cfc026a..b7d459df 100644
--- a/checks/check_extra777
+++ b/checks/check_extra777
@@ -15,7 +15,7 @@
# 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 "
+CHECK_TITLE_extra777="[extra777] Find VPC security groups with more than 50 ingress or egress rules "
CHECK_SCORED_extra777="NOT_SCORED"
CHECK_CIS_LEVEL_extra777="EXTRA"
CHECK_SEVERITY_extra777="Medium"
@@ -35,8 +35,11 @@ extra777(){
${PROFILE_OPT} \
--region ${regx} \
--query 'SecurityGroups[*].GroupId' \
- --output text | xargs
- )
+ --output text 2>&1| xargs )
+ if [[ $(echo "$SECURITY_GROUP_IDS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
for SECURITY_GROUP in ${SECURITY_GROUP_IDS}; do
@@ -58,6 +61,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}" "${SECURITY_GROUP}"
+ else
+ textPass "${regx}: ${SECURITY_GROUP} has ${INGRESS_TOTAL} inbound rules and ${EGRESS_TOTAL} outbound rules" "${regx}" "${SECURITY_GROUP}"
fi
done
done
diff --git a/checks/check_extra778 b/checks/check_extra778
index 0966ee74..c1771752 100644
--- a/checks/check_extra778
+++ b/checks/check_extra778
@@ -48,8 +48,11 @@ extra778(){
--filter "Name=group-id,Values=${SECURITY_GROUP}" \
--query "SecurityGroups[*].${DIRECTION_FILTER}[*].IpRanges[*].CidrIp" \
--region ${REGION} \
- --output text | xargs
- )
+ --output text 2>&1| xargs )
+ if [[ $(echo "$CIDR_IP_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
for CIDR_IP in ${CIDR_IP_LIST}; do
if [[ ! ${CIDR_IP} =~ ${RFC1918_REGEX} ]]; then
@@ -58,6 +61,8 @@ extra778(){
# 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}" "${SECURITY_GROUP}"
+ else
+ textPass "${REGION}: ${SECURITY_GROUP} has no potential wide-open non-RFC1918 address" "${REGION}" "${SECURITY_GROUP}"
fi
fi
done
@@ -68,8 +73,11 @@ extra778(){
${PROFILE_OPT} \
--region ${regx} \
--query 'SecurityGroups[*].GroupId' \
- --output text | xargs
- )
+ --output text 2>&1| xargs )
+ if [[ $(echo "$SECURITY_GROUP_IDS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
for SECURITY_GROUP in ${SECURITY_GROUP_IDS}; do
check_cidr "${SECURITY_GROUP}" "inbound" "${regx}"
check_cidr "${SECURITY_GROUP}" "outbound" "${regx}"
diff --git a/checks/check_extra779 b/checks/check_extra779
index ccb95abe..c835eb4c 100644
--- a/checks/check_extra779
+++ b/checks/check_extra779
@@ -31,7 +31,11 @@ extra779(){
for regx in $REGIONS; do
# crate a list of SG open to the world with port $ES_API_PORT or $ES_DATA_PORT or $ES_KIBANA_PORT
SG_LIST=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --output text \
- --query "SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=\`$ES_API_PORT\` && ToPort>=\`$ES_API_PORT\`) || (FromPort<=\`$ES_DATA_PORT\` && ToPort>=\`$ES_DATA_PORT\`) || (FromPort<=\`$ES_KIBANA_PORT\` && ToPort>=\`$ES_KIBANA_PORT\`)) && (contains(IpRanges[].CidrIp, \`0.0.0.0/0\`) || contains(Ipv6Ranges[].CidrIpv6, \`::/0\`))]) > \`0\`].{GroupId:GroupId}")
+ --query "SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=\`$ES_API_PORT\` && ToPort>=\`$ES_API_PORT\`) || (FromPort<=\`$ES_DATA_PORT\` && ToPort>=\`$ES_DATA_PORT\`) || (FromPort<=\`$ES_KIBANA_PORT\` && ToPort>=\`$ES_KIBANA_PORT\`)) && (contains(IpRanges[].CidrIp, \`0.0.0.0/0\`) || contains(Ipv6Ranges[].CidrIpv6, \`::/0\`))]) > \`0\`].{GroupId:GroupId}" 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
# in case of open security groups goes through each one
if [[ $SG_LIST ]];then
for sg in $SG_LIST;do
diff --git a/checks/check_extra78 b/checks/check_extra78
index bc32dc1c..ad8ec1bb 100644
--- a/checks/check_extra78
+++ b/checks/check_extra78
@@ -28,7 +28,11 @@ CHECK_CAF_EPIC_extra78='Data Protection'
extra78(){
# "Ensure there are no Public Accessible RDS instances "
for regx in $REGIONS; do
- LIST_OF_RDS_PUBLIC_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[?PubliclyAccessible==`true` && DBInstanceStatus==`"available"`].[DBInstanceIdentifier,Endpoint.Address]' --output text)
+ LIST_OF_RDS_PUBLIC_INSTANCES=$($AWSCLI rds describe-db-instances $PROFILE_OPT --region $regx --query 'DBInstances[?PubliclyAccessible==`true` && DBInstanceStatus==`"available"`].[DBInstanceIdentifier,Endpoint.Address]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_RDS_PUBLIC_INSTANCES" | grep AccessDenied) ]]; then
+ textInfo "$regx: Access Denied Trying to describe DB instances" "$regx"
+ continue
+ fi
if [[ $LIST_OF_RDS_PUBLIC_INSTANCES ]];then
while read -r rds_instance;do
RDS_NAME=$(echo $rds_instance | awk '{ print $1; }')
diff --git a/checks/check_extra780 b/checks/check_extra780
index d835d626..7cd183b3 100644
--- a/checks/check_extra780
+++ b/checks/check_extra780
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra780='IAM'
extra780(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
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)
diff --git a/checks/check_extra781 b/checks/check_extra781
index 38a4899a..55bb4748 100644
--- a/checks/check_extra781
+++ b/checks/check_extra781
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra781='Data Protection'
extra781(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
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)
diff --git a/checks/check_extra782 b/checks/check_extra782
index f6babb04..78afc60e 100644
--- a/checks/check_extra782
+++ b/checks/check_extra782
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra782='Data Protection'
extra782(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
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)
diff --git a/checks/check_extra783 b/checks/check_extra783
index ec8005e2..56d942c2 100644
--- a/checks/check_extra783
+++ b/checks/check_extra783
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra783='Data Protection'
extra783(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
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)
diff --git a/checks/check_extra784 b/checks/check_extra784
index 3a200968..dea6e510 100644
--- a/checks/check_extra784
+++ b/checks/check_extra784
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra784='IAM'
extra784(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
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)
diff --git a/checks/check_extra785 b/checks/check_extra785
index e47e0a6f..6a8a2495 100644
--- a/checks/check_extra785
+++ b/checks/check_extra785
@@ -30,7 +30,11 @@ CHECK_CAF_EPIC_extra785='Infrastructure Security'
extra785(){
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
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)
diff --git a/checks/check_extra786 b/checks/check_extra786
index 11643e4a..76430778 100644
--- a/checks/check_extra786
+++ b/checks/check_extra786
@@ -28,7 +28,11 @@ extra786(){
TEMP_EXTRA786_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.EXTRA786.XXXXXXXXXX)
$AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx \
--query 'Reservations[*].Instances[*].{HttpTokens:MetadataOptions.HttpTokens,HttpEndpoint:MetadataOptions.HttpEndpoint,InstanceId:InstanceId}' \
- --output text --max-items $MAXITEMS > $TEMP_EXTRA786_FILE
+ --output text --max-items $MAXITEMS > $TEMP_EXTRA786_FILE 2>&1
+ if [[ $(cat $TEMP_EXTRA786_FILE | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe instances" "$regx"
+ continue
+ fi
# if the file contains data, there are instances in that region
if [[ -s "$TEMP_EXTRA786_FILE" ]];then
# here we read content from the file fields instanceid httptokens_status httpendpoint
diff --git a/checks/check_extra787 b/checks/check_extra787
index ef61f44f..30b8a5ee 100644
--- a/checks/check_extra787
+++ b/checks/check_extra787
@@ -34,7 +34,11 @@ extra787(){
for regx in $REGIONS; do
# create a list of SG open to the world with port $ES_API_PORT or $ES_DATA_PORT or $ES_KIBANA_PORT
SG_LIST=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --output text \
- --query "SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=\`$ES_API_PORT\` && ToPort>=\`$ES_API_PORT\`) || (FromPort<=\`$ES_DATA_PORT\` && ToPort>=\`$ES_DATA_PORT\`) || (FromPort<=\`$ES_KIBANA_PORT\` && ToPort>=\`$ES_KIBANA_PORT\`)) && (contains(IpRanges[].CidrIp, \`0.0.0.0/0\`) || contains(Ipv6Ranges[].CidrIpv6, \`::/0\`))]) > \`0\`].{GroupId:GroupId}")
+ --query "SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=\`$ES_API_PORT\` && ToPort>=\`$ES_API_PORT\`) || (FromPort<=\`$ES_DATA_PORT\` && ToPort>=\`$ES_DATA_PORT\`) || (FromPort<=\`$ES_KIBANA_PORT\` && ToPort>=\`$ES_KIBANA_PORT\`)) && (contains(IpRanges[].CidrIp, \`0.0.0.0/0\`) || contains(Ipv6Ranges[].CidrIpv6, \`::/0\`))]) > \`0\`].{GroupId:GroupId}" 2>&1)
+ if [[ $(echo "$SG_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe security groups" "$regx"
+ continue
+ fi
# in case of open security groups goes through each one
if [[ $SG_LIST ]];then
for sg in $SG_LIST;do
diff --git a/checks/check_extra788 b/checks/check_extra788
index b407ccac..50a9fdf3 100644
--- a/checks/check_extra788
+++ b/checks/check_extra788
@@ -29,7 +29,11 @@ extra788(){
# "Check if Elasticsearch Service domains allow open access "
for regx in $REGIONS; do
- LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
+ LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text 2>&1)
+ if [[ $(echo "$LIST_OF_DOMAINS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list domain names" "$regx"
+ continue
+ fi
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.policy.XXXXXXXXXX)
diff --git a/checks/check_extra789 b/checks/check_extra789
index 66fe6250..b4d90f23 100644
--- a/checks/check_extra789
+++ b/checks/check_extra789
@@ -32,8 +32,11 @@ extra789(){
${PROFILE_OPT} \
--query "ServiceDetails[?Owner=='${ACCOUNT_NUM}'].ServiceId" \
--region ${regx} \
- --output text | xargs
- )
+ --output text | xargs 2>&1)
+ if [[ $(echo "$ENDPOINT_SERVICES_IDS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe VPC endpoint services" "$regx"
+ continue
+ fi
for ENDPOINT_SERVICE_ID in ${ENDPOINT_SERVICES_IDS}; do
diff --git a/checks/check_extra79 b/checks/check_extra79
index bcb414bb..918db5d1 100644
--- a/checks/check_extra79
+++ b/checks/check_extra79
@@ -28,8 +28,16 @@ CHECK_CAF_EPIC_extra79='Data Protection'
extra79(){
# "Check for internet facing Elastic Load Balancers "
for regx in $REGIONS; do
- LIST_OF_PUBLIC_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text)
- LIST_OF_PUBLIC_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text)
+ LIST_OF_PUBLIC_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_PUBLIC_ELBS" | grep AccessDenied) ]]; then
+ textInfo "$regx: Access Denied Trying to describe load balancers" "$regx"
+ continue
+ fi
+ LIST_OF_PUBLIC_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Scheme == `internet-facing`].[LoadBalancerName,DNSName]' --output text 2>&1)
+ if [[ $(echo "$LIST_OF_PUBLIC_ELBSV2" | grep AccessDenied) ]]; then
+ textInfo "$regx: Access Denied Trying to describe load balancers" "$regx"
+ continue
+ fi
LIST_OF_ALL_ELBS=$( echo $LIST_OF_PUBLIC_ELBS; echo $LIST_OF_PUBLIC_ELBSV2)
LIST_OF_ALL_ELBS_PER_LINE=$( echo $LIST_OF_ALL_ELBS| xargs -n2 )
if [[ $LIST_OF_ALL_ELBS ]];then
diff --git a/checks/check_extra790 b/checks/check_extra790
index f2680c78..d562a40c 100644
--- a/checks/check_extra790
+++ b/checks/check_extra790
@@ -32,8 +32,11 @@ extra790(){
${PROFILE_OPT} \
--query "ServiceDetails[?Owner=='${ACCOUNT_NUM}'].ServiceId" \
--region ${regx} \
- --output text | xargs
- )
+ --output text | xargs 2>&1)
+ if [[ $(echo "$ENDPOINT_SERVICES_IDS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe VPC endpoint services" "$regx"
+ continue
+ fi
for ENDPOINT_SERVICE_ID in ${ENDPOINT_SERVICES_IDS}; do
ENDPOINT_PERMISSIONS_LIST=$(${AWSCLI} ec2 describe-vpc-endpoint-service-permissions \
diff --git a/checks/check_extra792 b/checks/check_extra792
index 04b36bf3..ae22adc4 100644
--- a/checks/check_extra792
+++ b/checks/check_extra792
@@ -27,8 +27,16 @@ CHECK_CAF_EPIC_extra792='Data Protection'
extra792(){
# "Check if Elastic Load Balancers have insecure SSL ciphers "
for regx in $REGIONS; do
- LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text|xargs -n1)
- LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text|xargs -n1)
+ LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text 2>&1|xargs -n1 )
+ if [[ $(echo "$LIST_OF_ELBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
+ LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text 2>&1|xargs -n1 )
+ if [[ $(echo "$LIST_OF_ELBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
if [[ $LIST_OF_ELBS || $LIST_OF_ELBSV2 ]]; then
if [[ $LIST_OF_ELBS ]]; then
# https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-ssl-security-policy.html#ssl-ciphers
@@ -37,7 +45,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 +98,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')
diff --git a/checks/check_extra793 b/checks/check_extra793
index 413a8a47..505c6511 100644
--- a/checks/check_extra793
+++ b/checks/check_extra793
@@ -27,8 +27,16 @@ CHECK_CAF_EPIC_extra793='Data Protection'
extra793(){
# "Check if Elastic Load Balancers have encrypted listeners "
for regx in $REGIONS; do
- LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text|xargs -n1)
- LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?(Type == `application`)].LoadBalancerArn' --output text|xargs -n1)
+ LIST_OF_ELBS=$($AWSCLI elb describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output text 2>&1|xargs -n1)
+ if [[ $(echo "$LIST_OF_ELBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
+ LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[*].LoadBalancerArn' --output text 2>&1|xargs -n1)
+ if [[ $(echo "$LIST_OF_ELBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to describe load balancers" "$regx"
+ continue
+ fi
if [[ $LIST_OF_ELBS || $LIST_OF_ELBSV2 ]]; then
if [[ $LIST_OF_ELBS ]]; then
ENCRYPTEDPROTOCOLS=("HTTPS" "SSL")
diff --git a/checks/check_extra794 b/checks/check_extra794
index ef6f2aee..ef2b5c50 100644
--- a/checks/check_extra794
+++ b/checks/check_extra794
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra794='Logging and Monitoring'
extra794(){
for regx in $REGIONS; do
- CLUSTERS=$($AWSCLI eks list-clusters $PROFILE_OPT --region $regx --query 'clusters[]' --output text)
+ CLUSTERS=$($AWSCLI eks list-clusters $PROFILE_OPT --region $regx --query 'clusters[]' --output text 2>&1)
+ if [[ $(echo "$CLUSTERS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list EKS clusters" "$regx"
+ continue
+ fi
if [[ $CLUSTERS ]]; then
for CLUSTER in $CLUSTERS;do
CLUSTERDEF=$($AWSCLI eks describe-cluster $PROFILE_OPT --region $regx --name $CLUSTER --query 'cluster.logging.clusterLogging[0]')
@@ -35,7 +39,7 @@ extra794(){
if [[ $(echo $TYPES | egrep "api.*audit.*authenticator.*controllerManager.*scheduler") ]]; then
textPass "$regx: Control plane logging enabled and correctly configured for EKS cluster $CLUSTER" "$regx" "$CLUSTER"
else
- textFail "$regx: Control plane logging enabled, but not all log types collected for EKS cluster $CLUSTER" "$regx" "$CLUSTER"
+ textFail "$regx: Control plane logging enabled; not all log types collected for EKS cluster $CLUSTER" "$regx" "$CLUSTER"
fi
else
textFail "$regx: Control plane logging is not enabled for EKS cluster $CLUSTER" "$regx" "$CLUSTER"
diff --git a/checks/check_extra795 b/checks/check_extra795
index 7030d741..fa2398a3 100644
--- a/checks/check_extra795
+++ b/checks/check_extra795
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra795='Infrastructure Security'
extra795(){
for regx in $REGIONS; do
- CLUSTERS=$($AWSCLI eks list-clusters $PROFILE_OPT --region $regx --query 'clusters[]' --output text)
+ CLUSTERS=$($AWSCLI eks list-clusters $PROFILE_OPT --region $regx --query 'clusters[]' --output text 2>&1)
+ if [[ $(echo "$CLUSTERS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list EKS clusters" "$regx"
+ continue
+ fi
if [[ $CLUSTERS ]]; then
for CLUSTER in $CLUSTERS;do
CLUSTERDEF=$($AWSCLI eks describe-cluster $PROFILE_OPT --region $regx --name $CLUSTER --query 'cluster.resourcesVpcConfig')
diff --git a/checks/check_extra796 b/checks/check_extra796
index 34789c74..70611d9e 100644
--- a/checks/check_extra796
+++ b/checks/check_extra796
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra796='Infrastructure Security'
extra796(){
for regx in $REGIONS; do
- CLUSTERS=$($AWSCLI eks list-clusters $PROFILE_OPT --region $regx --query 'clusters[]' --output text)
+ CLUSTERS=$($AWSCLI eks list-clusters $PROFILE_OPT --region $regx --query 'clusters[]' --output text 2>&1)
+ if [[ $(echo "$CLUSTERS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list EKS clusters" "$regx"
+ continue
+ fi
if [[ $CLUSTERS ]]; then
for CLUSTER in $CLUSTERS;do
CLUSTERDEF=$($AWSCLI eks describe-cluster $PROFILE_OPT --region $regx --name $CLUSTER --query 'cluster.resourcesVpcConfig')
diff --git a/checks/check_extra797 b/checks/check_extra797
index 473c5376..beb28f76 100644
--- a/checks/check_extra797
+++ b/checks/check_extra797
@@ -25,7 +25,11 @@ CHECK_CAF_EPIC_extra797='Data Protection'
extra797(){
for regx in $REGIONS; do
- CLUSTERS=$($AWSCLI eks list-clusters $PROFILE_OPT --region $regx --query 'clusters[]' --output text)
+ CLUSTERS=$($AWSCLI eks list-clusters $PROFILE_OPT --region $regx --query 'clusters[]' --output text 2>&1)
+ if [[ $(echo "$CLUSTERS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list EKS clusters" "$regx"
+ continue
+ fi
if [[ $CLUSTERS ]]; then
for CLUSTER in $CLUSTERS;do
ENC_CONFIG=$($AWSCLI eks describe-cluster $PROFILE_OPT --region $regx --name $CLUSTER --query 'cluster.encryptionConfig')
diff --git a/checks/check_extra798 b/checks/check_extra798
index 0e14d22a..21604e16 100644
--- a/checks/check_extra798
+++ b/checks/check_extra798
@@ -26,7 +26,11 @@ CHECK_CAF_EPIC_extra798='Infrastructure Security'
extra798(){
for regx in $REGIONS; do
- LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --output text --query 'Functions[*].FunctionName')
+ LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --output text --query 'Functions[*].FunctionName' 2>&1)
+ if [[ $(echo "$LIST_OF_FUNCTIONS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
+ textInfo "$regx: Access Denied trying to list functions" "$regx"
+ continue
+ fi
if [[ $LIST_OF_FUNCTIONS ]]; then
for lambdafunction in $LIST_OF_FUNCTIONS; do
# get the policy per function
diff --git a/checks/check_sample b/checks/check_sample
index b7b284bf..1ec39a35 100644
--- a/checks/check_sample
+++ b/checks/check_sample
@@ -23,16 +23,20 @@
# --filter-pattern '{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }' \
# --metric-transformations metricName=CloudTrailEventCount,metricNamespace=CloudTrailMetrics,metricValue=1
-
# CHECK_ID_checkN="N.N"
# CHECK_TITLE_checkN="[checkN] Description "
# CHECK_SCORED_checkN="NOT_SCORED"
# CHECK_CIS_LEVEL_checkN="EXTRA"
-# CHECK_SEVERITY_check="Medium"
+# CHECK_SEVERITY_checkNN="Medium"
# 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"
-# CHECK_SERVICENAME_checkN="service" # get service short name from `curl -s https://api.regional-table.region-services.aws.a2z.com/index.json | jq -r '.prices[] | .id' | awk -F: '{ print $1 }' | sort -u`
-#
+# CHECK_SERVICENAME_checkN="service" # get service short name from `curl -s https://api.regional-table.region-services.aws.a2z.com/index.json | jq -r '.prices[] | .id' | awk -F: '{ print $1 }' | sort -u`
+# CHECK_RISK_checkN=""
+# CHECK_REMEDIATION_checkN=""
+# CHECK_DOC_checkN=""
+# CHECK_CAF_EPIC_checkN=""
+
+# Example of regional resource
# extraN(){
# # "Description "
# textInfo "Looking for instances in all regions... "
@@ -42,10 +46,28 @@
# while read -r instance;do
# INSTANCE_ID=$(echo $instance | awk '{ print $1; }')
# PUBLIC_IP=$(echo $instance | awk '{ print $2; }')
-# textFail "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx"
+# textFail "$regx: Instance: $INSTANCE_ID at IP: $PUBLIC_IP is internet-facing!" "$regx" "$INSTANCE_ID"
# done <<< "$LIST_OF_PUBLIC_INSTANCES"
# else
# textPass "$regx: no Internet Facing EC2 Instances found" "$regx"
# fi
# done
# }
+
+# Example of global resource
+# extraN(){
+# # "Description "
+# LIST_DISTRIBUTIONS=$($AWSCLI cloudfront list-distributions $PROFILE_OPT --query 'DistributionList.Items[*].Id' --output text |grep -v ^None)
+# if [[ $LIST_DISTRIBUTIONS ]]; then
+# for dist in $LIST_DISTRIBUTIONS; do
+# GEO_ENABLED=$($AWSCLI cloudfront get-distribution-config $PROFILE_OPT --id $dist --query DistributionConfig.Restrictions.GeoRestriction.RestrictionType --output text)
+# if [[ $GEO_ENABLED == "none" ]]; then
+# textFail "$REGION: CloudFront distribution $dist has not Geo restrictions" "$REGION" "$dist"
+# else
+# textPass "$REGION: CloudFront distribution $dist has Geo restrictions enabled" "$REGION" "$dist"
+# fi
+# done
+# else
+# textInfo "$REGION: No CloudFront distributions found"
+# fi
+# }
diff --git a/groups/group25_FTR b/groups/group25_FTR
index 7ca694f7..fd0f8bfd 100644
--- a/groups/group25_FTR
+++ b/groups/group25_FTR
@@ -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]
diff --git a/groups/group7_extras b/groups/group7_extras
index 60cffc06..eeb1d031 100644
--- a/groups/group7_extras
+++ b/groups/group7_extras
@@ -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,extra7166,extra7167,extra7168,extra7169,extra7170,extra7171'
-# 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
diff --git a/iam/create_role_to_assume_cfn.yaml b/iam/create_role_to_assume_cfn.yaml
index 1e1140a1..9a0c9f08 100644
--- a/iam/create_role_to_assume_cfn.yaml
+++ b/iam/create_role_to_assume_cfn.yaml
@@ -62,5 +62,9 @@ Resources:
- 'tag:GetTagKeys'
- 'lambda:GetFunction'
- 'glue:GetConnections'
+ - 'glue:GetSecurityConfiguration'
+ - 'glue:SearchTables'
- 's3:GetAccountPublicAccessBlock'
+ - 'shield:GetSubscriptionState'
+ - 'shield:DescribeProtection'
Resource: '*'
diff --git a/iam/prowler-additions-policy.json b/iam/prowler-additions-policy.json
index f0285c24..6921d3ab 100644
--- a/iam/prowler-additions-policy.json
+++ b/iam/prowler-additions-policy.json
@@ -8,10 +8,13 @@
"ecr:Describe*",
"support:Describe*",
"tag:GetTagKeys",
- "lambda:GetFunction",
+ "lambda:GetFunction",
"glue:GetConnections",
+ "glue:GetSecurityConfiguration",
"glue:SearchTables",
- "s3:GetAccountPublicAccessBlock"
+ "s3:GetAccountPublicAccessBlock",
+ "shield:GetSubscriptionState",
+ "shield:DescribeProtection"
],
"Resource": "*",
"Effect": "Allow",
diff --git a/include/assume_role b/include/assume_role
index 95bd3e00..7f94b4fd 100644
--- a/include/assume_role
+++ b/include/assume_role
@@ -11,9 +11,16 @@
# 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
+ if [[ "${PROFILE_OPT}" = "" ]]; then
+ # If profile is not defined, restore original credentials from environment variables, if they exists!
+ restoreInitialAWSCredentials
+ fi
+
+ # 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 +35,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 +44,70 @@ 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
+ ASSUME_AWS_ACCESS_KEY_ID=$(jq -r '.Credentials.AccessKeyId' "${TEMP_STS_ASSUMED_FILE}")
+ export AWS_ACCESS_KEY_ID=$ASSUME_AWS_ACCESS_KEY_ID
+ ASSUME_AWS_SECRET_ACCESS_KEY=$(jq -r '.Credentials.SecretAccessKey' "${TEMP_STS_ASSUMED_FILE}")
+ export AWS_SECRET_ACCESS_KEY=$ASSUME_AWS_SECRET_ACCESS_KEY
+ ASSUME_AWS_SESSION_TOKEN=$(jq -r '.Credentials.SessionToken' "${TEMP_STS_ASSUMED_FILE}")
+ export AWS_SESSION_TOKEN=$ASSUME_AWS_SESSION_TOKEN
+ ASSUME_AWS_SESSION_EXPIRATION=$(jq -r '.Credentials.Expiration | sub("\\+00:00";"Z") | fromdateiso8601' "${TEMP_STS_ASSUMED_FILE}")
+ export AWS_SESSION_EXPIRATION=$ASSUME_AWS_SESSION_EXPIRATION
+ # echo TEMP AWS_ACCESS_KEY_ID: $ASSUME_AWS_ACCESS_KEY_ID
+ # echo TEMP AWS_SECRET_ACCESS_KEY: $ASSUME_AWS_SECRET_ACCESS_KEY
+ # echo TEMP AWS_SESSION_TOKEN: $ASSUME_AWS_SESSION_TOKEN
+ # echo EXPIRATION EPOCH TIME: $ASSUME_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}"
-}
\ No newline at end of file
+ rm -fr "${TEMP_STS_ASSUMED_ERROR}"
+}
+
+backupInitialAWSCredentials() {
+
+ if [[ $(printenv AWS_ACCESS_KEY_ID) && $(printenv AWS_SECRET_ACCESS_KEY) && $(printenv AWS_SESSION_TOKEN) ]]; then
+ INITIAL_AWS_ACCESS_KEY_ID=$(printenv AWS_ACCESS_KEY_ID)
+ INITIAL_AWS_SECRET_ACCESS_KEY=$(printenv AWS_SECRET_ACCESS_KEY)
+ INITIAL_AWS_SESSION_TOKEN=$(printenv AWS_SESSION_TOKEN)
+ fi
+}
+
+restoreInitialAWSCredentials() {
+ if [[ $INITIAL_AWS_ACCESS_KEY_ID && $INITIAL_AWS_SECRET_ACCESS_KEY && $INITIAL_AWS_SESSION_TOKEN ]]; then
+ export AWS_ACCESS_KEY_ID=$INITIAL_AWS_ACCESS_KEY_ID
+ export AWS_SECRET_ACCESS_KEY=$INITIAL_AWS_SECRET_ACCESS_KEY
+ export AWS_SESSION_TOKEN=$INITIAL_AWS_SESSION_TOKEN
+ else
+ unset AWS_ACCESS_KEY_ID
+ unset AWS_SECRET_ACCESS_KEY
+ unset AWS_SESSION_TOKEN
+ fi
+}
diff --git a/include/aws_profile_loader b/include/aws_profile_loader
index a2e446d3..e79cea87 100644
--- a/include/aws_profile_loader
+++ b/include/aws_profile_loader
@@ -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
diff --git a/include/check3x b/include/check3x
index ea29047e..29de748e 100644
--- a/include/check3x
+++ b/include/check3x
@@ -18,7 +18,7 @@ check3x(){
# be based only on CloudTrail tail with CloudWatchLog configuration.
DESCRIBE_TRAILS_CACHE=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region "$REGION" --query 'trailList[?CloudWatchLogsLogGroupArn != `null`]' 2>&1)
if [[ $(echo "$DESCRIBE_TRAILS_CACHE" | grep AccessDenied) ]]; then
- textFail "$REGION: Access Denied trying to describe trails in $REGION" "$REGION"
+ textInfo "$REGION: Access Denied trying to describe trails in $REGION" "$REGION"
return
fi
diff --git a/include/outputs_bucket b/include/outputs_bucket
index f89a7fd4..621b9fca 100644
--- a/include/outputs_bucket
+++ b/include/outputs_bucket
@@ -15,18 +15,18 @@ if [[ $OUTPUT_BUCKET ]]; then
# output mode has to be set to other than text
if [[ "${MODES[@]}" =~ "html" ]] || [[ "${MODES[@]}" =~ "csv" ]] || [[ "${MODES[@]}" =~ "json" ]] || [[ "${MODES[@]}" =~ "json-asff" ]]; then
OUTPUT_BUCKET_WITHOUT_FOLDERS=$(echo $OUTPUT_BUCKET | awk -F'/' '{ print $1 }')
- OUTPUT_BUCKET_STATUS=$($AWSCLI s3api head-bucket --bucket "$OUTPUT_BUCKET" 2>&1 || true)
- if [[ ! -z $OUTPUT_BUCKET_STATUS ]]; then
- echo "$OPTRED ERROR!$OPTNORMAL wrong bucket name or not right permissions."
- exit 1
- else
+# OUTPUT_BUCKET_STATUS=$($AWSCLI s3api head-bucket --bucket "$OUTPUT_BUCKET" 2>&1 || true)
+# if [[ -z $OUTPUT_BUCKET_STATUS ]]; then
+# echo "$OPTRED ERROR!$OPTNORMAL wrong bucket name or not right permissions."
+# exit 1
+# else
# need to make sure last / is not set to avoid // in S3
if [[ $OUTPUT_BUCKET != *"/" ]]; then
OUTPUT_BUCKET="$OUTPUT_BUCKET"
else
OUTPUT_BUCKET=${OUTPUT_BUCKET::-1}
fi
- fi
+# fi
else
echo "$OPTRED ERROR!$OPTNORMAL - Mode (-M) has to be set as well. Use -h for help."
exit 1
@@ -38,19 +38,19 @@ copyToS3(){
# and processing by Quicksight or others.
if [[ $OUTPUT_BUCKET ]]; then
if [[ "${MODES[@]}" =~ "csv" ]]; then
- $AWSCLI s3 cp $OUTPUT_DIR/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}.$EXTENSION_CSV \
+ $AWSCLI $PROFILE_OPT s3 cp $OUTPUT_DIR/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}.$EXTENSION_CSV \
s3://$OUTPUT_BUCKET/csv/ --acl bucket-owner-full-control
fi
if [[ "${MODES[@]}" =~ "html" ]]; then
- $AWSCLI s3 cp $OUTPUT_DIR/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}.$EXTENSION_HTML \
+ $AWSCLI $PROFILE_OPT s3 cp $OUTPUT_DIR/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}.$EXTENSION_HTML \
s3://$OUTPUT_BUCKET/html/ --acl bucket-owner-full-control
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
- $AWSCLI s3 cp $OUTPUT_DIR/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}.$EXTENSION_JSON \
+ $AWSCLI $PROFILE_OPT s3 cp $OUTPUT_DIR/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}.$EXTENSION_JSON \
s3://$OUTPUT_BUCKET/json/ --acl bucket-owner-full-control
fi
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
- $AWSCLI s3 cp $OUTPUT_DIR/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}.$EXTENSION_ASFF \
+ $AWSCLI $PROFILE_OPT s3 cp $OUTPUT_DIR/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}.$EXTENSION_ASFF \
s3://$OUTPUT_BUCKET/json-asff/ --acl bucket-owner-full-control
fi
fi
diff --git a/include/securityhub_integration b/include/securityhub_integration
index 74a1c35d..92151d45 100644
--- a/include/securityhub_integration
+++ b/include/securityhub_integration
@@ -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(){
diff --git a/prowler b/prowler
index cae80272..ad6ab8f1 100755
--- a/prowler
+++ b/prowler
@@ -10,13 +10,7 @@
# Contact the author at https://blyx.com/contact
# and open issues or ask questions at https://github.com/toniblyx/prowler
-
-# All CIS based checks in checks folder are licensed under a Creative Commons
-# Attribution-NonCommercial-ShareAlike 4.0 International Public License.
-# The link to the license terms can be found at
-# https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
-#
-# Any other piece of code is licensed as Apache License 2.0 as specified in
+# Code is licensed as Apache License 2.0 as specified in
# each file. You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
@@ -32,7 +26,7 @@ OPTRED="[1;31m"
OPTNORMAL="[0;39m"
# Set the defaults variables
-PROWLER_VERSION=2.6.1-15November2021
+PROWLER_VERSION=2.7.0-24January2022
PROWLER_DIR=$(dirname "$0")
REGION=""
@@ -67,57 +61,62 @@ usage(){
USAGE:
`basename $0` [ -p -r -h ]
Options:
- -p specify your AWS profile to use (i.e.: default)
- -r specify an AWS region to direct API requests to
- (i.e.: us-east-1), all regions are checked anyway if the check requires it
- -c specify one or multiple check ids separated by commas, to see all available checks use "-l" option
+ -p Specify your AWS profile to use.
+ (i.e.: default)
+ -r Specify an AWS region to direct API requests to.
+ (i.e.: us-east-1), all regions are checked anyway if the check requires it.
+ -c Specify one or multiple check ids separated by commas, to see all available checks use "-l" option.
(i.e.: "check11" for check 1.1 or "extra71,extra72" for extra check 71 and extra check 72)
-C Checklist file. See checklist.txt for reference and format.
(i.e.: checklist.txt)
- -g specify a group of checks by id, to see all available group of checks use "-L"
+ -g Specify a group of checks by id, to see all available group of checks use "-L".
(i.e.: "group3" for entire section 3, "cislevel1" for CIS Level 1 Profile Definitions or "forensics-ready")
- -f specify an AWS region to run checks against
+ -f Specify an AWS region to run checks against.
(i.e.: us-west-1 or for multiple regions use single quote like 'us-west-1 us-west-2')
- -m specify the maximum number of items to return for long-running requests (default: 100)
- -M output mode: text (default), mono, html, json, json-asff, junit-xml, csv. They can be used combined comma separated.
- (separator is ","; data is on stdout; progress on stderr).
- -k keep the credential report
- -n show check numbers to sort easier
+ -m Specify the maximum number of items to return for long-running requests (default: 100).
+ -M Output or report mode: text (default), mono, html, json, json-asff, junit-xml, csv. They can be used combined comma separated.
+ (i.e.: "html,json"; files created in background; progress on stdout)
+ -k Keep the credential report for debugging.
+ -n Show check numbers to sort easier.
(i.e.: 1.01 instead of 1.1)
- -l list all available checks only (does not perform any check). Add -g to only list checks within the specified group
- -L list all groups (does not perform any check)
- -e exclude group extras
- -E execute all tests except a list of specified checks separated by comma (i.e. check21,check31)
- -b do not print Prowler banner
- -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 get only FAIL findings, will show WARNINGS when a resource is excluded
- -A account id for the account where to assume a role, requires -R and -T
+ -l List all available checks only (does not perform any check). Add -g to only list checks within the specified group.
+ -L List all groups (does not perform any check).
+ -e Exclude group extras.
+ -E Execute all tests except a list of specified checks separated by comma.
+ (i.e. check21,check31)
+ -b Do not print Prowler banner.
+ -s Show scoring report (it is included by default in the html 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 Get only FAIL findings, will show WARNINGS when a resource is excluded.
+ -A Account id for the account where to assume a role, requires -R.
(i.e.: 123456789012)
- -R role name or role arn to assume in the account, requires -A and -T
+ -R Role name or role arn to assume in the account, requires -A.
(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
+ -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.
(i.e.: whitelist_sample.txt)
-N Shodan API key used by check extra7102.
- -o Custom output directory, if not specified will use default prowler/output, requires -M
+ -o Custom output directory, if not specified will use default prowler/output, requires -M .
(i.e.: -M csv -o /tmp/reports/)
-B Custom output bucket, requires -M and it can work also with -o flag.
(i.e.: -M csv -B my-bucket or -M csv -B my-bucket/folder/)
- -F Custom output report name, if not specified will use default output/prowler-output-ACCOUNT_NUM-OUTPUT_DATE
- -z Failed Checks do not trigger exit code 3
+ -D Same as -B but do not use the assumed role credentials to put objects to the bucket, instead uses the initial credentials.
+ -F Custom output report name, if not specified will use default output/prowler-output-ACCOUNT_NUM-OUTPUT_DATE.format.
+ -z Failed checks do not trigger exit code 3.
-Z Specify one or multiple check ids separated by commas that will trigger exit code 3 if they fail. Unspecified checks will not trigger exit code 3. This will override "-z".
- (i.e.: "-Z check11,check12" will cause check11 and/or check12 to trigger exit code 3
- -V show version number & exit
- -h this help
+ (i.e.: "-Z check11,check12" will cause check11 and/or check12 to trigger exit code 3)
+ -V Show version number & exit.
+ -h This help.
"
exit
}
-while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:F:zZ:" OPTION; do
+while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:D:F:zZ:" OPTION; do
case $OPTION in
h )
usage
@@ -135,6 +134,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
@@ -210,6 +210,10 @@ while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:F:zZ:" OPTION; do
B )
OUTPUT_BUCKET=$OPTARG
;;
+ D )
+ OUTPUT_BUCKET=$OPTARG
+ OUTPUT_BUCKET_NOASSUME=1
+ ;;
F )
OUTPUT_FILE_NAME=$OPTARG
;;
@@ -392,13 +396,16 @@ 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
+ # echo ******* I am here again to check on my role *******
# 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 +504,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 +572,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,7 +646,8 @@ fi
# Gather account data / test aws cli connectivity
getWhoami
-if [[ $ACCOUNT_TO_ASSUME ]]; then
+if [[ -n "${ACCOUNT_TO_ASSUME}" || -n "${ROLE_TO_ASSUME}" ]]; then
+ backupInitialAWSCredentials
assume_role
fi
@@ -656,10 +664,13 @@ if [[ $GROUP_ID_READ ]];then
fi
cleanTemp
scoring
+ if [[ $OUTPUT_BUCKET_NOASSUME ]]; then
+ restoreInitialAWSCredentials
+ fi
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
@@ -684,6 +695,9 @@ if [[ $CHECK_ID ]];then
if [[ "${MODES[@]}" =~ "html" ]]; then
addHtmlFooter >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
fi
+ if [[ $OUTPUT_BUCKET_NOASSUME ]]; then
+ restoreInitialAWSCredentials
+ fi
copyToS3
scoring
cleanTemp
@@ -698,13 +712,9 @@ fi
scoring
cleanTemp
+if [[ $OUTPUT_BUCKET_NOASSUME ]]; then
+ restoreInitialAWSCredentials
+fi
copyToS3
-if [[ $ACCOUNT_TO_ASSUME ]]; then
- # unset env variables with assumed role credentials
- unset AWS_ACCESS_KEY_ID
- unset AWS_SECRET_ACCESS_KEY
- unset AWS_SESSION_TOKEN
-fi
-
exit $EXITCODE
diff --git a/util/Dockerfile b/util/Dockerfile
index 9467cd0c..0bfd188c 100644
--- a/util/Dockerfile
+++ b/util/Dockerfile
@@ -1,13 +1,25 @@
-FROM alpine:3.13
+# Build command
+# docker build --platform=linux/amd64 --no-cache -t prowler:latest -f util/Dockerfile .
+
+FROM public.ecr.aws/amazonlinux/amazonlinux:latest
+
+LABEL maintainer="https://github.com/toniblyx/prowler"
ARG USERNAME=prowler
ARG USERID=34000
-RUN addgroup -g ${USERID} ${USERNAME} && \
- adduser -s /bin/sh -G ${USERNAME} -D -u ${USERID} ${USERNAME} && \
- apk --update --no-cache add python3 bash curl jq file coreutils py3-pip git && \
- pip3 install --upgrade pip && \
- pip3 install awscli boto3 detect-secrets==1.0.3
+RUN yum install -y shadow-utils && \
+ useradd -s /bin/sh -U -u ${USERID} ${USERNAME} && \
+ yum install -y python3 bash curl jq coreutils py3-pip which unzip && \
+ yum upgrade -y && \
+ yum clean all && \
+ pip3 install --upgrade pip && \
+ pip3 install boto3 detect-secrets==1.0.3 && \
+ pip3 cache purge && \
+ curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip && \
+ unzip awscliv2.zip && \
+ aws/install && \
+ rm -rf aws awscliv2.zip /var/cache/yum
WORKDIR /prowler
diff --git a/util/codebuild/codebuild-prowler-audit-account-cfn.yaml b/util/codebuild/codebuild-prowler-audit-account-cfn.yaml
index 7cec6636..d417c078 100644
--- a/util/codebuild/codebuild-prowler-audit-account-cfn.yaml
+++ b/util/codebuild/codebuild-prowler-audit-account-cfn.yaml
@@ -184,15 +184,18 @@ Resources:
Version: '2012-10-17'
Statement:
- Action:
- - s3:GetAccountPublicAccessBlock
- - glue:GetConnections
- - glue:SearchTables
- ds:ListAuthorizedApplications
- ec2:GetEbsEncryptionByDefault
- ecr:Describe*
- support:Describe*
- tag:GetTagKeys
- lambda:GetFunction
+ - glue:GetConnections
+ - glue:GetSecurityConfiguration
+ - glue:SearchTables
+ - s3:GetAccountPublicAccessBlock
+ - shield:GetSubscriptionState
+ - shield:DescribeProtection
Effect: Allow
Resource: !Sub 'arn:aws:glue:${AWS::Region}:${AWS::AccountId}:catalog'
- PolicyName: CodeBuild
diff --git a/util/org-multi-account/ProwlerRole.yaml b/util/org-multi-account/ProwlerRole.yaml
index 544cf1cd..183b2bee 100644
--- a/util/org-multi-account/ProwlerRole.yaml
+++ b/util/org-multi-account/ProwlerRole.yaml
@@ -96,6 +96,8 @@ Resources:
- states:ListActivities
- support:Describe*
- tag:GetTagKeys
+ - shield:GetSubscriptionState
+ - shield:DescribeProtection
- PolicyName: Prowler-S3-Reports
PolicyDocument:
Version: 2012-10-17
diff --git a/util/org-multi-account/serverless_codebuild/templates/ProwlerCodeBuildStack.yaml b/util/org-multi-account/serverless_codebuild/templates/ProwlerCodeBuildStack.yaml
index d89c5452..bc7c0a2b 100644
--- a/util/org-multi-account/serverless_codebuild/templates/ProwlerCodeBuildStack.yaml
+++ b/util/org-multi-account/serverless_codebuild/templates/ProwlerCodeBuildStack.yaml
@@ -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"
diff --git a/util/org-multi-account/serverless_codebuild/templates/ProwlerRole.yaml b/util/org-multi-account/serverless_codebuild/templates/ProwlerRole.yaml
index 138d8809..5751f1f9 100644
--- a/util/org-multi-account/serverless_codebuild/templates/ProwlerRole.yaml
+++ b/util/org-multi-account/serverless_codebuild/templates/ProwlerRole.yaml
@@ -83,6 +83,7 @@ Resources:
- dax:ListTables
- ds:ListAuthorizedApplications
- ds:DescribeRoles
+ - ec2:GetEbsEncryptionByDefault
- ecr:Describe*
- lambda:GetAccountSettings
- lambda:GetFunctionConfiguration
@@ -96,6 +97,8 @@ Resources:
- states:ListActivities
- support:Describe*
- tag:GetTagKeys
+ - shield:GetSubscriptionState
+ - shield:DescribeProtection
- PolicyName: Prowler-S3-Reports
PolicyDocument:
Version: 2012-10-17
diff --git a/util/terraform-kickstarter/main.tf b/util/terraform-kickstarter/main.tf
index c51557b6..187b7723 100644
--- a/util/terraform-kickstarter/main.tf
+++ b/util/terraform-kickstarter/main.tf
@@ -311,15 +311,18 @@ resource "aws_iam_policy" "prowler_kickstarter_iam_policy" {
},
{
Action = [
- "s3:GetAccountPublicAccessBlock",
- "glue:GetConnections",
- "glue:SearchTables",
"ds:ListAuthorizedApplications",
"ec2:GetEbsEncryptionByDefault",
"ecr:Describe*",
"support:Describe*",
"tag:GetTagKeys",
- "lambda:GetFunction"
+ "lambda:GetFunction",
+ "glue:GetConnections",
+ "glue:GetSecurityConfiguration",
+ "glue:SearchTables",
+ "s3:GetAccountPublicAccessBlock",
+ "shield:GetSubscriptionState",
+ "shield:DescribeProtection"
]
Effect = "Allow"
Resource = "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:catalog"