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: + + screenshot 2016-09-13 16 05 42 + +- Sample screenshot of single check for check 3.3: + + screenshot 2016-09-14 13 20 46 + +- Sample screenshot of the html output `-M html`: + Prowler 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: - - screenshot 2016-09-13 16 05 42 - -- Sample screenshot of single check for check 3.3: - - screenshot 2016-09-14 13 20 46 - ## 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="" OPTNORMAL="" # 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