diff --git a/README.md b/README.md index 18072315..87ec9615 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX ./prowler ``` - Use `-l` to list all available checks and group of checks (sections) + Use `-l` to list all available checks and the groups (sections) that reference them If you want to avoid installing dependencies run it using Docker: @@ -254,7 +254,7 @@ This script has been written in bash using AWS-CLI and it works in Linux and OSX -k keep the credential report -n show check numbers to sort easier (i.e.: 1.01 instead of 1.1) - -l list all available checks only (does not perform any check) + -l list all available checks only (does not perform any check). Add -g to only list checks within the specified group -L list all groups (does not perform any check) -e exclude group extras -E execute all tests except a list of specified checks separated by comma (i.e. check21,check31) @@ -526,7 +526,6 @@ AWS is made to be flexible for service links within and between different AWS ac This group of checks helps to analyse a particular AWS account (subject) on existing links to other AWS accounts across various AWS services, in order to identify untrusted links. ### Run - To give it a quick shot just call: ```sh diff --git a/include/outputs b/include/outputs index 0b56ef88..662bee06 100644 --- a/include/outputs +++ b/include/outputs @@ -136,15 +136,20 @@ textTitle(){ *) ITEM_LEVEL="Unspecified or Invalid";; esac + local group_ids + if [[ -n "$5" ]]; then + group_ids="$CYAN [$5] $NORMAL" + fi + 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 - echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT" + echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT $group_ids" else - echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" + echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL $group_ids" fi fi } diff --git a/prowler b/prowler index f5e097f6..10a02791 100755 --- a/prowler +++ b/prowler @@ -48,6 +48,7 @@ SEND_TO_SECURITY_HUB=0 SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) TITLE_ID="" TITLE_TEXT="CALLER ERROR - UNSET TITLE" +TOTAL_CHECKS=() # Command usage menu usage(){ @@ -70,7 +71,7 @@ USAGE: -k keep the credential report -n show check numbers to sort easier (i.e.: 1.01 instead of 1.1) - -l list all available checks only (does not perform any check) + -l list all available checks only (does not perform any check). Add -g to only list checks within the specified group -L list all groups (does not perform any check) -e exclude group extras -E execute all tests except a list of specified checks separated by comma (i.e. check21,check31) @@ -233,14 +234,38 @@ if [[ $EXTERNAL_CHECKS_PATH ]]; then done fi -# Function to show the title of the check +# Get a list of total checks available by ID +for i in "${!GROUP_TITLE[@]}"; do + IFS=',' read -ra CHECKS <<< "${GROUP_CHECKS[$i]}" + for j in "${CHECKS[@]}"; do + TOTAL_CHECKS+=("$CHECK_ID_$j") + done +done +# Remove duplicates whilst preserving the order of checks, and store the result as an array +TOTAL_CHECKS=($(echo "${TOTAL_CHECKS[*]}" | tr ' ' '\n' | awk '!seen[$0]++')) + +# Function to show the title of the check, and optionally which group(s) it belongs to # using this way instead of arrays to keep bash3 (osx) and bash4(linux) compatibility show_check_title() { local check_id=CHECK_ID_$1 local check_title=CHECK_TITLE_$1 local check_scored=CHECK_SCORED_$1 local check_type=CHECK_TYPE_$1 - textTitle "${!check_id}" "${!check_title}" "${!check_scored}" "${!check_type}" + local group_ids + local group_index + # If requested ($2 is any non-null value) iterate all GROUP_CHECKS and produce a comma-separated list of all + # the GROUP_IDs that include this particular check + if [[ -n "$2" ]]; then + for group_index in "${!GROUP_ID[@]}"; do + if [[ "${GROUP_CHECKS[$group_index]}" =~ "$1" ]]; then + if [[ -n "$group_ids" ]]; then + group_ids+=", " + fi + group_ids+="${GROUP_ID[$group_index]}" + fi + done + fi + textTitle "${!check_id}" "${!check_title}" "${!check_scored}" "${!check_type}" "$group_ids" } # Function to show the title of a group, by numeric id @@ -358,24 +383,41 @@ execute_all() { done } -# Function to show the titles of everything +# Function to show the titles of either all checks or only those in the specified group show_all_titles() { - MAIN_GROUPS=(1 2 3 4 7) - for i in "${MAIN_GROUPS[@]}"; do - show_group_title $i - # Display the title of the checks in groups 1,2,3,4 and 7 - # Any other group has checks in these groups - IFS=',' read -ra CHECKS <<< ${GROUP_CHECKS[$i]} - for j in ${CHECKS[@]}; do - show_check_title $j - done - done + local checks + local check_id + local group_index + # If '-g ' has been specified, only show the titles of checks within the specified group + if [[ $GROUP_ID_READ ]];then + if [[ " ${GROUP_ID[@]} " =~ " ${GROUP_ID_READ} " ]]; then + for group_index in "${!GROUP_ID[@]}"; do + if [ "${GROUP_ID[$group_index]}" == "${GROUP_ID_READ}" ]; then + show_group_title "$group_index" + IFS=',' read -ra checks <<< "${GROUP_CHECKS[$group_index]}" + for check_id in ${checks[@]}; do + show_check_title "$check_id" + done + fi + done + else + textFail "Use a valid check group ID i.e.: group1, extras, forensics-ready, etc." + show_all_group_titles + exit $EXITCODE + fi + else + for check_id in "${TOTAL_CHECKS[@]}"; do + # Pass 1 so that the group IDs that this check belongs to are printed + show_check_title "$check_id" 1 + done + fi } show_all_group_titles() { - for i in "${!GROUP_TITLE[@]}"; do - show_group_title $i - done + local group_index + for group_index in "${!GROUP_TITLE[@]}"; do + show_group_title "$group_index" + done } # Function to execute all checks but exclude some of them @@ -388,16 +430,6 @@ get_all_checks_without_exclusion() { for E_CHECK in "${E_CHECKS[@]}"; do CHECKS_TO_EXCLUDE+=($E_CHECK) done - # Get a list of total checks available by ID - for i in "${!GROUP_TITLE[@]}"; do - # show_group_title $i - IFS=',' read -ra CHECKS <<< ${GROUP_CHECKS[$i]} - for j in ${CHECKS[@]}; do - TOTAL_CHECKS+=($CHECK_ID_$j) - done - done - # Remove duplicates whilst preserving the order of checks, and store the result as an array - TOTAL_CHECKS=($(echo "${TOTAL_CHECKS[*]}" | tr ' ' '\n' | awk '!seen[$0]++')) # Create a list that contains all checks but excluded ones for i in "${TOTAL_CHECKS[@]}"; do local COINCIDENCE=false