def _get_type_from_intrinsic_if(self, policy):
        """
        Returns the type of the given policy assuming that it is an intrinsic if function

        :param policy: Input value to get type from
        :return: PolicyTypes: Type of the given policy. PolicyTypes.UNKNOWN, if type could not be inferred
        """
        intrinsic_if_value = policy["Fn::If"]

        try:
            validate_intrinsic_if_items(intrinsic_if_value)
        except ValueError as e:
            raise InvalidTemplateException(e)

        if_data = intrinsic_if_value[1]
        else_data = intrinsic_if_value[2]

        if_data_type = self._get_type(if_data)
        else_data_type = self._get_type(else_data)

        if if_data_type == else_data_type:
            return if_data_type

        if is_intrinsic_no_value(if_data):
            return else_data_type

        if is_intrinsic_no_value(else_data):
            return if_data_type

        raise InvalidTemplateException(
            "Different policy types within the same Fn::If statement is unsupported. "
            "Separate different policy types into different Fn::If statements")
Exemple #2
0
    def test_is_intrinsic_no_value_must_return_false_for_other_value(self):
        bad_key = {"sRefs": "AWS::NoValue"}
        bad_value = {"Ref": "SWA::NoValue"}
        too_many_keys = {"Ref": "AWS::NoValue", "feR": "SWA::NoValue"}

        self.assertFalse(is_intrinsic_no_value(bad_key))
        self.assertFalse(is_intrinsic_no_value(bad_value))
        self.assertFalse(is_intrinsic_no_value(None))
        self.assertFalse(is_intrinsic_no_value(too_many_keys))
Exemple #3
0
    def _build_alarm_configuration(self, alarms):
        """
        Builds an AlarmConfiguration from a list of alarms

        Parameters
        ----------
        alarms : list[str]
            Alarms

        Returns
        -------
        dict
            AlarmsConfiguration for a deployment group

        Raises
        ------
        ValueError
            If alarms is not a list
        """
        if not isinstance(alarms, list):
            raise ValueError("Alarms must be a list")

        if len(alarms) == 0 or is_intrinsic_no_value(alarms[0]):
            return {}

        return {
            "Enabled": True,
            "Alarms": [{
                "Name": alarm
            } for alarm in alarms],
        }
Exemple #4
0
    def _convert_alarms(self, preference_alarms):
        """
        Converts deployment preference alarms to an AlarmsConfiguration

        Parameters
        ----------
        preference_alarms : dict
            Deployment preference alarms

        Returns
        -------
        dict
            AlarmsConfiguration if alarms is set, None otherwise

        Raises
        ------
        ValueError
            If Alarms is in the wrong format
        """
        if not preference_alarms or is_intrinsic_no_value(preference_alarms):
            return None

        if is_intrinsic_if(preference_alarms):
            processed_alarms = copy.deepcopy(preference_alarms)
            alarms_list = processed_alarms.get("Fn::If")
            validate_intrinsic_if_items(alarms_list)
            alarms_list[1] = self._build_alarm_configuration(alarms_list[1])
            alarms_list[2] = self._build_alarm_configuration(alarms_list[2])
            return processed_alarms

        return self._build_alarm_configuration(preference_alarms)
    def _set_default_authorizer(self, open_api_editor, authorizers,
                                default_authorizer, api_authorizers):
        """
        Sets the default authorizer if one is given in the template
        :param open_api_editor: editor object that contains the OpenApi definition
        :param authorizers: authorizer definitions converted from the API auth section
        :param default_authorizer: name of the default authorizer
        :param api_authorizers: API auth section authorizer defintions
        """
        if not default_authorizer:
            return

        if is_intrinsic_no_value(default_authorizer):
            return

        if is_intrinsic(default_authorizer):
            raise InvalidResourceException(
                self.logical_id,
                "Unable to set DefaultAuthorizer because intrinsic functions are not supported for this field.",
            )

        if not authorizers.get(default_authorizer):
            raise InvalidResourceException(
                self.logical_id,
                "Unable to set DefaultAuthorizer because '" +
                default_authorizer + "' was not defined in 'Authorizers'.",
            )

        for path in open_api_editor.iter_on_path():
            open_api_editor.set_path_default_authorizer(
                path,
                default_authorizer,
                authorizers=authorizers,
                api_authorizers=api_authorizers)
    def _process_intrinsic_if_policy_template(self, logical_id, policy_entry):
        intrinsic_if = policy_entry.data
        then_statement = intrinsic_if["Fn::If"][1]
        else_statement = intrinsic_if["Fn::If"][2]

        processed_then_statement = then_statement \
            if is_intrinsic_no_value(then_statement) \
            else self._process_policy_template(logical_id, then_statement)

        processed_else_statement = else_statement \
            if is_intrinsic_no_value(else_statement) \
            else self._process_policy_template(logical_id, else_statement)

        processed_intrinsic_if = {
            "Fn::If": [
                policy_entry.data["Fn::If"][0], processed_then_statement,
                processed_else_statement
            ]
        }

        return processed_intrinsic_if
