mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
Replace -J flag with junit-xml output format
Rearrange output functions so they support outputting text alongside other formats, if specified Add a convenience function for checking if JUnit output is enabled Move monochrome setting into loop so it better supports multiple formats Update README
This commit is contained in:
@@ -170,7 +170,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
|
|||||||
|
|
||||||
### Save your reports
|
### 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):
|
1. If you want to save your report for later analysis thare are different ways, natively (supported text, mono, csv, json, json-asff and junit-xml see note below for more info):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./prowler -M csv
|
./prowler -M csv
|
||||||
@@ -203,10 +203,10 @@ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
To generate JUnit report files add `-J`. This can be combined with any format. Files are written inside a prowler root directory named `junit-reports`:
|
To generate JUnit report files, include the junit-xml format. This can be combined with any other format. Files are written inside a prowler root directory named `junit-reports`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./prowler -J
|
./prowler -M text,junit-xml
|
||||||
```
|
```
|
||||||
|
|
||||||
>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`.
|
>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`.
|
||||||
@@ -249,7 +249,7 @@ 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, json-asff, csv. They can be used combined comma separated.
|
-M <mode> output mode: text (default), mono, json, json-asff, junit-xml, csv. They can be used combined comma separated.
|
||||||
(separator is ","; data is on stdout; progress on stderr).
|
(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
|
||||||
@@ -262,7 +262,6 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
|
|||||||
-V show version number & exit
|
-V show version number & exit
|
||||||
-s show scoring report
|
-s show scoring report
|
||||||
-S send check output to AWS Security Hub - only valid when the output mode is json-asff (i.e. "-M json-asff -S")
|
-S send check output to AWS Security Hub - only valid when the output mode is json-asff (i.e. "-M json-asff -S")
|
||||||
-J generate JUnit reports, readable by Jenkins or other CI tools. Files are written to ./junit-reports
|
|
||||||
-x specify external directory with custom checks (i.e. /my/own/checks, files must start by check)
|
-x specify external directory with custom checks (i.e. /my/own/checks, files must start by check)
|
||||||
-q suppress info messages and passing test output
|
-q suppress info messages and passing test output
|
||||||
-A account id for the account where to assume a role, requires -R and -T
|
-A account id for the account where to assume a role, requires -R and -T
|
||||||
|
|||||||
@@ -14,16 +14,15 @@
|
|||||||
|
|
||||||
IFS=',' read -ra MODES <<< "${MODE}"
|
IFS=',' read -ra MODES <<< "${MODE}"
|
||||||
for MODE in "${MODES[@]}"; do
|
for MODE in "${MODES[@]}"; do
|
||||||
if [[ "$MODE" != "mono" && "$MODE" != "text" && "$MODE" != "csv" && "$MODE" != "json" && "$MODE" != "json-asff" ]]; then
|
if [[ "$MODE" != "mono" && "$MODE" != "text" && "$MODE" != "csv" && "$MODE" != "json" && "$MODE" != "json-asff" && "$MODE" != "junit-xml" ]]; then
|
||||||
echo -e "${OPTRED}ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json or json-asff. ./prowler -h for help"
|
echo -e "${OPTRED}ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json, json-asff or junit-xml. ./prowler -h for help"
|
||||||
EXITCODE=1
|
EXITCODE=1
|
||||||
exit $EXITCODE
|
exit $EXITCODE
|
||||||
fi
|
fi
|
||||||
done
|
if [[ "$MODE" == "mono" || "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||||
|
MONOCHROME=1
|
||||||
if [[ "$MODE" == "mono" || "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
fi
|
||||||
MONOCHROME=1
|
done
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $MONOCHROME -eq 1 ]]; then
|
if [[ $MONOCHROME -eq 1 ]]; then
|
||||||
# Colors
|
# Colors
|
||||||
|
|||||||
@@ -15,6 +15,14 @@
|
|||||||
|
|
||||||
JUNIT_OUTPUT_DIRECTORY="junit-reports"
|
JUNIT_OUTPUT_DIRECTORY="junit-reports"
|
||||||
|
|
||||||
|
is_junit_output_enabled() {
|
||||||
|
if [[ ${MODES[@]} =~ "junit-xml" ]]; then
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
xml_escape() {
|
xml_escape() {
|
||||||
sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/\"/\"/g; s/'"'"'/\'/g' <<< "$1"
|
sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/\"/\"/g; s/'"'"'/\'/g' <<< "$1"
|
||||||
}
|
}
|
||||||
|
|||||||
109
include/outputs
109
include/outputs
@@ -27,29 +27,28 @@ textPass(){
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
PASS_COUNTER=$((PASS_COUNTER+1))
|
PASS_COUNTER=$((PASS_COUNTER+1))
|
||||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
if [[ $2 ]]; then
|
||||||
|
REPREGION=$2
|
||||||
|
else
|
||||||
|
REPREGION=$REGION
|
||||||
|
fi
|
||||||
|
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" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
|
||||||
|
fi
|
||||||
|
if [[ "${MODES[@]}" =~ "json" ]]; then
|
||||||
|
generateJsonOutput "$1" "Pass" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
|
||||||
|
fi
|
||||||
|
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
|
||||||
|
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "PASSED" "INFORMATIONAL")
|
||||||
|
echo "${JSON_ASFF_OUTPUT}" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_ASFF
|
||||||
|
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
||||||
|
sendToSecurityHub "${JSON_ASFF_OUTPUT}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if is_junit_output_enabled; then
|
||||||
output_junit_success "$1"
|
output_junit_success "$1"
|
||||||
fi
|
fi
|
||||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
|
if [[ "${MODES[@]}" =~ "text" ]]; then
|
||||||
if [[ $2 ]]; then
|
|
||||||
REPREGION=$2
|
|
||||||
else
|
|
||||||
REPREGION=$REGION
|
|
||||||
fi
|
|
||||||
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" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
|
|
||||||
fi
|
|
||||||
if [[ "${MODES[@]}" =~ "json" ]]; then
|
|
||||||
generateJsonOutput "$1" "Pass" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
|
|
||||||
fi
|
|
||||||
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
|
|
||||||
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "PASSED" "INFORMATIONAL")
|
|
||||||
echo "${JSON_ASFF_OUTPUT}" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_ASFF
|
|
||||||
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
|
||||||
sendToSecurityHub "${JSON_ASFF_OUTPUT}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " $OK PASS!$NORMAL $1"
|
echo " $OK PASS!$NORMAL $1"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -59,22 +58,21 @@ textInfo(){
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
if [[ $2 ]]; then
|
||||||
|
REPREGION=$2
|
||||||
|
else
|
||||||
|
REPREGION=$REGION
|
||||||
|
fi
|
||||||
|
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" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
|
||||||
|
fi
|
||||||
|
if [[ "${MODES[@]}" =~ "json" ]]; then
|
||||||
|
generateJsonOutput "$1" "Info" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
|
||||||
|
fi
|
||||||
|
if is_junit_output_enabled; then
|
||||||
output_junit_info "$1"
|
output_junit_info "$1"
|
||||||
fi
|
fi
|
||||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
|
if [[ "${MODES[@]}" =~ "text" ]]; then
|
||||||
if [[ $2 ]]; then
|
|
||||||
REPREGION=$2
|
|
||||||
else
|
|
||||||
REPREGION=$REGION
|
|
||||||
fi
|
|
||||||
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" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
|
|
||||||
fi
|
|
||||||
if [[ "${MODES[@]}" =~ "json" ]]; then
|
|
||||||
generateJsonOutput "$1" "Info" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " $NOTICE INFO! $1 $NORMAL"
|
echo " $NOTICE INFO! $1 $NORMAL"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -82,29 +80,28 @@ textInfo(){
|
|||||||
textFail(){
|
textFail(){
|
||||||
FAIL_COUNTER=$((FAIL_COUNTER+1))
|
FAIL_COUNTER=$((FAIL_COUNTER+1))
|
||||||
EXITCODE=3
|
EXITCODE=3
|
||||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
if [[ $2 ]]; then
|
||||||
|
REPREGION=$2
|
||||||
|
else
|
||||||
|
REPREGION=$REGION
|
||||||
|
fi
|
||||||
|
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" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
|
||||||
|
fi
|
||||||
|
if [[ "${MODES[@]}" =~ "json" ]]; then
|
||||||
|
generateJsonOutput "$1" "Fail" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
|
||||||
|
fi
|
||||||
|
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
|
||||||
|
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "FAILED" "HIGH")
|
||||||
|
echo "${JSON_ASFF_OUTPUT}" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_ASFF
|
||||||
|
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
||||||
|
sendToSecurityHub "${JSON_ASFF_OUTPUT}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if is_junit_output_enabled; then
|
||||||
output_junit_failure "$1"
|
output_junit_failure "$1"
|
||||||
fi
|
fi
|
||||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
|
if [[ "${MODES[@]}" =~ "text" ]]; then
|
||||||
if [[ $2 ]]; then
|
|
||||||
REPREGION=$2
|
|
||||||
else
|
|
||||||
REPREGION=$REGION
|
|
||||||
fi
|
|
||||||
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" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
|
|
||||||
fi
|
|
||||||
if [[ "${MODES[@]}" =~ "json" ]]; then
|
|
||||||
generateJsonOutput "$1" "Fail" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_JSON
|
|
||||||
fi
|
|
||||||
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
|
|
||||||
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "FAILED" "HIGH")
|
|
||||||
echo "${JSON_ASFF_OUTPUT}" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_ASFF
|
|
||||||
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
|
||||||
sendToSecurityHub "${JSON_ASFF_OUTPUT}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " $BAD FAIL! $1 $NORMAL"
|
echo " $BAD FAIL! $1 $NORMAL"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
19
prowler
19
prowler
@@ -45,7 +45,6 @@ SEP=','
|
|||||||
KEEPCREDREPORT=0
|
KEEPCREDREPORT=0
|
||||||
EXITCODE=0
|
EXITCODE=0
|
||||||
SEND_TO_SECURITY_HUB=0
|
SEND_TO_SECURITY_HUB=0
|
||||||
GENERATE_JUNIT=0
|
|
||||||
SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" )
|
SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" )
|
||||||
TITLE_ID=""
|
TITLE_ID=""
|
||||||
TITLE_TEXT="CALLER ERROR - UNSET TITLE"
|
TITLE_TEXT="CALLER ERROR - UNSET TITLE"
|
||||||
@@ -66,7 +65,7 @@ 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. They can be used combined comma separated.
|
-M <mode> output mode: text (default), mono, json, json-asff, junit-xml, csv. They can be used combined comma separated.
|
||||||
(separator is ","; data is on stdout; progress on stderr).
|
(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
|
||||||
@@ -79,7 +78,6 @@ USAGE:
|
|||||||
-V show version number & exit
|
-V show version number & exit
|
||||||
-s show scoring report
|
-s show scoring report
|
||||||
-S send check output to AWS Security Hub - only valid when the output mode is json-asff (i.e. "-M json-asff -S")
|
-S send check output to AWS Security Hub - only valid when the output mode is json-asff (i.e. "-M json-asff -S")
|
||||||
-J generate JUnit reports, readable by Jenkins or other CI tools. Files are written to ./junit-reports
|
|
||||||
-x specify external directory with custom checks (i.e. /my/own/checks, files must start by "check")
|
-x specify external directory with custom checks (i.e. /my/own/checks, files must start by "check")
|
||||||
-q suppress info messages and passing test output
|
-q suppress info messages and passing test output
|
||||||
-A account id for the account where to assume a role, requires -R and -T
|
-A account id for the account where to assume a role, requires -R and -T
|
||||||
@@ -94,7 +92,7 @@ USAGE:
|
|||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
while getopts ":hlLkqp:r:c:g:f:m:M:E:enbVsSJxI:A:R:T:" OPTION; do
|
while getopts ":hlLkqp:r:c:g:f:m:M:E:enbVsSxI:A:R:T:" OPTION; do
|
||||||
case $OPTION in
|
case $OPTION in
|
||||||
h )
|
h )
|
||||||
usage
|
usage
|
||||||
@@ -154,9 +152,6 @@ while getopts ":hlLkqp:r:c:g:f:m:M:E:enbVsSJxI:A:R:T:" OPTION; do
|
|||||||
S )
|
S )
|
||||||
SEND_TO_SECURITY_HUB=1
|
SEND_TO_SECURITY_HUB=1
|
||||||
;;
|
;;
|
||||||
J )
|
|
||||||
GENERATE_JUNIT=1
|
|
||||||
;;
|
|
||||||
x )
|
x )
|
||||||
EXTERNAL_CHECKS_PATH=$OPTARG
|
EXTERNAL_CHECKS_PATH=$OPTARG
|
||||||
;;
|
;;
|
||||||
@@ -280,12 +275,12 @@ execute_check() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
show_check_title ${alternate_name}
|
show_check_title ${alternate_name}
|
||||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
if is_junit_output_enabled; then
|
||||||
prepare_junit_check_output "$1"
|
prepare_junit_check_output "$1"
|
||||||
fi
|
fi
|
||||||
# Execute the check
|
# Execute the check
|
||||||
${alternate_name}
|
${alternate_name}
|
||||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
if is_junit_output_enabled; then
|
||||||
finalise_junit_check_output "$1"
|
finalise_junit_check_output "$1"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -300,12 +295,12 @@ execute_check() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
show_check_title $1
|
show_check_title $1
|
||||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
if is_junit_output_enabled; then
|
||||||
prepare_junit_check_output "$1"
|
prepare_junit_check_output "$1"
|
||||||
fi
|
fi
|
||||||
# Execute the check
|
# Execute the check
|
||||||
$1
|
$1
|
||||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
if is_junit_output_enabled; then
|
||||||
finalise_junit_check_output "$1"
|
finalise_junit_check_output "$1"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -443,7 +438,7 @@ if [[ "$SEND_TO_SECURITY_HUB" -eq 1 ]]; then
|
|||||||
checkSecurityHubCompatibility
|
checkSecurityHubCompatibility
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
if is_junit_output_enabled; then
|
||||||
prepare_junit_output
|
prepare_junit_output
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user