Esempio n. 1
0
def apply_patches():
    # Add missing managed polices
    aws_managed_policies.extend([
        AWSManagedPolicy.from_data(k, v)
        for k, v in ADDITIONAL_MANAGED_POLICIES.items()
    ])

    def iam_response_create_user(self):
        user = moto_iam_backend.create_user(
            self._get_param('UserName'), self._get_param('Path'),
            self._get_multi_param('Tags.member'))

        template = self.response_template(USER_RESPONSE_TEMPLATE)
        return template.render(action='Create',
                               user=user,
                               request_id=str(uuid.uuid4()))

    IamResponse.create_user = iam_response_create_user

    def iam_response_get_user(self):
        user_name = self._get_param('UserName')
        if not user_name:
            access_key_id = self.get_current_user()
            user = moto_iam_backend.get_user_from_access_key_id(access_key_id)
            if user is None:
                user = User('default_user')
        else:
            user = moto_iam_backend.get_user(user_name)

        template = self.response_template(USER_RESPONSE_TEMPLATE)
        return template.render(action='Get',
                               user=user,
                               request_id=str(uuid.uuid4()))

    IamResponse.get_user = iam_response_get_user

    def iam_response_delete_policy(self):
        policy_arn = self._get_param('PolicyArn')
        moto_iam_backend.managed_policies.pop(policy_arn, None)
        template = self.response_template(GENERIC_EMPTY_TEMPLATE)
        return template.render(name='DeletePolicyResponse')

    if not hasattr(IamResponse, 'delete_policy'):
        IamResponse.delete_policy = iam_response_delete_policy

    def iam_backend_detach_role_policy(policy_arn, role_name):
        try:
            role = moto_iam_backend.get_role(role_name)
            policy = role.managed_policies[policy_arn]
            policy.detach_from(role)
        except KeyError:
            raise IAMNotFoundException(
                'Policy {0} was not found.'.format(policy_arn))

    moto_iam_backend.detach_role_policy = iam_backend_detach_role_policy
