bring in megaprowler code

This commit is contained in:
Mr. Secure
2019-10-11 19:58:49 -05:00
parent fc77b4a55e
commit 64e38dd843
4 changed files with 701 additions and 0 deletions

68
util/Audit_Exec_Role.yaml Normal file
View File

@@ -0,0 +1,68 @@
---
AWSTemplateFormatVersion: '2010-09-09'
Description: Prowler Auditing Role - in Control Tower pick AWSControlTowerStackSetRole for IAM role and AWSControlTowerExecution for execution
Parameters:
AuditorAccountId:
Default: 987600001234
Description: AWS Account ID where the audit tooling executes
Type: Number
AuditRolePathName:
Default: '/audit/prowler/XA_AuditRole_Prowler'
Description: Path for role name in audit tooling account
Type: String
Resources:
XAAuditRole:
Type: "AWS::IAM::Role"
Properties: # /audit/prowler/XA_AuditRole_Prowler
RoleName: XA_AuditRole_Prowler
Path: "/audit/prowler/"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/SecurityAudit
- arn:aws:iam::aws:policy/AWSOrganizationsReadOnlyAccess
- arn:aws:iam::aws:policy/IAMReadOnlyAccess
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
AWS: # TODO: review permissions to see if this can be narrowed down - code build only perhaps
- !Sub "arn:aws:iam::${AuditorAccountId}:root"
- !Sub "arn:aws:iam::${AuditorAccountId}:role${AuditRolePathName}"
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: "ProwlerPolicyAdditions"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: "ProwlerPolicyAdditions"
Effect: "Allow"
Resource: "*"
Action:
- "acm:describecertificate"
- "acm:listcertificates"
- "es:describeelasticsearchdomainconfig"
- "logs:DescribeLogGroups"
- "logs:DescribeMetricFilters"
- "ses:getidentityverificationattributes"
- "sns:listsubscriptionsbytopic"
- "guardduty:ListDetectors"
- "guardduty:GetDetector"
- "S3:GetEncryptionConfiguration"
- "trustedadvisor:Describe*"
- "cloudtrail:GetEventSelectors"
- "apigateway:GET"
- "support:*"
Metadata:
cfn_nag:
rules_to_suppress:
- id: W28
reason: "the role name is intentionally static"
- id: W11
reason: "the policy grants read/view/audit access only, to all resources, by design"
- id: F3
reason: "Support does not allow or deny access to individual actions"

411
util/Audit_Pipeline.yaml Normal file
View File

