Allow multiple report types at once #345

This commit is contained in:
Toni de la Fuente
2020-04-14 22:28:58 +02:00
parent e6fe5addbc
commit 4ea1864365
4 changed files with 73 additions and 48 deletions

View File

@@ -159,7 +159,25 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
Valid check numbers are based on the AWS CIS Benchmark guide, so 1.1 is check11 and 3.10 is check310 Valid check numbers are based on the AWS CIS Benchmark guide, so 1.1 is check11 and 3.10 is check310
1. If you want to save your report for later analysis: ### Save your reports
1. If you want to save your report for later analysis thare are different ways, natively (supported text, mono, csv, json and json-asff see note below for more info):
```sh
./prowler -M csv
```
or with multiple formats at the same time:
```sh
./prowler -M csv,json,json-asff
```
or just a group of checks in multiple formats:
```sh
./prowler -g gdpr -M csv,json,json-asff
```
Now `-M` creates a file inside the prowler root directory named `prowler-output-YYYYMMDDHHMMSS.format`. You don't have to specify anything else, no pipes, no redirects.
or just saving the output to a file like below:
```sh ```sh
./prowler -M mono > prowler-report.txt ./prowler -M mono > prowler-report.txt
@@ -172,18 +190,9 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
./prowler | ansi2html -la > report.html ./prowler | ansi2html -la > report.html
``` ```
or if you want a pipe-delimited report file, do: >Note about output formats to use with `-M`: "text" is the default one with colors, "mono" is like default one but monochrome, "csv" is comma separated values, "json" plain basic json (without comma between lines) and "json-asff" is also json with Amazon Security Finding Format that you can ship to Security Hub using `-S`.
```sh or save your report in a S3 bucket (this only works for text or mono, for csv, json or json-asff it has to be copied afterwards):
./prowler -M csv > output.psv
```
or json formatted output using jq, do:
```sh
./prowler -M json > prowler-output.json
```
or save your report in a S3 bucket:
```sh ```sh
./prowler -M mono | aws s3 cp - s3://bucket-name/prowler-report.txt ./prowler -M mono | aws s3 cp - s3://bucket-name/prowler-report.txt
@@ -221,7 +230,8 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
-f <filterregion> specify an AWS region to run checks against -f <filterregion> specify an AWS region to run checks against
(i.e.: us-west-1) (i.e.: us-west-1)
-m <maxitems> specify the maximum number of items to return for long-running requests (default: 100) -m <maxitems> specify the maximum number of items to return for long-running requests (default: 100)
-M <mode> output mode: text (default), mono, json, csv (separator is ,; data is on stdout; progress on stderr) -M <mode> output mode: text (default), mono, json, json-asff, csv. They can be used combined comma separated.
(separator is ","; data is on stdout; progress on stderr).
-k keep the credential report -k keep the credential report
-n show check numbers to sort easier -n show check numbers to sort easier
(i.e.: 1.01 instead of 1.1) (i.e.: 1.01 instead of 1.1)
@@ -280,7 +290,7 @@ In order to remove noise and get only FAIL findings there is a `-q` flag that ma
Since version v2.3, Prowler supports natively sending findings to [AWS Security Hub](https://aws.amazon.com/security-hub). This integration allows Prowler to import its findings to AWS Security Hub. With Security Hub, you now have a single place that aggregates, organizes, and prioritizes your security alerts, or findings, from multiple AWS services, such as Amazon GuardDuty, Amazon Inspector, Amazon Macie, AWS Identity and Access Management (IAM) Access Analyzer, and AWS Firewall Manager, as well as from AWS Partner solutions and now from Prowler. It is as simple as running the commanbd below: Since version v2.3, Prowler supports natively sending findings to [AWS Security Hub](https://aws.amazon.com/security-hub). This integration allows Prowler to import its findings to AWS Security Hub. With Security Hub, you now have a single place that aggregates, organizes, and prioritizes your security alerts, or findings, from multiple AWS services, such as Amazon GuardDuty, Amazon Inspector, Amazon Macie, AWS Identity and Access Management (IAM) Access Analyzer, and AWS Firewall Manager, as well as from AWS Partner solutions and now from Prowler. It is as simple as running the commanbd below:
```sh ```
./prowler -M json-asff -S ./prowler -M json-asff -S
``` ```
There are two requirements: There are two requirements:

View File

@@ -11,13 +11,15 @@
# CONDITIONS OF ANY KIND, either express or implied. See the License for the # CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License. # specific language governing permissions and limitations under the License.
if [[ "$MODE" != "mono" && "$MODE" != "text" && "$MODE" != "csv" && "$MODE" != "json" && "$MODE" != "json-asff" ]]; then
echo "" IFS=',' read -ra MODES <<< "${MODE}"
echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json or json-asff." for MODE in "${MODES[@]}"; do
usage if [[ "$MODE" != "mono" && "$MODE" != "text" && "$MODE" != "csv" && "$MODE" != "json" && "$MODE" != "json-asff" ]]; then
EXITCODE=1 echo -e "${OPTRED}ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json or json-asff. ./prowler -h for help"
exit $EXITCODE EXITCODE=1
fi exit $EXITCODE
fi
done
if [[ "$MODE" == "mono" || "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then if [[ "$MODE" == "mono" || "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
MONOCHROME=1 MONOCHROME=1

View File

@@ -12,25 +12,36 @@
# specific language governing permissions and limitations under the License. # specific language governing permissions and limitations under the License.
# Output formatting functions # Output formatting functions
EXTENSION_CSV="csv"
EXTENSION_JSON="json"
EXTENSION_ASFF="asff-json"
EXTENSION_HTML="html" # not implemented yet, use ansi2html as in documentation
OUTPUT_DATE=$(date -u +"%Y%m%d%H%M%S")
OUTPUT_FILE_NAME=prowler-output-$OUTPUT_DATE
textPass(){ textPass(){
if [[ "$QUIET" == 1 ]]; then if [[ "$QUIET" == 1 ]]; then
return return
fi fi
PASS_COUNTER=$((PASS_COUNTER+1)) PASS_COUNTER=$((PASS_COUNTER+1))
if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
if [[ $2 ]]; then if [[ $2 ]]; then
REPREGION=$2 REPREGION=$2
else else
REPREGION=$REGION REPREGION=$REGION
fi fi
if [[ "$MODE" == "csv" ]]; then if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
elif [[ "$MODE" == "json" ]]; then fi
generateJsonOutput "$1" "Pass" if [[ "${MODES[@]}" =~ "json" ]]; then
elif [[ "$MODE" == "json-asff" ]]; then generateJsonOutput "$1" "Pass" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
fi
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "PASSED" "INFORMATIONAL") JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "PASSED" "INFORMATIONAL")
echo "${JSON_ASFF_OUTPUT}" echo "${JSON_ASFF_OUTPUT}" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_ASFF
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
sendToSecurityHub "${JSON_ASFF_OUTPUT}" sendToSecurityHub "${JSON_ASFF_OUTPUT}"
fi fi
@@ -45,16 +56,17 @@ textInfo(){
return return
fi fi
if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
if [[ $2 ]]; then if [[ $2 ]]; then
REPREGION=$2 REPREGION=$2
else else
REPREGION=$REGION REPREGION=$REGION
fi fi
if [[ "$MODE" == "csv" ]]; then if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
elif [[ "$MODE" == "json" ]]; then fi
generateJsonOutput "$1" "Info" if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "Info" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
fi fi
else else
echo " $NOTICE INFO! $1 $NORMAL" echo " $NOTICE INFO! $1 $NORMAL"
@@ -64,19 +76,21 @@ textInfo(){
textFail(){ textFail(){
FAIL_COUNTER=$((FAIL_COUNTER+1)) FAIL_COUNTER=$((FAIL_COUNTER+1))
EXITCODE=3 EXITCODE=3
if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
if [[ $2 ]]; then if [[ $2 ]]; then
REPREGION=$2 REPREGION=$2
else else
REPREGION=$REGION REPREGION=$REGION
fi fi
if [[ "$MODE" == "csv" ]]; then if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}FAIL${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}FAIL${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
elif [[ "$MODE" == "json" ]]; then fi
generateJsonOutput "$1" "Fail" if [[ "${MODES[@]}" =~ "json" ]]; then
elif [[ "$MODE" == "json-asff" ]]; then generateJsonOutput "$1" "Fail" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
fi
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "FAILED" "HIGH") JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "FAILED" "HIGH")
echo "${JSON_ASFF_OUTPUT}" echo "${JSON_ASFF_OUTPUT}" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_ASFF
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
sendToSecurityHub "${JSON_ASFF_OUTPUT}" sendToSecurityHub "${JSON_ASFF_OUTPUT}"
fi fi
@@ -117,9 +131,9 @@ textTitle(){
*) ITEM_LEVEL="Unspecified or Invalid";; *) ITEM_LEVEL="Unspecified or Invalid";;
esac esac
if [[ "$MODE" == "csv" ]]; then if [[ "${MODES[@]}" =~ "csv" ]]; then
>&2 echo "$TITLE_ID $TITLE_TEXT" >&2 echo "$TITLE_ID $TITLE_TEXT" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
elif [[ "$MODE" == "json" || "$MODE" == "json-asff" ]]; then elif [[ "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
: :
else else
if [[ "$ITEM_SCORED" == "Scored" ]]; then if [[ "$ITEM_SCORED" == "Scored" ]]; then

View File

@@ -65,7 +65,8 @@ USAGE:
-f <filterregion> specify an AWS region to run checks against -f <filterregion> specify an AWS region to run checks against
(i.e.: us-west-1) (i.e.: us-west-1)
-m <maxitems> specify the maximum number of items to return for long-running requests (default: 100) -m <maxitems> specify the maximum number of items to return for long-running requests (default: 100)
-M <mode> output mode: text (default), mono, json, json-asff, csv (separator is ","; data is on stdout; progress on stderr) -M <mode> output mode: text (default), mono, json, json-asff, csv. They can be used combined comma separated.
(separator is ","; data is on stdout; progress on stderr).
-k keep the credential report -k keep the credential report
-n show check numbers to sort easier -n show check numbers to sort easier
(i.e.: 1.01 instead of 1.1) (i.e.: 1.01 instead of 1.1)
@@ -393,7 +394,7 @@ get_all_checks_without_exclusion() {
} }
### All functions defined above ... run the workflow ### All functions defined above ... run the workflow
if [[ $MODE != "csv" ]]; then if [[ ${MODES[@]} =~ "mono" || ${MODES[@]} =~ "text" ]]; then
prowlerBanner prowlerBanner
fi fi
@@ -424,9 +425,7 @@ getWhoami
# Execute group of checks if called with -g # Execute group of checks if called with -g
if [[ $GROUP_ID_READ ]];then if [[ $GROUP_ID_READ ]];then
if [[ " ${GROUP_ID[@]} " =~ " ${GROUP_ID_READ} " ]]; then if [[ " ${GROUP_ID[@]} " =~ " ${GROUP_ID_READ} " ]]; then
if [[ $MODE == "csv" ]]; then
BANNER=0
fi
execute_group_by_id ${GROUP_ID_READ} ${EXCLUDE_CHECK_ID} execute_group_by_id ${GROUP_ID_READ} ${EXCLUDE_CHECK_ID}
cleanTemp cleanTemp
scoring scoring