Esempio n. 2
0
def apply_patches():
    # Add missing managed polices
    aws_managed_policies.extend([
        AWSManagedPolicy.from_data(k, v)
        for k, v in ADDITIONAL_MANAGED_POLICIES.items()
    ])

    if "Principal" not in VALID_STATEMENT_ELEMENTS:
        VALID_STATEMENT_ELEMENTS.append("Principal")

    @patch(IAMPolicyDocumentValidator._validate_resource_syntax,
           pass_target=False)
    def _validate_resource_syntax(statement, *args, **kwargs):
        # Note: Serverless generates policies without "Resource" section (only "Effect"/"Principal"/"Action"),
        # which causes several policy validators in moto to fail
        if statement.get("Resource") in [None, [None]]:
            statement["Resource"] = ["*"]

    # patch get_user to include tags

    @patch(IamResponse.get_user)
    def iam_response_get_user(fn, self):
        result = fn(self)
        regex = r"(.*<UserName>\s*)([^\s]+)(\s*</UserName>.*)"
        regex2 = r"(.*<UserId>\s*)([^\s]+)(\s*</UserId>.*)"
        flags = re.MULTILINE | re.DOTALL

        user_name = re.match(regex, result, flags=flags).group(2)
        # replace default user id/name in response
        if config.TEST_IAM_USER_NAME:
            result = re.sub(regex, r"\g<1>%s\3" % config.TEST_IAM_USER_NAME,
                            result)
            user_name = config.TEST_IAM_USER_NAME
        if config.TEST_IAM_USER_ID:
            result = re.sub(regex2, r"\g<1>%s\3" % config.TEST_IAM_USER_ID,
                            result)

        user = moto_iam_backend.users.get(user_name)
        if not user:
            return result
        tags = moto_iam_backend.tagger.list_tags_for_resource(user.arn)
        if tags and "<Tags>" not in result:
            tags_str = "".join([
                "<member><Key>%s</Key><Value>%s</Value></member>" %
                (t["Key"], t["Value"]) for t in tags["Tags"]
            ])
            result = result.replace("</Arn>",
                                    "</Arn><Tags>%s</Tags>" % tags_str)
        return result

    # patch delete_policy

    @patch(IamResponse.delete_policy, pass_target=False)
    def iam_response_delete_policy(self):
        policy_arn = self._get_param("PolicyArn")
        if moto_iam_backend.managed_policies.get(policy_arn):
            moto_iam_backend.managed_policies.pop(policy_arn, None)
            template = self.response_template(GENERIC_EMPTY_TEMPLATE)
            return template.render(name="DeletePolicy")
        else:
            raise IAMNotFoundException(
                "Policy {0} was not found.".format(policy_arn))

    # patch detach_role_policy

    @patch(moto_iam_backend.detach_role_policy, pass_target=False)
    def iam_backend_detach_role_policy(self, policy_arn, role_name):
        try:
            role = moto_iam_backend.get_role(role_name)
            policy = role.managed_policies[policy_arn]
            policy.detach_from(role)
        except KeyError:
            raise IAMNotFoundException(
                "Policy {0} was not found.".format(policy_arn))

    # patch/implement simulate_principal_policy

    def iam_response_simulate_principal_policy(self):
        def build_evaluation(action_name, resource_name, policy_statements):
            for statement in policy_statements:
                # TODO Implement evaluation logic here
                if (action_name in statement["Action"]
                        and resource_name in statement["Resource"]
                        and statement["Effect"] == "Allow"):

                    return {
                        "actionName": action_name,
                        "resourceName": resource_name,
                        "decision": "allowed",
                        "matchedStatements": [],
                    }

            return {
                "actionName": action_name,
                "resourceName": resource_name,
                "decision": "explicitDeny",
            }

        policy = moto_iam_backend.get_policy(
            self._get_param("PolicySourceArn"))
        policy_statements = json.loads(policy.document)["Statement"]
        actions = self._get_multi_param("ActionNames.member")
        resource_arns = self._get_multi_param("ResourceArns.member")
        evaluations = []
        for action in actions:
            for resource_arn in resource_arns:
                evaluations.append(
                    build_evaluation(action, resource_arn, policy_statements))

        template = self.response_template(SIMULATE_PRINCIPAL_POLICY_RESPONSE)
        return template.render(evaluations=evaluations)

    if not hasattr(IamResponse, "simulate_principal_policy"):
        IamResponse.simulate_principal_policy = iam_response_simulate_principal_policy

    # patch policy __init__ to set document as attribute

    @patch(Policy.__init__)
    def policy__init__(fn,
                       self,
                       name,
                       default_version_id=None,
                       description=None,
                       document=None,
                       **kwargs):
        fn(self, name, default_version_id, description, document, **kwargs)
        self.document = document

    # patch list_roles

    @patch(IamResponse.list_roles, pass_target=False)
    def iam_response_list_roles(self):
        roles = moto_iam_backend.get_roles()
        items = []
        for role in roles:
            item = deepcopy(role)
            item.assume_role_policy_document = quote(
                json.dumps(item.assume_role_policy_document or {}))
            items.append(item)

        prefix = self._get_param("PathPrefix")
        if prefix:
            filtered_roles = []
            for role in roles:
                if role.path.startswith(prefix):
                    filtered_roles.append(role)
            items = filtered_roles

        template = self.response_template(LIST_ROLES_TEMPLATE)
        return template.render(roles=items)

    # patch unapply_policy

    @patch(InlinePolicy.unapply_policy)
    def inline_policy_unapply_policy(fn, self, backend):
        try:
            fn(self, backend)
        except Exception:
            # Actually role can be deleted before policy being deleted in cloudformation
            pass

    # support update_group

    def update_group(self):
        group_name = self._get_param("GroupName")
        new_path = self._get_param("NewPath")
        new_group_name = self._get_param("NewGroupName") or group_name
        group = moto_iam_backend.get_group(group_name)
        group.path = new_path
        group.name = new_group_name
        moto_iam_backend.groups[new_group_name] = moto_iam_backend.groups.pop(
            group_name)
        return ""

    # TODO: potentially extend @patch utility to allow "conditional" patches like below ...
    if not hasattr(IamResponse, "update_group"):
        IamResponse.update_group = update_group

    # support instance profile tags

    def list_instance_profile_tags(self):
        profile_name = self._get_param("InstanceProfileName")
        profile = moto_iam_backend.get_instance_profile(profile_name)
        result = {
            "ListInstanceProfileTagsResponse": {
                "@xmlns": XMLNS_IAM,
                "ListInstanceProfileTagsResult": {
                    "Tags": profile.tags
                },
            }
        }
        return xmltodict.unparse(result)

    if not hasattr(IamResponse, "list_instance_profile_tags"):
        IamResponse.list_instance_profile_tags = list_instance_profile_tags

    # patch/implement tag_instance_profile

    def tag_instance_profile(self):
        profile_name = self._get_param("InstanceProfileName")
        tags = self._get_multi_param("Tags.member")
        tags = {tag["Key"]: tag["Value"] for tag in tags or []}
        profile = moto_iam_backend.get_instance_profile(profile_name)
        profile.tags.update(tags)
        return ""

    if not hasattr(IamResponse, "tag_instance_profile"):
        IamResponse.tag_instance_profile = tag_instance_profile

    # patch/implement untag_instance_profile

    def untag_instance_profile(self):
        profile_name = self._get_param("InstanceProfileName")
        tag_keys = self._get_multi_param("TagKeys.member")
        profile = moto_iam_backend.get_instance_profile(profile_name)
        profile.tags = {
            k: v
            for k, v in profile.tags.items() if k not in tag_keys
        }
        return ""

    if not hasattr(IamResponse, "untag_instance_profile"):
        IamResponse.untag_instance_profile = untag_instance_profile

    # support policy tags

    def tag_policy(self):
        policy_arn = self._get_param("PolicyArn")
        tags = self._get_multi_param("Tags.member")
        tags = {tag["Key"]: tag["Value"] for tag in tags or []}
        policy = moto_iam_backend.get_policy(policy_arn)
        policy.tags.update(tags)
        return ""

    if not hasattr(IamResponse, "tag_policy"):
        IamResponse.tag_policy = tag_policy

    def untag_policy(self):
        policy_arn = self._get_param("PolicyArn")
        tag_keys = self._get_multi_param("TagKeys.member")
        policy = moto_iam_backend.get_policy(policy_arn)
        policy.tags = {
            k: v
            for k, v in policy.tags.items() if k not in tag_keys
        }
        return ""

    if not hasattr(IamResponse, "untag_policy"):
        IamResponse.untag_policy = untag_policy

    # support service linked roles

    if not hasattr(IamResponse, "create_service_linked_role"):

        @property
        def role_arn(self):
            return getattr(self, "service_linked_role_arn",
                           None) or role_arn_orig.__get__(self)

        role_arn_orig = Role.arn
        Role.arn = role_arn

        def create_service_linked_role(self):
            service_name = self._get_param("AWSServiceName")
            description = self._get_param("Description")
            # TODO: how to support "CustomSuffix" API request parameter?
            policy_doc = json.dumps({
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Effect": "Allow",
                    "Principal": {
                        "Service": service_name
                    },
                    "Action": "sts:AssumeRole",
                }],
            })
            path = f"{SERVICE_LINKED_ROLE_PATH_PREFIX}/{service_name}"
            role_name = f"r-{short_uid()}"
            role = moto_iam_backend.create_role(
                role_name=role_name,
                assume_role_policy_document=policy_doc,
                path=path,
                permissions_boundary="",
                description=description,
                tags={},
                max_session_duration=3600,
            )
            template = self.response_template(GET_ROLE_TEMPLATE)
            role.service_linked_role_arn = "arn:aws:iam::{0}:role/aws-service-role/{1}/{2}".format(
                constants.TEST_AWS_ACCOUNT_ID, service_name, role.name)
            result = re.sub(
                r"<(/)?GetRole",
                r"<\1CreateServiceLinkedRole",
                template.render(role=role),
            )
            return result

        IamResponse.create_service_linked_role = create_service_linked_role

    if not hasattr(IamResponse, "delete_service_linked_role"):

        def delete_service_linked_role(self):
            role_name = self._get_param("RoleName")
            moto_iam_backend.delete_role(role_name)
            result = {
                "DeleteServiceLinkedRoleResponse": {
                    "@xmlns": XMLNS_IAM,
                    "DeleteServiceLinkedRoleResult": {
                        "DeletionTaskId": short_uid()
                    },
                }
            }
            return xmltodict.unparse(result)

        IamResponse.delete_service_linked_role = delete_service_linked_role

    if not hasattr(IamResponse, "get_service_linked_role_deletion_status"):

        def get_service_linked_role_deletion_status(self):
            result = {
                "GetServiceLinkedRoleDeletionStatusResponse": {
                    "@xmlns": XMLNS_IAM,
                    "GetServiceLinkedRoleDeletionStatusResult": {
                        "Status": "SUCCEEDED"
                    },
                }
            }
            return xmltodict.unparse(result)

        IamResponse.get_service_linked_role_deletion_status = (
            get_service_linked_role_deletion_status)

    managed_policies = moto_iam_backend.managed_policies
    if "arn:aws-us-gov:iam::aws:policy/AmazonRDSFullAccess" not in managed_policies:
        for name, data in aws_managed_policies_data_parsed.items():
            policy = AWSManagedPolicyUSGov.from_data(name, data)
            if policy.arn not in moto_iam_backend.managed_policies:
                moto_iam_backend.managed_policies[policy.arn] = policy