@@ -0,0 +1,411 @@
---
AWSTemplateFormatVersion: '2010-09-09'
Description: Prowler Auditing Tools Stack
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "Organizations and Accounts"
Parameters:
- pOrgMasterAccounts
- pOrgExcludedAccounts
- pStandAloneAccounts
- Label:
default: "Check Group and Execution"
Parameters:
- pProwlerCheckGroup
- pAuditEveryXHours
- Label:
default: "Advanced"
Parameters:
- pTimeoutMinutes
- pAuditRolePathName
- pCustomProwlerRepo
- pCustomProwlerCloneArgs
ParameterLabels:
pOrgMasterAccounts:
default: "Organization Master Accounts"
pOrgExcludedAccounts:
default: "Excluded Organiztion Members"
pStandAloneAccounts:
default: "Stand-alone Accounts"
pProwlerCheckGroup:
default: "Prowler Check Group"
pAuditEveryXHours:
default: "Perform Audit every X hours"
pTimeoutMinutes:
default: "Permit Audit to run for X minutes"
pAuditRolePathName:
default: "Custom audit role path"
pCustomProwlerRepo:
default: "Custom git repo location for prowler"
pCustomProwlerCloneArgs:
default: "Custom arguments to git clone --depth 1"
Parameters:
pAuditEveryXHours:
Default: 24
Type: Number
Description: Number of hours between prowler audit runs.
MinValue: 2
MaxValue: 168
pTimeoutMinutes:
Default: 30
Type: Number
Description: Timeout for running prowler across the fleet
pAuditRolePathName:
Default: '/audit/prowler/XA_AuditRole_Prowler'
Type: String
Description: Role path and name which prowler will assume in the target accounts (Audit_Exec_Role.yaml)
# TODO: Validation: begins with "/" and does NOT end with "/"
pOrgMasterAccounts:
Description: Comma Separated list of Organization Master Accounts, or 'none'
Default: 'none'
Type: String
MinLength: 4
AllowedPattern: ^(none|([0-9]{12}(,[0-9]{12})*))$
ConstraintDescription: comma separated list 12-digit account numbers, or 'none'
pOrgExcludedAccounts: # Comma Separated list of Org Member Accounts to EXCLUDE
Description: Comma Separated list of Skipped Organization Member Accounts, or 'none'
Default: 'none'
Type: String
MinLength: 4
AllowedPattern: ^(none|([0-9]{12}(,[0-9]{12})*))$
ConstraintDescription: comma separated list 12-digit account numbers, or 'none'
pStandAloneAccounts: # Comma Separated list of Stand-Alone Accounts
Description: Comma Separated list of Stand-alone Accounts, or 'none'
Default: 'none'
Type: String
MinLength: 4
AllowedPattern: ^(none|([0-9]{12}(,[0-9]{12})*))$
ConstraintDescription: comma separated list 12-digit account numbers, or 'none'
pProwlerCheckGroup:
Default: 'cislevel1'
Type: String
Description: Which group of checks should prowler run
AllowedValues:
- 'group1'
- 'group2'
- 'group3'
- 'group4'
- 'cislevel1'
- 'cislevel2'
- 'extras'
- 'forensics-ready'
- 'gdpr'
- 'hipaa'
- 'secrets'
- 'apigateway'
- 'rds'
pCustomProwlerRepo:
Type: String
Default: 'https://github.com/toniblyx/prowler.git'
MinLength: 10
pCustomProwlerCloneArgs:
Type: String
Default: '--branch master'
MinLength: 0
##### TODO
# pResultsBucket: # if specified, use an existing bucket for the data
# pEnableAthena:
# Default: false
# Type: Boolean
# Description: Set to true to enable creation of Athena/QuickSight resources
#### TODO
# Conditions:
# cUseAthena: False
Resources:
# S3 Bucket for Results, Config
ProwlerResultsBucket:
Type: "AWS::S3::Bucket"
Properties:
# BucketName: !Sub "audit-results-${AWS::AccountId}"
Tags:
- Key: "data-type"
Value: "it-audit:sensitive"
- Key: "data-public"
Value: "NO"
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
PublicAccessBlockConfiguration:
BlockPublicAcls: True
BlockPublicPolicy: True
IgnorePublicAcls: True
RestrictPublicBuckets: True
# LoggingConfiguration:
# TODO: Enable BucketLogging - requires more parameters
DeletionPolicy: "Retain"
Metadata:
cfn_nag:
rules_to_suppress:
- id: W35
reason: "Bucket logging requires additional configuration not yet supported by this template"
# Policy to allow assuming the XA_AuditRole_Prowler in target accounts
ProwlerAuditManagerRole:
Type: AWS::IAM::Role
Properties:
RoleName: AuditManagerRole_Prowler
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName: AssumeRole-XA_AuditRole_Prowler
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- !Sub "arn:aws:iam::*:role${pAuditRolePathName}"
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:GetObjectVersion
Resource:
- !Sub "${ProwlerResultsBucket.Arn}/*"
- Effect: Allow
Action:
- s3:ListBucket
- s3:HeadBucket
- s3:GetBucketLocation
- s3:GetBucketAcl
Resource:
- !Sub "${ProwlerResultsBucket.Arn}"
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
- !Sub "${ProwlerResultsBucket.Arn}"
- Effect: Allow
Action:
- ssm:GetParameters
Resource:
- !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/audit/prowler/config/*"
Metadata:
cfn_nag:
rules_to_suppress:
- id: W28
reason: "the role name is intentionally static"
- id: W11
reason: "not sure where the violation of w11 is"
## Code Build Job
ProwlerBuildProject:
Type: "AWS::CodeBuild::Project"
Properties:
Name: PerformProwlerAudit
Description: "Run Prowler audit on accounts in targeted organizations"
QueuedTimeoutInMinutes: 480
TimeoutInMinutes: !Ref pTimeoutMinutes
ServiceRole: !Ref ProwlerAuditManagerRole
EncryptionKey: !Sub "arn:aws:kms:us-east-1:${AWS::AccountId}:alias/aws/s3"
Environment:
Type: "LINUX_CONTAINER"
ComputeType: "BUILD_GENERAL1_MEDIUM"
PrivilegedMode: False
Image: "aws/codebuild/standard:2.0-1.12.0"
ImagePullCredentialsType: "CODEBUILD"
Artifacts:
Name: "ProwlerResults"
Type: "S3"
Location: !Ref ProwlerResultsBucket
Path: "prowler"
NamespaceType: NONE
Packaging: NONE
OverrideArtifactName: False
EncryptionDisabled: False
LogsConfig: # S3/logs/pipeline/
CloudWatchLogs:
Status: ENABLED
GroupName: "audit/prowler"
StreamName: "codebuild_runs"
S3Logs:
Status: DISABLED
# Location: !Sub "${ProwlerResultsBucket.Arn}/codebuild_run_logs"
EncryptionDisabled: False
BadgeEnabled: False
Tags:
- Key: "data-type"
Value: "it-audit:sensitive"
- Key: "data-public"
Value: "NO"
Cache:
Type: "NO_CACHE"
Source:
Type: NO_SOURCE
BuildSpec: |
version: 0.2
env:
parameter-store:
PROWL_CHECK_GROUP: /audit/prowler/config/check_group
PROWL_MASTER_ACCOUNTS: /audit/prowler/config/orgmaster_accounts
PROWL_STANDALONE_ACCOUNTS: /audit/prowler/config/standalone_accounts
PROWL_SKIP_ACCOUNTS: /audit/prowler/config/skip_accounts
PROWL_AUDIT_ROLE: /audit/prowler/config/audit_role
PROWLER_REPO: /audit/prowler/config/gitrepo
PROWLER_CLONE_ARGS: /audit/prowler/config/gitcloneargs
phases:
install:
runtime-versions:
python: 3.7
commands:
- aws --version
- git clone --depth 1 $PROWLER_REPO $PROWLER_CLONE_ARGS
pre_build:
commands:
- env | grep PROWL_
- export OUTBASE=$(date -u +"out/diagnostics/%Y/%m/%d")
- export STAMP=$(date -u +"%Y%m%dT%H%M%SZ")
- mkdir -p $OUTBASE || true
- prowler/prowler -V
- aws sts get-caller-identity > ${OUTBASE}/${STAMP}-caller-id.json
build:
commands:
#### Run Prowler against this account, but don't fail the build
# - export PROWLER_ACCOUNT_ID=$(aws sts get-caller-identity | jq -r '.Account')
# - /bin/bash prowler/prowler -g cislevel1 -M csv -n -k > ${OUTBASE}/${STAMP}.${PROWLER_ACCOUNT_ID}.prowler.cislevel1.csv || /bin/true
# - /bin/bash prowler/prowler -g forensics-ready -M csv -n -k > ${OUTBASE}/${STAMP}.${PROWLER_ACCOUNT_ID}.prowler.forensics-ready.csv || /bin/true
#### Run Prowler targeting all accounts in the configured organizations
- test -f prowler/util/config
- /bin/bash prowler/util/megaprowler.sh out
finally:
- ps axuwww | grep -E 'parallel|sem|prowler'
post_build:
commands:
- echo "attempting to collect any prowler credential reports ..."
- find /tmp/ -name prowler\* | xargs -I % cp % ${OUTDIAG} || true
artifacts:
files:
- out/**/*
discard-paths: no
ProwlerAuditTriggerRole:
Type: AWS::IAM::Role
Properties:
# RoleName: Let cloudformation create this
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: events.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName: AssumeRole-XA_AuditRole_Prowler
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- codebuild:StartBuild
Resource:
- !GetAtt ProwlerBuildProject.Arn
ProwlerAuditTrigger:
Type: AWS::Events::Rule
Properties:
Description: !Sub "Execute Prowler audit every ${pAuditEveryXHours} hours"
Name: "ScheduledProwler"
RoleArn: !GetAtt ProwlerAuditTriggerRole.Arn
## Other ways to define scheduling
# ScheduleExpression: "cron(MM HH ? * * *)"
# ScheduleExpression: "cron(45 15 ? * * *)"
# ScheduleExpression: !Sub "rate( ${pAuditEveryXHours} hours)"
ScheduleExpression: !Sub "rate(${pAuditEveryXHours} hours)"
State: ENABLED
Targets:
- Arn: !GetAtt ProwlerBuildProject.Arn
Id: 'ScheduledProwler'
RoleArn: !GetAtt ProwlerAuditTriggerRole.Arn
ProwlerConfigCheckGroup:
Type: AWS::SSM::Parameter
Properties:
Description: "Name of the prowler check group to use"
Name: "/audit/prowler/config/check_group"
Type: "String"
Value: !Ref pProwlerCheckGroup
ProwlerConfigMasterAccounts:
Type: AWS::SSM::Parameter
Properties:
Description: "List of organization master accounts"
Name: "/audit/prowler/config/orgmaster_accounts"
Type: "String"
Value: !Ref pOrgMasterAccounts
ProwlerConfigStandAloneAccounts:
Type: AWS::SSM::Parameter
Properties:
Description: "List of stand-alone accounts"
Name: "/audit/prowler/config/standalone_accounts"
Type: "String"
Value: !Ref pStandAloneAccounts
ProwlerConfigSkipAccounts:
Type: AWS::SSM::Parameter
Properties:
Description: "List of skipped organization member accounts"
Name: "/audit/prowler/config/skip_accounts"
Type: "String"
Value: !Ref pOrgExcludedAccounts
ProwlerConfigAuditRole:
Type: AWS::SSM::Parameter
Properties:
Description: "Role used to audit target accounts"
Name: "/audit/prowler/config/audit_role"
Type: "String"
Value: !Ref pAuditRolePathName
ProwlerConfigGitRepo:
Type: AWS::SSM::Parameter
Properties:
Description: "Git repository where prowler is gathered"
Name: "/audit/prowler/config/gitrepo"
Type: "String"
Value: !Ref pCustomProwlerRepo
ProwlerConfigGitCloneArgs:
Type: AWS::SSM::Parameter
Properties:
Description: "Git clone arguments"
Name: "/audit/prowler/config/gitcloneargs"
Type: "String"
Value: !Ref pCustomProwlerCloneArgs
# -- Conditional "cUseAthena"
# Athena
# QuickSight
# ???
Outputs:
ResultsBucket:
Description: S3 Bucket with Prowler Results, Logs, Configs
Value: !Ref ProwlerResultsBucket