Exemple #7
0
    def test_is_intrinsic_no_value_must_return_true_for_no_value(self):
        policy = {"Ref": "AWS::NoValue"}

        self.assertTrue(is_intrinsic_no_value(policy))
    def _construct_role(self, managed_policy_map):
        """Constructs a Lambda execution role based on this SAM function's Policies property.

        :returns: the generated IAM Role
        :rtype: model.iam.IAMRole
        """
        execution_role = IAMRole(self.logical_id + 'Role', attributes=self.get_passthrough_resource_attributes())
        execution_role.AssumeRolePolicyDocument = IAMRolePolicies.lambda_assume_role_policy()

        managed_policy_arns = [ArnGenerator.generate_aws_managed_policy_arn('service-role/AWSLambdaBasicExecutionRole')]
        if self.Tracing:
            managed_policy_arns.append(ArnGenerator.generate_aws_managed_policy_arn('AWSXrayWriteOnlyAccess'))
        if self.VpcConfig:
            managed_policy_arns.append(
                ArnGenerator.generate_aws_managed_policy_arn('service-role/AWSLambdaVPCAccessExecutionRoles')
            )

        function_policies = FunctionPolicies({"Policies": self.Policies},
                                             # No support for policy templates in the "core"
                                             policy_template_processor=None)
        policy_documents = []

        if self.DeadLetterQueue:
            policy_documents.append(IAMRolePolicies.dead_letter_queue_policy(
                self.dead_letter_queue_policy_actions[self.DeadLetterQueue['Type']],
                self.DeadLetterQueue['TargetArn']))

        for index, policy_entry in enumerate(function_policies.get()):

            if policy_entry.type is PolicyTypes.POLICY_STATEMENT:

                if is_intrinsic_if(policy_entry.data):

                    intrinsic_if = policy_entry.data
                    then_statement = intrinsic_if["Fn::If"][1]
                    else_statement = intrinsic_if["Fn::If"][2]

                    if not is_intrinsic_no_value(then_statement):
                        then_statement = {
                            'PolicyName': execution_role.logical_id + 'Policy' + str(index),
                            'PolicyDocument': then_statement
                        }
                        intrinsic_if["Fn::If"][1] = then_statement

                    if not is_intrinsic_no_value(else_statement):
                        else_statement = {
                            'PolicyName': execution_role.logical_id + 'Policy' + str(index),
                            'PolicyDocument': else_statement
                        }
                        intrinsic_if["Fn::If"][2] = else_statement

                    policy_documents.append(intrinsic_if)

                else:
                    policy_documents.append({
                        'PolicyName': execution_role.logical_id + 'Policy' + str(index),
                        'PolicyDocument': policy_entry.data
                    })

            elif policy_entry.type is PolicyTypes.MANAGED_POLICY:

                # There are three options:
                #   Managed Policy Name (string): Try to convert to Managed Policy ARN
                #   Managed Policy Arn (string): Insert it directly into the list
                #   Intrinsic Function (dict): Insert it directly into the list
                #
                # When you insert into managed_policy_arns list, de-dupe to prevent same ARN from showing up twice
                #

                policy_arn = policy_entry.data
                if isinstance(policy_entry.data, string_types) and policy_entry.data in managed_policy_map:
                    policy_arn = managed_policy_map[policy_entry.data]

                # De-Duplicate managed policy arns before inserting. Mainly useful
                # when customer specifies a managed policy which is already inserted
                # by SAM, such as AWSLambdaBasicExecutionRole
                if policy_arn not in managed_policy_arns:
                    managed_policy_arns.append(policy_arn)
            else:
                # Policy Templates are not supported here in the "core"
                raise InvalidResourceException(
                    self.logical_id,
                    "Policy at index {} in the 'Policies' property is not valid".format(index))

        execution_role.ManagedPolicyArns = list(managed_policy_arns)
        execution_role.Policies = policy_documents or None
        execution_role.PermissionsBoundary = self.PermissionsBoundary

        return execution_role