Esempio n. 3
0
def apply_patches():
    # Add missing managed polices
    aws_managed_policies.extend([
        AWSManagedPolicy.from_data(k, v)
        for k, v in ADDITIONAL_MANAGED_POLICIES.items()
    ])

    if 'Principal' not in VALID_STATEMENT_ELEMENTS:
        VALID_STATEMENT_ELEMENTS.append('Principal')

    def _validate_resource_syntax(statement, *args, **kwargs):
        # Note: Serverless generates policies without "Resource" section (only "Effect"/"Principal"/"Action"),
        # which causes several policy validators in moto to fail
        if statement.get('Resource') in [None, [None]]:
            statement['Resource'] = ['*']

    IAMPolicyDocumentValidator._validate_resource_syntax = _validate_resource_syntax

    def iam_response_get_user(self):
        result = iam_response_get_user_orig(self)
        user_name = re.sub(r'.*<UserName>\s*([^\s]+)\s*</UserName>.*', r'\1',
            result, flags=re.MULTILINE | re.DOTALL)
        user = moto_iam_backend.users[user_name]
        tags = moto_iam_backend.tagger.list_tags_for_resource(user.arn)
        if tags and '<Tags>' not in result:
            tags_str = ''.join([
                '<member><Key>%s</Key><Value>%s</Value></member>' % (t['Key'], t['Value']) for t in tags['Tags']])
            result = result.replace('</Arn>', '</Arn><Tags>%s</Tags>' % tags_str)
        return result

    iam_response_get_user_orig = IamResponse.get_user
    IamResponse.get_user = iam_response_get_user

    def iam_response_delete_policy(self):
        policy_arn = self._get_param('PolicyArn')
        moto_iam_backend.managed_policies.pop(policy_arn, None)
        template = self.response_template(GENERIC_EMPTY_TEMPLATE)
        return template.render(name='DeletePolicyResponse')

    if not hasattr(IamResponse, 'delete_policy'):
        IamResponse.delete_policy = iam_response_delete_policy

    def iam_backend_detach_role_policy(policy_arn, role_name):
        try:
            role = moto_iam_backend.get_role(role_name)
            policy = role.managed_policies[policy_arn]
            policy.detach_from(role)
        except KeyError:
            raise IAMNotFoundException('Policy {0} was not found.'.format(policy_arn))

    moto_iam_backend.detach_role_policy = iam_backend_detach_role_policy

    policy_init_orig = Policy.__init__

    def iam_response_simulate_principal_policy(self):
        def build_evaluation(action_name, resource_name, policy_statements):
            for statement in policy_statements:
                # TODO Implement evaluation logic here
                if action_name in statement['Action'] \
                        and resource_name in statement['Resource'] \
                        and statement['Effect'] == 'Allow':

                    return {
                        'actionName': action_name,
                        'resourceName': resource_name,
                        'decision': 'allowed',
                        'matchedStatements': []
                    }

            return {
                'actionName': action_name,
                'resourceName': resource_name,
                'decision': 'explicitDeny'
            }

        policy = moto_iam_backend.get_policy(self._get_param('PolicySourceArn'))
        policy_statements = json.loads(policy.document)['Statement']
        actions = self._get_multi_param('ActionNames.member')
        resource_arns = self._get_multi_param('ResourceArns.member')
        evaluations = []
        for action in actions:
            for resource_arn in resource_arns:
                evaluations.append(build_evaluation(action, resource_arn, policy_statements))

        template = self.response_template(SIMULATE_PRINCIPAL_POLICY_RESPONSE)
        return template.render(evaluations=evaluations)

    def policy__init__(
            self,
            name,
            default_version_id=None,
            description=None,
            document=None,
            **kwargs
    ):
        policy_init_orig(self, name, default_version_id, description, document, **kwargs)
        self.document = document

    Policy.__init__ = policy__init__

    IamResponse.simulate_principal_policy = iam_response_simulate_principal_policy

    def iam_response_list_roles(self):
        roles = moto_iam_backend.get_roles()
        items = []
        for role in roles:
            item = deepcopy(role)
            item.assume_role_policy_document = quote(json.dumps(item.assume_role_policy_document or {}))
            items.append(item)

        prefix = self._get_param('PathPrefix')
        if prefix:
            filtered_roles = []
            for role in roles:
                if role.path.startswith(prefix):
                    filtered_roles.append(role)
            items = filtered_roles

        template = self.response_template(LIST_ROLES_TEMPLATE)
        return template.render(roles=items)

    IamResponse.list_roles = iam_response_list_roles

    inline_policy_unapply_policy_orig = InlinePolicy.unapply_policy

    def inline_policy_unapply_policy(self, backend):
        try:
            inline_policy_unapply_policy_orig(self, backend)
        except Exception:
            # Actually role can be deleted before policy being deleted in cloudformation
            pass

    InlinePolicy.unapply_policy = inline_policy_unapply_policy

    # support update_group

    def update_group(self):
        group_name = self._get_param('GroupName')
        new_path = self._get_param('NewPath')
        new_group_name = self._get_param('NewGroupName') or group_name
        group = moto_iam_backend.get_group(group_name)
        group.path = new_path
        group.name = new_group_name
        moto_iam_backend.groups[new_group_name] = moto_iam_backend.groups.pop(group_name)
        return ''

    if not hasattr(IamResponse, 'update_group'):
        IamResponse.update_group = update_group

    # support instance profile tags

    def list_instance_profile_tags(self):
        profile_name = self._get_param('InstanceProfileName')
        profile = moto_iam_backend.get_instance_profile(profile_name)
        result = {
            'ListInstanceProfileTagsResponse': {
                '@xmlns': XMLNS_IAM,
                'ListInstanceProfileTagsResult': {'Tags': profile.tags}
            }
        }
        return xmltodict.unparse(result)

    if not hasattr(IamResponse, 'list_instance_profile_tags'):
        IamResponse.list_instance_profile_tags = list_instance_profile_tags

    def tag_instance_profile(self):
        profile_name = self._get_param('InstanceProfileName')
        tags = self._get_multi_param('Tags.member')
        tags = {tag['Key']: tag['Value'] for tag in tags or []}
        profile = moto_iam_backend.get_instance_profile(profile_name)
        profile.tags.update(tags)
        return ''

    if not hasattr(IamResponse, 'tag_instance_profile'):
        IamResponse.tag_instance_profile = tag_instance_profile

    def untag_instance_profile(self):
        profile_name = self._get_param('InstanceProfileName')
        tag_keys = self._get_multi_param('TagKeys.member')
        profile = moto_iam_backend.get_instance_profile(profile_name)
        profile.tags = {k: v for k, v in profile.tags.items() if k not in tag_keys}
        return ''

    if not hasattr(IamResponse, 'untag_instance_profile'):
        IamResponse.untag_instance_profile = untag_instance_profile

    # support policy tags

    def tag_policy(self):
        policy_arn = self._get_param('PolicyArn')
        tags = self._get_multi_param('Tags.member')
        tags = {tag['Key']: tag['Value'] for tag in tags or []}
        policy = moto_iam_backend.get_policy(policy_arn)
        policy.tags.update(tags)
        return ''

    if not hasattr(IamResponse, 'tag_policy'):
        IamResponse.tag_policy = tag_policy

    def untag_policy(self):
        policy_arn = self._get_param('PolicyArn')
        tag_keys = self._get_multi_param('TagKeys.member')
        policy = moto_iam_backend.get_policy(policy_arn)
        policy.tags = {k: v for k, v in policy.tags.items() if k not in tag_keys}
        return ''

    if not hasattr(IamResponse, 'untag_policy'):
        IamResponse.untag_policy = untag_policy

    # support service linked roles

    if not hasattr(IamResponse, 'create_service_linked_role'):
        @property
        def role_arn(self):
            return getattr(self, 'service_linked_role_arn', None) or role_arn_orig.__get__(self)

        role_arn_orig = Role.arn
        Role.arn = role_arn

        def create_service_linked_role(self):
            name_prefix = 'service-linked-role'
            service_name = self._get_param('AWSServiceName')
            description = self._get_param('Description')
            # TODO: how to support "CustomSuffix" API request parameter?
            policy_doc = json.dumps({
                'Version': '2012-10-17', 'Statement': [
                    {'Effect': 'Allow', 'Principal': {'Service': service_name}, 'Action': 'sts:AssumeRole'}]
            })
            role = moto_iam_backend.create_role(
                role_name='%s-%s' % (name_prefix, short_uid()), assume_role_policy_document=policy_doc, path='/',
                permissions_boundary='', description=description, tags={}, max_session_duration=3600)
            template = self.response_template(GET_ROLE_TEMPLATE)
            role.service_linked_role_arn = 'arn:aws:iam::{0}:role/aws-service-role/{1}/{2}'.format(
                constants.TEST_AWS_ACCOUNT_ID, service_name, role.name)
            result = re.sub(r'<(/)?GetRole', r'<\1CreateServiceLinkedRole', template.render(role=role))
            return result

        IamResponse.create_service_linked_role = create_service_linked_role

    if not hasattr(IamResponse, 'delete_service_linked_role'):
        def delete_service_linked_role(self):
            role_name = self._get_param('RoleName')
            moto_iam_backend.delete_role(role_name)
            result = {
                'DeleteServiceLinkedRoleResponse': {
                    '@xmlns': XMLNS_IAM,
                    'DeleteServiceLinkedRoleResult': {'DeletionTaskId': short_uid()}
                }
            }
            return xmltodict.unparse(result)

        IamResponse.delete_service_linked_role = delete_service_linked_role

    if not hasattr(IamResponse, 'get_service_linked_role_deletion_status'):
        def get_service_linked_role_deletion_status(self):
            result = {
                'GetServiceLinkedRoleDeletionStatusResponse': {
                    '@xmlns': XMLNS_IAM,
                    'GetServiceLinkedRoleDeletionStatusResult': {'Status': 'SUCCEEDED'}
                }
            }
            return xmltodict.unparse(result)

        IamResponse.get_service_linked_role_deletion_status = get_service_linked_role_deletion_status

    # fix missing regions in managed policies (e.g., aws-us-gov)
    # TODO: possibly find a more efficient way for this - e.g., lazy loading of policies in special regions

    class AWSManagedPolicyUSGov(AWSManagedPolicy):
        @property
        def arn(self):
            return 'arn:aws-us-gov:iam::aws:policy{0}{1}'.format(self.path, self.name)

    managed_policies = moto_iam_backend.managed_policies
    if 'arn:aws-us-gov:iam::aws:policy/AmazonRDSFullAccess' not in managed_policies:
        for name, data in aws_managed_policies_data_parsed.items():
            policy = AWSManagedPolicyUSGov.from_data(name, data)
            if policy.arn not in moto_iam_backend.managed_policies:
                moto_iam_backend.managed_policies[policy.arn] = policy
