From 9a44414a8eed47a44e485dda8d0553917f6908d0 Mon Sep 17 00:00:00 2001 From: Ben Allen Date: Mon, 26 Jun 2017 16:05:27 -0500 Subject: [PATCH] more CSV tweaks * handle multi-region tests cleanly * clean up report generation info --- prowler | 79 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/prowler b/prowler index 04ebfdaf..7ce453a1 100755 --- a/prowler +++ b/prowler @@ -245,25 +245,40 @@ TITLE_TEXT="CALLER ERROR - UNSET TITLE" ## Output formatting functions textOK(){ if [[ $MODE == "csv" ]]; then - echo "$PROFILE|$REGION|$TITLE_ID|PASS|$ITEM_SCORED|$TITLE_TEXT|$1" + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE|$REPREGION|$TITLE_ID|PASS|$ITEM_SCORED|$TITLE_TEXT|$1" else - echo " $TITLE_ID $OK OK! $NORMAL $@" + echo " $TITLE_ID $OK OK! $NORMAL $1" fi } textNotice(){ if [[ $MODE == "csv" ]]; then - echo "$PROFILE|$REGION|$TITLE_ID|INFO|$ITEM_SCORED|$TITLE_TEXT|$1" + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE|$REPREGION|$TITLE_ID|INFO|$ITEM_SCORED|$TITLE_TEXT|$1" else - echo " $TITLE_ID $NOTICE INFO! $@ $NORMAL" + echo " $TITLE_ID $NOTICE INFO! $1 $NORMAL" fi } textWarn(){ if [[ $MODE == "csv" ]]; then - echo "$PROFILE|$REGION|$TITLE_ID|WARNING|$ITEM_SCORED|$TITLE_TEXT|$1" + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE|$REPREGION|$TITLE_ID|WARNING|$ITEM_SCORED|$TITLE_TEXT|$1" else - echo " $TITLE_ID $BAD WARNING! $@ $NORMAL" + echo " $TITLE_ID $BAD WARNING! $1 $NORMAL" fi } @@ -289,7 +304,8 @@ textTitle(){ } printCsvHeader() { - >&2 echo "Pipe Delimited report on stdout; Diagnostics on stderr." + >&2 echo "Generateing pipe delimited report on stdout; Diagnostics on stderr." + >&2 echo " " echo "PROFILE|REGION|TITLE_ID|RESULT|SCORED|TITLE_TEXT|NOTES" } @@ -306,7 +322,8 @@ prowlerBanner() { getWhoami(){ if [[ $MODE == "csv" ]]; then CALLER_ARN=$($AWSCLI sts get-caller-identity --output json --profile $PROFILE --region $REGION --query "Arn" | tr -d '"') - echo "$PROFILE|$REGION|0.0|INFO|Report generated by user|$CALLER_ARN" + textTitle "0.0" "Show report generation info" + textNotice "ARN: $CALLER_ARN TIMESTAMP: $(date -Is)" else echo "" echo "This report is being generated using credentials below:" @@ -870,9 +887,9 @@ check25(){ for regx in $REGIONS; do CHECK_AWSCONFIG_STATUS=$($AWSCLI configservice get-status --profile $PROFILE --region $regx | grep "recorder: ON") if [[ $CHECK_AWSCONFIG_STATUS ]];then - textOK "Region $regx has AWS Config recorder: ON " + textOK "Region $regx has AWS Config recorder: ON" "$regx" else - textWarn "Region $regx has AWS Config disabled or not configured" + textWarn "Region $regx has AWS Config disabled or not configured" "$regx" fi done } @@ -926,22 +943,22 @@ check28(){ 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') if [[ $CHECK_KMS_KEY_TYPE == "EXTERNAL" ]];then - textOK "Key $key in Region $regx Customer Uploaded Key Material." + textOK "Key $key in Region $regx Customer Uploaded Key Material." "$regx" else CHECK_KMS_KEY_ROTATION=$($AWSCLI kms get-key-rotation-status --key-id $key --profile $PROFILE --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") if [[ $CHECK_KMS_KEY_ROTATION == "True" ]];then textOK "Key $key in Region $regx is set correctly" elif [[ $CHECK_KMS_KEY_ROTATION == "False" && $CHECK_KMS_DEFAULT_KEY ]];then - textNotice "Region $regx key $key is an AWS default master key and cannot be deleted nor modified." + textNotice "Region $regx key $key is an AWS default master key and cannot be deleted nor modified." "$regx" else - textWarn "Key $key in Region $regx is not set to rotate!!!" + textWarn "Key $key in Region $regx is not set to rotate!!!" "$regx" fi fi done else - textNotice "Region $regx doesn't have encryption keys " + textNotice "Region $regx doesn't have encryption keys" "$regx" fi done } @@ -1195,15 +1212,15 @@ check315(){ 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 TOPIC_SHORT=$(echo $topic | awk -F: '{ print $7 }') - textNotice "Region $regx with Topic $TOPIC_SHORT: " - textNotice "- Suscription: $CHECK_TOPIC_LIST " + textNotice "Region $regx with Topic $TOPIC_SHORT:" "$regx" + textNotice "- Suscription: $CHECK_TOPIC_LIST" "$regx" else - textWarn "No suscription found in: Region $regx and Topic $topic " - textWarn " - Region $regx and Topic $topic " + textWarn "No suscription found in: Region $regx and Topic $topic" "$regx" + textWarn " - Region $regx and Topic $topic" "$regx" fi done else - textNotice "Region $regx doesn't have topics " + textNotice "Region $regx doesn't have topics" "$regx" fi done } @@ -1216,10 +1233,10 @@ check41(){ 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`].{GroupName: GroupName}' --profile $PROFILE --region $regx --output text) if [[ $SG_LIST ]];then for SG in $SG_LIST;do - textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx " + textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" done else - textOK "No Security Groups found in $regx with port 22 TCP open to 0.0.0.0/0 " + textOK "No Security Groups found in $regx with port 22 TCP open to 0.0.0.0/0" "$regx" fi done } @@ -1232,10 +1249,10 @@ check42(){ 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) if [[ $SG_LIST ]];then for SG in $SG_LIST;do - textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx " + textWarn "Found Security Group: $SG open to 0.0.0.0/0 in Region $regx" "$regx" done else - textOK "No Security Groups found in $regx with port 3389 TCP open to 0.0.0.0/0 " + textOK "No Security Groups found in $regx with port 3389 TCP open to 0.0.0.0/0" "$regx" fi done } @@ -1248,10 +1265,10 @@ check43(){ CHECK_FL=$($AWSCLI ec2 describe-flow-logs --profile $PROFILE --region $regx --query 'FlowLogs[?FlowLogStatus==`ACTIVE`].LogGroupName' --output text) if [[ $CHECK_FL ]];then for FL in $CHECK_FL;do - textOK "VPCFlowLog is enabled for LogGroupName: $FL in Region $regx " + textOK "VPCFlowLog is enabled for LogGroupName: $FL in Region $regx" "$regx" done else - textWarn "No VPCFlowLog has been found in Region $regx " + textWarn "No VPCFlowLog has been found in Region $regx" "$regx" fi done } @@ -1263,9 +1280,9 @@ check44(){ 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) if [[ $CHECK_SGDEFAULT ]];then - textWarn "Default Security Groups found that allow 0.0.0.0 IN or OUT traffic in Region $regx" + textWarn "Default Security Groups found that allow 0.0.0.0 IN or OUT traffic in Region $regx" "$regx" else - textOK "No Default Security Groups open to 0.0.0.0 found in Region $regx " + textOK "No Default Security Groups open to 0.0.0.0 found in Region $regx" "$regx" fi done } @@ -1279,7 +1296,7 @@ check45(){ 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') if [[ $LIST_OF_VPCS_PEERING_CONNECTIONS ]];then - textNotice "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS, review its routing tables " + textNotice "$regx: $LIST_OF_VPCS_PEERING_CONNECTIONS, review its routing tables" "$regx" #LIST_OF_VPCS=$($AWSCLI ec2 describe-vpcs --profile $PROFILE --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 # for vpc in $LIST_OF_VPCS; do @@ -1287,7 +1304,7 @@ check45(){ # done #echo $VPCS_WITH_PEERING else - textOK "$regx: No VPC peering found " + textOK "$regx: No VPC peering found" "$regx" fi done } @@ -1453,5 +1470,7 @@ check43 check44 check45 -infoReferenceLong +if [[ $MODE != "csv" ]]; then + infoReferenceLong +fi cleanTemp