From 8913ca84d038405c9b3608b9bf8f2517b4c3ed5a Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 14:59:20 -0500 Subject: [PATCH 01/20] exit script if there are problems with the credentials. --- prowler | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/prowler b/prowler index d623447b..8488183d 100755 --- a/prowler +++ b/prowler @@ -324,7 +324,14 @@ prowlerBanner() { # Get whoami in AWS, who is the user running this shell script getWhoami(){ if [[ $MODE == "csv" ]]; then - CALLER_ARN=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Arn" | tr -d '"') + CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Arn") + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi + CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') textTitle "0.0" "Show report generation info" textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" else @@ -333,10 +340,24 @@ getWhoami(){ echo "" 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 - $AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION | grep ':' + echo "Caller Identity:" + $AWSCLI sts get-caller-identity --output text --profile $PROFILE --region $REGION --query "Arn" + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi + echo "" else echo "Caller Identity:" $AWSCLI sts get-caller-identity --output table --profile $PROFILE --region $REGION + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi echo "" fi fi From 5c335b28b2fb49bcb90ebe17b10a0a38ebd5d139 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 15:36:35 -0500 Subject: [PATCH 02/20] handle permission failure on list-subscriptions-by-topic gracefully --- prowler | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/prowler b/prowler index 8488183d..b51176b9 100755 --- a/prowler +++ b/prowler @@ -1230,12 +1230,19 @@ check315(){ ID315="3.15" TITLE315="Ensure appropriate subscribers to each SNS topic (Not Scored)" textTitle "$ID315" "$TITLE315" "0" + CAN_SNS_LIST_SUBS=1 for regx in $REGIONS; do TOPICS_LIST=$($AWSCLI sns list-topics --profile $PROFILE --region $regx --output text --query 'Topics[*].TopicArn') - if [[ $TOPICS_LIST ]];then + if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then for topic in $TOPICS_LIST; do - 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 | grep -v "None") - if [[ $CHECK_TOPIC_LIST ]]; then + 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) + if [[ $? -eq 255 ]]; then + # Permission error + export CAN_SNS_LIST_SUBS=0 + textNotice "No permission to list topics" + break; + fi + if [[ $(grep -v 'None' $CHECK_TOPIC_LIST) ]]; then TOPIC_SHORT=$(echo $topic | awk -F: '{ print $7 }') textNotice "Region $regx with Topic $TOPIC_SHORT:" "$regx" textNotice "- Suscription: $CHECK_TOPIC_LIST" "$regx" @@ -1244,6 +1251,8 @@ check315(){ textWarn " - Region $regx and Topic $topic" "$regx" fi done + elif [[ $CAN_SNS_LIST_SUBS -eq 0 ]]; then + break else textNotice "Region $regx doesn't have topics" "$regx" fi From 95a4b565754144f28a48de2518a7f46fb432ed2e Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 15:47:06 -0500 Subject: [PATCH 03/20] swallow error message for list-subscriptions-by-topic --- prowler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler b/prowler index b51176b9..1d033ba7 100755 --- a/prowler +++ b/prowler @@ -1235,7 +1235,7 @@ check315(){ TOPICS_LIST=$($AWSCLI sns list-topics --profile $PROFILE --region $regx --output text --query 'Topics[*].TopicArn') if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then for topic in $TOPICS_LIST; do - 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) + 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) if [[ $? -eq 255 ]]; then # Permission error export CAN_SNS_LIST_SUBS=0 From cf9a73d5392c40a11bdec37f8978c0409dc29541 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 15:52:21 -0500 Subject: [PATCH 04/20] gather count of topics per region, even when unable to list subscribers. --- prowler | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/prowler b/prowler index 1d033ba7..c70f154c 100755 --- a/prowler +++ b/prowler @@ -1239,7 +1239,9 @@ check315(){ if [[ $? -eq 255 ]]; then # Permission error export CAN_SNS_LIST_SUBS=0 - textNotice "No permission to list topics" + textNotice "No permission to list subscribers in topics" + ntopics=$(echo $TOPICS_LIST | wc -w ) + textNotice "Region $regx has $ntopics topics" "$regx" break; fi if [[ $(grep -v 'None' $CHECK_TOPIC_LIST) ]]; then @@ -1252,7 +1254,9 @@ check315(){ fi done elif [[ $CAN_SNS_LIST_SUBS -eq 0 ]]; then - break + ntopics=$(echo $TOPICS_LIST | wc -w ) + textNotice "Region $regx has $ntopics topics" "$regx" + # break else textNotice "Region $regx doesn't have topics" "$regx" fi From 7b6f168d8ce9b2e24a5eef9a1e4f6e1ba6bd1bbb Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Thu, 6 Jul 2017 14:14:57 -0500 Subject: [PATCH 05/20] update output for check 1.22 to handle multiple users --- prowler | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/prowler b/prowler index d623447b..7fa5f15b 100755 --- a/prowler +++ b/prowler @@ -733,10 +733,13 @@ check122(){ SUPPORTPOLICYARN=$($AWSCLI iam list-policies --query "Policies[?PolicyName == 'AWSSupportAccess'].Arn" --profile $PROFILE --region $REGION --output text) if [[ $SUPPORTPOLICYARN ]];then for policyarn in $SUPPORTPOLICYARN;do - POLICYTOSHOW=$($AWSCLI iam list-entities-for-policy --policy-arn $SUPPORTPOLICYARN --profile $PROFILE --region $REGION --output text) - if [[ $POLICYTOSHOW ]];then - textOK "Support Policy attached to $POLICYTOSHOW" - textNotice "Make sure your team can create a Support case with AWS " + POLICYUSERS=$($AWSCLI iam list-entities-for-policy --policy-arn $SUPPORTPOLICYARN --profile $PROFILE --region $REGION --output json) + if [[ $POLICYUSERS ]];then + textOK "Support Policy attached to $policyarn" + for user in $(echo "$POLICYUSERS" | grep UserName | cut -d'"' -f4) ; do + textNotice "User $user has support access via $policyarn" + done + # textNotice "Make sure your team can create a Support case with AWS " else textWarn "Support Policy not applied to any Group / User / Role " fi From df47f94cf9acf0269916e49af4cab0d7296667b7 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Fri, 7 Jul 2017 16:33:42 -0500 Subject: [PATCH 06/20] change name of temp file so that it's random Allows multiple instances of prowler to run in parallel (eg. via xargs -P ). Also, add trap handler to remove temp file if interrupted. --- prowler | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/prowler b/prowler index 7fa5f15b..b7edc4cd 100755 --- a/prowler +++ b/prowler @@ -362,7 +362,7 @@ genCredReport() { # Save report to a file, decode it, deletion at finish and after every single check, acb stands for AWS CIS Benchmark saveReport(){ - TEMP_REPORT_FILE=/tmp/.acb + TEMP_REPORT_FILE=$(mktemp -t prowler-XXXXX.cred_report ) $AWSCLI iam get-credential-report --query 'Content' --output text --profile $PROFILE --region $REGION | decode_report > $TEMP_REPORT_FILE } @@ -371,6 +371,9 @@ cleanTemp(){ rm -fr $TEMP_REPORT_FILE } +# Delete the temporary report file if we get interrupted/terminated +trap cleanTemp SIGHUP SIGINT SIGTERM + # Get a list of all available AWS Regions REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ --output text \ From 5bdd5d8e54d0b1772a22882008b7e057ace5bcc2 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Fri, 7 Jul 2017 16:35:32 -0500 Subject: [PATCH 07/20] add account number to CSV output. --- prowler | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/prowler b/prowler index b7edc4cd..8b48d361 100755 --- a/prowler +++ b/prowler @@ -250,7 +250,7 @@ textOK(){ else REPREGION=$REGION fi - echo "$PROFILE${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$TITLE_TEXT${SEP}$1" + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$TITLE_TEXT${SEP}$1" else echo " $OK OK! $NORMAL $1" fi @@ -263,7 +263,7 @@ textNotice(){ else REPREGION=$REGION fi - echo "$PROFILE${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$TITLE_TEXT${SEP}$1" + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$TITLE_TEXT${SEP}$1" else echo " $NOTICE INFO! $1 $NORMAL" fi @@ -276,7 +276,7 @@ textWarn(){ else REPREGION=$REGION fi - echo "$PROFILE${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$TITLE_TEXT${SEP}$1" + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$TITLE_TEXT${SEP}$1" else echo " $BAD WARNING! $1 $NORMAL" fi @@ -307,9 +307,9 @@ printCsvHeader() { >&2 echo "" >&2 echo "" >&2 echo "Generating \"${SEP}\" delimited report on stdout; Diagnostics on stderr." - >&2 echo " Using Profile $PROFILE" + >&2 echo " Using Profile $PROFILE, Account $ACCOUNT_NUM" >&2 echo "" - echo "PROFILE${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}TITLE_TEXT${SEP}NOTES" + echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}TITLE_TEXT${SEP}NOTES" } prowlerBanner() { @@ -323,6 +323,7 @@ prowlerBanner() { # Get whoami in AWS, who is the user running this shell script getWhoami(){ + ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Account" | tr -d '"') if [[ $MODE == "csv" ]]; then CALLER_ARN=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Arn" | tr -d '"') textTitle "0.0" "Show report generation info" From 043fa32aef9db05fc36b0bcfc8c74ad6b32b16f3 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 14:59:20 -0500 Subject: [PATCH 08/20] exit script if there are problems with the credentials. --- prowler | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/prowler b/prowler index 8b48d361..77ea6a94 100755 --- a/prowler +++ b/prowler @@ -325,7 +325,14 @@ prowlerBanner() { getWhoami(){ ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Account" | tr -d '"') if [[ $MODE == "csv" ]]; then - CALLER_ARN=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Arn" | tr -d '"') + CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Arn") + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi + CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') textTitle "0.0" "Show report generation info" textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" else @@ -334,10 +341,24 @@ getWhoami(){ echo "" 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 - $AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION | grep ':' + echo "Caller Identity:" + $AWSCLI sts get-caller-identity --output text --profile $PROFILE --region $REGION --query "Arn" + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi + echo "" else echo "Caller Identity:" $AWSCLI sts get-caller-identity --output table --profile $PROFILE --region $REGION + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi echo "" fi fi From 9ef23aecca004ba4ee719974240b9e8990c427b3 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 15:36:35 -0500 Subject: [PATCH 09/20] handle permission failure on list-subscriptions-by-topic gracefully --- prowler | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/prowler b/prowler index 77ea6a94..e629628e 100755 --- a/prowler +++ b/prowler @@ -1237,12 +1237,19 @@ check315(){ ID315="3.15" TITLE315="Ensure appropriate subscribers to each SNS topic (Not Scored)" textTitle "$ID315" "$TITLE315" "0" + CAN_SNS_LIST_SUBS=1 for regx in $REGIONS; do TOPICS_LIST=$($AWSCLI sns list-topics --profile $PROFILE --region $regx --output text --query 'Topics[*].TopicArn') - if [[ $TOPICS_LIST ]];then + if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then for topic in $TOPICS_LIST; do - 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 | grep -v "None") - if [[ $CHECK_TOPIC_LIST ]]; then + 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) + if [[ $? -eq 255 ]]; then + # Permission error + export CAN_SNS_LIST_SUBS=0 + textNotice "No permission to list topics" + break; + fi + if [[ $(grep -v 'None' $CHECK_TOPIC_LIST) ]]; then TOPIC_SHORT=$(echo $topic | awk -F: '{ print $7 }') textNotice "Region $regx with Topic $TOPIC_SHORT:" "$regx" textNotice "- Suscription: $CHECK_TOPIC_LIST" "$regx" @@ -1251,6 +1258,8 @@ check315(){ textWarn " - Region $regx and Topic $topic" "$regx" fi done + elif [[ $CAN_SNS_LIST_SUBS -eq 0 ]]; then + break else textNotice "Region $regx doesn't have topics" "$regx" fi From fe99890683228fbf1e49e24992623d630f64875d Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 15:47:06 -0500 Subject: [PATCH 10/20] swallow error message for list-subscriptions-by-topic --- prowler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler b/prowler index e629628e..6b8b4248 100755 --- a/prowler +++ b/prowler @@ -1242,7 +1242,7 @@ check315(){ TOPICS_LIST=$($AWSCLI sns list-topics --profile $PROFILE --region $regx --output text --query 'Topics[*].TopicArn') if [[ $TOPICS_LIST && $CAN_SNS_LIST_SUBS -eq 1 ]];then for topic in $TOPICS_LIST; do - 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) + 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) if [[ $? -eq 255 ]]; then # Permission error export CAN_SNS_LIST_SUBS=0 From 93b815ecf28cd750037578bf076fba04c117e940 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 15:52:21 -0500 Subject: [PATCH 11/20] gather count of topics per region, even when unable to list subscribers. --- prowler | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/prowler b/prowler index 6b8b4248..19e6b6a7 100755 --- a/prowler +++ b/prowler @@ -1246,7 +1246,9 @@ check315(){ if [[ $? -eq 255 ]]; then # Permission error export CAN_SNS_LIST_SUBS=0 - textNotice "No permission to list topics" + textNotice "No permission to list subscribers in topics" + ntopics=$(echo $TOPICS_LIST | wc -w ) + textNotice "Region $regx has $ntopics topics" "$regx" break; fi if [[ $(grep -v 'None' $CHECK_TOPIC_LIST) ]]; then @@ -1259,7 +1261,9 @@ check315(){ fi done elif [[ $CAN_SNS_LIST_SUBS -eq 0 ]]; then - break + ntopics=$(echo $TOPICS_LIST | wc -w ) + textNotice "Region $regx has $ntopics topics" "$regx" + # break else textNotice "Region $regx doesn't have topics" "$regx" fi From f787c57636d9eb9704e3c440cbfe166c35b579b5 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 16:04:27 -0500 Subject: [PATCH 12/20] improve trap handling --- prowler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler b/prowler index 19e6b6a7..82e47ac8 100755 --- a/prowler +++ b/prowler @@ -394,7 +394,7 @@ cleanTemp(){ } # Delete the temporary report file if we get interrupted/terminated -trap cleanTemp SIGHUP SIGINT SIGTERM +trap cleanTemp EXIT # Get a list of all available AWS Regions REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ From 866fe116105b826f1c66287bf0d62d4de3d08505 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 16:23:50 -0500 Subject: [PATCH 13/20] fix typo in function name --- prowler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler b/prowler index 82e47ac8..a2ace106 100755 --- a/prowler +++ b/prowler @@ -714,7 +714,7 @@ check118(){ # find attached policies in found roles ATTACHEDPOLICIES=$($AWSCLI iam list-attached-role-policies --role-name $role --profile $PROFILE --region $REGION --query "AttachedPolicies[*]" --output text) for policy in $ATTACHEDPOLICIES;do - text-notice "$AWSCLI iam get-role-policy --role-name $role --policy-name $policy --profile $PROFILE --region $REGION" + textNotice "$AWSCLI iam get-role-policy --role-name $role --policy-name $policy --profile $PROFILE --region $REGION" done done else From 68f8e08506164c9482ce21427e2f705826a13e65 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 16:24:42 -0500 Subject: [PATCH 14/20] add option (-k) to keep the credential report after execution. --- README.md | 1 + prowler | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0fbda960..0e78d34e 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ USAGE: -f specify an AWS region to run checks against (i.e.: us-west-1) -m specify the maximum number of items to return for long-running requests (default: 100) -M output mode: text (defalut), mono, csv (separator is "|"; data is on stdout; progress on stderr) + -k keep the credential report -h this help ``` diff --git a/prowler b/prowler index a2ace106..28f44e23 100755 --- a/prowler +++ b/prowler @@ -37,6 +37,7 @@ MAXITEMS=100 MONOCHROME=0 MODE="text" SEP=',' +KEEPCREDREPORT=0 # Command usage menu @@ -51,17 +52,21 @@ USAGE: -f specify an AWS region to run checks against (i.e.: us-west-1) -m specify the maximum number of items to return for long-running requests (default: 100) -M output mode: text (defalut), mono, csv (separator is \"${SEP}\"; data is on stdout; progress on stderr) + -k keep the credential report -h this help " exit } -while getopts ":hp:r:c:f:m:M:" OPTION; do +while getopts ":hkp:r:c:f:m:M:" OPTION; do case $OPTION in h ) usage exit 1 ;; + k ) + KEEPCREDREPORT=1 + ;; p ) PROFILE=$OPTARG ;; @@ -384,13 +389,19 @@ genCredReport() { # Save report to a file, decode it, deletion at finish and after every single check, acb stands for AWS CIS Benchmark saveReport(){ - TEMP_REPORT_FILE=$(mktemp -t prowler-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 + if [[ $KEEPCREDREPORT -eq 1 ]]; then + textTitle "0.2" "Saving IAM Credential Report ..." + textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE" + fi } # Delete temporary report file cleanTemp(){ - rm -fr $TEMP_REPORT_FILE + if [[ $KEEPCREDREPORT -ne 1 ]]; then + rm -fr $TEMP_REPORT_FILE + fi } # Delete the temporary report file if we get interrupted/terminated From 30c3a8aa76e6f1469bc5e26185bba310064e6b8b Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 10:48:37 -0500 Subject: [PATCH 15/20] correct typo in permission name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 55caac6d..87dea0e6 100644 --- a/README.md +++ b/README.md @@ -465,7 +465,7 @@ Instead of using default policy SecurityAudit for the account you use for checks "redshift:describe*", "route53:getchange", "route53:getcheckeripranges", - "route53:getgeolocations", + "route53:getgeolocation", "route53:gethealthcheck", "route53:gethealthcheckcount", "route53:gethealthchecklastfailurereason", From 1cbedb1eb62f8e00c152196dcff74394806091c0 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 10:49:11 -0500 Subject: [PATCH 16/20] add incremental policy file; update readme to show use case --- README.md | 38 +++++++++++++++++++++++++++++++++++ prowler-policy-additions.json | 18 +++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 prowler-policy-additions.json diff --git a/README.md b/README.md index 87dea0e6..670b3766 100644 --- a/README.md +++ b/README.md @@ -510,3 +510,41 @@ Instead of using default policy SecurityAudit for the account you use for checks }] } ``` + +Alternatively, here is a policy which defines the permissions which are NOT present in the AWS Managed SecurityAudit policy. Attach both this policy and the AWS Managed SecurityAudit policy to the group and you're good to go. + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "acm:DescribeCertificate", + "acm:ListCertificates", + "cloudwatchlogs:describeLogGroups", + "cloudwatchlogs:DescribeMetricFilters", + "es:DescribeElasticsearchDomainConfig", + "ses:GetIdentityVerificationAttributes", + "sns:ListSubscriptionsByTopic", + ], + "Effect": "Allow", + "Resource": "*" + } + ] +} +``` + +Quick bash script to set up a "prowler" IAM user and "SecurityAudit" group with the required permissions. To run the script below, you need user with administrative permissions; set the AWS_DEFAULT_PROFILE to use that account. + +``` +export AWS_DEFAULT_PROFILE=default +export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' | tr -d '"') +aws iam create-group --group-name SecurityAudit +aws iam create-policy --policy-name ProwlerAuditAdditions --policy-document file://$(pwd)/prowler-policy-additions.json +aws iam attach-group-policy --group-name SecurityAudit --policy-arn arn:aws:iam::aws:policy/SecurityAudit +aws iam attach-group-policy --group-name SecurityAudit --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/ProwlerAuditAdditions +aws iam create-user --user-name prowler +aws iam add-user-to-group --user-name prowler --group-name SecurityAudit +aws iam create-access-key --user-name prowler +unset ACCOUNT_ID AWS_DEFAULT_PROFILE +``` diff --git a/prowler-policy-additions.json b/prowler-policy-additions.json new file mode 100644 index 00000000..643cda1a --- /dev/null +++ b/prowler-policy-additions.json @@ -0,0 +1,18 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "acm:describecertificate", + "acm:listcertificates", + "cloudwatchlogs:describeloggroups", + "cloudwatchlogs:describemetricfilters", + "es:describeelasticsearchdomainconfig", + "ses:getidentityverificationattributes", + "sns:listsubscriptionsbytopic", + ], + "Effect": "Allow", + "Resource": "*" + } + ] +} From ca012ebf764f9c6552dcec6bd6585e8601580d87 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 10:55:26 -0500 Subject: [PATCH 17/20] fix policy document syntax error --- prowler-policy-additions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler-policy-additions.json b/prowler-policy-additions.json index 643cda1a..9104c6da 100644 --- a/prowler-policy-additions.json +++ b/prowler-policy-additions.json @@ -9,7 +9,7 @@ "cloudwatchlogs:describemetricfilters", "es:describeelasticsearchdomainconfig", "ses:getidentityverificationattributes", - "sns:listsubscriptionsbytopic", + "sns:listsubscriptionsbytopic" ], "Effect": "Allow", "Resource": "*" From c8a2e16a1c745a5b3c171c27ed189eded21b75fd Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 11:01:07 -0500 Subject: [PATCH 18/20] add note about saving the key material --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 670b3766..529dd007 100644 --- a/README.md +++ b/README.md @@ -548,3 +548,5 @@ aws iam add-user-to-group --user-name prowler --group-name SecurityAudit aws iam create-access-key --user-name prowler unset ACCOUNT_ID AWS_DEFAULT_PROFILE ``` + +The `aws iam create-access-key` command will output the secret access key and the key id; keep these somewhere safe, and add them to ~/.aws/credentials with an appropriate profile name to use them with prowler. This is the only time they secret key will be shown. If you loose it, you will need to generate a replacement. From 02a4ab665f60769d8f9c8d5ec1a2dd8133662b58 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 11:02:01 -0500 Subject: [PATCH 19/20] fix policy document syntax error in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 529dd007..c65b510e 100644 --- a/README.md +++ b/README.md @@ -525,7 +525,7 @@ Alternatively, here is a policy which defines the permissions which are NOT pres "cloudwatchlogs:DescribeMetricFilters", "es:DescribeElasticsearchDomainConfig", "ses:GetIdentityVerificationAttributes", - "sns:ListSubscriptionsByTopic", + "sns:ListSubscriptionsByTopic" ], "Effect": "Allow", "Resource": "*" From 118da69eb56c82b78a8943c8eee95d85f01ed6df Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Tue, 11 Jul 2017 11:08:30 -0500 Subject: [PATCH 20/20] add headings for incremental policy and bootstrap script --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index c65b510e..6a91e85b 100644 --- a/README.md +++ b/README.md @@ -511,6 +511,8 @@ Instead of using default policy SecurityAudit for the account you use for checks } ``` +### Incremental IAM Policy + Alternatively, here is a policy which defines the permissions which are NOT present in the AWS Managed SecurityAudit policy. Attach both this policy and the AWS Managed SecurityAudit policy to the group and you're good to go. ``` @@ -534,6 +536,8 @@ Alternatively, here is a policy which defines the permissions which are NOT pres } ``` +### Bootstrap Script + Quick bash script to set up a "prowler" IAM user and "SecurityAudit" group with the required permissions. To run the script below, you need user with administrative permissions; set the AWS_DEFAULT_PROFILE to use that account. ```