Skip to content

Commit

Permalink
Merge pull request #83 from aws-ia/sra-mig
Browse files Browse the repository at this point in the history
update publication phase
  • Loading branch information
kkvinjam committed Jan 10, 2024
2 parents 38ad1f1 + 5c35d72 commit 4be0b4c
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 48 deletions.
31 changes: 30 additions & 1 deletion .project_automation/publication/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,38 @@
PROJECT_PATH=${BASE_PATH}/project
PROJECT_TYPE_PATH=${BASE_PATH}/projecttype

BRANCH=main
EXISTING_GIT_VERSION="$(git tag -l)"
HUGO_VERSION=$(hugo version)
PUBLIC_PATH=./public
# ABP clones with HTTPS URL remotes
REPO_NAME=$(git config --get remote.origin.url | cut -d '/' -f5 | cut -d '.' -f1)
VERSION=$(cat VERSION)

BASE_URL="this would be the path to s3 bucket/${REPO_NAME}/"
S3_URI="s3://aws-abi-pilot/guide/${REPO_NAME}/"

print_header() {
printf "\n\n%s\n" "$*"
}

print_header 'Building site...'
cd ${PROJECT_PATH}/guide
hugo --verbose --debug

print_header 'Publishing...'
aws s3 sync --delete "${PUBLIC_PATH}" "${S3_URI}" --acl public-read

print_header 'Listing uploaded content...'
aws s3 ls --recursive --human-readable --summarize "${S3_URI}"

printf "\nPublished at ${BASE_URL}\n"

# Publish code to S3 bucket

cd ${PROJECT_PATH}

taskcat upload --bucket-name aws-abi --object-acl public-read
taskcat upload --bucket-name aws-abi-pilot --object-acl public-read