Esempio n. 4
0
def apply_patches():
    # Add missing managed polices
    aws_managed_policies.extend([
        AWSManagedPolicy.from_data(k, v)
        for k, v in ADDITIONAL_MANAGED_POLICIES.items()
    ])

    if 'Principal' not in VALID_STATEMENT_ELEMENTS:
        VALID_STATEMENT_ELEMENTS.append('Principal')

    def _validate_resource_syntax(statement, *args, **kwargs):
        # Note: Serverless generates policies without "Resource" section (only "Effect"/"Principal"/"Action"),
        # which causes several policy validators in moto to fail
        if statement.get('Resource') in [None, [None]]:
            statement['Resource'] = ['*']

    IAMPolicyDocumentValidator._validate_resource_syntax = _validate_resource_syntax

    def iam_response_create_user(self):
        user = moto_iam_backend.create_user(
            self._get_param('UserName'), self._get_param('Path'),
            self._get_multi_param('Tags.member'))

        template = self.response_template(USER_RESPONSE_TEMPLATE)
        return template.render(action='Create',
                               user=user,
                               request_id=str(uuid.uuid4()))

    IamResponse.create_user = iam_response_create_user

    def iam_response_get_user(self):
        user_name = self._get_param('UserName')
        if not user_name:
            access_key_id = self.get_current_user()
            user = moto_iam_backend.get_user_from_access_key_id(access_key_id)
            if user is None:
                user = User('default_user')
        else:
            user = moto_iam_backend.get_user(user_name)

        template = self.response_template(USER_RESPONSE_TEMPLATE)
        return template.render(action='Get',
                               user=user,
                               request_id=str(uuid.uuid4()))

    IamResponse.get_user = iam_response_get_user

    def iam_response_delete_policy(self):
        policy_arn = self._get_param('PolicyArn')
        moto_iam_backend.managed_policies.pop(policy_arn, None)
        template = self.response_template(GENERIC_EMPTY_TEMPLATE)
        return template.render(name='DeletePolicyResponse')

    if not hasattr(IamResponse, 'delete_policy'):
        IamResponse.delete_policy = iam_response_delete_policy

    def iam_backend_detach_role_policy(policy_arn, role_name):
        try:
            role = moto_iam_backend.get_role(role_name)
            policy = role.managed_policies[policy_arn]
            policy.detach_from(role)
        except KeyError:
            raise IAMNotFoundException(
                'Policy {0} was not found.'.format(policy_arn))

    moto_iam_backend.detach_role_policy = iam_backend_detach_role_policy

    policy_init_orig = Policy.__init__

    def iam_response_simulate_principal_policy(self):
        def build_evaluation(action_name, resource_name, policy_statements):
            for statement in policy_statements:
                # TODO Implement evaluation logic here
                if action_name in statement['Action'] \
                        and resource_name in statement['Resource'] \
                        and statement['Effect'] == 'Allow':

                    return {
                        'actionName': action_name,
                        'resourceName': resource_name,
                        'decision': 'allowed',
                        'matchedStatements': []
                    }

            return {
                'actionName': action_name,
                'resourceName': resource_name,
                'decision': 'explicitDeny'
            }

        policy = moto_iam_backend.get_policy(
            self._get_param('PolicySourceArn'))
        policy_statements = json.loads(policy.document)['Statement']
        actions = self._get_multi_param('ActionNames.member')
        resource_arns = self._get_multi_param('ResourceArns.member')
        evaluations = []
        for action in actions:
            for resource_arn in resource_arns:
                evaluations.append(
                    build_evaluation(action, resource_arn, policy_statements))

        template = self.response_template(SIMULATE_PRINCIPAL_POLICY_RESPONSE)
        return template.render(evaluations=evaluations)

    def policy__init__(self,
                       name,
                       default_version_id=None,
                       description=None,
                       document=None,
                       path=None,
                       create_date=None,
                       update_date=None):
        policy_init_orig(self, name, default_version_id, description, document,
                         path, create_date, update_date)
        self.document = document

    Policy.__init__ = policy__init__

    IamResponse.simulate_principal_policy = iam_response_simulate_principal_policy

    def iam_response_list_roles(self):
        roles = moto_iam_backend.get_roles()
        items = []
        for role in roles:
            item = deepcopy(role)
            item.assume_role_policy_document = quote(
                json.dumps(item.assume_role_policy_document or {}))
            items.append(item)

        prefix = self._get_param('PathPrefix')
        if prefix:
            filtered_roles = []
            for role in roles:
                if role.path.startswith(prefix):
                    filtered_roles.append(role)
            items = filtered_roles

        template = self.response_template(LIST_ROLES_TEMPLATE)
        return template.render(roles=items)

    IamResponse.list_roles = iam_response_list_roles

    inline_policy_unapply_policy_orig = InlinePolicy.unapply_policy

    def inline_policy_unapply_policy(self, backend):
        try:
            inline_policy_unapply_policy_orig(self, backend)
        except Exception:
            # Actually role can be deleted before policy being deleted in cloudformation
            pass

    InlinePolicy.unapply_policy = inline_policy_unapply_policy
