feat(metadata): Include account metadata in Prowler assessments (#1049)

* Add support for organizations accounts metadata part 1

* Add support for organizations accounts metadata part 2

* Add gathering account metadata from org

* chore(prowler): get accounts metadata

Use assume_role backing up normal assumed credentials to assume management account and then restore it to old ones

* fix(orgs metadata): deleted assume_role_orgs

* refactor(organization_metadata)

Reformulate to extract AWS Organizations metadata

* doc(org_metadata): include required -R in usage

* docs(org-metadata): Update README

Co-authored-by: n4ch04 <nachor1992@gmail.com>
Co-authored-by: Pepe Fagoaga <pepe@verica.io>
This commit is contained in:
Toni de la Fuente
2022-03-16 16:27:19 +01:00
committed by GitHub
parent c526c61d5e
commit 365b396f9a
6 changed files with 115 additions and 10 deletions

View File

@@ -92,7 +92,6 @@ cleanSTSAssumeFile() {
}
backupInitialAWSCredentials() {
if [[ $(printenv AWS_ACCESS_KEY_ID) && $(printenv AWS_SECRET_ACCESS_KEY) && $(printenv AWS_SESSION_TOKEN) ]]; then
INITIAL_AWS_ACCESS_KEY_ID=$(printenv AWS_ACCESS_KEY_ID)
INITIAL_AWS_SECRET_ACCESS_KEY=$(printenv AWS_SECRET_ACCESS_KEY)

View File

@@ -13,8 +13,5 @@
printCsvHeader() {
# >&2 echo ""
# >&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM"
echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}CHECK_RESULT${SEP}ITEM_SCORED${SEP}ITEM_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" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
# echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES${SEP}COMPLIANCE${SEP}SEVERITY${SEP}SERVICENAME" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}CHECK_RESULT${SEP}ITEM_SCORED${SEP}ITEM_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" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
}

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
# Gets account details with a given ACCOUNT_ID.
# Prowler requires organizations:ListAccounts* and organizations:ListTagsForResource
# in the management account in order to get that data. SecurityAudit managed policy includes them.
# Account Tags are in json format with comma, however they are converted to Base64
# in order to avoid breaking the CSV or JSON. To use them a post-processor is needed.
get_orgs_account_details(){
echo " Prowler is getting details from the AWS Organizations Management Account: ${MANAGEMENT_ACCOUNT_ID}..."
# Assume role to recover AWS Organizations metadata
assume_role
# The following code requires organizations:ListTagsForResource
ACCOUNTS_DETAILS=$($AWSCLI $PROFILE_OPT --region "${REGION}" organizations list-accounts --output json 2>&1)
if ! grep -q -E 'AccessDenied|UnauthorizedOperation|AuthorizationError' <<< "${ACCOUNTS_DETAILS}"
then
# Prowler gets only ACTIVE accounts details
ACCOUNT_DETAILS_EMAIL=$(jq -r --arg ACCOUNT_ID "${ACCOUNT_NUM}" '.Accounts[] | select(.Status == "ACTIVE") | select(.Id == $ACCOUNT_ID) | "\(.Email)"' <<< "${ACCOUNTS_DETAILS}")
ACCOUNT_DETAILS_NAME=$(jq -r --arg ACCOUNT_ID "${ACCOUNT_NUM}" '.Accounts[] | select(.Status == "ACTIVE") | select(.Id == $ACCOUNT_ID) | "\(.Name)"' <<< "${ACCOUNTS_DETAILS}")
ACCOUNT_DETAILS_ARN=$(jq -r --arg ACCOUNT_ID "${ACCOUNT_NUM}" '.Accounts[] | select(.Status == "ACTIVE") | select(.Id == $ACCOUNT_ID) | "\(.Arn)"' <<< "${ACCOUNTS_DETAILS}")
ACCOUNT_DETAILS_ORG=$(jq -r --arg ACCOUNT_ID "${ACCOUNT_NUM}" '.Accounts[] | select(.Status == "ACTIVE") | select(.Id == $ACCOUNT_ID) | "\(.Arn)"' <<< "${ACCOUNTS_DETAILS}" | awk -F/ '{ print $2 }')
ACCOUNT_DETAILS_TAGS=$($AWSCLI $PROFILE_OPT --region "${REGION}" organizations list-tags-for-resource --resource-id "${MANAGEMENT_ACCOUNT_ID}" --output json | jq -c '. | @base64' 2>&1)
else
# textFail "${regx}: Access Denied trying to list AWS Organization accounts. Prowler requires organizations:List*" "$regx"
textInfo "Access Denied trying to list AWS Organization accounts. Prowler requires organizations:List*"
exit 1
fi
}

View File

@@ -64,6 +64,11 @@ PROWLER_PARAMETERS=$@
# $CHECK_REMEDIATION text about remediation
# $CHECK_DOC link to related documentation
# $CHECK_CAF_EPIC it can be Logging and Monitoring, IAM, Data Protection, Infrastructure Security. Incident Response is not included since CAF has not specific checks on it logs enablement are part of Logging and Monitoring.
# $ACCOUNT_DETAILS_EMAIL
# $ACCOUNT_DETAILS_NAME
# $ACCOUNT_DETAILS_ARN
# $ACCOUNT_DETAILS_ORG
# $ACCOUNT_DETAILS_TAGS
# Ensure that output directory always exists when -M is used
if [[ $MODE ]];then
@@ -102,7 +107,7 @@ textPass(){
REPREGION=$REGION
fi
if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$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" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
echo "$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" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "Pass" "$CHECK_RESOURCE_ID" >> ${OUTPUT_FILE_NAME}.$EXTENSION_JSON
@@ -144,7 +149,7 @@ textInfo(){
REPREGION=$REGION
fi
if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$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" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
echo "$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" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "Info" "$CHECK_RESOURCE_ID" >> ${OUTPUT_FILE_NAME}.${EXTENSION_JSON}
@@ -209,7 +214,7 @@ textFail(){
fi
if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$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" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
echo "$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" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "${level}" "$CHECK_RESOURCE_ID">> ${OUTPUT_FILE_NAME}.${EXTENSION_JSON}
@@ -301,6 +306,11 @@ generateJsonOutput(){
--arg CHECK_REMEDIATION "$CHECK_REMEDIATION" \
--arg CHECK_DOC "$CHECK_DOC" \
--arg CHECK_RESOURCE_ID "$resource_id" \
--arg ACCOUNT_DETAILS_EMAIL "$ACCOUNT_DETAILS_EMAIL" \
--arg ACCOUNT_DETAILS_NAME "$ACCOUNT_DETAILS_NAME" \
--arg ACCOUNT_DETAILS_ARN "$ACCOUNT_DETAILS_ARN" \
--arg ACCOUNT_DETAILS_ORG "$ACCOUNT_DETAILS_ORG" \
--arg ACCOUNT_DETAILS_TAGS "$ACCOUNT_DETAILS_TAGS" \
-n '{
"Profile": $PROFILE,
"Account Number": $ACCOUNT_NUM,
@@ -319,7 +329,12 @@ generateJsonOutput(){
"Risk": $CHECK_RISK,
"Remediation": $CHECK_REMEDIATION,
"Doc link": $CHECK_DOC,
"Resource ID": $CHECK_RESOURCE_ID
"Resource ID": $CHECK_RESOURCE_ID,
"Account Email": $ACCOUNT_DETAILS_EMAIL,
"Account Name": $ACCOUNT_DETAILS_NAME,
"Account ARN": $ACCOUNT_DETAILS_ARN,
"Account Organization": $ACCOUNT_DETAILS_ORG,
"Account tags": $ACCOUNT_DETAILS_TAGS
}'
}