32
util/config Normal file
View File

@@ -0,0 +1,32 @@
#!/bin/bash
########### CODEBUILD CONFIGURATION ##################
## Collect environment parameters set by buildspec
CHECKGROUP=${PROWL_CHECK_GROUP}
if [ "none" == "${PROWL_MASTER_ACCOUNTS}" ]; then
ORG_MASTERS=""
else
ORG_MASTERS=$(echo ${PROWL_MASTER_ACCOUNTS} | tr "," " ")
fi
if [ "none" == "${PROWL_STANDALONE_ACCOUNTS}" ]; then
STANDALONE_ACCOUNTS=""
else
STANDALONE_ACCOUNTS=$(echo ${PROWL_STANDALONE_ACCOUNTS} | tr "," " ")
fi
if [ "none" == "${PROWL_SKIP_ACCOUNTS}" ]; then
SKIP_ACCOUNTS_REGEX='^$'
else
skip_inside=$(echo ${PROWL_SKIP_ACCOUNTS} | tr "," "|")
SKIP_ACCOUNTS_REGEX=$(echo "(${skip_inside})" )
fi
AUDIT_ROLE=${PROWL_AUDIT_ROLE}
# Adjust if you clone prowler from somewhere other than the default location
PROWLER='prowler/prowler'
# Change this if you want to ensure it breaks in code build
CREDSOURCE='EcsContainer'

