mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
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:
committed by
GitHub
parent
c526c61d5e
commit
365b396f9a
24
README.md
24
README.md
@@ -365,6 +365,30 @@ for accountId in $ACCOUNTS_IN_ORGS; do ./prowler -A $accountId -R RemoteRoleToAs
|
||||
```
|
||||
Usig the same for loop it can be scanned a list of accounts with a variable like `ACCOUNTS_LIST='11111111111 2222222222 333333333'`
|
||||
|
||||
### Get AWS Account details from your AWS Organization:
|
||||
|
||||
From Prowler v2.8, you can get additional information of the scanned account in CSV and JSON outputs. When scanning a single account you get the Account ID as part of the output. Now, if you have AWS Organizations and are scanning multiple accounts using the assume role functionality, Prowler can get your account details like Account Name, Email, ARN, Organization ID and Tags and you will have them next to every finding in the CSV and JSON outputs.
|
||||
In order to do that you can use the new option `-O <management account id>`, requires `-R <role to assume>` and also needs permissions `organizations:ListAccounts*` and `organizations:ListTagsForResource`. See the following sample command:
|
||||
```
|
||||
./prowler -R ProwlerScanRole -A 111111111111 -O 222222222222 -M json,csv
|
||||
```
|
||||
In that command Prowler will scan the account `111111111111` assuming the role `ProwlerScanRole` and getting the account details from the AWS Organizatiosn management account `222222222222` assuming the same role `ProwlerScanRole` for that and creating two reports with those details in JSON and CSV.
|
||||
|
||||
In the JSON output below (redacted) you can see tags coded in base64 to prevent breaking CSV or JSON due to its format:
|
||||
|
||||
```json
|
||||
"Account Email": "my-prod-account@domain.com",
|
||||
"Account Name": "my-prod-account",
|
||||
"Account ARN": "arn:aws:organizations::222222222222:account/o-abcde1234/111111111111",
|
||||
"Account Organization": "o-abcde1234",
|
||||
"Account tags": "\"eyJUYWdzIjpasf0=\""
|
||||
```
|
||||
The additional fields in CSV header output are as follow:
|
||||
|
||||
```csv
|
||||
ACCOUNT_DETAILS_EMAIL,ACCOUNT_DETAILS_NAME,ACCOUNT_DETAILS_ARN,ACCOUNT_DETAILS_ORG,ACCOUNT_DETAILS_TAGS
|
||||
```
|
||||
|
||||
### GovCloud
|
||||
|
||||
Prowler runs in GovCloud regions as well. To make sure it points to the right API endpoint use `-r` to either `us-gov-west-1` or `us-gov-east-1`. If not filter region is used it will look for resources in both GovCloud regions by default:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
41
include/organizations_metadata
Normal file
41
include/organizations_metadata
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}'
|
||||
}
|
||||
|
||||
|
||||
31
prowler
31
prowler
@@ -110,13 +110,15 @@ USAGE:
|
||||
-z Failed checks do not trigger exit code 3.
|
||||
-Z Specify one or multiple check ids separated by commas that will trigger exit code 3 if they fail. Unspecified checks will not trigger exit code 3. This will override "-z".
|
||||
(i.e.: "-Z check11,check12" will cause check11 and/or check12 to trigger exit code 3)
|
||||
-O <mgmnt acct ID> Specify AWS Organizations management account ID. Used to get account details, requires -R.
|
||||
(requires organizations:ListAccounts* and organizations:ListTagsForResource)
|
||||
-V Show version number & exit.
|
||||
-h This help.
|
||||
"
|
||||
exit
|
||||
}
|
||||
|
||||
while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:D:F:zZ:" OPTION; do
|
||||
while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:D:F:zZ:O:" OPTION; do
|
||||
case $OPTION in
|
||||
h )
|
||||
usage
|
||||
@@ -223,6 +225,10 @@ while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:D:F:zZ:" OPTION;
|
||||
Z )
|
||||
FAILED_CHECK_FAILED_SCAN_LIST=$OPTARG
|
||||
;;
|
||||
O )
|
||||
MANAGEMENT_ACCOUNT_ID=$OPTARG
|
||||
;;
|
||||
|
||||
: )
|
||||
echo ""
|
||||
echo "$OPTRED ERROR!$OPTNORMAL -$OPTARG requires an argument"
|
||||
@@ -287,6 +293,7 @@ unset AWS_DEFAULT_OUTPUT
|
||||
. $PROWLER_DIR/include/connection_tests
|
||||
. $PROWLER_DIR/include/securityhub_integration
|
||||
. $PROWLER_DIR/include/junit_integration
|
||||
. $PROWLER_DIR/include/organizations_metadata
|
||||
|
||||
# Parses the check file into CHECK_ID's.
|
||||
if [[ -n "$CHECK_FILE" ]]; then
|
||||
@@ -644,6 +651,28 @@ if is_junit_output_enabled; then
|
||||
prepare_junit_output
|
||||
fi
|
||||
|
||||
# First, check AWS Organizations Metadata
|
||||
if [[ -n "${MANAGEMENT_ACCOUNT_ID}" && -n "${ROLE_TO_ASSUME}" ]]
|
||||
then
|
||||
# Backing up initial credentials
|
||||
backupInitialAWSCredentials
|
||||
|
||||
# Backing up initial account to assume
|
||||
INITIAL_ACCOUNT_TO_ASSUME="${ACCOUNT_TO_ASSUME}"
|
||||
|
||||
# Set the new account to assume to recover AWS Organizations Metadata
|
||||
ACCOUNT_TO_ASSUME="${MANAGEMENT_ACCOUNT_ID}"
|
||||
|
||||
# Recover AWS Organizations Metadata
|
||||
get_orgs_account_details
|
||||
|
||||
# Restoring account to assume to -A field after getting account metadata
|
||||
ACCOUNT_TO_ASSUME="${INITIAL_ACCOUNT_TO_ASSUME}"
|
||||
|
||||
# Restoring initial credentials
|
||||
restoreInitialAWSCredentials
|
||||
fi
|
||||
|
||||
# Gather account data / test aws cli connectivity
|
||||
getWhoami
|
||||
if [[ -n "${ACCOUNT_TO_ASSUME}" || -n "${ROLE_TO_ASSUME}" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user