async def _generate_s3_inline_policy_statement_from_mapping( generator: ChangeGeneratorModel, ) -> Dict: """ Generates an S3 inline policy statement from a ChangeGeneratorModel. S3 is an edge case, thus it gets a unique function for this purpose. We need to consider the resource ARN and prefix. :param generator: ChangeGeneratorModel :return: policy_statement: A dictionary representing an inline policy statement. """ permissions_map = (self_service_iam_config.get("permissions_map", {}).get( "s3", {}).get("action_map")) if not permissions_map: raise MissingConfigurationValue( "Unable to find applicable action map configuration.") action_group_actions: List[str] = [] resource_arns = [] effect = generator.effect condition = generator.condition if isinstance(generator.resource_arn, str): generator.resource_arn = [generator.resource_arn] # Handle the bucket ARNs for arn in generator.resource_arn: if not arn.startswith("arn:aws:s3:::"): arn = f"arn:aws:s3:::{arn}" resource_arns.append(arn) # Make sure prefix starts with "/" if not generator.bucket_prefix.startswith("/"): generator.bucket_prefix = f"/{generator.bucket_prefix}" resource_arns.append(f"{arn}{generator.bucket_prefix}") for action in generator.action_groups: action_group_actions.append(action) actions = await _get_actions_from_groups(action_group_actions, permissions_map) if generator.extra_actions: actions.extend(generator.extra_actions) return await _generate_policy_statement(actions, resource_arns, effect, condition)
async def _generate_condition_with_substitutions( generator: ChangeGeneratorModel): """ Generates a condition with substitutions if they are needed. :param generator: :return: """ condition: Optional[Dict] = generator.condition if isinstance(condition, dict): condition = await iterate_and_format_dict(condition, generator.dict()) return condition
async def _generate_inline_policy_statement_from_mapping( generator: ChangeGeneratorModel, ) -> Dict: """ Generates an inline policy statement given a ChangeGeneratorModel from a action mapping stored in configuration. :param generator: ChangeGeneratorModel :return: policy_statement: A dictionary representing an inline policy statement. """ generator_type = generator.generator_type if not isinstance(generator_type, str): generator_type = generator.generator_type.value permissions_map = (self_service_iam_config.get("permissions_map", {}).get( generator_type, {}).get("action_map")) if not permissions_map: raise MissingConfigurationValue( f"Unable to find applicable action map configuration for {generator_type}." ) action_group_actions: List[str] = [] if isinstance(generator.resource_arn, str): generator.resource_arn = [generator.resource_arn] resource_arns = generator.resource_arn effect = generator.effect for action in generator.action_groups: # TODO: Seems like a datamodel bug when we don't have a enum defined for an array type, but I need to access # this as a string sometimes if isinstance(action, str): action_group_actions.append(action) else: action_group_actions.append(action) actions = await _get_actions_from_groups(action_group_actions, permissions_map) if generator.extra_actions: actions.extend(generator.extra_actions) condition: Optional[Dict] = await _generate_condition_with_substitutions( generator) return await _generate_policy_statement(actions, resource_arns, effect, condition)