Ejemplo n.º 1
0
 def __init__(self, logger):
     self.logger = logger
     self.org = Organizations(logger)
     self.s3 = S3(logger)
     self.param_handler = CFNParamsHandler(logger)
     self.manifest = Manifest(os.environ.get('MANIFEST_FILE_PATH'))
     self.manifest_folder = os.environ.get('MANIFEST_FOLDER')
Ejemplo n.º 2
0
    def start_launch_avm(self):
        try:
            self.logger.info("Starting the launch AVM trigger")

            org = Org({}, self.logger)
            organizations = Organizations(self.logger)
            delimiter = self.manifest.nested_ou_delimiter

            response = organizations.list_roots()
            self.logger.info("List roots Response")
            self.logger.info(response)
            self.root_id = response['Roots'][0].get('Id')

            for ou in self.manifest.organizational_units:
                self.avm_product_name = ou.include_in_baseline_products[0]

                # Find the AVM for this OU and get the AVM parameters
                for portfolio in self.manifest.portfolios:
                    for product in portfolio.products:
                        if product.name.strip() == self.avm_product_name.strip():
                            self.avm_params = self._load_params(product.parameter_file)
                            self.avm_portfolio_name = portfolio.name.strip()

                if len(self.avm_params) == 0:
                    raise Exception("Baseline product: {} for OU: {} is not found in the" \
                      " portfolios section of Manifest".format(self.avm_product, ou.name))

                ou_id = org._get_ou_id(organizations, self.root_id, ou.name, delimiter)

                self.logger.info("Processing Accounts under: {} in batches of size: {}".format(ou_id, self.batch_size))
                response = organizations.list_accounts_for_parent(ou_id, self.batch_size)
                self.logger.info("List Accounts for Parent OU {} Response".format(ou_id))
                self.logger.info(response)
                self._process_accounts_in_batches(response.get('Accounts'), organizations, ou_id, ou.name)
                next_token = response.get('NextToken', None)

                while next_token is not None:
                    self.logger.info("Next Token Returned: {}".format(next_token))
                    response = organizations.list_accounts_for_parent(ou_id, self.batch_size, next_token)
                    self.logger.info("List Accounts for Parent OU {} Response".format(ou_id))
                    self.logger.info(response)
                    self._process_accounts_in_batches(response.get('Accounts'), organizations, ou_id, ou.name)
                    next_token = response.get('NextToken', None)

            return
        except Exception as e:
            message = {'FILE': __file__.split('/')[-1], 'METHOD': inspect.stack()[0][3], 'EXCEPTION': str(e)}
            self.logger.exception(message)
            raise
