mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +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
|
||||
|
||||
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
|
||||
./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
|
||||
```
|
||||
|
||||
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
|
||||
./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`.
|
||||
@@ -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
|
||||
(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 (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).
|
||||
-k keep the credential report
|
||||
-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
|
||||
-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")
|
||||
-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)
|
||||
-q suppress info messages and passing test output
|
||||
-A account id for the account where to assume a role, requires -R and -T
|
||||
|
||||
@@ -14,16 +14,15 @@
|
||||
|
||||
IFS=',' read -ra MODES <<< "${MODE}"
|
||||
for MODE in "${MODES[@]}"; do
|
||||
if [[ "$MODE" != "mono" && "$MODE" != "text" && "$MODE" != "csv" && "$MODE" != "json" && "$MODE" != "json-asff" ]]; then
|
||||
echo -e "${OPTRED}ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json or json-asff. ./prowler -h for help"
|
||||
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, json-asff or junit-xml. ./prowler -h for help"
|
||||
EXITCODE=1
|
||||
exit $EXITCODE
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$MODE" == "mono" || "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||
MONOCHROME=1
|
||||
fi
|
||||
if [[ "$MODE" == "mono" || "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||
MONOCHROME=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $MONOCHROME -eq 1 ]]; then
|
||||
# Colors
|
||||
|
||||
@@ -15,6 +15,14 @@
|
||||
|
||||
JUNIT_OUTPUT_DIRECTORY="junit-reports"
|
||||
|
||||
is_junit_output_enabled() {
|
||||
if [[ ${MODES[@]} =~ "junit-xml" ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
xml_escape() {
|
||||
sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/\"/\"/g; s/'"'"'/\'/g' <<< "$1"
|
||||
}
|
||||
|
||||
109
include/outputs
109
include/outputs
@@ -27,29 +27,28 @@ textPass(){
|
||||
fi
|
||||
|
||||
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"
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; 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
|
||||
if [[ "${MODES[@]}" =~ "text" ]]; then
|
||||
echo " $OK PASS!$NORMAL $1"
|
||||
fi
|
||||
}
|
||||
@@ -59,22 +58,21 @@ textInfo(){
|
||||
return
|
||||
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"
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; 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
|
||||
if [[ "${MODES[@]}" =~ "text" ]]; then
|
||||
echo " $NOTICE INFO! $1 $NORMAL"
|
||||
fi
|
||||
}
|
||||
@@ -82,29 +80,28 @@ textInfo(){
|
||||
textFail(){
|
||||
FAIL_COUNTER=$((FAIL_COUNTER+1))
|
||||
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"
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; 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
|
||||
if [[ "${MODES[@]}" =~ "text" ]]; then
|
||||
echo " $BAD FAIL! $1 $NORMAL"
|
||||
fi
|
||||
}
|
||||
|
||||
19
prowler
19
prowler
@@ -45,7 +45,6 @@ SEP=','
|
||||
KEEPCREDREPORT=0
|
||||
EXITCODE=0
|
||||
SEND_TO_SECURITY_HUB=0
|
||||
GENERATE_JUNIT=0
|
||||
SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" )
|
||||
TITLE_ID=""
|
||||
TITLE_TEXT="CALLER ERROR - UNSET TITLE"
|
||||
@@ -66,7 +65,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 (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).
|
||||
-k keep the credential report
|
||||
-n show check numbers to sort easier
|
||||
@@ -79,7 +78,6 @@ USAGE:
|
||||
-V show version number & exit
|
||||
-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")
|
||||
-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")
|
||||
-q suppress info messages and passing test output
|
||||
-A account id for the account where to assume a role, requires -R and -T
|
||||
@@ -94,7 +92,7 @@ USAGE:
|
||||
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
|
||||
h )
|
||||
usage
|
||||
@@ -154,9 +152,6 @@ while getopts ":hlLkqp:r:c:g:f:m:M:E:enbVsSJxI:A:R:T:" OPTION; do
|
||||
S )
|
||||
SEND_TO_SECURITY_HUB=1
|
||||
;;
|
||||
J )
|
||||
GENERATE_JUNIT=1
|
||||
;;
|
||||
x )
|
||||
EXTERNAL_CHECKS_PATH=$OPTARG
|
||||
;;
|
||||
@@ -280,12 +275,12 @@ execute_check() {
|
||||
fi
|
||||
fi
|
||||
show_check_title ${alternate_name}
|
||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
||||
if is_junit_output_enabled; then
|
||||
prepare_junit_check_output "$1"
|
||||
fi
|
||||
# Execute the check
|
||||
${alternate_name}
|
||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
||||
if is_junit_output_enabled; then
|
||||
finalise_junit_check_output "$1"
|
||||
fi
|
||||
else
|
||||
@@ -300,12 +295,12 @@ execute_check() {
|
||||
fi
|
||||
fi
|
||||
show_check_title $1
|
||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
||||
if is_junit_output_enabled; then
|
||||
prepare_junit_check_output "$1"
|
||||
fi
|
||||
# Execute the check
|
||||
$1
|
||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
||||
if is_junit_output_enabled; then
|
||||
finalise_junit_check_output "$1"
|
||||
fi
|
||||
else
|
||||
@@ -443,7 +438,7 @@ if [[ "$SEND_TO_SECURITY_HUB" -eq 1 ]]; then
|
||||
checkSecurityHubCompatibility
|
||||
fi
|
||||
|
||||
if [[ "${GENERATE_JUNIT}" -eq 1 ]]; then
|
||||
if is_junit_output_enabled; then
|
||||
prepare_junit_output
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user