mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +00:00
Allow multiple report types at once #345
This commit is contained in:
38
README.md
38
README.md
@@ -159,7 +159,25 @@ 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
|
||||
|
||||
1. If you want to save your report for later analysis:
|
||||
### 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):
|
||||
|
||||
```sh
|
||||
./prowler -M csv
|
||||
```
|
||||
or with multiple formats at the same time:
|
||||
```sh
|
||||
./prowler -M csv,json,json-asff
|
||||
```
|
||||
or just a group of checks in multiple formats:
|
||||
```sh
|
||||
./prowler -g gdpr -M csv,json,json-asff
|
||||
```
|
||||
|
||||
Now `-M` creates a file inside the prowler root directory named `prowler-output-YYYYMMDDHHMMSS.format`. You don't have to specify anything else, no pipes, no redirects.
|
||||
|
||||
or just saving the output to a file like below:
|
||||
|
||||
```sh
|
||||
./prowler -M mono > prowler-report.txt
|
||||
@@ -172,18 +190,9 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX
|
||||
./prowler | ansi2html -la > report.html
|
||||
```
|
||||
|
||||
or if you want a pipe-delimited report file, do:
|
||||
>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`.
|
||||
|
||||
```sh
|
||||
./prowler -M csv > output.psv
|
||||
```
|
||||
or json formatted output using jq, do:
|
||||
|
||||
```sh
|
||||
./prowler -M json > prowler-output.json
|
||||
```
|
||||
|
||||
or save your report in a S3 bucket:
|
||||
or save your report in a S3 bucket (this only works for text or mono, for csv, json or json-asff it has to be copied afterwards):
|
||||
|
||||
```sh
|
||||
./prowler -M mono | aws s3 cp - s3://bucket-name/prowler-report.txt
|
||||
@@ -221,7 +230,8 @@ 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, csv (separator is ,; data is on stdout; progress on stderr)
|
||||
-M <mode> output mode: text (default), mono, json, json-asff, 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
|
||||
(i.e.: 1.01 instead of 1.1)
|
||||
@@ -280,7 +290,7 @@ In order to remove noise and get only FAIL findings there is a `-q` flag that ma
|
||||
|
||||
Since version v2.3, Prowler supports natively sending findings to [AWS Security Hub](https://aws.amazon.com/security-hub). This integration allows Prowler to import its findings to AWS Security Hub. With Security Hub, you now have a single place that aggregates, organizes, and prioritizes your security alerts, or findings, from multiple AWS services, such as Amazon GuardDuty, Amazon Inspector, Amazon Macie, AWS Identity and Access Management (IAM) Access Analyzer, and AWS Firewall Manager, as well as from AWS Partner solutions and now from Prowler. It is as simple as running the commanbd below:
|
||||
|
||||
```sh
|
||||
```
|
||||
./prowler -M json-asff -S
|
||||
```
|
||||
There are two requirements:
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations under the License.
|
||||
|
||||
if [[ "$MODE" != "mono" && "$MODE" != "text" && "$MODE" != "csv" && "$MODE" != "json" && "$MODE" != "json-asff" ]]; then
|
||||
echo ""
|
||||
echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, csv, json or json-asff."
|
||||
usage
|
||||
|
||||
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"
|
||||
EXITCODE=1
|
||||
exit $EXITCODE
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$MODE" == "mono" || "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||
MONOCHROME=1
|
||||
|
||||
@@ -12,25 +12,36 @@
|
||||
# specific language governing permissions and limitations under the License.
|
||||
|
||||
# Output formatting functions
|
||||
|
||||
EXTENSION_CSV="csv"
|
||||
EXTENSION_JSON="json"
|
||||
EXTENSION_ASFF="asff-json"
|
||||
EXTENSION_HTML="html" # not implemented yet, use ansi2html as in documentation
|
||||
OUTPUT_DATE=$(date -u +"%Y%m%d%H%M%S")
|
||||
OUTPUT_FILE_NAME=prowler-output-$OUTPUT_DATE
|
||||
|
||||
|
||||
textPass(){
|
||||
if [[ "$QUIET" == 1 ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
PASS_COUNTER=$((PASS_COUNTER+1))
|
||||
if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
|
||||
if [[ $2 ]]; then
|
||||
REPREGION=$2
|
||||
else
|
||||
REPREGION=$REGION
|
||||
fi
|
||||
if [[ "$MODE" == "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"
|
||||
elif [[ "$MODE" == "json" ]]; then
|
||||
generateJsonOutput "$1" "Pass"
|
||||
elif [[ "$MODE" == "json-asff" ]]; then
|
||||
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}"
|
||||
echo "${JSON_ASFF_OUTPUT}" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_ASFF
|
||||
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
||||
sendToSecurityHub "${JSON_ASFF_OUTPUT}"
|
||||
fi
|
||||
@@ -45,16 +56,17 @@ textInfo(){
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
|
||||
if [[ $2 ]]; then
|
||||
REPREGION=$2
|
||||
else
|
||||
REPREGION=$REGION
|
||||
fi
|
||||
if [[ "$MODE" == "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"
|
||||
elif [[ "$MODE" == "json" ]]; then
|
||||
generateJsonOutput "$1" "Info"
|
||||
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"
|
||||
@@ -64,19 +76,21 @@ textInfo(){
|
||||
textFail(){
|
||||
FAIL_COUNTER=$((FAIL_COUNTER+1))
|
||||
EXITCODE=3
|
||||
if [[ "$MODE" == "csv" || "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||
if [[ "${MODES[@]}" =~ "csv" || "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
|
||||
if [[ $2 ]]; then
|
||||
REPREGION=$2
|
||||
else
|
||||
REPREGION=$REGION
|
||||
fi
|
||||
if [[ "$MODE" == "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"
|
||||
elif [[ "$MODE" == "json" ]]; then
|
||||
generateJsonOutput "$1" "Fail"
|
||||
elif [[ "$MODE" == "json-asff" ]]; then
|
||||
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}"
|
||||
echo "${JSON_ASFF_OUTPUT}" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_ASFF
|
||||
if [[ "${SEND_TO_SECURITY_HUB}" -eq 1 ]]; then
|
||||
sendToSecurityHub "${JSON_ASFF_OUTPUT}"
|
||||
fi
|
||||
@@ -117,9 +131,9 @@ textTitle(){
|
||||
*) ITEM_LEVEL="Unspecified or Invalid";;
|
||||
esac
|
||||
|
||||
if [[ "$MODE" == "csv" ]]; then
|
||||
>&2 echo "$TITLE_ID $TITLE_TEXT"
|
||||
elif [[ "$MODE" == "json" || "$MODE" == "json-asff" ]]; then
|
||||
if [[ "${MODES[@]}" =~ "csv" ]]; then
|
||||
>&2 echo "$TITLE_ID $TITLE_TEXT" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
|
||||
elif [[ "${MODES[@]}" =~ "json" || "${MODES[@]}" =~ "json-asff" ]]; then
|
||||
:
|
||||
else
|
||||
if [[ "$ITEM_SCORED" == "Scored" ]]; then
|
||||
|
||||
9
prowler
9
prowler
@@ -65,7 +65,8 @@ 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 (separator is ","; data is on stdout; progress on stderr)
|
||||
-M <mode> output mode: text (default), mono, json, json-asff, 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
|
||||
(i.e.: 1.01 instead of 1.1)
|
||||
@@ -393,7 +394,7 @@ get_all_checks_without_exclusion() {
|
||||
}
|
||||
|
||||
### All functions defined above ... run the workflow
|
||||
if [[ $MODE != "csv" ]]; then
|
||||
if [[ ${MODES[@]} =~ "mono" || ${MODES[@]} =~ "text" ]]; then
|
||||
prowlerBanner
|
||||
fi
|
||||
|
||||
@@ -424,9 +425,7 @@ getWhoami
|
||||
# Execute group of checks if called with -g
|
||||
if [[ $GROUP_ID_READ ]];then
|
||||
if [[ " ${GROUP_ID[@]} " =~ " ${GROUP_ID_READ} " ]]; then
|
||||
if [[ $MODE == "csv" ]]; then
|
||||
BANNER=0
|
||||
fi
|
||||
|
||||
execute_group_by_id ${GROUP_ID_READ} ${EXCLUDE_CHECK_ID}
|
||||
cleanTemp
|
||||
scoring
|
||||
|
||||
Reference in New Issue
Block a user