Ejemplo n.º 3
0
    def start_core_account_sm(self, sm_arn_account):
        try:
            logger.info("Setting the lock_down_stack_sets_role={}".format(self.manifest.lock_down_stack_sets_role))

            if self.manifest.lock_down_stack_sets_role is True:
                self.ssm.put_parameter('lock_down_stack_sets_role_flag', 'yes')
            else:
                self.ssm.put_parameter('lock_down_stack_sets_role_flag', 'no')

            # Send metric - pipeline run count
            data = {"PipelineRunCount": "1"}
            self.send.metrics(data)

            logger.info("Processing Core Accounts from {} file".format(self.manifest_file_path))
            list_sm_exec_arns = []
            for ou in self.manifest.organizational_units:
                ou_name = ou.name
                logger.info("Generating the state machine input json for OU: {}".format(ou_name))

                if len(ou.core_accounts) == 0:
                    # Empty OU with no Accounts
                    sm_input = self._create_account_state_machine_input_map(ou_name)
                    self._run_or_queue_state_machine(sm_input, sm_arn_account, list_sm_exec_arns, ou_name)

                for account in ou.core_accounts:
                    account_name = account.name

                    if account_name.lower() == 'primary':
                        org = Organizations(self.logger)
                        response = org.describe_account(self.primary_account_id)
                        account_email = response.get('Account').get('Email', '')
                    else:
                        account_email = account.email

                    if not account_email:
                        raise Exception("Failed to retrieve the email address for the Account: {}".format(account_name))

                    ssm_map = self._create_ssm_input_map(account.ssm_parameters)

                    sm_input = self._create_account_state_machine_input_map(ou_name, account_name, account_email, ssm_map)
                    self._run_or_queue_state_machine(sm_input, sm_arn_account, list_sm_exec_arns, account_name)
            self._save_sm_exec_arn(list_sm_exec_arns)
            return
        except Exception as e:
            message = {'FILE': __file__.split('/')[-1], 'METHOD': inspect.stack()[0][3], 'EXCEPTION': str(e)}
            self.logger.exception(message)
            raise
 def get_organization_details(self):
     # > build dict
     # KEY: OU Name (in the manifest)
     # VALUE: OU ID (at root level)
     # > build list
     # all OU IDs under root
     org = Organizations(self.logger)
     all_ou_ids, ou_name_to_id_map = self._get_ou_ids(org)
     # > build list of all active accounts
     # use case: use to validate accounts in the manifest file.
     # > build dict
     # KEY: OU ID (for each OU at root level)
     # VALUE: get list of all active accounts
     # use case: map OU Name to account IDs
     accounts_in_all_ous, ou_id_to_account_map = self._get_accounts_in_ou(org, all_ou_ids)
     # build dict
     # KEY: email
     # VALUE: account id
     # use case: convert email in manifest to account ID for SM event
     name_to_account_map = self.get_account_for_name(org)
     return accounts_in_all_ous, ou_id_to_account_map, ou_name_to_id_map, name_to_account_map
Ejemplo n.º 5
0
    def get_state_machines_execution_status(self):
        try:
            sm_exec_arns = self.ssm.get_parameter(self.token)

            if sm_exec_arns == 'PASS':
                self.ssm.delete_parameter(self.token)
                return 'SUCCEEDED', ''
            else:
                list_sm_exec_arns = sm_exec_arns.split(
                    ","
                )  # Create a list from comma seperated string e.g. ['a','b','c']

                for sm_exec_arn in list_sm_exec_arns:
                    status = self.state_machine.check_state_machine_status(
                        sm_exec_arn)
                    if status == 'RUNNING':
                        return 'RUNNING', ''
                    elif status == 'SUCCEEDED':
                        continue
                    else:
                        self.ssm.delete_parameter(self.token)
                        self.ssm.delete_parameters_by_path(self.token)
                        err_msg = "State Machine Execution Failed, please check the Step function console for State Machine Execution ARN: {}".format(
                            sm_exec_arn)
                        return 'FAILED', err_msg

                if self.isSequential:
                    _params_list = self.ssm.get_parameters_by_path(self.token)
                    if _params_list:
                        params_list = sorted(_params_list,
                                             key=lambda i: i['Name'])
                        sm_input = json.loads(params_list[0].get('Value'))
                        if self.pipeline_stage == 'core_accounts':
                            sm_arn = self.sm_arns_map.get('account')
                            sm_name = sm_input.get('ResourceProperties').get(
                                'OUName') + "-" + sm_input.get(
                                    'ResourceProperties').get('AccountName')

                            account_name = sm_input.get(
                                'ResourceProperties').get('AccountName')
                            if account_name.lower() == 'primary':
                                org = Organizations(self.logger)
                                response = org.describe_account(
                                    self.primary_account_id)
                                account_email = response.get('Account').get(
                                    'Email', '')
                                sm_input.get('ResourceProperties').update(
                                    {'AccountEmail': account_email})

                        elif self.pipeline_stage == 'core_resources':
                            sm_arn = self.sm_arns_map.get('stack_set')
                            sm_name = sm_input.get('ResourceProperties').get(
                                'StackSetName')
                            sm_input = self._populate_ssm_params(sm_input)
                        elif self.pipeline_stage == 'service_control_policy':
                            sm_arn = self.sm_arns_map.get(
                                'service_control_policy')
                            sm_name = sm_input.get('ResourceProperties').get(
                                'PolicyDocument').get('Name')
                        elif self.pipeline_stage == 'service_catalog':
                            sm_arn = self.sm_arns_map.get('service_catalog')
                            sm_name = sm_input.get('ResourceProperties').get(
                                'SCProduct').get('ProductName')
                        elif self.pipeline_stage == 'baseline_resources':
                            sm_arn = self.sm_arns_map.get('stack_set')
                            sm_name = sm_input.get('ResourceProperties').get(
                                'StackSetName')
                            sm_input = self._populate_ssm_params(sm_input)

                        exec_name = "%s-%s-%s" % (sm_input.get(
                            'RequestType'), sm_name.replace(
                                " ", ""), time.strftime("%Y-%m-%dT%H-%M-%S"))
                        sm_exec_arn = self.state_machine.trigger_state_machine(
                            sm_arn, sm_input, exec_name)
                        self._save_sm_exec_arn([sm_exec_arn])
                        self.ssm.delete_parameter(params_list[0].get('Name'))
                        return 'RUNNING', ''

                self.ssm.delete_parameter(self.token)
                return 'SUCCEEDED', ''

        except Exception as e:
            message = {
                'FILE': __file__.split('/')[-1],
                'METHOD': inspect.stack()[0][3],
                'EXCEPTION': str(e)
            }
            self.logger.exception(message)
            raise