Esempio n. 5
0
def apply_patches():
    # support service linked roles

    @property
    def moto_role_arn(self):
        return getattr(self, "service_linked_role_arn",
                       None) or moto_role_og_arn_prop.__get__(self)

    moto_role_og_arn_prop = MotoRole.arn
    MotoRole.arn = moto_role_arn

    # Add missing managed polices

    aws_managed_policies.extend([
        AWSManagedPolicy.from_data(k, v)
        for k, v in ADDITIONAL_MANAGED_POLICIES.items()
    ])

    if "Principal" not in VALID_STATEMENT_ELEMENTS:
        VALID_STATEMENT_ELEMENTS.append("Principal")

    @patch(IAMPolicyDocumentValidator._validate_resource_syntax,
           pass_target=False)
    def _validate_resource_syntax(statement, *args, **kwargs):
        # Note: Serverless generates policies without "Resource" section (only "Effect"/"Principal"/"Action"),
        # which causes several policy validators in moto to fail
        if statement.get("Resource") in [None, [None]]:
            statement["Resource"] = ["*"]

    # patch get_user to include tags
    # TODO: remove this patch in favour of IamProvider.get_user.

    @patch(IamResponse.get_user)
    def iam_response_get_user(fn, self):
        result = fn(self)
        regex = r"(.*<UserName>\s*)([^\s]+)(\s*</UserName>.*)"
        regex2 = r"(.*<UserId>\s*)([^\s]+)(\s*</UserId>.*)"
        flags = re.MULTILINE | re.DOTALL

        user_name = re.match(regex, result, flags=flags).group(2)
        # replace default user id/name in response
        if config.TEST_IAM_USER_NAME:
            result = re.sub(regex, r"\g<1>%s\3" % config.TEST_IAM_USER_NAME,
                            result)
            user_name = config.TEST_IAM_USER_NAME
        if config.TEST_IAM_USER_ID:
            result = re.sub(regex2, r"\g<1>%s\3" % config.TEST_IAM_USER_ID,
                            result)

        user = moto_iam_backend.users.get(user_name)
        if not user:
            return result
        tags = moto_iam_backend.tagger.list_tags_for_resource(user.arn)
        if tags and "<Tags>" not in result:
            tags_str = "".join([
                "<member><Key>%s</Key><Value>%s</Value></member>" %
                (t["Key"], t["Value"]) for t in tags["Tags"]
            ])
            result = result.replace("</Arn>",
                                    "</Arn><Tags>%s</Tags>" % tags_str)
        return result

    # patch policy __init__ to set document as attribute

    @patch(Policy.__init__)
    def policy__init__(fn,
                       self,
                       name,
                       default_version_id=None,
                       description=None,
                       document=None,
                       **kwargs):
        fn(self, name, default_version_id, description, document, **kwargs)
        self.document = document

    # patch unapply_policy

    @patch(InlinePolicy.unapply_policy)
    def inline_policy_unapply_policy(fn, self, backend):
        try:
            fn(self, backend)
        except Exception:
            # Actually role can be deleted before policy being deleted in cloudformation
            pass
