mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
47
README.md
47
README.md
@@ -113,6 +113,7 @@ USAGE:
|
||||
-f <filterregion> specify an AWS region to run checks against (i.e.: us-west-1)
|
||||
-m <maxitems> specify the maximum number of items to return for long-running requests (default: 100)
|
||||
-M <mode> output mode: text (defalut), mono, csv (separator is "|"; data is on stdout; progress on stderr)
|
||||
-k keep the credential report
|
||||
-h this help
|
||||
|
||||
```
|
||||
@@ -465,7 +466,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",
|
||||
@@ -510,3 +511,47 @@ 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.
|
||||
|
||||
```
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"acm:DescribeCertificate",
|
||||
"acm:ListCertificates",
|
||||
"cloudwatchlogs:describeLogGroups",
|
||||
"cloudwatchlogs:DescribeMetricFilters",
|
||||
"es:DescribeElasticsearchDomainConfig",
|
||||
"ses:GetIdentityVerificationAttributes",
|
||||
"sns:ListSubscriptionsByTopic"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
65
prowler
65
prowler
@@ -37,6 +37,7 @@ MAXITEMS=100
|
||||
MONOCHROME=0
|
||||
MODE="text"
|
||||
SEP=','
|
||||
KEEPCREDREPORT=0
|
||||
|
||||
|
||||
# Command usage menu
|
||||
@@ -51,17 +52,21 @@ USAGE:
|
||||
-f <filterregion> specify an AWS region to run checks against (i.e.: us-west-1)
|
||||
-m <maxitems> specify the maximum number of items to return for long-running requests (default: 100)
|
||||
-M <mode> 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
|
||||
;;
|
||||
@@ -325,7 +330,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 +346,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
|
||||
@@ -363,17 +389,23 @@ 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
|
||||
trap cleanTemp SIGHUP SIGINT SIGTERM
|
||||
trap cleanTemp EXIT
|
||||
|
||||
# Get a list of all available AWS Regions
|
||||
REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \
|
||||
@@ -693,7 +725,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
|
||||
@@ -1216,12 +1248,21 @@ 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 2> /dev/null)
|
||||
if [[ $? -eq 255 ]]; then
|
||||
# Permission error
|
||||
export CAN_SNS_LIST_SUBS=0
|
||||
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
|
||||
TOPIC_SHORT=$(echo $topic | awk -F: '{ print $7 }')
|
||||
textNotice "Region $regx with Topic $TOPIC_SHORT:" "$regx"
|
||||
textNotice "- Suscription: $CHECK_TOPIC_LIST" "$regx"
|
||||
@@ -1230,6 +1271,10 @@ check315(){
|
||||
textWarn " - Region $regx and Topic $topic" "$regx"
|
||||
fi
|
||||
done
|
||||
elif [[ $CAN_SNS_LIST_SUBS -eq 0 ]]; then
|
||||
ntopics=$(echo $TOPICS_LIST | wc -w )
|
||||
textNotice "Region $regx has $ntopics topics" "$regx"
|
||||
# break
|
||||
else
|
||||
textNotice "Region $regx doesn't have topics" "$regx"
|
||||
fi
|
||||
|
||||
18
prowler-policy-additions.json
Normal file
18
prowler-policy-additions.json
Normal file
@@ -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": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user