Ejemplo n.º 6
0
    def start_launch_avm(self, sm_arn_launch_avm):
        try:
            logger.info("Starting the launch AVM trigger")
            list_sm_exec_arns = []
            ou_id_map = {}

            org = Organizations(self.logger)
            response = org.list_roots()
            self.logger.info("List roots Response")
            self.logger.info(response)
            root_id = response['Roots'][0].get('Id')

            response = org.list_organizational_units_for_parent(
                ParentId=root_id)
            next_token = response.get('NextToken', None)

            for ou in response['OrganizationalUnits']:
                ou_id_map.update({ou.get('Name'): ou.get('Id')})

            while next_token is not None:
                response = org.list_organizational_units_for_parent(
                    ParentId=root_id, NextToken=next_token)
                next_token = response.get('NextToken', None)
                for ou in response['OrganizationalUnits']:
                    ou_id_map.update({ou.get('Name'): ou.get('Id')})

            self.logger.info("ou_id_map={}".format(ou_id_map))

            for portfolio in self.manifest.portfolios:
                for product in portfolio.products:
                    if product.product_type.lower() == 'baseline':
                        _params = self._load_params(product.parameter_file)
                        logger.info(
                            "Input parameters format for AVM: {}".format(
                                _params))
                        list_of_accounts = []
                        for ou in product.apply_baseline_to_accounts_in_ou:
                            self.logger.debug(
                                "Looking up ou={} in ou_id_map".format(ou))
                            ou_id = ou_id_map.get(ou)
                            self.logger.debug(
                                "ou_id={} for ou={} in ou_id_map".format(
                                    ou_id, ou))

                            response = org.list_accounts_for_parent(ou_id)
                            self.logger.debug(
                                "List Accounts for Parent Response")
                            self.logger.debug(response)
                            for account in response.get('Accounts'):
                                params = _params.copy()
                                for key, value in params.items():
                                    if value.lower() == 'accountemail':
                                        params.update(
                                            {key: account.get('Email')})
                                    elif value.lower() == 'accountname':
                                        params.update(
                                            {key: account.get('Name')})
                                    elif value.lower() == 'orgunitname':
                                        params.update({key: ou})

                                logger.info(
                                    "Input parameters format for Account: {} are {}"
                                    .format(account.get('Name'), params))

                                list_of_accounts.append(params)

                        if len(list_of_accounts) > 0:
                            sm_input = self._create_launch_avm_state_machine_input_map(
                                portfolio.name, product.name, list_of_accounts)
                            logger.info(
                                "Launch AVM state machine Input: {}".format(
                                    sm_input))
                            exec_name = "%s-%s-%s" % (
                                sm_input.get('RequestType'), "Launch-AVM",
                                time.strftime("%Y-%m-%dT%H-%M-%S"))
                            sm_exec_arn = self.state_machine.trigger_state_machine(
                                sm_arn_launch_avm, sm_input, exec_name)
                            list_sm_exec_arns.append(sm_exec_arn)

                    time.sleep(int(wait_time))  # Sleeping for sometime
            self._save_sm_exec_arn(list_sm_exec_arns)
            return
        except Exception as e:
            message = {
                'FILE': __file__.split('/')[-1],
                'METHOD': inspect.stack()[0][3],
                'EXCEPTION': str(e)
            }
            self.logger.exception(message)
            raise
