def worker_thread(account_id, sts, config, s3, cache, kms_dict): """ The Worker thread function that is created for each account in which CloudFormation create_stack is called """ LOGGER.debug("%s - Starting new worker thread", account_id) organizations = Organizations(role=boto3, account_id=account_id) ou_id = organizations.get_parent_info().get("ou_parent_id") account_state = is_account_in_invalid_state(ou_id, config.config) if account_state: LOGGER.info("%s %s", account_id, account_state) return account_path = organizations.build_account_path( ou_id, [], # Initial empty array to hold OU Path, cache) try: role = ensure_generic_account_can_be_setup(sts, config, account_id) # Regional base stacks can be updated after global for region in list( set([config.deployment_account_region] + config.target_regions)): # Ensuring the kms_arn on the target account is up-to-date parameter_store = ParameterStore(region, role) parameter_store.put_parameter('kms_arn', kms_dict[region]) cloudformation = CloudFormation( region=region, deployment_account_region=config.deployment_account_region, role=role, wait=True, stack_name=None, s3=s3, s3_key_path=account_path, account_id=account_id) try: cloudformation.create_stack() except GenericAccountConfigureError as error: if 'Unable to fetch parameters' in str(error): LOGGER.error( '%s - Failed to update its base stack due to missing parameters (deployment_account_id or kms_arn), ' 'ensure this account has been bootstrapped correctly by being moved from the root ' 'into an Organizational Unit within AWS Organizations.', account_id) raise Exception from error except GenericAccountConfigureError as generic_account_error: LOGGER.info(generic_account_error) return
def worker_thread(account_id, sts, config, s3, cache): """ The Worker thread function that is created for each account in which CloudFormation create_stack is called """ LOGGER.info("Starting new worker thread for %s", account_id) organizations = Organizations(boto3, account_id) ou_id = organizations.get_parent_info().get("ou_parent_id") if is_account_invalid_state(ou_id, config.config): LOGGER.info("%s is in an invalid state", account_id) return account_path = organizations.build_account_path( ou_id, [], # Initial empty array to hold OU Path, cache) LOGGER.info("The Account path for %s is %s", account_id, account_path) try: role = ensure_generic_account_can_be_setup(sts, config, account_id) # Regional base stacks can be updated after global for region in list( set([config.deployment_account_region] + config.target_regions)): cloudformation = CloudFormation( region=region, deployment_account_region=config.deployment_account_region, role=role, wait=True, stack_name=None, s3=s3, s3_key_path=account_path) cloudformation.create_stack() except GenericAccountConfigureError as generic_account_error: LOGGER.info(generic_account_error) return
def main(): config = Config() config.store_config() try: parameter_store = ParameterStore(REGION_DEFAULT, boto3) deployment_account_id = parameter_store.fetch_parameter( 'deployment_account_id') organizations = Organizations(boto3, deployment_account_id) sts = STS(boto3) deployment_account_role = prepare_deployment_account( sts=sts, deployment_account_id=deployment_account_id, config=config) cache = Cache() ou_id = organizations.get_parent_info().get("ou_parent_id") account_path = organizations.build_account_path(ou_id=ou_id, account_path=[], cache=cache) s3 = S3(REGION_DEFAULT, boto3, S3_BUCKET_NAME) # First Setup the Deployment Account in all regions (KMS Key and S3 Bucket + Parameter Store values) for region in list( set([config.deployment_account_region] + config.target_regions)): cloudformation = CloudFormation( region=region, deployment_account_region=config.deployment_account_region, role=deployment_account_role, wait=True, stack_name=None, s3=s3, s3_key_path=account_path) cloudformation.create_stack() update_deployment_account_output_parameters( deployment_account_region=config.deployment_account_region, region=region, deployment_account_role=deployment_account_role, cloudformation=cloudformation) threads = [] account_ids = organizations.get_account_ids() for account_id in account_ids: t = PropagatingThread(target=worker_thread, args=(account_id, sts, config, s3, cache)) t.start() threads.append(t) for thread in threads: thread.join() step_functions = StepFunctions( role=deployment_account_role, deployment_account_id=deployment_account_id, deployment_account_region=config.deployment_account_region, regions=config.target_regions, account_ids=[ i for i in account_ids if i != config.deployment_account_region ], update_pipelines_only=1) step_functions.execute_statemachine() except ParameterNotFoundError: LOGGER.info("Deployment Account has not yet been Bootstrapped.") return
def main(): # pylint: disable=R0915 LOGGER.info("ADF Version %s", ADF_VERSION) LOGGER.info("ADF Log Level is %s", ADF_LOG_LEVEL) policies = OrganizationPolicy() config = Config() config.store_config() try: parameter_store = ParameterStore(REGION_DEFAULT, boto3) deployment_account_id = parameter_store.fetch_parameter( 'deployment_account_id') organizations = Organizations(role=boto3, account_id=deployment_account_id) policies.apply(organizations, parameter_store, config.config) sts = STS() deployment_account_role = prepare_deployment_account( sts=sts, deployment_account_id=deployment_account_id, config=config) cache = Cache() ou_id = organizations.get_parent_info().get("ou_parent_id") account_path = organizations.build_account_path(ou_id=ou_id, account_path=[], cache=cache) s3 = S3(region=REGION_DEFAULT, bucket=S3_BUCKET_NAME) kms_and_bucket_dict = {} # First Setup/Update the Deployment Account in all regions (KMS Key and # S3 Bucket + Parameter Store values) for region in list( set([config.deployment_account_region] + config.target_regions)): cloudformation = CloudFormation( region=region, deployment_account_region=config.deployment_account_region, role=deployment_account_role, wait=True, stack_name=None, s3=s3, s3_key_path="adf-bootstrap/" + account_path, account_id=deployment_account_id) cloudformation.create_stack() update_deployment_account_output_parameters( deployment_account_region=config.deployment_account_region, region=region, kms_and_bucket_dict=kms_and_bucket_dict, deployment_account_role=deployment_account_role, cloudformation=cloudformation) if region == config.deployment_account_region: cloudformation.create_iam_stack() # Updating the stack on the master account in deployment region cloudformation = CloudFormation( region=config.deployment_account_region, deployment_account_region=config.deployment_account_region, role=boto3, wait=True, stack_name=None, s3=s3, s3_key_path='adf-build', account_id=ACCOUNT_ID) cloudformation.create_stack() threads = [] account_ids = [ account_id["Id"] for account_id in organizations.get_accounts() ] for account_id in [ account for account in account_ids if account != deployment_account_id ]: thread = PropagatingThread(target=worker_thread, args=(account_id, sts, config, s3, cache, kms_and_bucket_dict)) thread.start() threads.append(thread) for thread in threads: thread.join() LOGGER.info("Executing Step Function on Deployment Account") step_functions = StepFunctions( role=deployment_account_role, deployment_account_id=deployment_account_id, deployment_account_region=config.deployment_account_region, regions=config.target_regions, account_ids=account_ids, update_pipelines_only=0) step_functions.execute_statemachine() except ParameterNotFoundError: LOGGER.info( 'A Deployment Account is ready to be bootstrapped! ' 'The Account provisioner will now kick into action, ' 'be sure to check out its progress in AWS Step Functions in this account.' ) return
def main(): try: parameter_store = ParameterStore(REGION_DEFAULT, boto3) deployment_account_id = parameter_store.fetch_parameter( 'deployment_account_id') config = Config() config.store_config() if deployment_account_id is None: raise NotConfiguredError( "Deployment Account has not yet been configured") organizations = Organizations(boto3, deployment_account_id) sts = STS(boto3) ou_id = organizations.get_parent_info().get("ou_parent_id") deployment_account_role = ensure_deployment_account_configured( sts, config, ou_id, deployment_account_id) cache = Cache() account_path = organizations.build_account_path( ou_id, [], # Initial empty array to hold OU Path cache) s3 = S3(REGION_DEFAULT, boto3, S3_BUCKET) # (First) Setup the Deployment Account in all regions (KMS Key and S3 Bucket + Parameter Store values) for region in list( set([config.deployment_account_region] + config.target_regions)): cloudformation = CloudFormation( region=region, deployment_account_region=config.deployment_account_region, role=deployment_account_role, wait=True, stack_name=None, s3=s3, s3_key_path=account_path, file_path=None, ) cloudformation.create_stack() update_deployment_account_output_parameters( deployment_account_region=config.deployment_account_region, region=region, deployment_account_role=deployment_account_role, cloudformation=cloudformation) threads = [] account_ids = organizations.get_account_ids() for account_id in account_ids: t = PropagatingThread(target=worker_thread, args=(account_id, sts, config, s3, cache)) t.start() threads.append(t) for thread in threads: thread.join() step_functions = StepFunctions( role=deployment_account_role, deployment_account_id=deployment_account_id, deployment_account_region=config.deployment_account_region, regions=config.target_regions, account_ids=[ i for i in account_ids if i != config.deployment_account_region ], update_pipelines_only=False) step_functions.execute_statemachine() except NotConfiguredError as not_configured_error: LOGGER.info(not_configured_error)
def main(): #pylint: disable=R0915 LOGGER.info("ADF Version %s", ADF_VERSION) LOGGER.info("ADF Log Level is %s", ADF_LOG_LEVEL) scp = SCP() config = Config() config.store_config() try: parameter_store = ParameterStore(REGION_DEFAULT, boto3) deployment_account_id = parameter_store.fetch_parameter( 'deployment_account_id' ) organizations = Organizations( role=boto3, account_id=deployment_account_id ) scp.apply(organizations, parameter_store, config.config) sts = STS() deployment_account_role = prepare_deployment_account( sts=sts, deployment_account_id=deployment_account_id, config=config ) cache = Cache() ou_id = organizations.get_parent_info().get("ou_parent_id") account_path = organizations.build_account_path( ou_id=ou_id, account_path=[], cache=cache ) s3 = S3( region=REGION_DEFAULT, bucket=S3_BUCKET_NAME ) # Updating the stack on the master account in deployment region cloudformation = CloudFormation( region=config.deployment_account_region, deployment_account_region=config.deployment_account_region, # pylint: disable=R0801 role=boto3, wait=True, stack_name=None, s3=s3, s3_key_path='adf-build', account_id=ACCOUNT_ID ) cloudformation.create_stack() # First Setup/Update the Deployment Account in all regions (KMS Key and S3 Bucket + Parameter Store values) for region in list(set([config.deployment_account_region] + config.target_regions)): cloudformation = CloudFormation( region=region, deployment_account_region=config.deployment_account_region, role=deployment_account_role, wait=True, stack_name=None, s3=s3, s3_key_path=account_path, account_id=deployment_account_id ) cloudformation.create_stack() update_deployment_account_output_parameters( deployment_account_region=config.deployment_account_region, region=region, deployment_account_role=deployment_account_role, cloudformation=cloudformation ) threads = [] account_ids = organizations.get_account_ids() for account_id in [account for account in account_ids if account != deployment_account_id]: thread = PropagatingThread(target=worker_thread, args=( account_id, sts, config, s3, cache )) thread.start() threads.append(thread) for thread in threads: thread.join() step_functions = StepFunctions( role=deployment_account_role, deployment_account_id=deployment_account_id, deployment_account_region=config.deployment_account_region, regions=config.target_regions, account_ids=account_ids, update_pipelines_only=0 ) step_functions.execute_statemachine() except ParameterNotFoundError: LOGGER.info( 'You are now ready to bootstrap a deployment account ' 'by moving it into your deployment OU. ' 'Once you have moved it into the deployment OU, ' 'be sure to check out its progress in AWS Step Functions' ) return