diff --git a/README.md b/README.md
index d81156e1..c8ee0050 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,10 @@
- [Features](#features)
- [Requirements and Installation](#requirements-and-installation)
- [Usage](#usage)
+- [Screenshots](#screenshots)
- [Advanced Usage](#advanced-usage)
- [Security Hub integration](#security-hub-integration)
- [Fix](#fix)
-- [Screenshots](#screenshots)
- [Troubleshooting](#troubleshooting)
- [Extras](#extras)
- [Forensics Ready Checks](#forensics-ready-checks)
@@ -168,9 +168,22 @@ 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
+## Screenshots
+
+- Sample screenshot of report first lines:
+
+
+
+- Sample screenshot of single check for check 3.3:
+
+
+
+- Sample screenshot of the html output `-M html`:
+
+
### Save your reports
-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):
+1. If you want to save your report for later analysis thare are different ways, natively (supported text, mono, csv, json, json-asff, junit-xml and html, see note below for more info):
```sh
./prowler -M csv
@@ -179,7 +192,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
or with multiple formats at the same time:
```sh
- ./prowler -M csv,json,json-asff
+ ./prowler -M csv,json,json-asff,html
```
or just a group of checks in multiple formats:
@@ -188,6 +201,12 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
./prowler -g gdpr -M csv,json,json-asff
```
+ or if you want a sorted and dynamic HTML report do:
+
+ ```sh
+ ./prowler -M html
+ ```
+
Now `-M` creates a file inside the prowler `output` directory named `prowler-output-AWSACCOUNTID-YYYYMMDDHHMMSS.format`. You don't have to specify anything else, no pipes, no redirects.
or just saving the output to a file like below:
@@ -196,13 +215,6 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
./prowler -M mono > prowler-report.txt
```
- or if you want a coloured HTML report do:
-
- ```sh
- pip install ansi2html
- ./prowler | ansi2html -la > report.html
- ```
-
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
@@ -374,16 +386,6 @@ Whitelist option works along with other options and adds a `WARNING` instead of
Check your report and fix the issues following all specific guidelines per check in
-## Screenshots
-
-- Sample screenshot of report first lines:
-
-
-
-- Sample screenshot of single check for check 3.3:
-
-
-
## Troubleshooting
### STS expired token
diff --git a/include/colors b/include/colors
index dd8cf233..dd8a8d20 100644
--- a/include/colors
+++ b/include/colors
@@ -14,8 +14,8 @@
IFS=',' read -ra MODES <<< "${MODE}"
for MODE in "${MODES[@]}"; do
- 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"
+ if [[ "$MODE" != "mono" && "$MODE" != "text" && "$MODE" != "csv" && "$MODE" != "json" && "$MODE" != "json-asff" && "$MODE" != "junit-xml" && "$MODE" != "html" ]]; then
+ echo -e "${OPTRED}ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json, json-asff, junit-xml or html. ./prowler -h for help"
EXITCODE=1
exit $EXITCODE
fi
diff --git a/include/outputs b/include/outputs
index e127a434..660eb744 100644
--- a/include/outputs
+++ b/include/outputs
@@ -17,13 +17,23 @@ EXTENSION_CSV="csv"
EXTENSION_JSON="json"
EXTENSION_ASFF="asff-json"
EXTENSION_TEXT="txt"
-EXTENSION_HTML="html" # not implemented yet, use ansi2html as in documentation
+EXTENSION_HTML="html"
OUTPUT_DATE=$(date -u +"%Y%m%d%H%M%S")
OUTPUT_DIR="${PROWLER_DIR}/output"
OUTPUT_FILE_NAME="${OUTPUT_DIR}/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}"
+HTML_LOGO_URL="https://github.com/toniblyx/prowler/"
+HTML_LOGO_IMG="https://raw.githubusercontent.com/toniblyx/prowler/master/util/html/prowler-logo.png"
+TIMESTAMP=$(get_iso8601_timestamp)
+PROWLER_PARAMETERS=$@
-# Ensure that output directory always exists
-mkdir -p "${OUTPUT_DIR}"
+# Ensure that output directory always exists when -M is used
+if [[ $MODE ]];then
+ mkdir -p "${OUTPUT_DIR}"
+ if [[ "${MODES[@]}" =~ "html" ]]; then
+ addHtmlHeader > ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ HTML_REPORT_INIT="1"
+ fi
+fi
if [[ $PROFILE == "" ]];then
PROFILE="ENV"
@@ -62,6 +72,9 @@ textPass(){
if [[ "${MODES[@]}" =~ "text" || "${MODES[@]}" =~ "mono" ]]; then
echo " $OK PASS!$NORMAL $1"
fi
+ if [[ "${MODES[@]}" =~ "html" ]]; then
+ generateHtmlOutput "$1" "PASS"
+ fi
}
textInfo(){
@@ -89,6 +102,9 @@ textInfo(){
if [[ "${MODES[@]}" =~ "text" ]]; then
echo " $NOTICE INFO! $1 $NORMAL"
fi
+ if [[ "${MODES[@]}" =~ "html" ]]; then
+ generateHtmlOutput "$1" "INFO"
+ fi
}
textFail(){
@@ -147,6 +163,9 @@ textFail(){
if [[ "${MODES[@]}" =~ "text" ]]; then
echo " $colorcode ${level}! $1 $NORMAL"
fi
+ if [[ "${MODES[@]}" =~ "html" ]]; then
+ generateHtmlOutput "$1" "${level}"
+ fi
}
textTitle(){
@@ -284,3 +303,56 @@ generateJsonAsffOutput(){
}
}'
}
+
+generateHtmlOutput(){
+ local message=$1
+ local status=$2
+ if [[ $status == "INFO" ]];then
+ echo '' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo 'INFO | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$ACCOUNT_NUM' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$REPREGION' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$ITEM_LEVEL' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$TITLE_ID' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$TITLE_TEXT' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$message' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo '
' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ fi
+ if [[ $status == "PASS" ]];then
+ echo '' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo 'PASS | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$ACCOUNT_NUM' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$REPREGION' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$ITEM_LEVEL' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$TITLE_ID' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$TITLE_TEXT' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$message' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo '
' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ fi
+ if [[ $status == "FAIL" ]];then
+ echo '' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo '| | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo 'FAIL | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$ACCOUNT_NUM' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$REPREGION' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$ITEM_LEVEL' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$TITLE_ID' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$TITLE_TEXT' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$message' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo '
' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ fi
+ if [[ $status == "WARNING" ]];then
+ echo '' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo 'WARN | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$ACCOUNT_NUM' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$REPREGION' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$ITEM_LEVEL' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$TITLE_ID' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$TITLE_TEXT' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo ''$message' | ' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ echo '
'>> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ fi
+}
diff --git a/prowler b/prowler
index 37f13914..f73005ba 100755
--- a/prowler
+++ b/prowler
@@ -32,7 +32,7 @@ OPTRED="[1;31m"
OPTNORMAL="[0;39m"
# Set the defaults variables
-PROWLER_VERSION=2.3.0RC
+PROWLER_VERSION=2.3.0RC2
PROWLER_DIR=$(dirname "$0")
REGION=""
@@ -196,6 +196,10 @@ done
clean_up() {
rm -f /tmp/prowler*.policy.*
+ # in case html output is used, make sure it closes html file properly
+ if [[ "${MODES[@]}" =~ "html" ]]; then
+ addHtmlFooter >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ fi
}
handle_ctrl_c() {
@@ -213,16 +217,17 @@ trap handle_ctrl_c INT
. $PROWLER_DIR/include/aws_profile_loader
. $PROWLER_DIR/include/awscli_detector
. $PROWLER_DIR/include/whoami
-. $PROWLER_DIR/include/outputs
+. $PROWLER_DIR/include/assume_role
. $PROWLER_DIR/include/csv_header
. $PROWLER_DIR/include/banner
+. $PROWLER_DIR/include/html_report
+. $PROWLER_DIR/include/outputs
. $PROWLER_DIR/include/credentials_report
. $PROWLER_DIR/include/scoring
. $PROWLER_DIR/include/python_detector
. $PROWLER_DIR/include/secrets_detector
. $PROWLER_DIR/include/check_creds_last_used
. $PROWLER_DIR/include/check3x
-. $PROWLER_DIR/include/assume_role
. $PROWLER_DIR/include/connection_tests
. $PROWLER_DIR/include/securityhub_integration
. $PROWLER_DIR/include/junit_integration
@@ -509,6 +514,9 @@ if [[ $GROUP_ID_READ ]];then
if [[ " ${GROUP_ID[@]} " =~ " ${GROUP_ID_READ} " ]]; then
execute_group_by_id ${GROUP_ID_READ} ${EXCLUDE_CHECK_ID}
+ if [[ "${MODES[@]}" =~ "html" ]]; then
+ addHtmlFooter >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ fi
cleanTemp
scoring
exit $EXITCODE
@@ -535,11 +543,17 @@ if [[ $CHECK_ID ]];then
for CHECK in "${CHECKS[@]}"; do
execute_check $CHECK
done
+ if [[ "${MODES[@]}" =~ "html" ]]; then
+ addHtmlFooter >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+ fi
cleanTemp
exit $EXITCODE
fi
execute_all
+if [[ "${MODES[@]}" =~ "html" ]]; then
+ addHtmlFooter >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
+fi
scoring
cleanTemp
@@ -550,5 +564,4 @@ if [[ $ACCOUNT_TO_ASSUME ]]; then
unset AWS_SESSION_TOKEN
fi
-
-exit $EXITCODE
+exit $EXITCODE
\ No newline at end of file