Ejemplo n.º 7
0
    def start_launch_avm(self):
        """
        Get a list of accounts
        Find the portfolio id and product id for the AVM product
        Call _process_accounts_in_batches to build and submit input data for
        each batch to a state machine instance
        """
        try:
            self.logger.info("Starting the launch AVM trigger")

            org = Org({}, self.logger)
            organizations = Organizations(self.logger)
            delimiter = ':'
            if self.manifest.nested_ou_delimiter:
                delimiter = self.manifest.nested_ou_delimiter

            response = organizations.list_roots()
            self.logger.debug("List roots Response")
            self.logger.debug(response)
            self.root_id = response['Roots'][0].get('Id')

            for ou in self.manifest.organizational_units:
                self.avm_product_name = ou.include_in_baseline_products[0]

                # Find the AVM for this OU and get the AVM parameters
                for portfolio in self.manifest.portfolios:
                    for product in portfolio.products:
                        if product.name.strip() == self.avm_product_name.strip(
                        ):
                            self.avm_params = self._load_params(
                                product.parameter_file)
                            self.avm_portfolio_name = portfolio.name.strip()
                            self.avm_product_id = self.sc_products.get(
                                portfolio.name.strip()).get(
                                    product.name.strip())
                """
                Get provisioned product data for all accounts
                Note: this reduces the number of API calls, but produces a large
                in-memory dictionary. However, even at 1,000 accounts this should
                not be a concern
                Populates:
                self.provisioned_products = {}              # [productid] = []
                self.provisioned_products_by_account = {}   # [account] = [] list of ppids
                self.stacks = {}                            # [stackname] = stackinfo
                """
                self.get_indexed_provisioned_products()

                if not self.avm_params:
                    raise Exception("Baseline product: {} for OU: {} is not found in the" \
                      " portfolios section of Manifest".format(self.avm_product_name, ou.name))

                ou_id = org._get_ou_id(organizations, self.root_id, ou.name,
                                       delimiter)

                self.logger.info(
                    "Processing Accounts under: {} in batches of size: {}".
                    format(ou_id, self.batch_size))
                response = organizations.list_accounts_for_parent(
                    ou_id, self.batch_size)
                self.logger.info(
                    "List Accounts for Parent OU {} Response".format(ou_id))
                self.logger.info(response)
                self._process_accounts_in_batches(response.get('Accounts'),
                                                  organizations, ou_id,
                                                  ou.name)
                next_token = response.get('NextToken', None)

                while next_token is not None:
                    self.logger.info(
                        "Next Token Returned: {}".format(next_token))
                    response = organizations.list_accounts_for_parent(
                        ou_id, self.batch_size, next_token)
                    self.logger.info(
                        "List Accounts for Parent OU {} Response".format(
                            ou_id))
                    self.logger.info(response)
                    self._process_accounts_in_batches(response.get('Accounts'),
                                                      organizations, ou_id,
                                                      ou.name)
                    next_token = response.get('NextToken', None)

            return
        except Exception as e:
            message = {
                'FILE': __file__.split('/')[-1],
                'METHOD': inspect.stack()[0][3],
                'EXCEPTION': str(e)
            }
            self.logger.exception(message)
            raise