190
util/megaprowler.sh Normal file
View File

@@ -0,0 +1,190 @@
#!/bin/bash
# source the configuration data from "config" in this directory
if [[ -f $(dirname $0)/config ]]; then
. $(dirname $0)/config
else
echo "CONFIG file missing - $(dirname $0)/config"
exit -1
fi
## Check Environment variables which are set by config
if [[ "${ORG_MASTERS}X" == "X" && "${STANDALONE_ACCOUNTS}X" == "X" ]]; then
echo "No audit targets specified. Failing."
exit 15
fi
if [[ -z $SKIP_ACCOUNTS_REGEX ]]; then
SKIP_ACCOUNTS_REGEX=""
fi
if [[ -z $CHECKGROUP ]]; then
echo "Missing check group from config file"
exit -1
fi
if [[ -z $AUDIT_ROLE ]]; then
echo "Missing audit role from config file"
exit -1
fi
## ========================================================================================
## Check Arguments
if [ $# -lt 1 ]; then
echo "NEED AN OUTPUT DIRECTORY"
exit 2
else
if [[ -d $1 && -w $1 ]]; then
OUTBASE=$1
else
echo "Output directory missing or write-protected"
exit 1
fi
fi
## Check Requirements
if [[ -x $(which aws) ]]; then
aws --version
else
echo "AWS CLI is not in PATH ... giving up"
exit 4
fi
if [[ -x $(which jq) ]]; then
jq --version
else
echo "JQ is not in PATH ... giving up"
exit 4
fi
# Ensure AWS Credentials are present in environment
if [[ -z $CREDSOURCE ]]; then
echo "No source for base credentials ... giving up"
exit 5
fi
# if [[ Ec2InstanceMetadata ]]
if [[ -f ${PROWLER} && -x ${PROWLER} ]]; then
PROWLER_VERSION=$(${PROWLER} -V)
else
echo "Unable to execute prowler from ${PROWLER}"
exit 3
fi
## Preflight checks complete
DAYPATH=$(date -u +%Y/%m/%d)
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
## Create output subdirs
OUTDATA="${OUTBASE}/data/${DAYPATH}"
OUTLOGS="${OUTBASE}/logs/${DAYPATH}"
mkdir -p ${OUTDATA} ${OUTLOGS}
if [[ -x $(which parallel) ]]; then
# Note: the "standard" codebuild container includes parallel
echo "Using GNU sem/parallel, with NCPU+4 jobs"
parallel --citation > /dev/null 2> /dev/null
PARALLEL_START="parallel --semaphore --fg --id p_${STAMP} --jobs +4 --env AWS_SHARED_CREDENTIALS_FILE"
PARALLEL_START_SUFFIX=''
PARALLEL_END="parallel --semaphore --wait --id p_${STAMP}"
else
echo "Consider installing GNU Parallel to avoid punishing your system"
PARALLEL_START=''
PARALLEL_START_SUFFIX=' &'
PARALLEL_END="echo 'WAITING BLINDLY FOR PROCESSES TO COMPLETE'; wait ; sleep 30 ; wait"
fi
echo "Execution Timestamp: ${STAMP}"
ALL_ACCOUNTS=""
# Create a temporary credential file
export AWS_MASTERS_CREDENTIALS_FILE=$(mktemp -t prowler.masters-XXXXXX)
echo "Preparing Credentials ${AWS_MASTERS_CREDENTIALS_FILE} ( ${CREDSOURCE} )"
echo "# Master Credentials ${STAMP}" >> $AWS_MASTERS_CREDENTIALS_FILE
echo "" >> $AWS_MASTERS_CREDENTIALS_FILE
AWS_TARGETS_CREDENTIALS_FILE=$(mktemp -t prowler.targets-XXXXXX)
echo "Preparing Credentials ${AWS_TARGETS_CREDENTIALS_FILE} ( ${CREDSOURCE} )"
echo "# Target Credentials ${STAMP}" >> $AWS_TARGETS_CREDENTIALS_FILE
echo "" >> $AWS_TARGETS_CREDENTIALS_FILE
## Visit the Organization Master accounts & build a list of all member accounts
export AWS_SHARED_CREDENTIALS_FILE=$AWS_MASTERS_CREDENTIALS_FILE
for org in $ORG_MASTERS ; do
echo -n "Preparing organization $org "
# create credential profile
echo "[audit_${org}]" >> $AWS_MASTERS_CREDENTIALS_FILE
echo "role_arn = arn:aws:iam::${org}:role${AUDIT_ROLE}" >> $AWS_MASTERS_CREDENTIALS_FILE
echo "credential_source = ${CREDSOURCE}" >> $AWS_MASTERS_CREDENTIALS_FILE
echo "" >> $AWS_MASTERS_CREDENTIALS_FILE
# Get the Organization ID to use for output paths, collecting info, etc
org_id=$(aws --output json --profile audit_${org} organizations describe-organization | jq -r '.Organization.Id' )
echo "( $org_id )"
ORG_ID_LIST="${ORG_ID_LIST} ${org_id}"
# Build the list of all accounts in the organizations
aws --output json --profile audit_${org} organizations list-accounts > ${OUTLOGS}/${STAMP}-${org_id}-account-list.json
ORG_ACCOUNTS=$( cat ${OUTLOGS}/${STAMP}-${org_id}-account-list.json | jq -r '.Accounts[].Id' | tr "\n" " ")
ALL_ACCOUNTS="${ALL_ACCOUNTS} ${ORG_ACCOUNTS}"
# Add the Org's Accounts (including master) to the TARGETS_CREDENTIALS file
for target in $ORG_ACCOUNTS ; do
if $(echo $target | grep -qE $SKIP_ACCOUNTS_REGEX) ; then
echo " skipping account ${target} ( ${org_id} )"
continue
fi
# echo " ${org_id}_${target}"
echo "[${org_id}_${target}]" >> $AWS_TARGETS_CREDENTIALS_FILE
echo "role_arn = arn:aws:iam::${target}:role${AUDIT_ROLE}" >> $AWS_TARGETS_CREDENTIALS_FILE
echo "credential_source = ${CREDSOURCE}" >> $AWS_TARGETS_CREDENTIALS_FILE
echo "" >> $AWS_TARGETS_CREDENTIALS_FILE
done
done
# Prepare credentials for standalone accounts
if [[ "" != "${STANDALONE_ACCOUNTS}" ]] ; then
# mkdir -p ${OUTBASE}/data/standalone/${DAYPATH} ${OUTBASE}/logs/standalone/${DAYPATH}
for target in $STANDALONE_ACCOUNTS ; do
echo "Preparing account ${target} ( standalone )"
echo "[standalone_${target}]" >> $AWS_TARGETS_CREDENTIALS_FILE
echo "role_arn = arn:aws:iam::${target}:role${AUDIT_ROLE}" >> $AWS_TARGETS_CREDENTIALS_FILE
echo "credential_source = ${CREDSOURCE}" >> $AWS_TARGETS_CREDENTIALS_FILE
echo "" >> $AWS_TARGETS_CREDENTIALS_FILE
done
ALL_ACCOUNTS="${ALL_ACCOUNTS} ${STANDALONE_ACCOUNTS}"
fi
# grep -E '^\[' $AWS_MASTERS_CREDENTIALS_FILE $AWS_TARGETS_CREDENTIALS_FILE
# Switch to Target Credential Set
export AWS_SHARED_CREDENTIALS_FILE=${AWS_TARGETS_CREDENTIALS_FILE}
## visit each target account
NUM_ACCOUNTS=$(grep -cE '^\[' ${AWS_TARGETS_CREDENTIALS_FILE})
echo "Launching ${CHECKGROUP} audit of ${NUM_ACCOUNTS} accounts"
for member in $(grep -E '^\[' ${AWS_TARGETS_CREDENTIALS_FILE} | tr -d '][') ; do
ORG_ID=$(echo $member | cut -d'_' -f1)
ACCOUNT_NUM=$(echo $member | cut -d'_' -f2)
${PARALLEL_START} "${PROWLER} -p ${member} -n -M csv -g ${CHECKGROUP} 2> ${OUTLOGS}/${STAMP}-${ORG_ID}-${ACCOUNT_NUM}-prowler-${CHECKGROUP}.log > ${OUTDATA}/${STAMP}-${ORG_ID}-${ACCOUNT_NUM}-prowler-${CHECKGROUP}.csv ; echo \"${ORG_ID}-${ACCOUNT_NUM}-prowler-${CHECKGROUP} finished\" " ${PARALLEL_START_SUFFIX}
done
echo -n "waiting for parallel threads to complete - " ; date
${PARALLEL_END}
echo "Completed ${CHECKGROUP} audit with stamp ${STAMP}"
# mkdir -p ${OUTBASE}/logs/debug/${DAYPATH}
# cp $AWS_MASTERS_CREDENTIALS_FILE ${OUTLOGS}/${STAMP}-master_creds.txt
# cp $AWS_TARGETS_CREDENTIALS_FILE ${OUTLOGS}/${STAMP}-target_creds.txt
rm $AWS_MASTERS_CREDENTIALS_FILE $AWS_TARGETS_CREDENTIALS_FILE