Exemple #9
0
def construct_role_for_resource(
    resource_logical_id,
    attributes,
    managed_policy_map,
    assume_role_policy_document,
    resource_policies,
    managed_policy_arns=None,
    policy_documents=None,
    permissions_boundary=None,
    tags=None,
):
    """
    Constructs an execution role for a resource.
    :param resource_logical_id: The logical_id of the SAM resource that the role will be associated with
    :param attributes: Map of resource attributes to their values
    :param managed_policy_map: Map of managed policy names to the ARNs
    :param assume_role_policy_document: The trust policy that must be associated with the role
    :param resource_policies: ResourcePolicies object encapuslating the policies property of SAM resource
    :param managed_policy_arns: List of managed policy ARNs to be associated with the role
    :param policy_documents: List of policy documents to be associated with the role
    :param permissions_boundary: The ARN of the policy used to set the permissions boundary for the role
    :param tags: Tags to be associated with the role

    :returns: the generated IAM Role
    :rtype: model.iam.IAMRole
    """
    role_logical_id = resource_logical_id + "Role"
    execution_role = IAMRole(logical_id=role_logical_id, attributes=attributes)
    execution_role.AssumeRolePolicyDocument = assume_role_policy_document

    if not managed_policy_arns:
        managed_policy_arns = []

    if not policy_documents:
        policy_documents = []

    for index, policy_entry in enumerate(resource_policies.get()):
        if policy_entry.type is PolicyTypes.POLICY_STATEMENT:

            if is_intrinsic_if(policy_entry.data):

                intrinsic_if = policy_entry.data
                then_statement = intrinsic_if["Fn::If"][1]
                else_statement = intrinsic_if["Fn::If"][2]

                if not is_intrinsic_no_value(then_statement):
                    then_statement = {
                        "PolicyName":
                        execution_role.logical_id + "Policy" + str(index),
                        "PolicyDocument":
                        then_statement,
                    }
                    intrinsic_if["Fn::If"][1] = then_statement

                if not is_intrinsic_no_value(else_statement):
                    else_statement = {
                        "PolicyName":
                        execution_role.logical_id + "Policy" + str(index),
                        "PolicyDocument":
                        else_statement,
                    }
                    intrinsic_if["Fn::If"][2] = else_statement

                policy_documents.append(intrinsic_if)

            else:
                policy_documents.append({
                    "PolicyName":
                    execution_role.logical_id + "Policy" + str(index),
                    "PolicyDocument":
                    policy_entry.data,
                })

        elif policy_entry.type is PolicyTypes.MANAGED_POLICY:

            # There are three options:
            #   Managed Policy Name (string): Try to convert to Managed Policy ARN
            #   Managed Policy Arn (string): Insert it directly into the list
            #   Intrinsic Function (dict): Insert it directly into the list
            #
            # When you insert into managed_policy_arns list, de-dupe to prevent same ARN from showing up twice
            #

            policy_arn = policy_entry.data
            if isinstance(
                    policy_entry.data,
                    string_types) and policy_entry.data in managed_policy_map:
                policy_arn = managed_policy_map[policy_entry.data]

            # De-Duplicate managed policy arns before inserting. Mainly useful
            # when customer specifies a managed policy which is already inserted
            # by SAM, such as AWSLambdaBasicExecutionRole
            if policy_arn not in managed_policy_arns:
                managed_policy_arns.append(policy_arn)
        else:
            # Policy Templates are not supported here in the "core"
            raise InvalidResourceException(
                resource_logical_id,
                "Policy at index {} in the '{}' property is not valid".format(
                    index, resource_policies.POLICIES_PROPERTY_NAME),
            )

    execution_role.ManagedPolicyArns = list(managed_policy_arns)
    execution_role.Policies = policy_documents or None
    execution_role.PermissionsBoundary = permissions_boundary
    execution_role.Tags = tags

    return execution_role