Ejemplo n.º 8
0
    def start_launch_avm(self, sm_arn_launch_avm):
        try:
            self.logger.info("Starting the launch AVM trigger")

            org = Org({}, self.logger)
            organizations = Organizations(self.logger)
            delimiter = self.manifest.nested_ou_delimiter

            response = organizations.list_roots()
            self.logger.info("List roots Response")
            self.logger.info(response)
            root_id = response['Roots'][0].get('Id')

            for ou in self.manifest.organizational_units:
                list_of_accounts = []
                _params = []
                avm_product = ou.include_in_baseline_products[0]

                # Find the AVM for this OU and get the product parameters
                for portfolio in self.manifest.portfolios:
                    for product in portfolio.products:
                        if product.name.strip() == avm_product.strip():
                            _params = self._load_params(product.parameter_file)
                            portfolio_name = portfolio.name.strip()

                if len(_params) == 0:
                    raise Exception("Baseline product: {} for OU: {} is not found in the" \
                      " portfolios section of Manifest".format(avm_product, ou.name))

                ou_id = org._get_ou_id(organizations, root_id, ou.name,
                                       delimiter)
                response = organizations.list_accounts_for_parent(ou_id)
                self.logger.info(
                    "List Accounts for Parent OU {} Response".format(ou_id))
                self.logger.info(response)
                for account in response.get('Accounts'):
                    if account.get('Status').upper() == 'SUSPENDED':
                        organizations.move_account(account.get('Id'), ou_id,
                                                   root_id)
                        continue
                    else:
                        params = _params.copy()
                        for key, value in params.items():
                            if value.lower() == 'accountemail':
                                params.update({key: account.get('Email')})
                            elif value.lower() == 'accountname':
                                params.update({key: account.get('Name')})
                            elif value.lower() == 'orgunitname':
                                params.update({key: ou.name})

                        self.logger.info(
                            "Input parameters format for Account: {} are {}".
                            format(account.get('Name'), params))

                        list_of_accounts.append(params)

                if len(list_of_accounts) > 0:
                    sm_input = self._create_launch_avm_state_machine_input_map(
                        portfolio_name, avm_product.strip(), list_of_accounts)
                    self.logger.info(
                        "Launch AVM state machine Input: {}".format(sm_input))
                    exec_name = "%s-%s-%s" % (
                        sm_input.get('RequestType'), "Launch-AVM",
                        time.strftime("%Y-%m-%dT%H-%M-%S"))
                    sm_exec_arn = self.state_machine.trigger_state_machine(
                        sm_arn_launch_avm, sm_input, exec_name)
                    self.list_sm_exec_arns.append(sm_exec_arn)

                    time.sleep(int(wait_time))  # Sleeping for sometime
            return
        except Exception as e:
            message = {
                'FILE': __file__.split('/')[-1],
                'METHOD': inspect.stack()[0][3],
                'EXCEPTION': str(e)
            }
            self.logger.exception(message)
            raise