# if [ -n "${BASE_PATH}" ]
# then
Expand Down
2 changes: 1 addition & 1 deletion guide/content/how-to-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The below example refers to steps followed to create the sample ABI project in t
cd submodules
git submodule add https://github.com/aws-samples/aws-security-reference-architecture-examples.git
```
Check here for [List of available ABI Modules](/available_modules/index.html).
Check here for [List of available ABI Modules](/things-to-know/index.html).

3. Build and update the code as per your project needs. Follow the structure explained in the [Project Structure](/project-structure/index.html) section to organize your code. Below is an example of the directory structure for the sample ABI project in this repository:

Expand Down
119 changes: 73 additions & 46 deletions scripts/cleanup_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,26 @@

STACKSTATUS = [ 'ROLLBACK_FAILED', 'ROLLBACK_COMPLETE', 'DELETE_FAILED', 'DELETE_COMPLETE']

def list_stacksets():
def list_stacksets(context=CF):
'''List all stacksets in the account'''
response = CF.list_stack_sets()
response = context.list_stack_sets()
stacksets = response['Summaries']
while response.get('NextToken'):
response = CF.list_stack_sets(NextToken=response['NextToken'])
response = context.list_stack_sets(NextToken=response['NextToken'])
stacksets.extend(response['Summaries'])
return stacksets

def list_active_stackset_names():
def list_active_stackset_names(context=CF):
'''List all stackset names in the account'''
cf_names = []
for cfn in list_stacksets():
for cfn in list_stacksets(context):
if cfn['Status'] != 'DELETED':
cf_names += [cfn['StackSetName']]
return cf_names

def list_stackset_names(filters=None):
def list_stackset_names(context=CF, filters=None):
'''List all stackset names in the account'''
cf_info = list_stacksets()
cf_info = list_stacksets(context)
cf_names = []
for cfn in cf_info:
if cfn['Status'] != 'DELETED':
Expand All @@ -56,35 +56,35 @@ def list_stackset_names(filters=None):

return cf_names

def list_stackset_instances(stackset_name):
def list_stackset_instances(context=CF, ss_name=None):
'''List all stackset instances in the account'''
response = CF.list_stack_instances(StackSetName=stackset_name)
response = context.list_stack_instances(StackSetName=ss_name)
stackinstances = response['Summaries']
while response.get('NextToken'):
response = CF.list_stack_instances(StackSetName=stackset_name,
response = context.list_stack_instances(StackSetName=ss_name,
NextToken=response['NextToken'])
stackinstances.extend(response['Summaries'])
return stackinstances

def delete_stack_instances(stackset_name, retain_stacks=False):
'''Delete all stackset instances in the account'''
stackinstances = list_stackset_instances(stackset_name)
stackinstances = list_stackset_instances(ss_name=stackset_name)
for stackinstance in stackinstances:
CF.delete_stack_instances(StackSetName=stackset_name,
Regions=[stackinstance['Region']],
RetainStacks=retain_stacks)

def si_account_list(stackset_name):
'''List all stackset instance accounts'''
stackinstances = list_stackset_instances(stackset_name)
stackinstances = list_stackset_instances(ss_name=stackset_name)
stackinstance_names = []
for stackinstance in stackinstances:
stackinstance_names += [stackinstance['Account']]
return stackinstance_names

def si_region_list(stackset_name):
'''List all stackset instance regions'''
stackinstances = list_stackset_instances(stackset_name)
stackinstances = list_stackset_instances(ss_name=stackset_name)
stackinstance_regions = []
for stackinstance in stackinstances:
stackinstance_regions += [stackinstance['Region']]
Expand Down Expand Up @@ -121,15 +121,15 @@ def delete_all_stackinstances(stackset_name):
RetainStacks=False)

loop = 1
while len(list_stackset_instances(stackset_name)) > 0 and loop < 30:
while len(list_stackset_instances(ss_name=stackset_name)) > 0 and loop < 30:
sleep(10)
loop += 1

return response

def delete_stacksets(filters):
'''Delete all stacksets created by CfCT solution in the account'''
cf_names = list_stackset_names(filters)
cf_names = list_stackset_names(filters=filters)
for cf_name in cf_names:
op_info = delete_all_stackinstances(cf_name)
op_id = op_info['OperationId']
Expand Down Expand Up @@ -177,11 +177,11 @@ def delete_stack(filters='tCaT-'):
stack_name = stack['StackName']
stack_status = stack['StackStatus']
if stack_name.startswith(filters) and stack_status != 'DELETE_COMPLETE':
print('Deleting stack: %s', stack_name)
print(f"Deleting stack: {stack_name}")
CF.delete_stack(StackName=stack_name)
wait = 1
while list_stack_status_by_name(stack_name) not in STACKSTATUS and wait < 60:
print('Wait: %s, Stack: %s', stack_name, wait)
print(f"Wait: {wait}, Stack: {stack_name}")
sleep(10)
wait += 1

Expand Down Expand Up @@ -228,28 +228,33 @@ def delete_s3_buckets(item):
else:
raise exe

def list_all_parameters(ssm_session=SSM):
def list_all_parameters(context):
''''List all parameters in the account'''
response = ssm_session.describe_parameters()
response = context.describe_parameters()
parameters = response['Parameters']
while response.get('NextToken'):
response = ssm_session.describe_parameters(NextToken=response['NextToken'])
response = context.describe_parameters(NextToken=response['NextToken'])
parameters.extend(response['Parameters'])
return parameters

def delete_parameters(item):
'''Delete all parameters created in the account'''

print(f"Recieved item: {item}")
filters = item['Filter']
(ssm_session, account, target) = get_client_session(item, 'ssm')
print(f"SSM action on {target} with filters: {filters}")
print(f"SSM action on {account}/{target} with filters: {filters}")

parameters = list_all_parameters(ssm_session)
parameters = list_all_parameters(context=ssm_session)
for parameter in parameters:
param_name = parameter['Name']
print(f"param_name: {param_name}")
if param_name.startswith(filters):
print(f"..Deleting parameter {param_name}.")
res = ssm_session.get_parameter(Name=param_name)['Parameter']['ARN']
print(f"res: {res}")
ssm_session.delete_parameter(Name=param_name)
print(f"..Deleted parameter {param_name}.")

def get_temp_credentials(aws_account, role_name='AWSControlTowerExecution'):
'''
Expand Down Expand Up @@ -288,11 +293,12 @@ def establish_remote_session(account):
aws_secret_access_key=sts_creds['SecretAccessKey'],
aws_session_token=sts_creds['SessionToken']
)
print(f"Established session for {account} with {role}")
break

return result

def get_log_archive_account(parameter_name='/sra/control-tower/log-archive-account-id'):
def get_log_archive_account(parameter_name='/sra/gd/control-tower/log-archive-account-id'):
'''
Get log archive account ID
'''
Expand Down Expand Up @@ -342,7 +348,7 @@ def delete_cw_logs(item):

filters = item['Filter']
(cw_session, account, target) = get_client_session(item, 'logs')
print(f"LOG GROUP action on {target} with filters: {filters}")
print(f"LOG GROUP action on {account}/{target} with filters: {filters}")

log_groups = list_cw_lognames(context=cw_session)
for log_group_name in log_groups:
Expand Down Expand Up @@ -390,7 +396,6 @@ def delete_detector():
print('Deleting GuardDuty Detector in %s', account['Id'])
gd_client.delete_detector(DetectorId=det_id)


def list_cb_projects():
'''
List all CodeBuild projects
Expand All @@ -405,45 +410,65 @@ def list_cb_projects():
return projects

def delete_build_projects(filters='sra-codebuild-'):
'''
Delete the CodeBuild projects in all accounts in the organization in the current region
'''
''' Delete the CodeBuild projects in all accounts in the organization in the current region '''
projects = list_cb_projects()
for project in projects:
if project.startswith(filters):
print('Deleting CodeBuild project: %s', project)
cb_session = SESSION.client('codebuild')
cb_session.delete_project(name=project)

def get_account_info(ss_name='AWSControlTowerLoggingResources'):
def get_log_account_info(context, ss_name='AWSControlTowerLoggingResources'):
''' List first stack instances in a stackset '''

cf_client = context.client('cloudformation')
if ss_name in list_active_stackset_names(cf_client):
instance = cf_client.list_stack_instances(StackSetName=ss_name)
account_id = instance['Summaries'][0]['Account']
for account in get_list_of_accounts():
if account['Id'] == account_id:
account_name = account['Name']
else:
account_id = get_account_id('Log Archive')
account_name = 'LogArchive'

return {'AccountName': account_name, 'AccountID': account_id}

def get_audit_account_info(context, ss_name='AWSControlTowerLoggingResources'):
'''
List first stack instances in a stackset
'''
result = None

if ss_name in list_active_stackset_names():
instance = CF.list_stack_instances(StackSetName=ss_name)
cf_client = context.client('cloudformation')
if ss_name in list_active_stackset_names(cf_client):
instance = cf_client.list_stack_instances(StackSetName=ss_name)
account_id = instance['Summaries'][0]['Account']
for account in get_list_of_accounts():
if account['Id'] == account_id:
account_name = account['Name']
result = {'AccountName': account_name, 'AccountID': account_id}
return result
else:
account_id = get_account_id('Audit')
account_name = 'Audit'

return {'AccountName': account_name, 'AccountID': account_id}

def get_client_session(item, client_name):
'''
Return a session for parent or child
'''
''' Return a session for parent or child '''

account = None
if 'Account' in item:
if item['Account'] in ACCOUNTS:
print(f"Using account {ACCOUNTS[item['Account']]} for {client_name}")
account = get_account_id(ACCOUNTS[item['Account']])
print(f"Got account ID: {account}")

if account:
print(f"Establishing session to : {account}")
session = establish_remote_session(account)
client_session = session.client(client_name)
target = account
else:
print(f"Using local session for {client_name}")
client_session = boto3.client(client_name)
target = STS.get_caller_identity()['Account']

Expand All @@ -456,7 +481,7 @@ def delete_iam_role(item):

role_name = item['Filter']
(iam_session, account, target) = get_client_session(item, 'iam')
print(f"IAM action on {target} with role_name: {role_name}")
print(f"IAM action on {account}/{target} with role_name: {role_name}")

try:
policies = iam_session.list_attached_role_policies(RoleName=role_name)
Expand Down Expand Up @@ -502,23 +527,25 @@ def run_cleanup(config):
description='Clear the configuration.')
PARSER.add_argument("-C", "--config", default='cleanup_config.json',
help="Clear content from config")
PARSER.add_argument("-r", "--home_region", default='us-east-1',
help="Control Tower home region")

ARGS = PARSER.parse_args()
CT_HOME = ARGS.home_region

ACC_SESSION = boto3.session.Session(region_name=CT_HOME)
LOG_ACCT_NAME = 'Log Archive'
AUDIT_ACCT_NAME = 'Audit'

LOG_ACCT_INFO = get_log_account_info(context=ACC_SESSION)
AUDIT_ACCT_INFO = get_audit_account_info(ACC_SESSION)

LOG_ACCT_INFO = get_account_info('AWSControlTowerLoggingResources')
AUDIT_ACCT_INFO = get_account_info('AWSControlTowerSecurityResources')
if LOG_ACCT_INFO:
LOG_ACCT_NAME = LOG_ACCT_INFO['AccountName']
else:
LOG_ACCT_NAME = 'Log Archive'

if AUDIT_ACCT_INFO:
AUDIT_ACCT_NAME = AUDIT_ACCT_INFO['AccountName']
else:
AUDIT_ACCT_NAME = 'Audit'

ACCOUNTS = {"log_account": LOG_ACCT_NAME, "audit": AUDIT_ACCT_NAME}
print('Recieved Account Info: %s', ACCOUNTS)
CLEAR_CFG = ARGS.config

if isfile(CLEAR_CFG):
Expand Down

0 comments on commit 4be0b4c

Please sign in to comment.