Esempio n. 6
0
def apply_patches():
    # Add missing managed polices
    aws_managed_policies.extend([
        AWSManagedPolicy.from_data(k, v)
        for k, v in ADDITIONAL_MANAGED_POLICIES.items()
    ])

    def iam_response_create_user(self):
        user = moto_iam_backend.create_user(
            self._get_param('UserName'),
            self._get_param('Path'),
            self._get_multi_param('Tags.member')
        )

        template = self.response_template(USER_RESPONSE_TEMPLATE)
        return template.render(
            action='Create',
            user=user,
            request_id=str(uuid.uuid4())
        )

    IamResponse.create_user = iam_response_create_user

    def iam_response_get_user(self):
        user_name = self._get_param('UserName')
        if not user_name:
            access_key_id = self.get_current_user()
            user = moto_iam_backend.get_user_from_access_key_id(access_key_id)
            if user is None:
                user = User('default_user')
        else:
            user = moto_iam_backend.get_user(user_name)

        template = self.response_template(USER_RESPONSE_TEMPLATE)
        return template.render(
            action='Get',
            user=user,
            request_id=str(uuid.uuid4())
        )

    IamResponse.get_user = iam_response_get_user

    def iam_response_delete_policy(self):
        policy_arn = self._get_param('PolicyArn')
        moto_iam_backend.managed_policies.pop(policy_arn, None)
        template = self.response_template(GENERIC_EMPTY_TEMPLATE)
        return template.render(name='DeletePolicyResponse')

    if not hasattr(IamResponse, 'delete_policy'):
        IamResponse.delete_policy = iam_response_delete_policy

    def iam_backend_detach_role_policy(policy_arn, role_name):
        try:
            role = moto_iam_backend.get_role(role_name)
            policy = role.managed_policies[policy_arn]
            policy.detach_from(role)
        except KeyError:
            raise IAMNotFoundException('Policy {0} was not found.'.format(policy_arn))

    moto_iam_backend.detach_role_policy = iam_backend_detach_role_policy

    policy_init_orig = Policy.__init__

    def iam_response_simulate_principal_policy(self):
        def build_evaluation(action_name, resource_name, policy_statements):
            for statement in policy_statements:
                # TODO Implement evaluation logic here
                if action_name in statement['Action'] \
                        and resource_name in statement['Resource'] \
                        and statement['Effect'] == 'Allow':

                    return {
                        'actionName': action_name,
                        'resourceName': resource_name,
                        'decision': 'allowed',
                        'matchedStatements': []
                    }

            return {
                'actionName': action_name,
                'resourceName': resource_name,
                'decision': 'explicitDeny'
            }

        policy = moto_iam_backend.get_policy(self._get_param('PolicySourceArn'))
        policy_statements = json.loads(policy.document)['Statement']
        actions = self._get_multi_param('ActionNames.member')
        resource_arns = self._get_multi_param('ResourceArns.member')
        evaluations = []
        for action in actions:
            for resource_arn in resource_arns:
                evaluations.append(build_evaluation(action, resource_arn, policy_statements))

        template = self.response_template(SIMULATE_PRINCIPAL_POLICY_RESPONSE)
        return template.render(evaluations=evaluations)

    def policy__init__(
            self,
            name,
            default_version_id=None,
            description=None,
            document=None,
            path=None,
            create_date=None,
            update_date=None
    ):
        policy_init_orig(self, name, default_version_id, description, document, path, create_date, update_date)
        self.document = document

    Policy.__init__ = policy__init__

    IamResponse.simulate_principal_policy = iam_response_simulate_principal_policy

    def iam_response_list_roles(self):
        roles = moto_iam_backend.get_roles()
        items = []
        for role in roles:
            item = deepcopy(role)
            item.assume_role_policy_document = quote(json.dumps(item.assume_role_policy_document or {}))
            items.append(item)

        template = self.response_template(LIST_ROLES_TEMPLATE)
        return template.render(roles=items)

    IamResponse.list_roles = iam_response_list_roles
