project继承domain管理权限

在需要project继承domain的管理权限之时,需要首先在keystone.conf中将os_inherit:enable置于true,这样在做role的grant的时候,就可以以此作为判断是否需要继承domain的管理权限,看看router的定义:

# keystone\keystone\assignment\routers.py
if CONF.os_inherit.enabled:
            self._add_resource(
                mapper, grant_controller,
                path='/OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/'
                '{role_id}/inherited_to_projects',
                get_head_action='check_grant',
                put_action='create_grant',
                delete_action='revoke_grant',
                rel=build_os_inherit_relation(
                    resource_name='domain_user_role_inherited_to_projects'),
                path_vars={
                    'domain_id': json_home.Parameters.DOMAIN_ID,
                    'role_id': json_home.Parameters.ROLE_ID,
                    'user_id': json_home.Parameters.USER_ID,
                })


path以OS-INHERIT开头并以inherited_to_projects结尾,assignment将会被置为1。

# keystone\keystone\assignment\controllers.py

    @controller.protected(callback=_check_grant_protection)
    def create_grant(self, context, role_id, user_id=None,
                     group_id=None, domain_id=None, project_id=None):
        """Grants a role to a user or group on either a domain or project."""
        self._require_domain_xor_project(domain_id, project_id)
        self._require_user_xor_group(user_id, group_id)

        self.assignment_api.create_grant(
            role_id, user_id, group_id, domain_id, project_id,
            self._check_if_inherited(context), context)



    def _check_if_inherited(self, context):
        return (CONF.os_inherit.enabled and
                context['path'].startswith('/OS-INHERIT') and
                context['path'].endswith('/inherited_to_projects'))



这样写数据库的时候,将以此来写入inertied字段:


# keystone\keystone\assignment\core.py

    @notifications.role_assignment('created')
    def create_grant(self, role_id, user_id=None, group_id=None,
                     domain_id=None, project_id=None,
                     inherited_to_projects=False, context=None):
        self.role_api.get_role(role_id)
        if domain_id:
            self.resource_api.get_domain(domain_id)
        if project_id:
            self.resource_api.get_project(project_id)
        self.driver.create_grant(role_id, user_id, group_id, domain_id,
                                 project_id, <strong>inherited_to_projects</strong>)


# keystone\assignment\backends\sql.py

    def create_grant(self, role_id, user_id=None, group_id=None,
                     domain_id=None, project_id=None,
                     inherited_to_projects=False):

        assignment_type = AssignmentType.calculate_type(
            user_id, group_id, project_id, domain_id)
        try:
            with sql.transaction() as session:
                session.add(RoleAssignment(
                    type=assignment_type,
                    actor_id=user_id or group_id,
                    target_id=project_id or domain_id,
                    role_id=role_id,
                    inherited=<strong>inherited_to_projects</strong>))
        except sql.DBDuplicateEntry:
            # The v3 grant APIs are silent if the assignment already exists
            pass


在做角色验证的时候,会根据配置CONF.os_inherit.enabled是否被置为true来判断是否从project对应的domain中获取权限。

# keystone\keystone\token\providers\common.py

    def _populate_roles(self, token_data, user_id, domain_id, project_id,
                        trust, access_token):
...
if token_domain_id or token_project_id:
            roles = self._get_roles_for_user(token_user_id,
                                             token_domain_id,
                                             token_project_id)


            # user has no project or domain roles, therefore access denied
            if not filtered_roles:
                if token_project_id:
                    msg = _('User %(user_id)s has no access '
                            'to project %(project_id)s') % {
                                'user_id': user_id,
                                'project_id': token_project_id}


然后会根据keystone的配置来看是否需要从domain中获取权限。


# keystone\keystone\assignment\core.py

这里role list则为用户所具有的角色的一个列表。

def _get_user_project_roles(user_id, project_ref):

            role_list = []
            try:
                metadata_ref = self._get_metadata(user_id=user_id,
                                                  tenant_id=project_ref['id'])
                role_list = self._roles_from_role_dicts(
                    metadata_ref.get('roles', {}), False)
            except exception.MetadataNotFound:
                pass

            if CONF.os_inherit.enabled:
                # Now get any inherited roles for the owning domain
                try:
                    metadata_ref = self._get_metadata(
                        user_id=user_id, domain_id=project_ref['domain_id'])
                    role_list += self._roles_from_role_dicts(
                        metadata_ref.get('roles', {}), True)
                except (exception.MetadataNotFound, exception.NotImplemented):
                    pass
                # As well inherited roles from parent projects
                for p in self.list_project_parents(project_ref['id']):
                    p_roles = self.list_grants(
                        user_id=user_id, project_id=p['id'],
                        inherited_to_projects=True)
                    role_list += [x['id'] for x in p_roles]

            return role_list

猜你喜欢

转载自blog.csdn.net/chenwei8280/article/details/46560947