mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
issue #85
This commit is contained in:
@@ -61,7 +61,7 @@ arn:aws:iam::aws:policy/SecurityAudit
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
1 - Run the prowler.sh command without options (it will use your default credentials and run checks over all regions when needed, default region is us-east-1):
|
1 - Run the prowler.sh command without options (it will use your environment variable credentials if exist or default in ~/.aws/credentials file and run checks over all regions when needed, default region is us-east-1):
|
||||||
|
|
||||||
```
|
```
|
||||||
./prowler
|
./prowler
|
||||||
|
|||||||
231
prowler
231
prowler
@@ -30,7 +30,6 @@ OPTRED="[1;31m"
|
|||||||
OPTNORMAL="[0;39m"
|
OPTNORMAL="[0;39m"
|
||||||
|
|
||||||
# Set the defaults for these getopts variables
|
# Set the defaults for these getopts variables
|
||||||
PROFILE="default"
|
|
||||||
REGION="us-east-1"
|
REGION="us-east-1"
|
||||||
FILTERREGION=""
|
FILTERREGION=""
|
||||||
MAXITEMS=100
|
MAXITEMS=100
|
||||||
@@ -230,9 +229,31 @@ else
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -f ~/.aws/credentials ]]; then
|
# Check environment if profile provided reads it from creds file, then instance profile
|
||||||
|
# if not profile provided loads it from environment variables
|
||||||
|
|
||||||
|
if [[ $PROFILE ]]; then
|
||||||
|
PROFILE_OPT="--profile $PROFILE"
|
||||||
|
if [[ ! -f ~/.aws/credentials ]]; then
|
||||||
echo -e "\n$RED ERROR!$NORMAL AWS credentials file not found (~/.aws/credentials). Run 'aws configure' first. \n"
|
echo -e "\n$RED ERROR!$NORMAL AWS credentials file not found (~/.aws/credentials). Run 'aws configure' first. \n"
|
||||||
return 1
|
return 1
|
||||||
|
else
|
||||||
|
# if Prowler runs insinde an AWS instance with IAM instance profile attached
|
||||||
|
INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/)
|
||||||
|
if [[ $INSTANCE_PROFILE ]]; then
|
||||||
|
AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g')
|
||||||
|
AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g')
|
||||||
|
AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g')
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then
|
||||||
|
PROFILE="ENV"
|
||||||
|
PROFILE_OPT=""
|
||||||
|
else
|
||||||
|
PROFILE="default"
|
||||||
|
PROFILE_OPT="--profile $PROFILE"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# AWS-CLI variables
|
# AWS-CLI variables
|
||||||
@@ -242,13 +263,6 @@ if [ -z "${AWSCLI}" ]; then
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# if this script runs in an AWS instance
|
|
||||||
# INSTANCE_PROFILE=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/)
|
|
||||||
# AWS_ACCESS_KEY_ID=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g')
|
|
||||||
# AWS_SECRET_ACCESS_KEY_ID=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g')
|
|
||||||
# AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
|
|
||||||
# AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY_ID}
|
|
||||||
|
|
||||||
TITLE_ID=""
|
TITLE_ID=""
|
||||||
TITLE_TEXT="CALLER ERROR - UNSET TITLE"
|
TITLE_TEXT="CALLER ERROR - UNSET TITLE"
|
||||||
## Output formatting functions
|
## Output formatting functions
|
||||||
@@ -350,9 +364,9 @@ prowlerBanner() {
|
|||||||
|
|
||||||
# Get whoami in AWS, who is the user running this shell script
|
# Get whoami in AWS, who is the user running this shell script
|
||||||
getWhoami(){
|
getWhoami(){
|
||||||
ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Account" | tr -d '"')
|
ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"')
|
||||||
if [[ $MODE == "csv" ]]; then
|
if [[ $MODE == "csv" ]]; then
|
||||||
CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Arn")
|
CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn")
|
||||||
if [[ 255 -eq $? ]]; then
|
if [[ 255 -eq $? ]]; then
|
||||||
# Failed to get own identity ... exit
|
# Failed to get own identity ... exit
|
||||||
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
|
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
|
||||||
@@ -370,7 +384,7 @@ getWhoami(){
|
|||||||
echo -e "AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n"
|
echo -e "AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n"
|
||||||
if [[ $MONOCHROME -eq 1 ]]; then
|
if [[ $MONOCHROME -eq 1 ]]; then
|
||||||
echo "Caller Identity:"
|
echo "Caller Identity:"
|
||||||
$AWSCLI sts get-caller-identity --output text --profile $PROFILE --region $REGION --query "Arn"
|
$AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn"
|
||||||
if [[ 255 -eq $? ]]; then
|
if [[ 255 -eq $? ]]; then
|
||||||
# Failed to get own identity ... exit
|
# Failed to get own identity ... exit
|
||||||
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
|
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
|
||||||
@@ -380,10 +394,11 @@ getWhoami(){
|
|||||||
echo ""
|
echo ""
|
||||||
else
|
else
|
||||||
echo "Caller Identity:"
|
echo "Caller Identity:"
|
||||||
$AWSCLI sts get-caller-identity --output table --profile $PROFILE --region $REGION
|
$AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION
|
||||||
if [[ 255 -eq $? ]]; then
|
if [[ 255 -eq $? ]]; then
|
||||||
# Failed to get own identity ... exit
|
# Failed to get own identity ... exit
|
||||||
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
|
echo variableeeee $PROFILE_OPT
|
||||||
|
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!x"
|
||||||
>&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
|
>&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
@@ -401,7 +416,7 @@ printColorsCode(){
|
|||||||
# Generate Credential Report
|
# Generate Credential Report
|
||||||
genCredReport() {
|
genCredReport() {
|
||||||
textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT"
|
textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT"
|
||||||
until $( $AWSCLI iam generate-credential-report --output text --query 'State' --profile $PROFILE --region $REGION |grep -q -m 1 "COMPLETE") ; do
|
until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@@ -409,7 +424,7 @@ genCredReport() {
|
|||||||
# Save report to a file, decode it, deletion at finish and after every single check
|
# Save report to a file, decode it, deletion at finish and after every single check
|
||||||
saveReport(){
|
saveReport(){
|
||||||
TEMP_REPORT_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-XXXXX.cred_report )
|
TEMP_REPORT_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-XXXXX.cred_report )
|
||||||
$AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION | decode_report > $TEMP_REPORT_FILE
|
$AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE
|
||||||
if [[ $KEEPCREDREPORT -eq 1 ]]; then
|
if [[ $KEEPCREDREPORT -eq 1 ]]; then
|
||||||
textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT"
|
textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT"
|
||||||
textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE"
|
textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE"
|
||||||
@@ -429,7 +444,7 @@ trap cleanTemp EXIT
|
|||||||
# Get a list of all available AWS Regions
|
# Get a list of all available AWS Regions
|
||||||
REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \
|
REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \
|
||||||
--output text \
|
--output text \
|
||||||
--profile $PROFILE \
|
$PROFILE_OPT \
|
||||||
--region $REGION \
|
--region $REGION \
|
||||||
--region-names $FILTERREGION)
|
--region-names $FILTERREGION)
|
||||||
|
|
||||||
@@ -482,11 +497,11 @@ check13(){
|
|||||||
cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$5 }' |grep $i| awk '{ print $1 }'|tr '\n' ' ';
|
cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$5 }' |grep $i| awk '{ print $1 }'|tr '\n' ' ';
|
||||||
done)
|
done)
|
||||||
# list of users that have used password
|
# list of users that have used password
|
||||||
USERS_PASSWORD_USED=$($AWSCLI iam list-users --query "Users[?PasswordLastUsed].UserName" --output text --profile $PROFILE --region $REGION)
|
USERS_PASSWORD_USED=$($AWSCLI iam list-users --query "Users[?PasswordLastUsed].UserName" --output text $PROFILE_OPT --region $REGION)
|
||||||
if [[ $USERS_PASSWORD_USED ]]; then
|
if [[ $USERS_PASSWORD_USED ]]; then
|
||||||
# look for users with a password last used more or equal to 90 days
|
# look for users with a password last used more or equal to 90 days
|
||||||
for i in $USERS_PASSWORD_USED; do
|
for i in $USERS_PASSWORD_USED; do
|
||||||
DATEUSED=$($AWSCLI iam list-users --query "Users[?UserName=='$i'].PasswordLastUsed" --output text --profile $PROFILE --region $REGION | cut -d'T' -f1)
|
DATEUSED=$($AWSCLI iam list-users --query "Users[?UserName=='$i'].PasswordLastUsed" --output text $PROFILE_OPT --region $REGION | cut -d'T' -f1)
|
||||||
HOWOLDER=$(how_older_from_today $DATEUSED)
|
HOWOLDER=$(how_older_from_today $DATEUSED)
|
||||||
if [ $HOWOLDER -gt "90" ];then
|
if [ $HOWOLDER -gt "90" ];then
|
||||||
textWarn "User \"$i\" has not logged in during the last 90 days "
|
textWarn "User \"$i\" has not logged in during the last 90 days "
|
||||||
@@ -550,7 +565,7 @@ check14(){
|
|||||||
check15(){
|
check15(){
|
||||||
ID15="1.5,1.05"
|
ID15="1.5,1.05"
|
||||||
TITLE15="Ensure IAM password policy requires at least one uppercase letter (Scored)"
|
TITLE15="Ensure IAM password policy requires at least one uppercase letter (Scored)"
|
||||||
COMMAND15=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --output json --query 'PasswordPolicy.RequireUppercaseCharacters' 2> /dev/null) # must be true
|
COMMAND15=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireUppercaseCharacters' 2> /dev/null) # must be true
|
||||||
textTitle "$ID15" "$TITLE15" "SCORED" "LEVEL1"
|
textTitle "$ID15" "$TITLE15" "SCORED" "LEVEL1"
|
||||||
if [[ $COMMAND15 == "true" ]];then
|
if [[ $COMMAND15 == "true" ]];then
|
||||||
textOK "Password Policy requires upper case"
|
textOK "Password Policy requires upper case"
|
||||||
@@ -562,7 +577,7 @@ check15(){
|
|||||||
check16(){
|
check16(){
|
||||||
ID16="1.6,1.06"
|
ID16="1.6,1.06"
|
||||||
TITLE16="Ensure IAM password policy require at least one lowercase letter (Scored)"
|
TITLE16="Ensure IAM password policy require at least one lowercase letter (Scored)"
|
||||||
COMMAND16=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --output json --query 'PasswordPolicy.RequireLowercaseCharacters' 2> /dev/null) # must be true
|
COMMAND16=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireLowercaseCharacters' 2> /dev/null) # must be true
|
||||||
textTitle "$ID16" "$TITLE16" "SCORED" "LEVEL1"
|
textTitle "$ID16" "$TITLE16" "SCORED" "LEVEL1"
|
||||||
if [[ $COMMAND16 == "true" ]];then
|
if [[ $COMMAND16 == "true" ]];then
|
||||||
textOK "Password Policy requires lower case"
|
textOK "Password Policy requires lower case"
|
||||||
@@ -574,7 +589,7 @@ check16(){
|
|||||||
check17(){
|
check17(){
|
||||||
ID17="1.7,1.07"
|
ID17="1.7,1.07"
|
||||||
TITLE17="Ensure IAM password policy require at least one symbol (Scored)"
|
TITLE17="Ensure IAM password policy require at least one symbol (Scored)"
|
||||||
COMMAND17=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --output json --query 'PasswordPolicy.RequireSymbols' 2> /dev/null) # must be true
|
COMMAND17=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireSymbols' 2> /dev/null) # must be true
|
||||||
textTitle "$ID17" "$TITLE17" "SCORED" "LEVEL1"
|
textTitle "$ID17" "$TITLE17" "SCORED" "LEVEL1"
|
||||||
if [[ $COMMAND17 == "true" ]];then
|
if [[ $COMMAND17 == "true" ]];then
|
||||||
textOK "Password Policy requires symbol"
|
textOK "Password Policy requires symbol"
|
||||||
@@ -586,7 +601,7 @@ check17(){
|
|||||||
check18(){
|
check18(){
|
||||||
ID18="1.8,1.08"
|
ID18="1.8,1.08"
|
||||||
TITLE18="Ensure IAM password policy require at least one number (Scored)"
|
TITLE18="Ensure IAM password policy require at least one number (Scored)"
|
||||||
COMMAND18=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --output json --query 'PasswordPolicy.RequireNumbers' 2> /dev/null) # must be true
|
COMMAND18=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireNumbers' 2> /dev/null) # must be true
|
||||||
textTitle "$ID18" "$TITLE18" "SCORED" "LEVEL1"
|
textTitle "$ID18" "$TITLE18" "SCORED" "LEVEL1"
|
||||||
if [[ $COMMAND18 == "true" ]];then
|
if [[ $COMMAND18 == "true" ]];then
|
||||||
textOK "Password Policy requires number"
|
textOK "Password Policy requires number"
|
||||||
@@ -598,7 +613,7 @@ check18(){
|
|||||||
check19(){
|
check19(){
|
||||||
ID19="1.9,1.09"
|
ID19="1.9,1.09"
|
||||||
TITLE19="Ensure IAM password policy requires minimum length of 14 or greater (Scored)"
|
TITLE19="Ensure IAM password policy requires minimum length of 14 or greater (Scored)"
|
||||||
COMMAND19=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --output json --query 'PasswordPolicy.MinimumPasswordLength' 2> /dev/null)
|
COMMAND19=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.MinimumPasswordLength' 2> /dev/null)
|
||||||
textTitle "$ID19" "$TITLE19" "SCORED" "LEVEL1"
|
textTitle "$ID19" "$TITLE19" "SCORED" "LEVEL1"
|
||||||
if [[ $COMMAND19 -gt "13" ]];then
|
if [[ $COMMAND19 -gt "13" ]];then
|
||||||
textOK "Password Policy requires more than 13 characters"
|
textOK "Password Policy requires more than 13 characters"
|
||||||
@@ -610,7 +625,7 @@ check19(){
|
|||||||
check110(){
|
check110(){
|
||||||
ID110="1.10"
|
ID110="1.10"
|
||||||
TITLE110="Ensure IAM password policy prevents password reuse, 24 or greater (Scored)"
|
TITLE110="Ensure IAM password policy prevents password reuse, 24 or greater (Scored)"
|
||||||
COMMAND110=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' --output text 2> /dev/null)
|
COMMAND110=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' --output text 2> /dev/null)
|
||||||
textTitle "$ID110" "$TITLE110" "SCORED" "LEVEL1"
|
textTitle "$ID110" "$TITLE110" "SCORED" "LEVEL1"
|
||||||
if [[ $COMMAND110 ]];then
|
if [[ $COMMAND110 ]];then
|
||||||
if [[ $COMMAND110 -gt "23" ]];then
|
if [[ $COMMAND110 -gt "23" ]];then
|
||||||
@@ -626,7 +641,7 @@ check110(){
|
|||||||
check111(){
|
check111(){
|
||||||
ID111="1.11"
|
ID111="1.11"
|
||||||
TITLE111="Ensure IAM password policy expires passwords within 90 days or less (Scored)"
|
TITLE111="Ensure IAM password policy expires passwords within 90 days or less (Scored)"
|
||||||
COMMAND111=$($AWSCLI iam get-account-password-policy --profile $PROFILE --region $REGION --output json | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g' 2> /dev/null)
|
COMMAND111=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json | grep MaxPasswordAge | awk -F: '{ print $2 }'|sed 's/\ //g'|sed 's/,/ /g' 2> /dev/null)
|
||||||
textTitle "$ID111" "$TITLE111" "SCORED" "LEVEL1"
|
textTitle "$ID111" "$TITLE111" "SCORED" "LEVEL1"
|
||||||
if [[ $COMMAND111 ]];then
|
if [[ $COMMAND111 ]];then
|
||||||
if [ $COMMAND111 == "90" ];then
|
if [ $COMMAND111 == "90" ];then
|
||||||
@@ -659,7 +674,7 @@ check112(){
|
|||||||
check113(){
|
check113(){
|
||||||
ID113="1.13"
|
ID113="1.13"
|
||||||
TITLE113="Ensure MFA is enabled for the root account (Scored)"
|
TITLE113="Ensure MFA is enabled for the root account (Scored)"
|
||||||
COMMAND113=$($AWSCLI iam get-account-summary --profile $PROFILE --region $REGION --output json|grep AccountMFAEnabled | awk -F': ' '{ print $2 }'|sed 's/,//')
|
COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json|grep AccountMFAEnabled | awk -F': ' '{ print $2 }'|sed 's/,//')
|
||||||
textTitle "$ID113" "$TITLE113" "SCORED" "LEVEL1"
|
textTitle "$ID113" "$TITLE113" "SCORED" "LEVEL1"
|
||||||
if [ $COMMAND113 == "1" ]; then
|
if [ $COMMAND113 == "1" ]; then
|
||||||
textOK "Virtual MFA is enabled for root"
|
textOK "Virtual MFA is enabled for root"
|
||||||
@@ -671,10 +686,10 @@ check113(){
|
|||||||
check114(){
|
check114(){
|
||||||
ID114="1.14"
|
ID114="1.14"
|
||||||
TITLE114="Ensure hardware MFA is enabled for the root account (Scored)"
|
TITLE114="Ensure hardware MFA is enabled for the root account (Scored)"
|
||||||
COMMAND113=$($AWSCLI iam get-account-summary --profile $PROFILE --region $REGION --output json|grep AccountMFAEnabled | awk -F': ' '{ print $2 }'|sed 's/,//')
|
COMMAND113=$($AWSCLI iam get-account-summary $PROFILE_OPT --region $REGION --output json|grep AccountMFAEnabled | awk -F': ' '{ print $2 }'|sed 's/,//')
|
||||||
textTitle "$ID114" "$TITLE114" "SCORED" "LEVEL1"
|
textTitle "$ID114" "$TITLE114" "SCORED" "LEVEL1"
|
||||||
if [ $COMMAND113 == "1" ]; then
|
if [ $COMMAND113 == "1" ]; then
|
||||||
COMMAND114=$($AWSCLI iam list-virtual-mfa-devices --profile $PROFILE --region $REGION --query 'VirtualMFADevices' --output text|grep :root |wc -l)
|
COMMAND114=$($AWSCLI iam list-virtual-mfa-devices $PROFILE_OPT --region $REGION --query 'VirtualMFADevices' --output text|grep :root |wc -l)
|
||||||
if [ $COMMAND114 == "1" ]; then
|
if [ $COMMAND114 == "1" ]; then
|
||||||
textOK "Virtual MFA is enabled for root"
|
textOK "Virtual MFA is enabled for root"
|
||||||
else
|
else
|
||||||
@@ -698,10 +713,10 @@ check116(){
|
|||||||
ID116="1.16"
|
ID116="1.16"
|
||||||
TITLE116="Ensure IAM policies are attached only to groups or roles (Scored)"
|
TITLE116="Ensure IAM policies are attached only to groups or roles (Scored)"
|
||||||
textTitle "$ID116" "$TITLE116" "SCORED" "LEVEL1"
|
textTitle "$ID116" "$TITLE116" "SCORED" "LEVEL1"
|
||||||
LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text --profile $PROFILE --region $REGION)
|
LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION)
|
||||||
C116_NUM_USERS=0
|
C116_NUM_USERS=0
|
||||||
for user in $LIST_USERS;do
|
for user in $LIST_USERS;do
|
||||||
USER_POLICY=$($AWSCLI iam list-attached-user-policies --output text --profile $PROFILE --region $REGION --user-name $user)
|
USER_POLICY=$($AWSCLI iam list-attached-user-policies --output text $PROFILE_OPT --region $REGION --user-name $user)
|
||||||
if [[ $USER_POLICY ]]; then
|
if [[ $USER_POLICY ]]; then
|
||||||
textWarn "$user has policy directly attached "
|
textWarn "$user has policy directly attached "
|
||||||
C116_NUM_USERS=$(expr $C116_NUM_USERS + 1)
|
C116_NUM_USERS=$(expr $C116_NUM_USERS + 1)
|
||||||
@@ -725,21 +740,21 @@ check118(){
|
|||||||
ID118="1.18"
|
ID118="1.18"
|
||||||
TITLE118="Ensure IAM Master and IAM Manager roles are active (Scored)"
|
TITLE118="Ensure IAM Master and IAM Manager roles are active (Scored)"
|
||||||
textTitle "$ID118" "$TITLE118" "SCORED" "LEVEL1"
|
textTitle "$ID118" "$TITLE118" "SCORED" "LEVEL1"
|
||||||
FINDMASTERANDMANAGER=$($AWSCLI iam list-roles --profile $PROFILE --region $REGION --query "Roles[*].{RoleName:RoleName}" --output text | grep -E 'Master|Manager'| tr '\n' ' ')
|
FINDMASTERANDMANAGER=$($AWSCLI iam list-roles $PROFILE_OPT --region $REGION --query "Roles[*].{RoleName:RoleName}" --output text | grep -E 'Master|Manager'| tr '\n' ' ')
|
||||||
if [[ $FINDMASTERANDMANAGER ]];then
|
if [[ $FINDMASTERANDMANAGER ]];then
|
||||||
textNotice "Found next roles as possible IAM Master and IAM Manager candidates: "
|
textNotice "Found next roles as possible IAM Master and IAM Manager candidates: "
|
||||||
textNotice "$FINDMASTERANDMANAGER "
|
textNotice "$FINDMASTERANDMANAGER "
|
||||||
textNotice "run the commands below to check their policies with section 1.18 in the guide..."
|
textNotice "run the commands below to check their policies with section 1.18 in the guide..."
|
||||||
for role in $FINDMASTERANDMANAGER;do
|
for role in $FINDMASTERANDMANAGER;do
|
||||||
# find inline policies in found roles
|
# find inline policies in found roles
|
||||||
INLINEPOLICIES=$($AWSCLI iam list-role-policies --role-name $role --profile $PROFILE --region $REGION --query "PolicyNames[*]" --output text)
|
INLINEPOLICIES=$($AWSCLI iam list-role-policies --role-name $role $PROFILE_OPT --region $REGION --query "PolicyNames[*]" --output text)
|
||||||
for policy in $INLINEPOLICIES;do
|
for policy in $INLINEPOLICIES;do
|
||||||
textNotice "INLINE: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy --profile $PROFILE --region $REGION --output json"
|
textNotice "INLINE: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json"
|
||||||
done
|
done
|
||||||
# find attached policies in found roles
|
# find attached policies in found roles
|
||||||
ATTACHEDPOLICIES=$($AWSCLI iam list-attached-role-policies --role-name $role --profile $PROFILE --region $REGION --query "AttachedPolicies[*]" --output text)
|
ATTACHEDPOLICIES=$($AWSCLI iam list-attached-role-policies --role-name $role $PROFILE_OPT --region $REGION --query "AttachedPolicies[*]" --output text)
|
||||||
for policy in $ATTACHEDPOLICIES;do
|
for policy in $ATTACHEDPOLICIES;do
|
||||||
textNotice "ATTACHED: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy --profile $PROFILE --region $REGION --output json"
|
textNotice "ATTACHED: $AWSCLI iam get-role-policy --role-name $role --policy-name $policy $PROFILE_OPT --region $REGION --output json"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
@@ -777,10 +792,10 @@ check122(){
|
|||||||
ID122="1.22"
|
ID122="1.22"
|
||||||
TITLE122="Ensure a support role has been created to manage incidents with AWS Support (Scored)"
|
TITLE122="Ensure a support role has been created to manage incidents with AWS Support (Scored)"
|
||||||
textTitle "$ID122" "$TITLE122" "SCORED" "LEVEL1"
|
textTitle "$ID122" "$TITLE122" "SCORED" "LEVEL1"
|
||||||
SUPPORTPOLICYARN=$($AWSCLI iam list-policies --query "Policies[?PolicyName == 'AWSSupportAccess'].Arn" --profile $PROFILE --region $REGION --output text)
|
SUPPORTPOLICYARN=$($AWSCLI iam list-policies --query "Policies[?PolicyName == 'AWSSupportAccess'].Arn" $PROFILE_OPT --region $REGION --output text)
|
||||||
if [[ $SUPPORTPOLICYARN ]];then
|
if [[ $SUPPORTPOLICYARN ]];then
|
||||||
for policyarn in $SUPPORTPOLICYARN;do
|
for policyarn in $SUPPORTPOLICYARN;do
|
||||||
POLICYUSERS=$($AWSCLI iam list-entities-for-policy --policy-arn $SUPPORTPOLICYARN --profile $PROFILE --region $REGION --output json)
|
POLICYUSERS=$($AWSCLI iam list-entities-for-policy --policy-arn $SUPPORTPOLICYARN $PROFILE_OPT --region $REGION --output json)
|
||||||
if [[ $POLICYUSERS ]];then
|
if [[ $POLICYUSERS ]];then
|
||||||
textOK "Support Policy attached to $policyarn"
|
textOK "Support Policy attached to $policyarn"
|
||||||
for user in $(echo "$POLICYUSERS" | grep UserName | cut -d'"' -f4) ; do
|
for user in $(echo "$POLICYUSERS" | grep UserName | cut -d'"' -f4) ; do
|
||||||
@@ -800,7 +815,7 @@ check123(){
|
|||||||
ID123="1.23"
|
ID123="1.23"
|
||||||
TITLE123="Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)"
|
TITLE123="Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)"
|
||||||
textTitle "$ID123" "$TITLE123" "NOT_SCORED" "LEVEL1"
|
textTitle "$ID123" "$TITLE123" "NOT_SCORED" "LEVEL1"
|
||||||
LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text --profile $PROFILE --region $REGION)
|
LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION)
|
||||||
# List of USERS with KEY1 last_used_date as N/A
|
# List of USERS with KEY1 last_used_date as N/A
|
||||||
LIST_USERS_KEY1_NA=$(for user in $LIST_USERS; do grep $user $TEMP_REPORT_FILE|awk -F, '{ print $1,$11 }'|grep N/A |awk '{ print $1 }'; done)
|
LIST_USERS_KEY1_NA=$(for user in $LIST_USERS; do grep $user $TEMP_REPORT_FILE|awk -F, '{ print $1,$11 }'|grep N/A |awk '{ print $1 }'; done)
|
||||||
LIST_USERS_KEY1_ACTIVE=$(for user in $LIST_USERS_KEY1_NA; do grep $user $TEMP_REPORT_FILE|awk -F, '{ print $1,$9 }'|grep "true$"|awk '{ print $1 }'|sed 's/[[:blank:]]+/,/g' ; done)
|
LIST_USERS_KEY1_ACTIVE=$(for user in $LIST_USERS_KEY1_NA; do grep $user $TEMP_REPORT_FILE|awk -F, '{ print $1,$9 }'|grep "true$"|awk '{ print $1 }'|sed 's/[[:blank:]]+/,/g' ; done)
|
||||||
@@ -827,12 +842,12 @@ check124(){
|
|||||||
ID124="1.24"
|
ID124="1.24"
|
||||||
TITLE124="Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)"
|
TITLE124="Ensure IAM policies that allow full \"*:*\" administrative privileges are not created (Scored)"
|
||||||
textTitle "$ID124" "$TITLE124" "SCORED" "LEVEL1"
|
textTitle "$ID124" "$TITLE124" "SCORED" "LEVEL1"
|
||||||
LIST_CUSTOM_POLICIES=$($AWSCLI iam list-policies --output text --profile $PROFILE --region $REGION|grep 'arn:aws:iam::[0-9]\{12\}:'|awk '{ print $2 }')
|
LIST_CUSTOM_POLICIES=$($AWSCLI iam list-policies --output text $PROFILE_OPT --region $REGION|grep 'arn:aws:iam::[0-9]\{12\}:'|awk '{ print $2 }')
|
||||||
if [[ $LIST_CUSTOM_POLICIES ]]; then
|
if [[ $LIST_CUSTOM_POLICIES ]]; then
|
||||||
textNotice "Looking for custom policies: (skipping default policies - it may take few seconds...)"
|
textNotice "Looking for custom policies: (skipping default policies - it may take few seconds...)"
|
||||||
for policy in $LIST_CUSTOM_POLICIES; do
|
for policy in $LIST_CUSTOM_POLICIES; do
|
||||||
POLICY_VERSION=$($AWSCLI iam list-policies --profile $PROFILE --region $REGION --query 'Policies[*].[Arn,DefaultVersionId]' --output text|grep -w $policy |awk '{ print $2}')
|
POLICY_VERSION=$($AWSCLI iam list-policies $PROFILE_OPT --region $REGION --query 'Policies[*].[Arn,DefaultVersionId]' --output text|grep -w $policy |awk '{ print $2}')
|
||||||
POLICY_WITH_FULL=$($AWSCLI iam get-policy-version --output text --policy-arn $policy --version-id $POLICY_VERSION --query "PolicyVersion.Document.Statement[?Effect == 'Allow' && contains(Resource, '*') && contains (Action, '*')]" --profile $PROFILE --region $REGION)
|
POLICY_WITH_FULL=$($AWSCLI iam get-policy-version --output text --policy-arn $policy --version-id $POLICY_VERSION --query "PolicyVersion.Document.Statement[?Effect == 'Allow' && contains(Resource, '*') && contains (Action, '*')]" $PROFILE_OPT --region $REGION)
|
||||||
if [[ $POLICY_WITH_FULL ]]; then
|
if [[ $POLICY_WITH_FULL ]]; then
|
||||||
POLICIES_ALLOW_LIST="$POLICIES_ALLOW_LIST $policy"
|
POLICIES_ALLOW_LIST="$POLICIES_ALLOW_LIST $policy"
|
||||||
fi
|
fi
|
||||||
@@ -854,10 +869,10 @@ check21(){
|
|||||||
ID21="2.1,2.01"
|
ID21="2.1,2.01"
|
||||||
TITLE21="Ensure CloudTrail is enabled in all regions (Scored)"
|
TITLE21="Ensure CloudTrail is enabled in all regions (Scored)"
|
||||||
textTitle "$ID21" "$TITLE21" "SCORED" "LEVEL1"
|
textTitle "$ID21" "$TITLE21" "SCORED" "LEVEL1"
|
||||||
LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].Name' --output text)
|
LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].Name' --output text)
|
||||||
if [[ $LIST_OF_TRAILS ]];then
|
if [[ $LIST_OF_TRAILS ]];then
|
||||||
for trail in $LIST_OF_TRAILS;do
|
for trail in $LIST_OF_TRAILS;do
|
||||||
MULTIREGION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].IsMultiRegionTrail' --output text --trail-name-list $trail)
|
MULTIREGION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].IsMultiRegionTrail' --output text --trail-name-list $trail)
|
||||||
if [[ $MULTIREGION_TRAIL_STATUS == 'False' ]];then
|
if [[ $MULTIREGION_TRAIL_STATUS == 'False' ]];then
|
||||||
textWarn "$trail trail in $REGION is not enabled in multi region mode"
|
textWarn "$trail trail in $REGION is not enabled in multi region mode"
|
||||||
else
|
else
|
||||||
@@ -873,10 +888,10 @@ check22(){
|
|||||||
ID22="2.2,2.02"
|
ID22="2.2,2.02"
|
||||||
TITLE22="Ensure CloudTrail log file validation is enabled (Scored)"
|
TITLE22="Ensure CloudTrail log file validation is enabled (Scored)"
|
||||||
textTitle "$ID22" "$TITLE22" "SCORED" "LEVEL2"
|
textTitle "$ID22" "$TITLE22" "SCORED" "LEVEL2"
|
||||||
LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].Name' --output text)
|
LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].Name' --output text)
|
||||||
if [[ $LIST_OF_TRAILS ]];then
|
if [[ $LIST_OF_TRAILS ]];then
|
||||||
for trail in $LIST_OF_TRAILS;do
|
for trail in $LIST_OF_TRAILS;do
|
||||||
LOGFILEVALIDATION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].LogFileValidationEnabled' --output text --trail-name-list $trail)
|
LOGFILEVALIDATION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].LogFileValidationEnabled' --output text --trail-name-list $trail)
|
||||||
if [[ $LOGFILEVALIDATION_TRAIL_STATUS == 'False' ]];then
|
if [[ $LOGFILEVALIDATION_TRAIL_STATUS == 'False' ]];then
|
||||||
textWarn "$trail trail in $REGION has not log file validation enabled"
|
textWarn "$trail trail in $REGION has not log file validation enabled"
|
||||||
else
|
else
|
||||||
@@ -892,10 +907,10 @@ check23(){
|
|||||||
ID23="2.3,2.03"
|
ID23="2.3,2.03"
|
||||||
TITLE23="Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)"
|
TITLE23="Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)"
|
||||||
textTitle "$ID23" "$TITLE23" "SCORED" "LEVEL1"
|
textTitle "$ID23" "$TITLE23" "SCORED" "LEVEL1"
|
||||||
CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text --profile $PROFILE --region $REGION)
|
CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text $PROFILE_OPT --region $REGION)
|
||||||
if [[ $CLOUDTRAILBUCKET ]];then
|
if [[ $CLOUDTRAILBUCKET ]];then
|
||||||
for bucket in $CLOUDTRAILBUCKET;do
|
for bucket in $CLOUDTRAILBUCKET;do
|
||||||
CLOUDTRAILBUCKET_HASALLPERMISIONS=$($AWSCLI s3api get-bucket-acl --bucket $bucket --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' --profile $PROFILE --region $REGION --output text)
|
CLOUDTRAILBUCKET_HASALLPERMISIONS=$($AWSCLI s3api get-bucket-acl --bucket $bucket --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' $PROFILE_OPT --region $REGION --output text)
|
||||||
if [[ $CLOUDTRAILBUCKET_HASALLPERMISIONS ]];then
|
if [[ $CLOUDTRAILBUCKET_HASALLPERMISIONS ]];then
|
||||||
textWarn "check your $bucket CloudTrail bucket ACL and Policy!"
|
textWarn "check your $bucket CloudTrail bucket ACL and Policy!"
|
||||||
else
|
else
|
||||||
@@ -911,12 +926,12 @@ check24(){
|
|||||||
ID24="2.4,2.04"
|
ID24="2.4,2.04"
|
||||||
TITLE24="Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)"
|
TITLE24="Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)"
|
||||||
textTitle "$ID24" "$TITLE24" "SCORED" "LEVEL1"
|
textTitle "$ID24" "$TITLE24" "SCORED" "LEVEL1"
|
||||||
TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion}' --output text | tr "\t" ',')
|
TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion}' --output text | tr "\t" ',')
|
||||||
if [[ $TRAILS_AND_REGIONS ]];then
|
if [[ $TRAILS_AND_REGIONS ]];then
|
||||||
for reg_trail in $TRAILS_AND_REGIONS;do
|
for reg_trail in $TRAILS_AND_REGIONS;do
|
||||||
trail=$(echo $reg_trail | cut -d',' -f2)
|
trail=$(echo $reg_trail | cut -d',' -f2)
|
||||||
TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1)
|
TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1)
|
||||||
LATESTDELIVERY_TIMESTAMP=$($AWSCLI cloudtrail get-trail-status --name $trail --profile $PROFILE --region $TRAIL_REGION --query 'LatestCloudWatchLogsDeliveryTime' --output text|grep -v None)
|
LATESTDELIVERY_TIMESTAMP=$($AWSCLI cloudtrail get-trail-status --name $trail $PROFILE_OPT --region $TRAIL_REGION --query 'LatestCloudWatchLogsDeliveryTime' --output text|grep -v None)
|
||||||
if [[ ! $LATESTDELIVERY_TIMESTAMP ]];then
|
if [[ ! $LATESTDELIVERY_TIMESTAMP ]];then
|
||||||
textWarn "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)"
|
textWarn "$trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)"
|
||||||
else
|
else
|
||||||
@@ -939,7 +954,7 @@ check25(){
|
|||||||
TITLE25="Ensure AWS Config is enabled in all regions (Scored)"
|
TITLE25="Ensure AWS Config is enabled in all regions (Scored)"
|
||||||
textTitle "$ID25" "$TITLE25" "SCORED" "LEVEL1"
|
textTitle "$ID25" "$TITLE25" "SCORED" "LEVEL1"
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice get-status --profile $PROFILE --region $regx --output json| grep "recorder: ON")
|
CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice get-status $PROFILE_OPT --region $regx --output json| grep "recorder: ON")
|
||||||
if [[ $CHECK_AWSCONFIG_STATUS ]];then
|
if [[ $CHECK_AWSCONFIG_STATUS ]];then
|
||||||
textOK "Region $regx has AWS Config recorder: ON" "$regx"
|
textOK "Region $regx has AWS Config recorder: ON" "$regx"
|
||||||
else
|
else
|
||||||
@@ -952,10 +967,10 @@ check26(){
|
|||||||
ID26="2.6,2.06"
|
ID26="2.6,2.06"
|
||||||
TITLE26="Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)"
|
TITLE26="Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)"
|
||||||
textTitle "$ID26" "$TITLE26" "SCORED" "LEVEL1"
|
textTitle "$ID26" "$TITLE26" "SCORED" "LEVEL1"
|
||||||
CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text --profile $PROFILE --region $REGION)
|
CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].S3BucketName' --output text $PROFILE_OPT --region $REGION)
|
||||||
if [[ $CLOUDTRAILBUCKET ]];then
|
if [[ $CLOUDTRAILBUCKET ]];then
|
||||||
for bucket in $CLOUDTRAILBUCKET;do
|
for bucket in $CLOUDTRAILBUCKET;do
|
||||||
CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket --profile $PROFILE --region $REGION --query 'LoggingEnabled.TargetBucket' --output text|grep -v None)
|
CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --region $REGION --query 'LoggingEnabled.TargetBucket' --output text|grep -v None)
|
||||||
if [[ $CLOUDTRAILBUCKET_LOGENABLED ]];then
|
if [[ $CLOUDTRAILBUCKET_LOGENABLED ]];then
|
||||||
textOK "Bucket access logging enabled in $bucket"
|
textOK "Bucket access logging enabled in $bucket"
|
||||||
else
|
else
|
||||||
@@ -971,10 +986,10 @@ check27(){
|
|||||||
ID27="2.7,2.07"
|
ID27="2.7,2.07"
|
||||||
TITLE27="Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)"
|
TITLE27="Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)"
|
||||||
textTitle "$ID27" "$TITLE27" "SCORED" "LEVEL2"
|
textTitle "$ID27" "$TITLE27" "SCORED" "LEVEL2"
|
||||||
CLOUDTRAILNAME=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].Name' --output text --profile $PROFILE --region $REGION)
|
CLOUDTRAILNAME=$($AWSCLI cloudtrail describe-trails --query 'trailList[*].Name' --output text $PROFILE_OPT --region $REGION)
|
||||||
if [[ $CLOUDTRAILNAME ]];then
|
if [[ $CLOUDTRAILNAME ]];then
|
||||||
for trail in $CLOUDTRAILNAME;do
|
for trail in $CLOUDTRAILNAME;do
|
||||||
CLOUDTRAILENC_ENABLED=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --trail $trail --query 'trailList[*].KmsKeyId' --output text)
|
CLOUDTRAILENC_ENABLED=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --trail $trail --query 'trailList[*].KmsKeyId' --output text)
|
||||||
if [[ $CLOUDTRAILENC_ENABLED ]];then
|
if [[ $CLOUDTRAILENC_ENABLED ]];then
|
||||||
textOK "KMS key found for $trail"
|
textOK "KMS key found for $trail"
|
||||||
else
|
else
|
||||||
@@ -991,16 +1006,16 @@ check28(){
|
|||||||
TITLE28="Ensure rotation for customer created CMKs is enabled (Scored)"
|
TITLE28="Ensure rotation for customer created CMKs is enabled (Scored)"
|
||||||
textTitle "$ID28" "$TITLE28" "SCORED" "LEVEL2"
|
textTitle "$ID28" "$TITLE28" "SCORED" "LEVEL2"
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
CHECK_KMS_KEYLIST=$($AWSCLI kms list-keys --profile $PROFILE --region $regx --output text --query 'Keys[*].KeyId')
|
CHECK_KMS_KEYLIST=$($AWSCLI kms list-keys $PROFILE_OPT --region $regx --output text --query 'Keys[*].KeyId')
|
||||||
if [[ $CHECK_KMS_KEYLIST ]];then
|
if [[ $CHECK_KMS_KEYLIST ]];then
|
||||||
CHECK_KMS_KEYLIST_NO_DEFAULT=$(for key in $CHECK_KMS_KEYLIST ; do $AWSCLI kms describe-key --key-id $key --profile $PROFILE --region $regx --output text|grep -v 'Default master key that protects my ACM private keys when no other key is defined'|awk '{ print $3 }'|awk -F'/' '{ print $2 }'; done)
|
CHECK_KMS_KEYLIST_NO_DEFAULT=$(for key in $CHECK_KMS_KEYLIST ; do $AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --output text|grep -v 'Default master key that protects my ACM private keys when no other key is defined'|awk '{ print $3 }'|awk -F'/' '{ print $2 }'; done)
|
||||||
for key in $CHECK_KMS_KEYLIST_NO_DEFAULT; do
|
for key in $CHECK_KMS_KEYLIST_NO_DEFAULT; do
|
||||||
CHECK_KMS_KEY_TYPE=$($AWSCLI kms describe-key --key-id $key --profile $PROFILE --region $regx --query 'KeyMetadata.Origin' | sed 's/["]//g')
|
CHECK_KMS_KEY_TYPE=$($AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --query 'KeyMetadata.Origin' | sed 's/["]//g')
|
||||||
if [[ $CHECK_KMS_KEY_TYPE == "EXTERNAL" ]];then
|
if [[ $CHECK_KMS_KEY_TYPE == "EXTERNAL" ]];then
|
||||||
textOK "Key $key in Region $regx Customer Uploaded Key Material." "$regx"
|
textOK "Key $key in Region $regx Customer Uploaded Key Material." "$regx"
|
||||||
else
|
else
|
||||||
CHECK_KMS_KEY_ROTATION=$($AWSCLI kms get-key-rotation-status --key-id $key --profile $PROFILE --region $regx --output text)
|
CHECK_KMS_KEY_ROTATION=$($AWSCLI kms get-key-rotation-status --key-id $key $PROFILE_OPT --region $regx --output text)
|
||||||
#CHECK_KMS_DEFAULT_KEY=$($AWSCLI kms describe-key --key-id $key --profile $PROFILE --region $regx --query 'KeyMetadata.Description' | sed -n '/Default master key that protects my ACM private keys when no other key is defined /p'|| echo "False")
|
#CHECK_KMS_DEFAULT_KEY=$($AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --query 'KeyMetadata.Description' | sed -n '/Default master key that protects my ACM private keys when no other key is defined /p'|| echo "False")
|
||||||
if [[ $CHECK_KMS_KEY_ROTATION == "True" ]];then
|
if [[ $CHECK_KMS_KEY_ROTATION == "True" ]];then
|
||||||
textOK "Key $key in Region $regx is set correctly"
|
textOK "Key $key in Region $regx is set correctly"
|
||||||
elif [[ $CHECK_KMS_KEY_ROTATION == "False" && $CHECK_KMS_DEFAULT_KEY ]];then
|
elif [[ $CHECK_KMS_KEY_ROTATION == "False" && $CHECK_KMS_DEFAULT_KEY ]];then
|
||||||
@@ -1021,9 +1036,9 @@ check31(){
|
|||||||
ID31="3.1,3.01"
|
ID31="3.1,3.01"
|
||||||
TITLE31="Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)"
|
TITLE31="Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)"
|
||||||
textTitle "$ID31" "$TITLE31" "SCORED" "LEVEL1"
|
textTitle "$ID31" "$TITLE31" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep AccessDenied)
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep AccessDenied)
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters for Access Denied enabled"
|
textOK "CloudWatch group found with metric filters for Access Denied enabled"
|
||||||
else
|
else
|
||||||
@@ -1038,9 +1053,9 @@ check32(){
|
|||||||
ID32="3.2,3.02"
|
ID32="3.2,3.02"
|
||||||
TITLE32="Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)"
|
TITLE32="Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)"
|
||||||
textTitle "$ID32" "$TITLE32" "SCORED" "LEVEL1"
|
textTitle "$ID32" "$TITLE32" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'userIdentity.sessionContext.attributes.mfaAuthenticated.*true')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'userIdentity.sessionContext.attributes.mfaAuthenticated.*true')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters for sign-in Console without MFA enabled"
|
textOK "CloudWatch group found with metric filters for sign-in Console without MFA enabled"
|
||||||
else
|
else
|
||||||
@@ -1055,9 +1070,9 @@ check33(){
|
|||||||
ID33="3.3,3.03"
|
ID33="3.3,3.03"
|
||||||
TITLE33="Ensure a log metric filter and alarm exist for usage of root account (Scored)"
|
TITLE33="Ensure a log metric filter and alarm exist for usage of root account (Scored)"
|
||||||
textTitle "$ID33" "$TITLE33" "SCORED" "LEVEL1"
|
textTitle "$ID33" "$TITLE33" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION |grep -E 'userIdentity.*Root.*AwsServiceEvent')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION |grep -E 'userIdentity.*Root.*AwsServiceEvent')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters for usage of root account enabled"
|
textOK "CloudWatch group found with metric filters for usage of root account enabled"
|
||||||
else
|
else
|
||||||
@@ -1072,9 +1087,9 @@ check34(){
|
|||||||
ID34="3.4,3.04"
|
ID34="3.4,3.04"
|
||||||
TITLE34="Ensure a log metric filter and alarm exist for IAM policy changes (Scored)"
|
TITLE34="Ensure a log metric filter and alarm exist for IAM policy changes (Scored)"
|
||||||
textTitle "$ID34" "$TITLE34" "SCORED" "LEVEL1"
|
textTitle "$ID34" "$TITLE34" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'DeleteGroupPolicy.*DeleteRolePolicy.*DeleteUserPolicy.*PutGroupPolicy.*PutRolePolicy.*PutUserPolicy.*CreatePolicy.*DeletePolicy.*CreatePolicyVersion.*DeletePolicyVersion.*AttachRolePolicy.*DetachRolePolicy.*AttachUserPolicy.*DetachUserPolicy.*AttachGroupPolicy.*DetachGroupPolicy')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'DeleteGroupPolicy.*DeleteRolePolicy.*DeleteUserPolicy.*PutGroupPolicy.*PutRolePolicy.*PutUserPolicy.*CreatePolicy.*DeletePolicy.*CreatePolicyVersion.*DeletePolicyVersion.*AttachRolePolicy.*DetachRolePolicy.*AttachUserPolicy.*DetachUserPolicy.*AttachGroupPolicy.*DetachGroupPolicy')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters for IAM policy changes enabled"
|
textOK "CloudWatch group found with metric filters for IAM policy changes enabled"
|
||||||
else
|
else
|
||||||
@@ -1089,9 +1104,9 @@ check35(){
|
|||||||
ID35="3.5,3.05"
|
ID35="3.5,3.05"
|
||||||
TITLE35="Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)"
|
TITLE35="Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)"
|
||||||
textTitle "$ID35" "$TITLE35" "SCORED" "LEVEL1"
|
textTitle "$ID35" "$TITLE35" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'CreateTrail.*UpdateTrail.*DeleteTrail.*StartLogging.*StopLogging')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'CreateTrail.*UpdateTrail.*DeleteTrail.*StartLogging.*StopLogging')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters for CloudTrail configuration changes enabled"
|
textOK "CloudWatch group found with metric filters for CloudTrail configuration changes enabled"
|
||||||
else
|
else
|
||||||
@@ -1106,9 +1121,9 @@ check36(){
|
|||||||
ID36="3.6,3.06"
|
ID36="3.6,3.06"
|
||||||
TITLE36="Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)"
|
TITLE36="Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)"
|
||||||
textTitle "$ID36" "$TITLE36" "SCORED" "LEVEL2"
|
textTitle "$ID36" "$TITLE36" "SCORED" "LEVEL2"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'ConsoleLogin.*Failed')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'ConsoleLogin.*Failed')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters for usage of root account enabled"
|
textOK "CloudWatch group found with metric filters for usage of root account enabled"
|
||||||
else
|
else
|
||||||
@@ -1123,9 +1138,9 @@ check37(){
|
|||||||
ID37="3.7,3.07"
|
ID37="3.7,3.07"
|
||||||
TITLE37="Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)"
|
TITLE37="Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)"
|
||||||
textTitle "$ID37" "$TITLE37" "SCORED" "LEVEL2"
|
textTitle "$ID37" "$TITLE37" "SCORED" "LEVEL2"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'kms.amazonaws.com.*DisableKey.*ScheduleKeyDeletion')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'kms.amazonaws.com.*DisableKey.*ScheduleKeyDeletion')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters enabled"
|
textOK "CloudWatch group found with metric filters enabled"
|
||||||
else
|
else
|
||||||
@@ -1140,9 +1155,9 @@ check38(){
|
|||||||
ID38="3.8,3.08"
|
ID38="3.8,3.08"
|
||||||
TITLE38="Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)"
|
TITLE38="Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)"
|
||||||
textTitle "$ID38" "$TITLE38" "SCORED" "LEVEL1"
|
textTitle "$ID38" "$TITLE38" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 's3.amazonaws.com.*PutBucketAcl.*PutBucketPolicy.*PutBucketCors.*PutBucketLifecycle.*PutBucketReplication.*DeleteBucketPolicy.*DeleteBucketCors.*DeleteBucketLifecycle.*DeleteBucketReplication')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 's3.amazonaws.com.*PutBucketAcl.*PutBucketPolicy.*PutBucketCors.*PutBucketLifecycle.*PutBucketReplication.*DeleteBucketPolicy.*DeleteBucketCors.*DeleteBucketLifecycle.*DeleteBucketReplication')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters enabled"
|
textOK "CloudWatch group found with metric filters enabled"
|
||||||
else
|
else
|
||||||
@@ -1157,9 +1172,9 @@ check39(){
|
|||||||
ID39="3.9,3.09"
|
ID39="3.9,3.09"
|
||||||
TITLE39="Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)"
|
TITLE39="Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)"
|
||||||
textTitle "$ID39" "$TITLE39" "SCORED" "LEVEL2"
|
textTitle "$ID39" "$TITLE39" "SCORED" "LEVEL2"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'config.amazonaws.com.*StopConfigurationRecorder.*DeleteDeliveryChannel.*PutDeliveryChannel.*PutConfigurationRecorder')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'config.amazonaws.com.*StopConfigurationRecorder.*DeleteDeliveryChannel.*PutDeliveryChannel.*PutConfigurationRecorder')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters enabled"
|
textOK "CloudWatch group found with metric filters enabled"
|
||||||
else
|
else
|
||||||
@@ -1174,9 +1189,9 @@ check310(){
|
|||||||
ID310="3.10"
|
ID310="3.10"
|
||||||
TITLE310="Ensure a log metric filter and alarm exist for security group changes (Scored)"
|
TITLE310="Ensure a log metric filter and alarm exist for security group changes (Scored)"
|
||||||
textTitle "$ID310" "$TITLE310" "SCORED" "LEVEL2"
|
textTitle "$ID310" "$TITLE310" "SCORED" "LEVEL2"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'AuthorizeSecurityGroupIngress.*AuthorizeSecurityGroupEgress.*RevokeSecurityGroupIngress.*RevokeSecurityGroupEgress.*CreateSecurityGroup.*DeleteSecurityGroup')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'AuthorizeSecurityGroupIngress.*AuthorizeSecurityGroupEgress.*RevokeSecurityGroupIngress.*RevokeSecurityGroupEgress.*CreateSecurityGroup.*DeleteSecurityGroup')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters enabled"
|
textOK "CloudWatch group found with metric filters enabled"
|
||||||
else
|
else
|
||||||
@@ -1191,9 +1206,9 @@ check311(){
|
|||||||
ID311="3.11"
|
ID311="3.11"
|
||||||
TITLE311="Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)"
|
TITLE311="Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)"
|
||||||
textTitle "$ID311" "$TITLE311" "SCORED" "LEVEL2"
|
textTitle "$ID311" "$TITLE311" "SCORED" "LEVEL2"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'CreateNetworkAcl.*CreateNetworkAclEntry.*DeleteNetworkAcl.*DeleteNetworkAclEntry.*ReplaceNetworkAclEntry.*ReplaceNetworkAclAssociation')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'CreateNetworkAcl.*CreateNetworkAclEntry.*DeleteNetworkAcl.*DeleteNetworkAclEntry.*ReplaceNetworkAclEntry.*ReplaceNetworkAclAssociation')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters enabled"
|
textOK "CloudWatch group found with metric filters enabled"
|
||||||
else
|
else
|
||||||
@@ -1208,9 +1223,9 @@ check312(){
|
|||||||
ID312="3.12"
|
ID312="3.12"
|
||||||
TITLE312="Ensure a log metric filter and alarm exist for changes to network gateways (Scored)"
|
TITLE312="Ensure a log metric filter and alarm exist for changes to network gateways (Scored)"
|
||||||
textTitle "$ID312" "$TITLE312" "SCORED" "LEVEL1"
|
textTitle "$ID312" "$TITLE312" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'CreateCustomerGateway.*DeleteCustomerGateway.*AttachInternetGateway.*CreateInternetGateway.*DeleteInternetGateway.*DetachInternetGateway')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'CreateCustomerGateway.*DeleteCustomerGateway.*AttachInternetGateway.*CreateInternetGateway.*DeleteInternetGateway.*DetachInternetGateway')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters enabled"
|
textOK "CloudWatch group found with metric filters enabled"
|
||||||
else
|
else
|
||||||
@@ -1225,9 +1240,9 @@ check313(){
|
|||||||
ID313="3.13"
|
ID313="3.13"
|
||||||
TITLE313="Ensure a log metric filter and alarm exist for route table changes (Scored)"
|
TITLE313="Ensure a log metric filter and alarm exist for route table changes (Scored)"
|
||||||
textTitle "$ID313" "$TITLE313" "SCORED" "LEVEL1"
|
textTitle "$ID313" "$TITLE313" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'CreateRoute.*CreateRouteTable.*ReplaceRoute.*ReplaceRouteTableAssociation.*DeleteRouteTable.*DeleteRoute.*DisassociateRouteTable')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'CreateRoute.*CreateRouteTable.*ReplaceRoute.*ReplaceRouteTableAssociation.*DeleteRouteTable.*DeleteRoute.*DisassociateRouteTable')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters enabled"
|
textOK "CloudWatch group found with metric filters enabled"
|
||||||
else
|
else
|
||||||
@@ -1242,9 +1257,9 @@ check314(){
|
|||||||
ID314="3.14"
|
ID314="3.14"
|
||||||
TITLE314="Ensure a log metric filter and alarm exist for VPC changes (Scored)"
|
TITLE314="Ensure a log metric filter and alarm exist for VPC changes (Scored)"
|
||||||
textTitle "$ID314" "$TITLE314" "SCORED" "LEVEL1"
|
textTitle "$ID314" "$TITLE314" "SCORED" "LEVEL1"
|
||||||
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails --profile $PROFILE --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | awk -F: '{ print $7 }')
|
||||||
if [[ $CLOUDWATCH_GROUP ]];then
|
if [[ $CLOUDWATCH_GROUP ]];then
|
||||||
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP --profile $PROFILE --region $REGION --query 'metricFilters' | grep -E 'CreateVpc.*DeleteVpc.*ModifyVpcAttribute.*AcceptVpcPeeringConnection.*CreateVpcPeeringConnection.*DeleteVpcPeeringConnection.*RejectVpcPeeringConnection.*AttachClassicLinkVpc.*DetachClassicLinkVpc.*DisableVpcClassicLink.*EnableVpcClassicLink')
|
METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $CLOUDWATCH_GROUP $PROFILE_OPT --region $REGION --query 'metricFilters' | grep -E 'CreateVpc.*DeleteVpc.*ModifyVpcAttribute.*AcceptVpcPeeringConnection.*CreateVpcPeeringConnection.*DeleteVpcPeeringConnection.*RejectVpcPeeringConnection.*AttachClassicLinkVpc.*DetachClassicLinkVpc.*DisableVpcClassicLink.*EnableVpcClassicLink')
|
||||||
if [[ $METRICFILTER_SET ]];then
|
if [[ $METRICFILTER_SET ]];then
|
||||||
textOK "CloudWatch group found with metric filters enabled"
|
textOK "CloudWatch group found with metric filters enabled"
|
||||||
else
|
else
|
||||||
@@ -1261,13 +1276,13 @@ check315(){
|
|||||||
textTitle "$ID315" "$TITLE315" "NOT_SCORED" "LEVEL1"
|
textTitle "$ID315" "$TITLE315" "NOT_SCORED" "LEVEL1"
|
||||||
CAN_SNS_LIST_SUBS=1
|
CAN_SNS_LIST_SUBS=1
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
TOPICS_LIST=$($AWSCLI sns list-topics --profile $PROFILE --region $regx --output text --query 'Topics[*].TopicArn')
|
TOPICS_LIST=$($AWSCLI sns list-topics $PROFILE_OPT --region $regx --output text --query 'Topics[*].TopicArn')
|
||||||
ntopics=$(echo $TOPICS_LIST | wc -w )
|
ntopics=$(echo $TOPICS_LIST | wc -w )
|
||||||
if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then
|
if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then
|
||||||
textNotice "Region $regx has $ntopics topics" "$regx"
|
textNotice "Region $regx has $ntopics topics" "$regx"
|
||||||
for topic in $TOPICS_LIST; do
|
for topic in $TOPICS_LIST; do
|
||||||
TOPIC_SHORT=$(echo $topic | awk -F: '{ print $6 }')
|
TOPIC_SHORT=$(echo $topic | awk -F: '{ print $6 }')
|
||||||
CHECK_TOPIC_LIST=$($AWSCLI sns list-subscriptions-by-topic --topic-arn $topic --profile $PROFILE --region $regx --query 'Subscriptions[*].{Endpoint:Endpoint,Protocol:Protocol}' --output text --max-items $MAXITEMS 2> /dev/null)
|
CHECK_TOPIC_LIST=$($AWSCLI sns list-subscriptions-by-topic --topic-arn $topic $PROFILE_OPT --region $regx --query 'Subscriptions[*].{Endpoint:Endpoint,Protocol:Protocol}' --output text --max-items $MAXITEMS 2> /dev/null)
|
||||||
if [[ $? -eq 255 ]]; then
|
if [[ $? -eq 255 ]]; then
|
||||||
# Permission error
|
# Permission error
|
||||||
export CAN_SNS_LIST_SUBS=0
|
export CAN_SNS_LIST_SUBS=0
|
||||||
@@ -1297,7 +1312,7 @@ check41(){
|
|||||||
TITLE41="Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)"
|
TITLE41="Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)"
|
||||||
textTitle "$ID41" "$TITLE41" "SCORED" "LEVEL1"
|
textTitle "$ID41" "$TITLE41" "SCORED" "LEVEL1"
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
SG_LIST=$($AWSCLI ec2 describe-security-groups --filters "Name=ip-permission.to-port,Values=22" --query 'SecurityGroups[?length(IpPermissions[?ToPort==`22` && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' --profile $PROFILE --region $regx --output text)
|
SG_LIST=$($AWSCLI ec2 describe-security-groups --filters "Name=ip-permission.to-port,Values=22" --query 'SecurityGroups[?length(IpPermissions[?ToPort==`22` && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupId:GroupId}' $PROFILE_OPT --region $regx --output text)
|
||||||
if [[ $SG_LIST ]];then
|
if [[ $SG_LIST ]];then
|
||||||
for SG in $SG_LIST;do
|
for SG in $SG_LIST;do
|
||||||
textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx"
|
textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx"
|
||||||
@@ -1313,7 +1328,7 @@ check42(){
|
|||||||
TITLE42="Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)"
|
TITLE42="Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)"
|
||||||
textTitle "$ID42" "$TITLE42" "SCORED" "LEVEL1"
|
textTitle "$ID42" "$TITLE42" "SCORED" "LEVEL1"
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
SG_LIST=$($AWSCLI ec2 describe-security-groups --filters "Name=ip-permission.to-port,Values=3389" --query 'SecurityGroups[?length(IpPermissions[?ToPort==`3389` && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupName: GroupName}' --profile $PROFILE --region $regx --output text)
|
SG_LIST=$($AWSCLI ec2 describe-security-groups --filters "Name=ip-permission.to-port,Values=3389" --query 'SecurityGroups[?length(IpPermissions[?ToPort==`3389` && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]) > `0`].{GroupName: GroupName}' $PROFILE_OPT --region $regx --output text)
|
||||||
if [[ $SG_LIST ]];then
|
if [[ $SG_LIST ]];then
|
||||||
for SG in $SG_LIST;do
|
for SG in $SG_LIST;do
|
||||||
textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx"
|
textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx"
|
||||||
@@ -1329,7 +1344,7 @@ check43(){
|
|||||||
TITLE43="Ensure VPC Flow Logging is Enabled in all VPCs (Scored)"
|
TITLE43="Ensure VPC Flow Logging is Enabled in all VPCs (Scored)"
|
||||||
textTitle "$ID43" "$TITLE43" "SCORED" "LEVEL2"
|
textTitle "$ID43" "$TITLE43" "SCORED" "LEVEL2"
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
CHECK_FL=$($AWSCLI ec2 describe-flow-logs --profile $PROFILE --region $regx --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].LogGroupName' --output text)
|
CHECK_FL=$($AWSCLI ec2 describe-flow-logs $PROFILE_OPT --region $regx --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].LogGroupName' --output text)
|
||||||
if [[ $CHECK_FL ]];then
|
if [[ $CHECK_FL ]];then
|
||||||
for FL in $CHECK_FL;do
|
for FL in $CHECK_FL;do
|
||||||
textOK "VPCFlowLog is enabled for LogGroupName: $FL in Region $regx" "$regx"
|
textOK "VPCFlowLog is enabled for LogGroupName: $FL in Region $regx" "$regx"
|
||||||
@@ -1345,7 +1360,7 @@ check44(){
|
|||||||
TITLE44="Ensure the default security group of every VPC restricts all traffic (Scored)"
|
TITLE44="Ensure the default security group of every VPC restricts all traffic (Scored)"
|
||||||
textTitle "$ID44" "$TITLE44" "SCORED" "LEVEL2"
|
textTitle "$ID44" "$TITLE44" "SCORED" "LEVEL2"
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
CHECK_SGDEFAULT=$($AWSCLI ec2 describe-security-groups --profile $PROFILE --region $regx --filters Name=group-name,Values='default' --query 'SecurityGroups[*].{IpPermissions:IpPermissions,IpPermissionsEgress:IpPermissionsEgress,GroupId:GroupId}' --output text |grep 0.0.0.0)
|
CHECK_SGDEFAULT=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --filters Name=group-name,Values='default' --query 'SecurityGroups[*].{IpPermissions:IpPermissions,IpPermissionsEgress:IpPermissionsEgress,GroupId:GroupId}' --output text |grep 0.0.0.0)
|
||||||
if [[ $CHECK_SGDEFAULT ]];then
|
if [[ $CHECK_SGDEFAULT ]];then
|
||||||
textWarn "Default Security Groups found that allow 0.0.0.0 IN or OUT traffic in Region $regx" "$regx"
|
textWarn "Default Security Groups found that allow 0.0.0.0 IN or OUT traffic in Region $regx" "$regx"
|
||||||
else
|
else
|
||||||
@@ -1361,13 +1376,13 @@ check45(){
|
|||||||
textTitle "$ID45" "$TITLE45" "NOT_SCORED" "LEVEL2"
|
textTitle "$ID45" "$TITLE45" "NOT_SCORED" "LEVEL2"
|
||||||
textNotice "Looking for VPC peering in all regions... "
|
textNotice "Looking for VPC peering in all regions... "
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
LIST_OF_VPCS_PEERING_CONNECTIONS=$($AWSCLI ec2 describe-vpc-peering-connections --output text --profile $PROFILE --region $regx --query 'VpcPeeringConnections[*].VpcPeeringConnectionId')
|
LIST_OF_VPCS_PEERING_CONNECTIONS=$($AWSCLI ec2 describe-vpc-peering-connections --output text $PROFILE_OPT --region $regx --query 'VpcPeeringConnections[*].VpcPeeringConnectionId')
|
||||||
if [[ $LIST_OF_VPCS_PEERING_CONNECTIONS ]];then
|
if [[ $LIST_OF_VPCS_PEERING_CONNECTIONS ]];then
|
||||||
textNotice "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS - review routing tables" "$regx"
|
textNotice "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS - review routing tables" "$regx"
|
||||||
#LIST_OF_VPCS=$($AWSCLI ec2 describe-vpcs --profile $PROFILE --region $regx --query 'Vpcs[*].VpcId' --output text)
|
#LIST_OF_VPCS=$($AWSCLI ec2 describe-vpcs $PROFILE_OPT --region $regx --query 'Vpcs[*].VpcId' --output text)
|
||||||
#aws ec2 describe-route-tables --filter "Name=vpc-id,Values=vpc-0213e864" --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" --profile $PROFILE --region $regx
|
#aws ec2 describe-route-tables --filter "Name=vpc-id,Values=vpc-0213e864" --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" $PROFILE_OPT --region $regx
|
||||||
# for vpc in $LIST_OF_VPCS; do
|
# for vpc in $LIST_OF_VPCS; do
|
||||||
# VPCS_WITH_PEERING=$($AWSCLI ec2 describe-route-tables --filter "Name=vpc-id,Values=$vpc" --profile $PROFILE --region $regx --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" |grep GatewayId|grep pcx-)
|
# VPCS_WITH_PEERING=$($AWSCLI ec2 describe-route-tables --filter "Name=vpc-id,Values=$vpc" $PROFILE_OPT --region $regx --query "RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes, AssociatedSubnets:Associations[*].SubnetId}" |grep GatewayId|grep pcx-)
|
||||||
# done
|
# done
|
||||||
#echo $VPCS_WITH_PEERING
|
#echo $VPCS_WITH_PEERING
|
||||||
else
|
else
|
||||||
@@ -1383,15 +1398,15 @@ extra71(){
|
|||||||
textTitle "$ID71" "$TITLE71" "NOT_SCORED" "EXTRA"
|
textTitle "$ID71" "$TITLE71" "NOT_SCORED" "EXTRA"
|
||||||
|
|
||||||
ADMIN_GROUPS=''
|
ADMIN_GROUPS=''
|
||||||
AWS_GROUPS=$($AWSCLI --profile $PROFILE iam list-groups --output text --query 'Groups[].GroupName')
|
AWS_GROUPS=$($AWSCLI $PROFILE_OPT iam list-groups --output text --query 'Groups[].GroupName')
|
||||||
for grp in $AWS_GROUPS; do
|
for grp in $AWS_GROUPS; do
|
||||||
# aws --profile onlinetraining iam list-attached-group-policies --group-name Administrators --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess'
|
# aws --profile onlinetraining iam list-attached-group-policies --group-name Administrators --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess'
|
||||||
# list-attached-group-policies
|
# list-attached-group-policies
|
||||||
CHECK_ADMIN_GROUP=$($AWSCLI --profile $PROFILE iam list-attached-group-policies --group-name $grp --output json --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess')
|
CHECK_ADMIN_GROUP=$($AWSCLI $PROFILE_OPT iam list-attached-group-policies --group-name $grp --output json --query 'AttachedPolicies[].PolicyArn' | grep 'arn:aws:iam::aws:policy/AdministratorAccess')
|
||||||
if [[ $CHECK_ADMIN_GROUP ]]; then
|
if [[ $CHECK_ADMIN_GROUP ]]; then
|
||||||
ADMIN_GROUPS="$ADMIN_GROUPS $grp"
|
ADMIN_GROUPS="$ADMIN_GROUPS $grp"
|
||||||
textNotice "$grp group provides administrative access"
|
textNotice "$grp group provides administrative access"
|
||||||
ADMIN_USERS=$($AWSCLI --profile $PROFILE iam get-group --group-name $grp --output json --query 'Users[].UserName' | grep '"' | cut -d'"' -f2 )
|
ADMIN_USERS=$($AWSCLI $PROFILE_OPT iam get-group --group-name $grp --output json --query 'Users[].UserName' | grep '"' | cut -d'"' -f2 )
|
||||||
for auser in $ADMIN_USERS; do
|
for auser in $ADMIN_USERS; do
|
||||||
# users in group are Administrators
|
# users in group are Administrators
|
||||||
# users
|
# users
|
||||||
@@ -1417,9 +1432,9 @@ extra72(){
|
|||||||
textTitle "$ID72" "$TITLE72" "NOT_SCORED" "EXTRA"
|
textTitle "$ID72" "$TITLE72" "NOT_SCORED" "EXTRA"
|
||||||
textNotice "Looking for EBS Snapshots in all regions... "
|
textNotice "Looking for EBS Snapshots in all regions... "
|
||||||
for regx in $REGIONS; do
|
for regx in $REGIONS; do
|
||||||
LIST_OF_EBS_SNAPSHOTS=$($AWSCLI ec2 describe-snapshots --profile $PROFILE --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 | grep -v None 2> /dev/null)
|
||||||
for snapshot in $LIST_OF_EBS_SNAPSHOTS; do
|
for snapshot in $LIST_OF_EBS_SNAPSHOTS; do
|
||||||
SNAPSHOT_IS_PUBLIC=$($AWSCLI ec2 describe-snapshot-attribute --profile $PROFILE --region $regx --output text --snapshot-id $snapshot --attribute createVolumePermission --query "CreateVolumePermissions[?Group=='all']")
|
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
|
if [[ $SNAPSHOT_IS_PUBLIC ]];then
|
||||||
textWarn "$regx: $snapshot is currently Public!" "$regx"
|
textWarn "$regx: $snapshot is currently Public!" "$regx"
|
||||||
else
|
else
|
||||||
@@ -1436,9 +1451,9 @@ extra73(){
|
|||||||
TITLE73="Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)"
|
TITLE73="Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)"
|
||||||
textTitle "$ID73" "$TITLE73" "NOT_SCORED" "EXTRA"
|
textTitle "$ID73" "$TITLE73" "NOT_SCORED" "EXTRA"
|
||||||
textNotice "Looking for open S3 Buckets (ACLs and Policies) in all regions... "
|
textNotice "Looking for open S3 Buckets (ACLs and Policies) in all regions... "
|
||||||
ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' --profile $PROFILE --region $REGION --output text)
|
ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' $PROFILE_OPT --region $REGION --output text)
|
||||||
for bucket in $ALL_BUCKETS_LIST; do
|
for bucket in $ALL_BUCKETS_LIST; do
|
||||||
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket --profile $PROFILE --region $REGION --output text)
|
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket $PROFILE_OPT --region $REGION --output text)
|
||||||
if [[ "None" == $BUCKET_LOCATION ]]; then
|
if [[ "None" == $BUCKET_LOCATION ]]; then
|
||||||
BUCKET_LOCATION="us-east-1"
|
BUCKET_LOCATION="us-east-1"
|
||||||
fi
|
fi
|
||||||
@@ -1446,14 +1461,14 @@ extra73(){
|
|||||||
BUCKET_LOCATION="eu-west-1"
|
BUCKET_LOCATION="eu-west-1"
|
||||||
fi
|
fi
|
||||||
# check if AllUsers is in the ACL as Grantee
|
# check if AllUsers is in the ACL as Grantee
|
||||||
CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE)
|
CHECK_BUCKET_ALLUSERS_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AllUsers']" --output text |grep -v GRANTEE)
|
||||||
CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL)
|
CHECK_BUCKET_ALLUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_ALLUSERS_ACL)
|
||||||
# check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only
|
# check if AuthenticatedUsers is in the ACL as Grantee, they will have access with sigened URL only
|
||||||
CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE)
|
CHECK_BUCKET_AUTHUSERS_ACL=$($AWSCLI s3api get-bucket-acl $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --query "Grants[?Grantee.URI == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers']" --output text |grep -v GRANTEE)
|
||||||
CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL)
|
CHECK_BUCKET_AUTHUSERS_ACL_SINGLE_LINE=$(echo -ne $CHECK_BUCKET_AUTHUSERS_ACL)
|
||||||
# to prevent error NoSuchBucketPolicy first clean the output controlling stderr
|
# to prevent error NoSuchBucketPolicy first clean the output controlling stderr
|
||||||
TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX)
|
TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX)
|
||||||
$AWSCLI s3api get-bucket-policy --profile $PROFILE --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null
|
$AWSCLI s3api get-bucket-policy $PROFILE_OPT --region $BUCKET_LOCATION --bucket $bucket --output text --query Policy > $TEMP_POLICY_FILE 2> /dev/null
|
||||||
# check if the S3 policy has Principal as *
|
# check if the S3 policy has Principal as *
|
||||||
CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*)
|
CHECK_BUCKET_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'|awk '/Principal/ && !skip { print } { skip = /Deny/} '|grep ^\"Principal|grep \*)
|
||||||
if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then
|
if [[ $CHECK_BUCKET_ALLUSERS_ACL || $CHECK_BUCKET_AUTHUSERS_ACL || $CHECK_BUCKET_ALLUSERS_POLICY ]];then
|
||||||
|
|||||||
Reference in New Issue
Block a user