Esempio n. 7
0
def apply_patches():
    # Add missing managed polices
    aws_managed_policies.extend([
        AWSManagedPolicy.from_data(k, v)
        for k, v in ADDITIONAL_MANAGED_POLICIES.items()
    ])

    if 'Principal' not in VALID_STATEMENT_ELEMENTS:
        VALID_STATEMENT_ELEMENTS.append('Principal')

    def _validate_resource_syntax(statement, *args, **kwargs):
        # Note: Serverless generates policies without "Resource" section (only "Effect"/"Principal"/"Action"),
        # which causes several policy validators in moto to fail
        if statement.get('Resource') in [None, [None]]:
            statement['Resource'] = ['*']

    IAMPolicyDocumentValidator._validate_resource_syntax = _validate_resource_syntax

    def iam_response_get_user(self):
        result = iam_response_get_user_orig(self)
        user_name = re.sub(r'.*<UserName>\s*([^\s]+)\s*</UserName>.*',
                           r'\1',
                           result,
                           flags=re.MULTILINE | re.DOTALL)
        user = moto_iam_backend.users[user_name]
        tags = moto_iam_backend.tagger.list_tags_for_resource(user.arn)
        if tags and '<Tags>' not in result:
            tags_str = ''.join([
                '<member><Key>%s</Key><Value>%s</Value></member>' %
                (t['Key'], t['Value']) for t in tags['Tags']
            ])
            result = result.replace('</Arn>',
                                    '</Arn><Tags>%s</Tags>' % tags_str)
        return result

    iam_response_get_user_orig = IamResponse.get_user
    IamResponse.get_user = iam_response_get_user

    def iam_response_delete_policy(self):
        policy_arn = self._get_param('PolicyArn')
        moto_iam_backend.managed_policies.pop(policy_arn, None)
        template = self.response_template(GENERIC_EMPTY_TEMPLATE)
        return template.render(name='DeletePolicyResponse')

    if not hasattr(IamResponse, 'delete_policy'):
        IamResponse.delete_policy = iam_response_delete_policy

    def iam_backend_detach_role_policy(policy_arn, role_name):
        try:
            role = moto_iam_backend.get_role(role_name)
            policy = role.managed_policies[policy_arn]
            policy.detach_from(role)
        except KeyError:
            raise IAMNotFoundException(
                'Policy {0} was not found.'.format(policy_arn))

    moto_iam_backend.detach_role_policy = iam_backend_detach_role_policy

    policy_init_orig = Policy.__init__

    def iam_response_simulate_principal_policy(self):
        def build_evaluation(action_name, resource_name, policy_statements):
            for statement in policy_statements:
                # TODO Implement evaluation logic here
                if action_name in statement['Action'] \
                        and resource_name in statement['Resource'] \
                        and statement['Effect'] == 'Allow':

                    return {
                        'actionName': action_name,
                        'resourceName': resource_name,
                        'decision': 'allowed',
                        'matchedStatements': []
                    }

            return {
                'actionName': action_name,
                'resourceName': resource_name,
                'decision': 'explicitDeny'
            }

        policy = moto_iam_backend.get_policy(
            self._get_param('PolicySourceArn'))
        policy_statements = json.loads(policy.document)['Statement']
        actions = self._get_multi_param('ActionNames.member')
        resource_arns = self._get_multi_param('ResourceArns.member')
        evaluations = []
        for action in actions:
            for resource_arn in resource_arns:
                evaluations.append(
                    build_evaluation(action, resource_arn, policy_statements))

        template = self.response_template(SIMULATE_PRINCIPAL_POLICY_RESPONSE)
        return template.render(evaluations=evaluations)

    def policy__init__(self,
                       name,
                       default_version_id=None,
                       description=None,
                       document=None,
                       path=None,
                       create_date=None,
                       update_date=None):
        policy_init_orig(self, name, default_version_id, description, document,
                         path, create_date, update_date)
        self.document = document

    Policy.__init__ = policy__init__

    IamResponse.simulate_principal_policy = iam_response_simulate_principal_policy

    def iam_response_list_roles(self):
        roles = moto_iam_backend.get_roles()
        items = []
        for role in roles:
            item = deepcopy(role)
            item.assume_role_policy_document = quote(
                json.dumps(item.assume_role_policy_document or {}))
            items.append(item)

        prefix = self._get_param('PathPrefix')
        if prefix:
            filtered_roles = []
            for role in roles:
                if role.path.startswith(prefix):
                    filtered_roles.append(role)
            items = filtered_roles

        template = self.response_template(LIST_ROLES_TEMPLATE)
        return template.render(roles=items)

    IamResponse.list_roles = iam_response_list_roles

    inline_policy_unapply_policy_orig = InlinePolicy.unapply_policy

    def inline_policy_unapply_policy(self, backend):
        try:
            inline_policy_unapply_policy_orig(self, backend)
        except Exception:
            # Actually role can be deleted before policy being deleted in cloudformation
            pass

    InlinePolicy.unapply_policy = inline_policy_unapply_policy