#!/usr/bin/env bash

# Copyright 2018 Toni de la Fuente

# Prowler is a tool that provides automate auditing and hardening guidance of an
# AWS account. It is based on AWS-CLI commands. It follows some guidelines
# present in the CIS Amazon Web Services Foundations Benchmark at:
# https://d0.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf

# Contact the author at https://blyx.com/contact
# and open issues or ask questions at https://github.com/prowler-cloud/prowler

# Code is licensed as Apache License 2.0 as specified in
# each file. You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0

# Load all of the groups of checks inside groups folder named as "groupNumber*"
load_groups() {
for group in "${PROWLER_DIR}"/groups/group[0-9]*; do
     # shellcheck source=/dev/null
	. "${group}"
done
}

# Load a single check
load_check(){
    CHECK=${1}
    # shellcheck source=/dev/null
    . "$PROWLER_DIR/checks/${CHECK}" 2>/dev/null
}

get_checks() {
    # Parses the check file into CHECK_ID's.
    if [[ -n "$CHECK_FILE" ]]
    then
        if [[ -f $CHECK_FILE ]]
        then
            # Parses the file, converting it to a comma seperated list. Ignores all # comments and removes extra blank spaces
            # REVIEW THIS OPTION -C
            CHECKS_FROM_FILE="$(awk '!/^[[:space:]]*#/{print }' <(cat ${CHECK_FILE} | sed 's/[[:space:]]*#.*$//g;/^$/d' | sed 'H;1h;$!d;x;y/\n/,/' | tr -d ' '))"
            IFS=',' read -ra TOTAL_CHECKS <<< "${CHECKS_FROM_FILE}"
        else
            # If the file doesn't exist, exits Prowler
            echo "$CHECK_FILE does not exist"
            EXITCODE=1
            exit $EXITCODE
        fi

    # If '-g <group_id>' has been specified, only show the titles of checks within the specified group
    # reading groups from GROUP_ID_READ
    elif [[ "${GROUP_ID_READ}" ]]
    then
        for GROUP in "${GROUP_ID[@]}"
        do
            if [[ "${GROUP}" == "${GROUP_ID_READ}" ]]
            then
            IS_GROUP=1
            fi
        done
        if [[ IS_GROUP -eq 0 ]]
        then
            textFail "Group ${GROUP_ID_READ} does not exist. Valid check groups are: ${GROUP_ID[*]}"
            exit $EXITCODE
        fi
        # Iterate over every group removing echar comma
        for GROUP_IDENTIFIER in ${GROUP_ID_READ//,/ }
        do
            # Iterate over every GroupID to find the belongin checks
            for I in "${!GROUP_ID[@]}"
            do
                if [[ "${EXTRAS}" -eq 1 && "${GROUP_ID[I]}" == "extras" ]]
                then
                    continue
                else
                    if [[ "${GROUP_ID[I]}" == "${GROUP_IDENTIFIER}" ]]
                    then
                        # shellcheck disable=SC2068
                        for CHECK_IDENTIFIER in ${GROUP_CHECKS[I]//,/ }
                        do
                            # Include every check if not present
                            if [[ ! "${CHECK_LIST_BY_GROUP[*]}" =~ ${CHECK_IDENTIFIER} ]] && ! grep -E -w -q "${EXCLUDE_CHECK_ID//,/|}" <<< "${CHECK_IDENTIFIER}"
                            then
                                CHECK_LIST_BY_GROUP+=("${CHECK_IDENTIFIER}")
                            fi
                        done
                    fi
                fi
            done
        done
        TOTAL_CHECKS=("${CHECK_LIST_BY_GROUP[@]}")

    # If -c option is set with checks
    elif [ -n "${CHECK_ID}" ]
    then
        IFS=',' read -ra TOTAL_CHECKS <<< "${CHECK_ID}"

    # If no option input to include/exclude checks
    else
        # if -e is passed we dont want extra checks
        if [[ "${EXTRAS}" -eq 1 ]]
            then
            if [[ -n "$EXCLUDE_CHECK_ID" ]]
            then
                EXCLUDE_CHECK_ID="${EXCLUDE_CHECK_ID},${GROUP_CHECKS[7]}"
            else
                EXCLUDE_CHECK_ID="${GROUP_CHECKS[7]}"
            fi
        fi
        # Always ignore the following checks if not supplied with -C
        IGNORED_CHECKS="sample,extra9999"
        EXCLUDE_CHECK_ID="${EXCLUDE_CHECK_ID/%/,}${IGNORED_CHECKS}"

        for CHECK in "${PROWLER_DIR}"/checks/check*; do
            # Relative path required to load every check
            CHECK_DIR_NAME=$(basename "${CHECK}")
            # Name of the check
            CHECK_NAME=${CHECK_DIR_NAME//check_/}
            # If a group identifier is passed
            if ! grep -E -w -q "${EXCLUDE_CHECK_ID//,/|}" <<< "${CHECK_NAME}"
            then
                TOTAL_CHECKS+=("${CHECK_NAME}")
            fi

        done
    fi

    # Iterate over the final list of checks after being parsed all the input options to load the selected checks
    for LOAD_PATH_CHECK in "${TOTAL_CHECKS[@]}"
    do
        # If the check is extra, the path needs to add check_ after the check name
        if [[ "${LOAD_PATH_CHECK}" =~ 'extra' ]]
        then
            LOAD_PATH_CHECK=${LOAD_PATH_CHECK/#/check_}
        fi
        load_check "${LOAD_PATH_CHECK}"
    done
}
