mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
refactor(outputs): Consolidate Prowler output functions (#1180)
* chore(db providers): db providers first version * chore(db provider): added db provider setup into Readme * fix(csv_line): csv_line out of conditional * fix(README): text instead of varchar in table * fix(help): help message extended Co-authored-by: Sergio Garcia <38561120+sergargar@users.noreply.github.com> * fix(typo): Update README.md Co-authored-by: Pepe Fagoaga <pepe@verica.io> * fix(table): add if not exists Co-authored-by: Pepe Fagoaga <pepe@verica.io> * fix(typo): Readme postgreSQL Co-authored-by: Pepe Fagoaga <pepe@verica.io> * fix(db_connector): details to add a new provider * fix(typo): Uppercase Prowler Co-authored-by: Toni de la Fuente <toni@blyx.com> * fix(prowler): deleted unused variable * chore(checks): test db connector previous to send data * chore(input tests): input tests moved to main * fix(typo): Readme typos * chore(table): table name from pgpass file * fix(grep test): Added missing -E flag * chore(table): check of table name and Readme * chore(error colors): Added error colors * chore(inputcheck): checks about mode and output inputs into main * fix(inputs) custom output file name * fix(outputs): comment profile * chore(textXXX): both 3 textfunctions using general * fix(allowlist): allowlist check included as function * fix(headers): Add headers to certain output files * fix(reformulate): change structure and delete comments * fix(testing): Input test after load includes * fix(variables): Added named vars * fix(colors): Deleted unused colors * fix(outputs): fine tuning * fix(outputs): allowlist parameters read * fix(allowlist): allowlist logic reformulated * fix(REPREGION): REPREGION change by REGION_FROM_CHECK Co-authored-by: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Co-authored-by: Pepe Fagoaga <pepe@verica.io> Co-authored-by: Toni de la Fuente <toni@blyx.com>
This commit is contained in:
@@ -340,6 +340,7 @@ Jump into the section for the database provider you want to use and follow the r
|
||||
- Mac -> `brew install libpq`
|
||||
- Ubuntu -> `sudo apt-get install postgresql-client `
|
||||
- RHEL/Centos -> `sudo yum install postgresql10`
|
||||
|
||||
- Configure a `~/.pgpass` file into the root folder of the user that is going to launch Prowler ([pgpass file doc](https://www.postgresql.org/docs/current/libpq-pgpass.html)), including an extra field at the end of the line, separated by `:`, to name the table, for instance:
|
||||
`hostname:port:database:username:password:prowler_findings`
|
||||
- Create a table in your PostgreSQL database to store the Prowler's data. You can use the following SQL statement to create the table:
|
||||
@@ -372,6 +373,7 @@ account_details_org TEXT,
|
||||
account_details_tags TEXT
|
||||
);
|
||||
```
|
||||
|
||||
- Execute Prowler with `-d` flag, for example:
|
||||
`./prowler -M csv -d postgres`
|
||||
> *Note*: This command creates a `csv` output file and stores the Prowler output in the configured PostgreSQL DB. It's an example, `-d` flag **does not** require `-M` to run.
|
||||
|
||||
+13
-52
@@ -12,58 +12,19 @@
|
||||
# specific language governing permissions and limitations under the License.
|
||||
|
||||
|
||||
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" && "$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
|
||||
if [[ "$MODE" == "mono" || "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||
MONOCHROME=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $MONOCHROME -eq 1 ]]; then
|
||||
# Colors
|
||||
NORMAL=''
|
||||
WARNING='' # Bad (red)
|
||||
SECTION='' # Section (yellow)
|
||||
NOTICE='' # Notice (yellow)
|
||||
OK='' # Ok (green)
|
||||
BAD='' # Bad (red)
|
||||
CYAN=''
|
||||
BLUE=''
|
||||
BROWN=''
|
||||
DARKGRAY=''
|
||||
GRAY=''
|
||||
GREEN=''
|
||||
MAGENTA=''
|
||||
PURPLE=''
|
||||
RED=''
|
||||
YELLOW=''
|
||||
WHITE=''
|
||||
else
|
||||
# Colors
|
||||
# NOTE: Your editor may NOT show the 0x1b / escape character left of the '['
|
||||
NORMAL="[0;39m"
|
||||
WARNING="[0;33m" # Warning (brown)
|
||||
SECTION="[1;33m" # Section (yellow)
|
||||
NOTICE="[1;33m" # Notice (yellow)
|
||||
OK="[1;32m" # Ok (green)
|
||||
BAD="[1;31m" # Bad (red)
|
||||
CYAN="[0;36m"
|
||||
BLUE="[0;34m"
|
||||
BROWN="[0;33m"
|
||||
DARKGRAY="[0;30m"
|
||||
GRAY="[0;37m"
|
||||
GREEN="[1;32m"
|
||||
MAGENTA="[1;35m"
|
||||
PURPLE="[0;35m"
|
||||
RED="[1;31m"
|
||||
YELLOW="[1;33m"
|
||||
WHITE="[1;37m"
|
||||
fi
|
||||
# Colors
|
||||
# NOTE: Your editor may NOT show the 0x1b / escape character left of the '['
|
||||
NORMAL="[0;39m"
|
||||
WARNING="[0;33m" # Warning (brown)
|
||||
NOTICE="[1;33m" # Notice (yellow)
|
||||
OK="[1;32m" # Ok (green)
|
||||
BAD="[1;31m" # Bad (red)
|
||||
CYAN="[0;36m"
|
||||
BLUE="[0;34m"
|
||||
BROWN="[0;33m"
|
||||
MAGENTA="[1;35m"
|
||||
RED="[1;31m"
|
||||
YELLOW="[1;33m"
|
||||
|
||||
printColorsCode(){
|
||||
if [[ $MONOCHROME -eq 0 ]]; then
|
||||
|
||||
@@ -28,7 +28,6 @@ postgresql_connector () {
|
||||
|
||||
CSV_REGISTRY="${1}"
|
||||
psql -q -U "${PSQL_USER}" -h "${PSQL_HOSTNAME}" -c "copy ${PSQL_TABLE} from stdin with null as E'\'\'' delimiter ','" <<< "${CSV_REGISTRY}"
|
||||
|
||||
}
|
||||
|
||||
db_exit_abnormally() {
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ addHtmlHeader() {
|
||||
PROFILE="ENV"
|
||||
fi
|
||||
if [[ -z $HTML_REPORT_INIT ]]; then
|
||||
cat <<EOF
|
||||
cat <<EOF >> "${OUTPUT_FILE_NAME}"."${EXTENSION_HTML}"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
+182
-237
@@ -11,45 +11,12 @@
|
||||
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations under the License.
|
||||
|
||||
# Output formatting functions
|
||||
|
||||
EXTENSION_CSV="csv"
|
||||
EXTENSION_JSON="json"
|
||||
EXTENSION_ASFF="asff.json"
|
||||
EXTENSION_TEXT="txt"
|
||||
EXTENSION_HTML="html"
|
||||
OUTPUT_DATE=$(date -u +"%Y%m%d%H%M%S")
|
||||
OUTPUT_DIR="${PROWLER_DIR}/output" # default output if none
|
||||
if [[ $OUTPUT_DIR_CUSTOM ]]; then
|
||||
# output mode has to be set to other than text
|
||||
if [[ ! " ${MODES[@]} " =~ " text " || ${check_id} == 7.1 || ${check_id} == 7.74 ]]; then
|
||||
if [[ ! -d $OUTPUT_DIR_CUSTOM ]]; then
|
||||
echo "$OPTRED ERROR!$OPTNORMAL directory \"$OUTPUT_DIR_CUSTOM\" does not exist."
|
||||
exit 1
|
||||
else
|
||||
OUTPUT_DIR=$OUTPUT_DIR_CUSTOM
|
||||
fi
|
||||
else
|
||||
echo "$OPTRED ERROR!$OPTNORMAL - Mode (-M) has to be set as well. Use -h for help."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -z ${OUTPUT_FILE_NAME+x} ]; then
|
||||
OUTPUT_FILE_NAME="${OUTPUT_DIR}/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}"
|
||||
else
|
||||
OUTPUT_FILE_NAME="${OUTPUT_DIR}/$OUTPUT_FILE_NAME"
|
||||
fi
|
||||
HTML_LOGO_URL="https://github.com/prowler-cloud/prowler/"
|
||||
HTML_LOGO_IMG="https://github.com/prowler-cloud/prowler/raw/master/util/html/prowler-logo-new.png"
|
||||
TIMESTAMP=$(get_iso8601_timestamp)
|
||||
PROWLER_PARAMETERS=$@
|
||||
|
||||
|
||||
# Available parameters for outputs formats (implemented this in CSV from v2.4):
|
||||
|
||||
# Output format
|
||||
# $PROFILE profile used to run Prowler (--profile in AWS CLI)
|
||||
# $ACCOUNT_NUM AWS Account ID
|
||||
# $REPREGION AWS region scanned
|
||||
# $REGION_FROM_CHECK AWS region scanned
|
||||
# $TITLE_ID Numeric identifier of each check (1.2, 2.3, etc), originally based on CIS checks.
|
||||
# $CHECK_RESULT values can be PASS, FAIL, INFO or WARNING if allowlisted
|
||||
# $ITEM_SCORED corresponds to CHECK_SCORED, values can be Scored/Not Scored. This is CIS only, will be deprecated in Prowler.
|
||||
@@ -71,249 +38,227 @@ PROWLER_PARAMETERS=$@
|
||||
# $ACCOUNT_DETAILS_ORG
|
||||
# $ACCOUNT_DETAILS_TAGS
|
||||
|
||||
EXTENSION_CSV="csv"
|
||||
EXTENSION_JSON="json"
|
||||
EXTENSION_ASFF="asff.json"
|
||||
EXTENSION_TEXT="txt"
|
||||
EXTENSION_HTML="html"
|
||||
HTML_LOGO_URL="https://github.com/prowler-cloud/prowler/"
|
||||
HTML_LOGO_IMG="https://github.com/prowler-cloud/prowler/raw/master/util/html/prowler-logo-new.png"
|
||||
TIMESTAMP=$(get_iso8601_timestamp)
|
||||
PROWLER_PARAMETERS=$@
|
||||
|
||||
|
||||
# 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"
|
||||
# Set exitcode for codebuild/jenkins-like integrations
|
||||
set_exitcode () {
|
||||
if [ "${FAILED_CHECK_FAILED_SCAN}" == 1 ] && [ -z "${FAILED_CHECK_FAILED_SCAN_LIST}" ]
|
||||
then
|
||||
EXITCODE=3
|
||||
export EXITCODE
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "csv" ]]; then
|
||||
printCsvHeader
|
||||
if [[ "${FAILED_CHECK_FAILED_SCAN_LIST}" =~ ${CHECK_NAME} ]]
|
||||
then
|
||||
EXITCODE=3
|
||||
export EXITCODE
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# textInfo "HTML report will be saved: ${OUTPUT_FILE_NAME}.$EXTENSION_HTML"
|
||||
# textInfo "JSON ASFF report will be saved: ${OUTPUT_FILE_NAME}.$EXTENSION_ASFF"
|
||||
# textInfo "CSV report will be saved: ${OUTPUT_FILE_NAME}.$EXTENSION_CSV"
|
||||
# textInfo "JSON report will be saved: ${OUTPUT_FILE_NAME}.$EXTENSION_JSON"
|
||||
|
||||
if [[ $PROFILE == "" ]];then
|
||||
PROFILE="ENV"
|
||||
fi
|
||||
|
||||
textPass(){
|
||||
CHECK_RESULT="PASS"
|
||||
CHECK_RESULT_EXTENDED="$1"
|
||||
CHECK_RESOURCE_ID="$3"
|
||||
|
||||
if [[ "$QUIET" == 1 ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
PASS_COUNTER=$((PASS_COUNTER+1))
|
||||
if [[ $2 ]]; then
|
||||
REPREGION=$2
|
||||
else
|
||||
REPREGION=$REGION
|
||||
fi
|
||||
|
||||
CSV_LINE="${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}"
|
||||
|
||||
if [[ "${MODES[@]}" =~ "csv" ]]; then
|
||||
# Writting csv file replacing commas
|
||||
echo "${CSV_LINE}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "json" ]]; then
|
||||
generateJsonOutput "$1" "Pass" "$CHECK_RESOURCE_ID" >> ${OUTPUT_FILE_NAME}.$EXTENSION_JSON
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
|
||||
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "PASSED" "$CHECK_RESOURCE_ID")
|
||||
echo "${JSON_ASFF_OUTPUT}" >> $OUTPUT_FILE_NAME.$EXTENSION_ASFF
|
||||
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
||||
sendToSecurityHub "${JSON_ASFF_OUTPUT}" "${REPREGION}"
|
||||
# Add header to certain output files readed from mode
|
||||
output_files_init() {
|
||||
for MODE in "${MODES[@]}";
|
||||
do
|
||||
if [ "${MODE}" == 'html' ]
|
||||
then
|
||||
addHtmlHeader
|
||||
HTML_REPORT_INIT="1"
|
||||
export HTML_REPORT_INIT
|
||||
fi
|
||||
if [ "${MODE}" == 'csv' ]
|
||||
then
|
||||
printCsvHeader
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Check if resource checked is allowlisted
|
||||
allowlist_check() {
|
||||
# Checked value is the whole log message that comes as argument
|
||||
CHECKED_VALUE=${1}
|
||||
# Default value of result is Fail
|
||||
CHECK_RESULT='FAIL'
|
||||
## ignore allowlists for current check
|
||||
while read -r excluded_item; do
|
||||
# IGNORE_CHECK_NAME is the check with resources allowlisted
|
||||
# RESOURCE_VALUE is what it comes after 'CHECK_NAME:'
|
||||
IGNORE_CHECK_NAME=$(awk -F ":" '{print $1}' <<< "${excluded_item}")
|
||||
RESOURCE_VALUE=$(awk -F "${CHECK_NAME}:" '{print $2}' <<< "${excluded_item}")
|
||||
if [[ "${IGNORE_CHECK_NAME}" == "${CHECK_NAME}" ]]
|
||||
then
|
||||
if [[ "${CHECKED_VALUE}" =~ ${RESOURCE_VALUE} ]]
|
||||
then
|
||||
CHECK_RESULT="WARNING"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
done <<< "$IGNORES"
|
||||
echo "${CHECK_RESULT}"
|
||||
}
|
||||
|
||||
is_quiet() {
|
||||
IS_QUIET="${1}"
|
||||
if [ "${IS_QUIET}" -eq 1 ]
|
||||
then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
if is_junit_output_enabled; then
|
||||
output_junit_success "$1"
|
||||
}
|
||||
|
||||
general_output() {
|
||||
CHECK_RESULT="${1}"
|
||||
CHECK_RESULT_EXTENDED="${2}"
|
||||
CHECK_RESOURCE_ID="${3}"
|
||||
REGION_FROM_CHECK="${4}"
|
||||
CSV_LINE="${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REGION_FROM_CHECK/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}"
|
||||
COLOR_CODE="$OK"
|
||||
|
||||
# Check if color is different than normal (pass)
|
||||
if [ "${CHECK_RESULT}" == 'INFO' ]
|
||||
then
|
||||
COLOR_CODE="${NOTICE}"
|
||||
elif [ "${CHECK_RESULT}" == 'FAIL' ]
|
||||
then
|
||||
COLOR_CODE="${BAD}"
|
||||
elif [ "${CHECK_RESULT}" == 'WARNING' ]
|
||||
then
|
||||
COLOR_CODE="${WARNING}"
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "mono" ]]; then
|
||||
echo " $OK PASS!$NORMAL $1" >> ${OUTPUT_FILE_NAME}.$EXTENSION_TEXT
|
||||
fi
|
||||
# if [[ "${MODES[@]}" =~ "text" || "${MODES[@]}" =~ "mono" ]]; then
|
||||
# runs showing console output no mater what output is selected
|
||||
echo " $OK PASS!$NORMAL $1"
|
||||
# fi
|
||||
if [[ "${MODES[@]}" =~ "html" ]]; then
|
||||
generateHtmlOutput "$1" "PASS"
|
||||
# Check if region is passed
|
||||
if [ -z "${REGION_FROM_CHECK}" ]
|
||||
then
|
||||
REGION_FROM_CHECK=$REGION
|
||||
fi
|
||||
# Iterating over input modes
|
||||
for MODE in "${MODES[@]}";
|
||||
do
|
||||
if [ "${MODE}" == 'html' ]
|
||||
then
|
||||
generateHtmlOutput "${CHECK_RESULT_EXTENDED}" "${CHECK_RESULT}"
|
||||
elif [ "${MODE}" == 'csv' ]
|
||||
then
|
||||
echo "${CSV_LINE}" >> "${OUTPUT_FILE_NAME}"."${EXTENSION_CSV}"
|
||||
elif [ "${MODE}" == 'json' ]
|
||||
then
|
||||
generateJsonOutput "${CHECK_RESULT_EXTENDED}" "${CHECK_RESULT}" "$CHECK_RESOURCE_ID" >> "${OUTPUT_FILE_NAME}"."${EXTENSION_JSON}"
|
||||
elif [ "${MODE}" == 'json-asff' ]
|
||||
then
|
||||
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "${CHECK_RESULT_EXTENDED}" "PASSED" "$CHECK_RESOURCE_ID")
|
||||
echo "${JSON_ASFF_OUTPUT}" >> "${OUTPUT_FILE_NAME}"."${EXTENSION_ASFF}"
|
||||
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
||||
sendToSecurityHub "${JSON_ASFF_OUTPUT}" "${REGION_FROM_CHECK}"
|
||||
fi
|
||||
elif is_junit_output_enabled
|
||||
then
|
||||
if [ "${CHECK_RESULT}" == 'PASS' ]
|
||||
then
|
||||
output_junit_success "${CHECK_RESULT_EXTENDED}"
|
||||
elif [ "${CHECK_RESULT}" == 'INFO' ]
|
||||
then
|
||||
output_junit_info "${CHECK_RESULT_EXTENDED}"
|
||||
elif [ "${CHECK_RESULT}" == 'FAIL' ]
|
||||
then
|
||||
output_junit_failure "${CHECK_RESULT_EXTENDED}"
|
||||
elif [ "${CHECK_RESULT}" == 'WARNING' ]
|
||||
then
|
||||
output_junit_skipped "${CHECK_RESULT_EXTENDED}"
|
||||
fi
|
||||
elif [ "${MODE}" == 'mono' ]
|
||||
then
|
||||
echo " $COLOR_CODE ${CHECK_RESULT}! $NORMAL ${CHECK_RESULT_EXTENDED}">> "${OUTPUT_FILE_NAME}"."${EXTENSION_TEXT}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Print in screen
|
||||
echo " $COLOR_CODE ${CHECK_RESULT}!$NORMAL ${CHECK_RESULT_EXTENDED}"
|
||||
|
||||
#checking database provider
|
||||
if [[ ${DATABASE_PROVIDER} == 'postgresql' ]]
|
||||
then
|
||||
postgresql_connector "${CSV_LINE}"
|
||||
fi
|
||||
}
|
||||
|
||||
textPass(){
|
||||
CHECK_RESULT="PASS"
|
||||
CHECK_RESULT_EXTENDED="${1}"
|
||||
CHECK_RESOURCE_ID="${3}"
|
||||
CHECK_REGION="${2}"
|
||||
|
||||
if is_quiet "${QUIET}"
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
general_output "${CHECK_RESULT}" "${CHECK_RESULT_EXTENDED}" "${CHECK_RESOURCE_ID}" "${CHECK_REGION}"
|
||||
}
|
||||
|
||||
textInfo(){
|
||||
CHECK_RESULT="INFO"
|
||||
CHECK_RESULT_EXTENDED="$1"
|
||||
CHECK_RESOURCE_ID="$3"
|
||||
CHECK_RESULT_EXTENDED="${1}"
|
||||
CHECK_RESOURCE_ID="${3}"
|
||||
CHECK_REGION="${2}"
|
||||
|
||||
if [[ "$QUIET" == 1 ]]; then
|
||||
if is_quiet "${QUIET}"
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ $2 ]]; then
|
||||
REPREGION=$2
|
||||
else
|
||||
REPREGION=$REGION
|
||||
fi
|
||||
|
||||
CSV_LINE="${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}"
|
||||
|
||||
if [[ "${MODES[@]}" =~ "csv" ]]; then
|
||||
# Writing csv file replacing commas
|
||||
echo "${CSV_LINE}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "json" ]]; then
|
||||
generateJsonOutput "$1" "Info" "$CHECK_RESOURCE_ID" >> ${OUTPUT_FILE_NAME}.${EXTENSION_JSON}
|
||||
fi
|
||||
if is_junit_output_enabled; then
|
||||
output_junit_info "$1"
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "mono" ]]; then
|
||||
echo " $NOTICE INFO! $1 $NORMAL" >> ${OUTPUT_FILE_NAME}.$EXTENSION_TEXT
|
||||
fi
|
||||
# if [[ "${MODES[@]}" =~ "text" ]]; then
|
||||
echo " $NOTICE INFO! $1 $NORMAL"
|
||||
# fi
|
||||
if [[ "${MODES[@]}" =~ "html" ]]; then
|
||||
generateHtmlOutput "$1" "INFO" "$CHECK_RESOURCE_ID"
|
||||
fi
|
||||
|
||||
#checking database provider
|
||||
if [[ ${DATABASE_PROVIDER} == 'postgresql' ]]
|
||||
then
|
||||
postgresql_connector "${CSV_LINE}"
|
||||
fi
|
||||
general_output "${CHECK_RESULT}" "${CHECK_RESULT_EXTENDED}" "${CHECK_RESOURCE_ID}" "${CHECK_REGION}"
|
||||
}
|
||||
|
||||
textFail(){
|
||||
## ignore allowlists for current check
|
||||
level="FAIL"
|
||||
colorcode="$BAD"
|
||||
while read -r excluded_item; do
|
||||
# ignore_check_name is the check with resources allowlisted
|
||||
ignore_check_name=$(awk -F ":" '{print $1}' <<< "${excluded_item}")
|
||||
# Resource value is what it comes after CHECK_NAME: :
|
||||
resource_value=$(awk -F "$CHECK_NAME:" '{print $2}' <<< "${excluded_item}")
|
||||
# Checked value is the whole log message that comes as argument
|
||||
checked_value=$1
|
||||
if [[ "${ignore_check_name}" != "${CHECK_NAME}" ]]; then
|
||||
# not for this check
|
||||
continue
|
||||
fi
|
||||
# To set WARNING flag checked_value have to include value of resource_value
|
||||
# If it is treated as only expanse (*[]*) will not detect regex like [:alpha:]
|
||||
if [[ "${checked_value}" =~ ${resource_value} ]]; then
|
||||
level="WARNING"
|
||||
colorcode="${WARNING}"
|
||||
break
|
||||
fi
|
||||
done <<< "$IGNORES"
|
||||
|
||||
CHECK_RESULT='FAIL'
|
||||
CHECK_RESULT_EXTENDED="${1}"
|
||||
CHECK_RESOURCE_ID="${3}"
|
||||
CHECK_REGION="${2}"
|
||||
|
||||
# Check if resources are whitelisted
|
||||
CHECK_RESULT=$(allowlist_check "${CHECK_RESULT_EXTENDED}")
|
||||
|
||||
# only set non-0 exit code on FAIL mode, WARN is ok
|
||||
if [[ "$level" == "FAIL" ]]; then
|
||||
FAIL_COUNTER=$((FAIL_COUNTER+1))
|
||||
if [ "$FAILED_CHECK_FAILED_SCAN" == 1 ] && [ -z "$FAILED_CHECK_FAILED_SCAN_LIST" ] ; then
|
||||
EXITCODE=3
|
||||
fi
|
||||
if [[ "${FAILED_CHECK_FAILED_SCAN_LIST[@]}" =~ "$CHECK_NAME" ]]; then
|
||||
EXITCODE=3
|
||||
fi
|
||||
fi
|
||||
|
||||
CHECK_RESULT=$level
|
||||
CHECK_RESULT_EXTENDED="$1"
|
||||
CHECK_RESOURCE_ID="$3"
|
||||
|
||||
if [[ $2 ]]; then
|
||||
REPREGION=$2
|
||||
else
|
||||
REPREGION=$REGION
|
||||
fi
|
||||
|
||||
CSV_LINE="${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}"
|
||||
|
||||
if [[ "${MODES[@]}" =~ "csv" ]]; then
|
||||
# Writing csv file replacing commas
|
||||
echo "${CSV_LINE}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "json" ]]; then
|
||||
generateJsonOutput "$1" "${level}" "$CHECK_RESOURCE_ID">> ${OUTPUT_FILE_NAME}.${EXTENSION_JSON}
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "json-asff" ]]; then
|
||||
JSON_ASFF_OUTPUT=$(generateJsonAsffOutput "$1" "${level}" "$CHECK_RESOURCE_ID")
|
||||
echo "${JSON_ASFF_OUTPUT}" >> ${OUTPUT_FILE_NAME}.${EXTENSION_ASFF}
|
||||
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
||||
sendToSecurityHub "${JSON_ASFF_OUTPUT}" "${REPREGION}"
|
||||
fi
|
||||
fi
|
||||
if is_junit_output_enabled; then
|
||||
if [[ "${level}" == "FAIL" ]]; then
|
||||
output_junit_failure "$1"
|
||||
elif [[ "${level}" == "WARNING" ]]; then
|
||||
output_junit_skipped "$1"
|
||||
fi
|
||||
fi
|
||||
if [[ "${MODES[@]}" =~ "mono" ]]; then
|
||||
echo " $colorcode ${level}! $1 $NORMAL" >> ${OUTPUT_FILE_NAME}.$EXTENSION_TEXT
|
||||
fi
|
||||
# if [[ "${MODES[@]}" =~ "text" ]]; then
|
||||
echo " $colorcode ${level}! $1 $NORMAL"
|
||||
# fi
|
||||
if [[ "${MODES[@]}" =~ "html" ]]; then
|
||||
generateHtmlOutput "$1" "${level}" "$CHECK_RESOURCE_ID"
|
||||
fi
|
||||
|
||||
#checking database provider
|
||||
if [[ ${DATABASE_PROVIDER} == 'postgresql' ]]
|
||||
if [[ "${CHECK_RESULT}" == "FAIL" ]]
|
||||
then
|
||||
postgresql_connector "${CSV_LINE}"
|
||||
set_exitcode
|
||||
fi
|
||||
|
||||
general_output "${CHECK_RESULT}" "${CHECK_RESULT_EXTENDED}" "${CHECK_RESOURCE_ID}" "${CHECK_REGION}"
|
||||
}
|
||||
|
||||
textTitle(){
|
||||
CHECKS_COUNTER=$((CHECKS_COUNTER+1))
|
||||
TITLE_ID="$1"
|
||||
|
||||
TITLE_ID="${1}"
|
||||
TITLE_TEXT="${2}"
|
||||
CHECK_ASFF_COMP_TYPE="${6}"
|
||||
|
||||
if [[ $NUMERAL ]]; then
|
||||
# Left-pad the check ID with zeros to simplify sorting, e.g. 1.1 -> 1.01
|
||||
TITLE_ID=$(awk -F'.' '{ printf "%d.%02d", $1, $2 }' <<< "$TITLE_ID")
|
||||
fi
|
||||
|
||||
TITLE_TEXT=$2
|
||||
local CHECK_SERVICENAME="$MAGENTA$3$NORMAL"
|
||||
local CHECK_SEVERITY="$BROWN[$4]$NORMAL"
|
||||
|
||||
case "$6" in
|
||||
case "${CHECK_ASFF_COMP_TYPE}" in
|
||||
LEVEL1) ITEM_CIS_LEVEL="CIS Level 1";;
|
||||
LEVEL2) ITEM_CIS_LEVEL="CIS Level 2";;
|
||||
EXTRA) ITEM_CIS_LEVEL="Extra";;
|
||||
SUPPORT) ITEM_CIS_LEVEL="Support";;
|
||||
*) ITEM_CIS_LEVEL="Unspecified or Invalid";;
|
||||
esac
|
||||
|
||||
local group_ids
|
||||
# if [[ -n "$4" ]]; then
|
||||
group_ids="$CYAN[$5]$NORMAL"
|
||||
# fi
|
||||
|
||||
# if [[ "${MODES[@]}" =~ "csv" ]]; then
|
||||
# >&2 echo "$TITLE_ID $TITLE_TEXT" >> ${OUTPUT_FILE_NAME}.${EXTENSION_CSV}
|
||||
# elif [[ "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
|
||||
# :
|
||||
# else
|
||||
# # if [[ "$ITEM_SCORED" == "Scored" ]]; then
|
||||
# echo -e "$TITLE_ID $CHECK_SERVICENAME $TITLE_TEXT $CHECK_SEVERITY $group_ids "
|
||||
echo -e "$TITLE_ID $TITLE_TEXT - $CHECK_SERVICENAME $CHECK_SEVERITY"
|
||||
# # else
|
||||
# # echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $6 $NORMAL $group_ids "
|
||||
# # fi
|
||||
# fi
|
||||
|
||||
echo -e "$TITLE_ID $TITLE_TEXT - $CHECK_SERVICENAME $CHECK_SEVERITY"
|
||||
}
|
||||
|
||||
generateJsonOutput(){
|
||||
@@ -330,7 +275,7 @@ generateJsonOutput(){
|
||||
--arg SCORED "$ITEM_SCORED" \
|
||||
--arg ITEM_CIS_LEVEL "$ITEM_CIS_LEVEL" \
|
||||
--arg TITLE_ID "$TITLE_ID" \
|
||||
--arg REPREGION "$REPREGION" \
|
||||
--arg REGION_FROM_CHECK "$REGION_FROM_CHECK" \
|
||||
--arg TYPE "$CHECK_ASFF_COMPLIANCE_TYPE" \
|
||||
--arg TIMESTAMP "$(get_iso8601_timestamp)" \
|
||||
--arg SERVICENAME "$CHECK_SERVICENAME" \
|
||||
@@ -354,7 +299,7 @@ generateJsonOutput(){
|
||||
"Scored": $SCORED,
|
||||
"Level": $ITEM_CIS_LEVEL,
|
||||
"Control ID": $TITLE_ID,
|
||||
"Region": $REPREGION,
|
||||
"Region": $REGION_FROM_CHECK,
|
||||
"Timestamp": $TIMESTAMP,
|
||||
"Compliance": $TYPE,
|
||||
"Service": $SERVICENAME,
|
||||
@@ -399,15 +344,15 @@ generateJsonAsffOutput(){
|
||||
--arg TYPE "$CHECK_ASFF_COMPLIANCE_TYPE" \
|
||||
--arg COMPLIANCE_RELATED_REQUIREMENTS "$CHECK_ASFF_COMPLIANCE_TYPE" \
|
||||
--arg RESOURCE_TYPE "$CHECK_ASFF_RESOURCE_TYPE" \
|
||||
--arg REPREGION "$REPREGION" \
|
||||
--arg REGION_FROM_CHECK "$REGION_FROM_CHECK" \
|
||||
--arg TIMESTAMP "$(get_iso8601_timestamp)" \
|
||||
--arg PROWLER_VERSION "$PROWLER_VERSION" \
|
||||
--arg AWS_PARTITION "$AWS_PARTITION" \
|
||||
--arg CHECK_RESOURCE_ID "$resource_id" \
|
||||
-n '{
|
||||
"SchemaVersion": "2018-10-08",
|
||||
"Id": "prowler-\($TITLE_ID)-\($ACCOUNT_NUM)-\($REPREGION)-\($UNIQUE_ID)",
|
||||
"ProductArn": "arn:\($AWS_PARTITION):securityhub:\($REPREGION)::product/prowler/prowler",
|
||||
"Id": "prowler-\($TITLE_ID)-\($ACCOUNT_NUM)-\($REGION_FROM_CHECK)-\($UNIQUE_ID)",
|
||||
"ProductArn": "arn:\($AWS_PARTITION):securityhub:\($REGION_FROM_CHECK)::product/prowler/prowler",
|
||||
"RecordState": "ACTIVE",
|
||||
"ProductFields": {
|
||||
"ProviderName": "Prowler",
|
||||
@@ -432,7 +377,7 @@ generateJsonAsffOutput(){
|
||||
"Type": $RESOURCE_TYPE,
|
||||
"Id": $CHECK_RESOURCE_ID,
|
||||
"Partition": $AWS_PARTITION,
|
||||
"Region": $REPREGION
|
||||
"Region": $REGION_FROM_CHECK
|
||||
}
|
||||
],
|
||||
"Compliance": {
|
||||
@@ -466,7 +411,7 @@ generateHtmlOutput(){
|
||||
echo ' <td>'$status'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo ' <td>'$CHECK_SEVERITY'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo ' <td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo ' <td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo ' <td>'$REGION_FROM_CHECK'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo ' <td>'$CHECK_ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo ' <td>'$CHECK_SERVICENAME'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo ' <td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
|
||||
@@ -41,6 +41,7 @@ EXITCODE=0
|
||||
SEND_TO_SECURITY_HUB=0
|
||||
FAILED_CHECK_FAILED_SCAN=1
|
||||
PROWLER_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" )
|
||||
OUTPUT_DATE=$(date -u +"%Y%m%d%H%M%S")
|
||||
TITLE_ID=""
|
||||
TITLE_TEXT="CALLER ERROR - UNSET TITLE"
|
||||
ALLOWLIST_FILE=""
|
||||
@@ -309,8 +310,7 @@ unset AWS_DEFAULT_OUTPUT
|
||||
. $PROWLER_DIR/include/db_connector
|
||||
|
||||
|
||||
|
||||
|
||||
#Parsing input options
|
||||
# Parses the check file into CHECK_ID's.
|
||||
if [[ -n "$CHECK_FILE" ]]; then
|
||||
if [[ -f $CHECK_FILE ]]; then
|
||||
@@ -369,11 +369,66 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check modes
|
||||
if [ -n "${MODE}" ]
|
||||
then
|
||||
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" && "$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
|
||||
done
|
||||
fi
|
||||
|
||||
#Check output dir custom
|
||||
if [ -n "${OUTPUT_DIR_CUSTOM}" ]
|
||||
then
|
||||
# If dir custom, mode has to be enabled (if you provide a custom directory it's because you want to store something)
|
||||
if [ "${MODE}" != 'text' ]
|
||||
then
|
||||
# Check if custom folder exists
|
||||
if [ ! -d "${OUTPUT_DIR_CUSTOM}" ]
|
||||
then
|
||||
echo "$OPTRED ERROR!$OPTNORMAL directory \"$OUTPUT_DIR_CUSTOM\" does not exist."
|
||||
exit 1
|
||||
else
|
||||
OUTPUT_DIR=$OUTPUT_DIR_CUSTOM
|
||||
fi
|
||||
else
|
||||
echo "$OPTRED ERROR!$OPTNORMAL - When using custom directory output Mode (-M) has to be set as well. Use -h for help."
|
||||
exit 1
|
||||
fi
|
||||
# If custom output dir is not provided output dir -> default
|
||||
else
|
||||
OUTPUT_DIR="${PROWLER_DIR}/output"
|
||||
if [ ! -d "${OUTPUT_DIR}" ]
|
||||
then
|
||||
mkdir -p "${OUTPUT_DIR}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# End of input parameters tests
|
||||
|
||||
# Pre-process allowlist file if supplied
|
||||
if [[ -n "$ALLOWLIST_FILE" ]]; then
|
||||
allowlist
|
||||
fi
|
||||
|
||||
# Create output file name
|
||||
if [ -n "${OUTPUT_FILE_NAME}" ]
|
||||
then
|
||||
OUTPUT_FILE_NAME="${OUTPUT_DIR}/$OUTPUT_FILE_NAME"
|
||||
else
|
||||
OUTPUT_FILE_NAME="${OUTPUT_DIR}/prowler-output-${ACCOUNT_NUM}-${OUTPUT_DATE}"
|
||||
fi
|
||||
|
||||
# Add headers to certain output files
|
||||
output_files_init
|
||||
|
||||
|
||||
|
||||
# Load all of the groups of checks inside groups folder named as "groupNumber*"
|
||||
for group in $(ls $PROWLER_DIR/groups/group[0-9]*|grep -v groupN_sample); do
|
||||
. "$group"
|
||||
|
||||
@@ -169,14 +169,14 @@ unset HTML_REPORT_INIT
|
||||
}
|
||||
|
||||
addHtmlHeader > ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
while IFS=, read -r PROFILE ACCOUNT_NUM REPREGION TITLE_ID RESULT SCORED LEVEL TITLE_TEXT NOTES ASFF_COMPLIANCE_TYPE CHECK_SEVERITY CHECK_SERVICENAME;do
|
||||
while IFS=, read -r PROFILE ACCOUNT_NUM REGION_FROM_CHECK TITLE_ID RESULT SCORED LEVEL TITLE_TEXT NOTES ASFF_COMPLIANCE_TYPE CHECK_SEVERITY CHECK_SERVICENAME;do
|
||||
if [[ $RESULT == "INFO" ]]; then
|
||||
echo '<tr class="table-info">' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td><i class="fas fa-info-circle"></i></td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>INFO</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$CHECK_SEVERITY'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$REGION_FROM_CHECK'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$CHECK_SERVICENAME'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
@@ -190,7 +190,7 @@ while IFS=, read -r PROFILE ACCOUNT_NUM REPREGION TITLE_ID RESULT SCORED LEVEL T
|
||||
echo '<td>PASS</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$CHECK_SEVERITY'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$REGION_FROM_CHECK'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$CHECK_SERVICENAME'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
@@ -204,7 +204,7 @@ while IFS=, read -r PROFILE ACCOUNT_NUM REPREGION TITLE_ID RESULT SCORED LEVEL T
|
||||
echo '<td>FAIL</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$CHECK_SEVERITY'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$REGION_FROM_CHECK'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$CHECK_SERVICENAME'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
@@ -218,7 +218,7 @@ while IFS=, read -r PROFILE ACCOUNT_NUM REPREGION TITLE_ID RESULT SCORED LEVEL T
|
||||
echo '<td>WARN</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$CHECK_SEVERITY'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$REGION_FROM_CHECK'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$CHECK_SERVICENAME'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
echo '<td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
|
||||
|
||||
Reference in New Issue
Block a user