Ejemplo n.º 9
0
class BaselineResourceParser:
    def __init__(self, logger):
        self.logger = logger
        self.org = Organizations(logger)
        self.s3 = S3(logger)
        self.param_handler = CFNParamsHandler(logger)
        self.manifest = Manifest(os.environ.get('MANIFEST_FILE_PATH'))
        self.manifest_folder = os.environ.get('MANIFEST_FOLDER')

    def parse_baseline_resource_manifest(self):

        self.logger.info("Parsing Core Resources from {} file".format(
            os.environ.get('MANIFEST_FILE_PATH')))

        state_machine_inputs = []

        avm_to_account_ids_map = self.get_avm_to_accounts_map()

        for resource in self.manifest.baseline_resources:
            self.logger.info(">>>> START : {} >>>>".format(resource.name))
            avm_list = resource.baseline_products
            account_list = get_reduced_merged_list(avm_to_account_ids_map,
                                                   avm_list)

            if resource.deploy_method.lower() == 'stack_set':
                sm_input = self._get_state_machine_input(
                    resource, account_list)
                state_machine_inputs.append(sm_input)
            else:
                raise Exception(
                    "Unsupported deploy_method: {} found for "
                    "resource {} and Account: {} in Manifest".format(
                        resource.deploy_method, resource.name, account_list))
            self.logger.info("<<<< FINISH : {} <<<<".format(resource.name))

        # Exit if there are no CloudFormation resources
        if len(state_machine_inputs) == 0:
            self.logger.info("CloudFormation resources not found in the "
                             "manifest")
            sys.exit(0)
        else:
            return state_machine_inputs

    def get_avm_to_accounts_map(self):
        # get root ID
        root_id = self._get_root_id()
        ou_id_list = []
        ou_name_to_id_map = {}
        ou_id_to_avm_name_map = {}
        # get OUs from the manifest
        for org_unit in self.manifest.organizational_units:
            self.logger.info("Processing OU Name: {}".format(org_unit.name))
            self.logger.info(org_unit.include_in_baseline_products)
            ou_id = self.get_ou_id(root_id, org_unit.name,
                                   self.manifest.nested_ou_delimiter)
            ou_id_list.append(ou_id)
            ou_name_to_id_map.update({org_unit.name: ou_id})
            ou_id_to_avm_name_map.update(
                {ou_id: org_unit.include_in_baseline_products[0]})
        accounts_in_all_ous, ou_id_to_account_map = self._get_accounts_in_ou(
            ou_id_list)

        self.logger.info(
            "Printing list of OU Ids in the Manifest: {}".format(ou_id_list))
        self.logger.info(ou_name_to_id_map)
        self.logger.info(
            "Printing all accounts in OUs managed by ALZ: {}".format(
                accounts_in_all_ous))
        self.logger.info("Printing OU Id to Accounts Map")
        self.logger.info(ou_id_to_account_map)
        self.logger.info("Printing OU Id to AVM Product Map")
        self.logger.info(ou_id_to_avm_name_map)
        avm_to_ou_ids_map = flip_dict_properties(ou_id_to_avm_name_map)
        avm_to_accounts_map = join_dict_per_key_value_relation(
            avm_to_ou_ids_map, ou_id_to_account_map)
        self.logger.info("Printing AVM Product to Accounts Map")
        self.logger.info(avm_to_accounts_map)
        return avm_to_accounts_map

    def get_ou_id(self, parent_id, nested_ou_name, delimiter):
        self.logger.info(
            "Looking up the OU Id for OUName: '{}' with nested ou delimiter: '{}'"
            .format(nested_ou_name, delimiter))
        nested_ou_name_list = self._empty_separator_handler(
            delimiter, nested_ou_name)
        response = self._list_ou_for_parent(
            parent_id, list_sanitizer(nested_ou_name_list))
        self.logger.info(response)
        return response

    @staticmethod
    def _empty_separator_handler(delimiter, nested_ou_name):
        if delimiter == "":
            nested_ou_name_list = [nested_ou_name]
        else:
            nested_ou_name_list = nested_ou_name.split(delimiter)
        return nested_ou_name_list

    def get_accounts_in_ou(self, ou_id_to_account_map, ou_name_to_id_map,
                           resource):
        accounts_in_ou = []
        ou_ids_manifest = []
        # convert OU Name to OU IDs
        for ou_name in resource.deploy_to_ou:
            ou_id = [
                value for key, value in ou_name_to_id_map.items()
                if ou_name in key
            ]
            ou_ids_manifest.extend(ou_id)
        # convert OU IDs to accounts
        for ou_id, accounts in ou_id_to_account_map.items():
            if ou_id in ou_ids_manifest:
                accounts_in_ou.extend(accounts)
        self.logger.info(">>> Accounts: {} in OUs: {}".format(
            accounts_in_ou, resource.deploy_to_ou))
        return accounts_in_ou

    def _get_root_id(self):
        response = self.org.list_roots()
        self.logger.info("Response: List Roots")
        self.logger.info(response)
        return response['Roots'][0].get('Id')

    def _list_ou_for_parent(self, parent_id, nested_ou_name_list):
        ou_list = self.org.list_organizational_units_for_parent(parent_id)
        index = 0  # always process the first item
        self.logger.info(
            "Looking for existing OU: '{}' under parent id: '{}'".format(
                nested_ou_name_list[index], parent_id))
        for dictionary in ou_list:
            if dictionary.get('Name') == nested_ou_name_list[index]:
                self.logger.info(
                    "OU Name: '{}' exists under parent id: '{}'".format(
                        dictionary.get('Name'), parent_id))
                nested_ou_name_list.pop(
                    index)  # pop the first item in the list
                if len(nested_ou_name_list) == 0:
                    self.logger.info("Returning last level OU ID: {}".format(
                        dictionary.get('Id')))
                    return dictionary.get('Id')
                else:
                    return self._list_ou_for_parent(dictionary.get('Id'),
                                                    nested_ou_name_list)

    def _get_accounts_in_ou(self, ou_id_list):
        _accounts_in_ou = []
        accounts_in_all_ous = []
        ou_id_to_account_map = {}

        for _ou_id in ou_id_list:
            self.logger.info("Getting accounts under OU ID: {}".format(_ou_id))
            _account_list = self.org.list_all_accounts_for_parent(_ou_id)
            self.logger.info(_account_list)
            for _account in _account_list:
                self.logger.info(_account)
                # filter ACTIVE and CREATED accounts
                if _account.get('Status') == "ACTIVE":
                    # create a list of accounts in OU
                    accounts_in_all_ous.append(_account.get('Id'))
                    _accounts_in_ou.append(_account.get('Id'))

            # create a map of accounts for each ou
            self.logger.info("Creating Key:Value Mapping - "
                             "OU ID: {} ; Account List: {}".format(
                                 _ou_id, _accounts_in_ou))
            ou_id_to_account_map.update({_ou_id: _accounts_in_ou})
            self.logger.info(ou_id_to_account_map)

            # reset list of accounts in the OU
            _accounts_in_ou = []

        self.logger.info(
            "All accounts in OU List: {}".format(accounts_in_all_ous))
        self.logger.info("OU to Account ID mapping")
        self.logger.info(ou_id_to_account_map)
        return accounts_in_all_ous, ou_id_to_account_map

    # return list of strings
    @staticmethod
    def _convert_list_values_to_string(_list):
        return list(map(str, _list))

    def _get_state_machine_input(self, resource, account_list) -> dict:
        local_file = StageFile(self.logger, resource.template_file)
        template_url = local_file.get_staged_file()

        parameters = {}

        # set region variables
        if len(resource.regions) > 0:
            region = resource.regions[0]
            region_list = resource.regions
        else:
            region = self.manifest.region
            region_list = [region]

        # if parameter file link is provided for the CFN resource
        if resource.parameter_file:
            parameters = self._load_params(resource.parameter_file,
                                           account_list, region)

        ssm_parameters = self._create_ssm_input_map(resource.ssm_parameters)

        accounts = "" if resource.parameter_override == 'true' or account_list == [] else account_list
        regions = "" if resource.parameter_override == 'true' or account_list == [] else region_list

        # generate state machine input list
        stack_set_name = "AWS-Landing-Zone-Baseline-{}".format(resource.name)
        resource_properties = StackSetResourceProperties(
            stack_set_name, template_url, parameters,
            os.environ.get('CAPABILITIES'), accounts, regions, ssm_parameters)
        ss_input = InputBuilder(resource_properties.get_stack_set_input_map())
        return ss_input.input_map()

    def _load_params(self, relative_parameter_path, account=None, region=None):
        if relative_parameter_path.lower().startswith('s3'):
            parameter_file = self.s3.get_s3_object(relative_parameter_path)
        else:
            parameter_file = os.path.join(self.manifest_folder,
                                          relative_parameter_path)

        self.logger.info(
            "Parsing the parameter file: {}".format(parameter_file))

        with open(parameter_file, 'r') as content_file:
            parameter_file_content = content_file.read()

        params = json.loads(parameter_file_content)

        sm_params = self.param_handler.update_params(params, account, region,
                                                     False)

        self.logger.info(
            "Input Parameters for State Machine: {}".format(sm_params))
        return sm_params

    def _create_ssm_input_map(self, ssm_parameters):
        ssm_input_map = {}

        for ssm_parameter in ssm_parameters:
            key = ssm_parameter.name
            value = ssm_parameter.value
            ssm_value = self.param_handler.update_params(
                transform_params({key: value}))
            ssm_input_map.update(ssm_value)
        return ssm_input_map