From 92fd2dbfb672d7b2b1cdfd5dd5cf89f7716b3e12 Mon Sep 17 00:00:00 2001 From: asteroide Date: Tue, 1 Sep 2015 16:03:26 +0200 Subject: Update Keystone code from official Github repository with branch Master on 09/01/2015. Change-Id: I0ff6099e6e2580f87f502002a998bbfe12673498 --- keystone-moon/keystone/assignment/core.py | 660 +++++++++++++++++++++--------- 1 file changed, 465 insertions(+), 195 deletions(-) (limited to 'keystone-moon/keystone/assignment/core.py') diff --git a/keystone-moon/keystone/assignment/core.py b/keystone-moon/keystone/assignment/core.py index 0f9c03e9..a001e6b1 100644 --- a/keystone-moon/keystone/assignment/core.py +++ b/keystone-moon/keystone/assignment/core.py @@ -12,9 +12,10 @@ # License for the specific language governing permissions and limitations # under the License. -"""Main entry point into the assignment service.""" +"""Main entry point into the Assignment service.""" import abc +import copy from oslo_config import cfg from oslo_log import log @@ -28,7 +29,6 @@ from keystone import exception from keystone.i18n import _ from keystone.i18n import _LI from keystone import notifications -from keystone.openstack.common import versionutils CONF = cfg.CONF @@ -36,40 +36,6 @@ LOG = log.getLogger(__name__) MEMOIZE = cache.get_memoization_decorator(section='role') -def deprecated_to_role_api(f): - """Specialized deprecation wrapper for assignment to role api. - - This wraps the standard deprecation wrapper and fills in the method - names automatically. - - """ - @six.wraps(f) - def wrapper(*args, **kwargs): - x = versionutils.deprecated( - what='assignment.' + f.__name__ + '()', - as_of=versionutils.deprecated.KILO, - in_favor_of='role.' + f.__name__ + '()') - return x(f) - return wrapper() - - -def deprecated_to_resource_api(f): - """Specialized deprecation wrapper for assignment to resource api. - - This wraps the standard deprecation wrapper and fills in the method - names automatically. - - """ - @six.wraps(f) - def wrapper(*args, **kwargs): - x = versionutils.deprecated( - what='assignment.' + f.__name__ + '()', - as_of=versionutils.deprecated.KILO, - in_favor_of='resource.' + f.__name__ + '()') - return x(f) - return wrapper() - - @dependency.provider('assignment_api') @dependency.requires('credential_api', 'identity_api', 'resource_api', 'revoke_api', 'role_api') @@ -80,6 +46,9 @@ class Manager(manager.Manager): dynamically calls the backend. """ + + driver_namespace = 'keystone.assignment' + _PROJECT = 'project' _ROLE_REMOVED_FROM_USER = 'role_removed_from_user' _INVALIDATION_USER_PROJECT_TOKENS = 'invalidate_user_project_tokens' @@ -129,7 +98,7 @@ class Manager(manager.Manager): """ def _get_group_project_roles(user_id, project_ref): group_ids = self._get_group_ids_for_user_id(user_id) - return self.driver.list_role_ids_for_groups_on_project( + return self.list_role_ids_for_groups_on_project( group_ids, project_ref['id'], project_ref['domain_id'], @@ -155,7 +124,8 @@ class Manager(manager.Manager): except (exception.MetadataNotFound, exception.NotImplemented): pass # As well inherited roles from parent projects - for p in self.list_project_parents(project_ref['id']): + for p in self.resource_api.list_project_parents( + project_ref['id']): p_roles = self.list_grants( user_id=user_id, project_id=p['id'], inherited_to_projects=True) @@ -207,7 +177,7 @@ class Manager(manager.Manager): return self._roles_from_role_dicts( metadata_ref.get('roles', {}), False) - self.get_domain(domain_id) + self.resource_api.get_domain(domain_id) user_role_list = _get_user_domain_roles(user_id, domain_id) group_role_list = _get_group_domain_roles(user_id, domain_id) # Use set() to process the list to remove any duplicates @@ -218,11 +188,11 @@ class Manager(manager.Manager): if project_id is not None: project = self.resource_api.get_project(project_id) - role_ids = self.driver.list_role_ids_for_groups_on_project( + role_ids = self.list_role_ids_for_groups_on_project( group_ids, project_id, project['domain_id'], self._list_parent_ids_of_project(project_id)) elif domain_id is not None: - role_ids = self.driver.list_role_ids_for_groups_on_domain( + role_ids = self.list_role_ids_for_groups_on_domain( group_ids, domain_id) else: raise AttributeError(_("Must specify either domain or project")) @@ -261,10 +231,24 @@ class Manager(manager.Manager): tenant_id, CONF.member_role_id) - def add_role_to_user_and_project(self, user_id, tenant_id, role_id): - self.resource_api.get_project(tenant_id) + @notifications.role_assignment('created') + def _add_role_to_user_and_project_adapter(self, role_id, user_id=None, + group_id=None, domain_id=None, + project_id=None, + inherited_to_projects=False, + context=None): + + # The parameters for this method must match the parameters for + # create_grant so that the notifications.role_assignment decorator + # will work. + + self.resource_api.get_project(project_id) self.role_api.get_role(role_id) - self.driver.add_role_to_user_and_project(user_id, tenant_id, role_id) + self.driver.add_role_to_user_and_project(user_id, project_id, role_id) + + def add_role_to_user_and_project(self, user_id, tenant_id, role_id): + self._add_role_to_user_and_project_adapter( + role_id, user_id=user_id, project_id=tenant_id) def remove_user_from_project(self, tenant_id, user_id): """Remove user from a tenant @@ -299,7 +283,7 @@ class Manager(manager.Manager): # optimization with the various backend technologies (SQL, LDAP etc.). group_ids = self._get_group_ids_for_user_id(user_id) - project_ids = self.driver.list_project_ids_for_user( + project_ids = self.list_project_ids_for_user( user_id, group_ids, hints or driver_hints.Hints()) if not CONF.os_inherit.enabled: @@ -309,7 +293,7 @@ class Manager(manager.Manager): # inherited role (direct or group) on any parent project, in which # case we must add in all the projects in that parent's subtree. project_ids = set(project_ids) - project_ids_inherited = self.driver.list_project_ids_for_user( + project_ids_inherited = self.list_project_ids_for_user( user_id, group_ids, hints or driver_hints.Hints(), inherited=True) for proj_id in project_ids_inherited: project_ids.update( @@ -317,7 +301,7 @@ class Manager(manager.Manager): self.resource_api.list_projects_in_subtree(proj_id))) # Now do the same for any domain inherited roles - domain_ids = self.driver.list_domain_ids_for_user( + domain_ids = self.list_domain_ids_for_user( user_id, group_ids, hints or driver_hints.Hints(), inherited=True) project_ids.update( @@ -335,33 +319,42 @@ class Manager(manager.Manager): # projects for a user is pushed down into the driver to enable # optimization with the various backend technologies (SQL, LDAP etc.). group_ids = self._get_group_ids_for_user_id(user_id) - domain_ids = self.driver.list_domain_ids_for_user( + domain_ids = self.list_domain_ids_for_user( user_id, group_ids, hints or driver_hints.Hints()) return self.resource_api.list_domains_from_ids(domain_ids) def list_domains_for_groups(self, group_ids): - domain_ids = self.driver.list_domain_ids_for_groups(group_ids) + domain_ids = self.list_domain_ids_for_groups(group_ids) return self.resource_api.list_domains_from_ids(domain_ids) def list_projects_for_groups(self, group_ids): project_ids = ( - self.driver.list_project_ids_for_groups(group_ids, - driver_hints.Hints())) + self.list_project_ids_for_groups(group_ids, driver_hints.Hints())) if not CONF.os_inherit.enabled: return self.resource_api.list_projects_from_ids(project_ids) - # Inherited roles are enabled, so check to see if these groups have any - # roles on any domain, in which case we must add in all the projects - # in that domain. + # os_inherit extension is enabled, so check to see if these groups have + # any inherited role assignment on: i) any domain, in which case we + # must add in all the projects in that domain; ii) any project, in + # which case we must add in all the subprojects under that project in + # the hierarchy. - domain_ids = self.driver.list_domain_ids_for_groups( - group_ids, inherited=True) + domain_ids = self.list_domain_ids_for_groups(group_ids, inherited=True) project_ids_from_domains = ( self.resource_api.list_project_ids_from_domain_ids(domain_ids)) + parents_ids = self.list_project_ids_for_groups(group_ids, + driver_hints.Hints(), + inherited=True) + + subproject_ids = [] + for parent_id in parents_ids: + subtree = self.resource_api.list_projects_in_subtree(parent_id) + subproject_ids += [subproject['id'] for subproject in subtree] + return self.resource_api.list_projects_from_ids( - list(set(project_ids + project_ids_from_domains))) + list(set(project_ids + project_ids_from_domains + subproject_ids))) def list_role_assignments_for_role(self, role_id=None): # NOTE(henry-nash): Currently the efficiency of the key driver @@ -374,17 +367,37 @@ class Manager(manager.Manager): return [r for r in self.driver.list_role_assignments() if r['role_id'] == role_id] - def remove_role_from_user_and_project(self, user_id, tenant_id, role_id): - self.driver.remove_role_from_user_and_project(user_id, tenant_id, + @notifications.role_assignment('deleted') + def _remove_role_from_user_and_project_adapter(self, role_id, user_id=None, + group_id=None, + domain_id=None, + project_id=None, + inherited_to_projects=False, + context=None): + + # The parameters for this method must match the parameters for + # delete_grant so that the notifications.role_assignment decorator + # will work. + + self.driver.remove_role_from_user_and_project(user_id, project_id, role_id) self.identity_api.emit_invalidate_user_token_persistence(user_id) self.revoke_api.revoke_by_grant(role_id, user_id=user_id, - project_id=tenant_id) + project_id=project_id) + + def remove_role_from_user_and_project(self, user_id, tenant_id, role_id): + self._remove_role_from_user_and_project_adapter( + role_id, user_id=user_id, project_id=tenant_id) @notifications.internal(notifications.INVALIDATE_USER_TOKEN_PERSISTENCE) def _emit_invalidate_user_token_persistence(self, user_id): self.identity_api.emit_invalidate_user_token_persistence(user_id) + def _emit_invalidate_grant_token_persistence(self, user_id, project_id): + self.identity_api.emit_invalidate_grant_token_persistence( + {'user_id': user_id, 'project_id': project_id} + ) + @notifications.role_assignment('created') def create_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, @@ -405,7 +418,7 @@ class Manager(manager.Manager): self.resource_api.get_domain(domain_id) if project_id: self.resource_api.get_project(project_id) - self.driver.check_grant_role_id( + self.check_grant_role_id( role_id, user_id, group_id, domain_id, project_id, inherited_to_projects) return role_ref @@ -417,11 +430,15 @@ class Manager(manager.Manager): self.resource_api.get_domain(domain_id) if project_id: self.resource_api.get_project(project_id) - grant_ids = self.driver.list_grant_role_ids( + grant_ids = self.list_grant_role_ids( user_id, group_id, domain_id, project_id, inherited_to_projects) return self.role_api.list_roles_from_ids(grant_ids) @notifications.role_assignment('deleted') + def _emit_revoke_user_grant(self, role_id, user_id, domain_id, project_id, + inherited_to_projects, context): + self._emit_invalidate_grant_token_persistence(user_id, project_id) + def delete_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False, context=None): @@ -430,17 +447,29 @@ class Manager(manager.Manager): role_id=role_id, domain_id=domain_id, project_id=project_id) + self._emit_revoke_user_grant( + role_id, user_id, domain_id, project_id, + inherited_to_projects, context) else: try: - # NOTE(morganfainberg): The user ids are the important part - # for invalidating tokens below, so extract them here. - for user in self.identity_api.list_users_in_group(group_id): - if user['id'] != user_id: - self._emit_invalidate_user_token_persistence( - user['id']) - self.revoke_api.revoke_by_grant( - user_id=user['id'], role_id=role_id, - domain_id=domain_id, project_id=project_id) + # Group may contain a lot of users so revocation will be + # by role & domain/project + if domain_id is None: + self.revoke_api.revoke_by_project_role_assignment( + project_id, role_id + ) + else: + self.revoke_api.revoke_by_domain_role_assignment( + domain_id, role_id + ) + if CONF.token.revoke_by_id: + # NOTE(morganfainberg): The user ids are the important part + # for invalidating tokens below, so extract them here. + for user in self.identity_api.list_users_in_group( + group_id): + self._emit_revoke_user_grant( + role_id, user['id'], domain_id, project_id, + inherited_to_projects, context) except exception.GroupNotFound: LOG.debug('Group %s not found, no tokens to invalidate.', group_id) @@ -457,8 +486,356 @@ class Manager(manager.Manager): self.resource_api.get_project(project_id) self.driver.delete_grant(role_id, user_id, group_id, domain_id, project_id, inherited_to_projects) - if user_id is not None: - self._emit_invalidate_user_token_persistence(user_id) + + # The methods _expand_indirect_assignment, _list_direct_role_assignments + # and _list_effective_role_assignments below are only used on + # list_role_assignments, but they are not in its scope as nested functions + # since it would significantly increase McCabe complexity, that should be + # kept as it is in order to detect unnecessarily complex code, which is not + # this case. + + def _expand_indirect_assignment(self, ref, user_id=None, + project_id=None): + """Returns a list of expanded role assignments. + + This methods is called for each discovered assignment that either needs + a group assignment expanded into individual user assignments, or needs + an inherited assignment to be applied to its children. + + In all cases, if either user_id and/or project_id is specified, then we + filter the result on those values. + + """ + + def create_group_assignment(base_ref, user_id): + """Creates a group assignment from the provided ref.""" + + ref = copy.deepcopy(base_ref) + + ref['user_id'] = user_id + + indirect = ref.setdefault('indirect', {}) + indirect['group_id'] = ref.pop('group_id') + + return ref + + def expand_group_assignment(ref, user_id): + """Expands group role assignment. + + For any group role assignment on a target, it is replaced by a list + of role assignments containing one for each user of that group on + that target. + + An example of accepted ref is: + + { + 'group_id': group_id, + 'project_id': project_id, + 'role_id': role_id + } + + Once expanded, it should be returned as a list of entities like the + one below, one for each each user_id in the provided group_id. + + { + 'user_id': user_id, + 'project_id': project_id, + 'role_id': role_id, + 'indirect' : { + 'group_id': group_id + } + } + + Returned list will be formatted by the Controller, which will + deduce a role assignment came from group membership if it has both + 'user_id' in the main body of the dict and 'group_id' in indirect + subdict. + + """ + if user_id: + return [create_group_assignment(ref, user_id=user_id)] + + return [create_group_assignment(ref, user_id=m['id']) + for m in self.identity_api.list_users_in_group( + ref['group_id'])] + + def expand_inherited_assignment(ref, user_id, project_id=None): + """Expands inherited role assignments. + + If this is a group role assignment on a target, replace it by a + list of role assignments containing one for each user of that + group, on every project under that target. + + If this is a user role assignment on a target, replace it by a + list of role assignments for that user on every project under + that target. + + An example of accepted ref is: + + { + 'group_id': group_id, + 'project_id': parent_id, + 'role_id': role_id, + 'inherited_to_projects': 'projects' + } + + Once expanded, it should be returned as a list of entities like the + one below, one for each each user_id in the provided group_id and + for each subproject_id in the project_id subtree. + + { + 'user_id': user_id, + 'project_id': subproject_id, + 'role_id': role_id, + 'indirect' : { + 'group_id': group_id, + 'project_id': parent_id + } + } + + Returned list will be formatted by the Controller, which will + deduce a role assignment came from group membership if it has both + 'user_id' in the main body of the dict and 'group_id' in the + 'indirect' subdict, as well as it is possible to deduce if it has + come from inheritance if it contains both a 'project_id' in the + main body of the dict and 'parent_id' in the 'indirect' subdict. + + """ + def create_inherited_assignment(base_ref, project_id): + """Creates a project assignment from the provided ref. + + base_ref can either be a project or domain inherited + assignment ref. + + """ + ref = copy.deepcopy(base_ref) + + indirect = ref.setdefault('indirect', {}) + if ref.get('project_id'): + indirect['project_id'] = ref.pop('project_id') + else: + indirect['domain_id'] = ref.pop('domain_id') + + ref['project_id'] = project_id + ref.pop('inherited_to_projects') + + return ref + + # Define expanded project list to which to apply this assignment + if project_id: + # Since ref is an inherited assignment, it must have come from + # the domain or a parent. We only need apply it to the project + # requested. + project_ids = [project_id] + elif ref.get('domain_id'): + # A domain inherited assignment, so apply it to all projects + # in this domain + project_ids = ( + [x['id'] for x in + self.resource_api.list_projects_in_domain( + ref['domain_id'])]) + else: + # It must be a project assignment, so apply it to the subtree + project_ids = ( + [x['id'] for x in + self.resource_api.list_projects_in_subtree( + ref['project_id'])]) + + new_refs = [] + if 'group_id' in ref: + # Expand role assignment for all members and for all projects + for ref in expand_group_assignment(ref, user_id): + new_refs += [create_inherited_assignment(ref, proj_id) + for proj_id in project_ids] + else: + # Expand role assignment for all projects + new_refs += [create_inherited_assignment(ref, proj_id) + for proj_id in project_ids] + + return new_refs + + if ref.get('inherited_to_projects') == 'projects': + return expand_inherited_assignment(ref, user_id, project_id) + elif 'group_id' in ref: + return expand_group_assignment(ref, user_id) + return [ref] + + def _list_effective_role_assignments(self, role_id, user_id, group_id, + domain_id, project_id, inherited): + """List role assignments in effective mode. + + When using effective mode, besides the direct assignments, the indirect + ones that come from grouping or inheritance are retrieved and will then + be expanded. + + The resulting list of assignments will be filtered by the provided + parameters, although since we are in effective mode, group can never + act as a filter (since group assignments are expanded into user roles) + and domain can only be filter if we want non-inherited assignments, + since domains can't inherit assignments. + + The goal of this method is to only ask the driver for those + assignments as could effect the result based on the parameter filters + specified, hence avoiding retrieving a huge list. + + """ + + def list_role_assignments_for_actor( + role_id, inherited, user_id=None, + group_ids=None, project_id=None, domain_id=None): + """List role assignments for actor on target. + + List direct and indirect assignments for an actor, optionally + for a given target (i.e. project or domain). + + :param role_id: List for a specific role, can be None meaning all + roles + :param inherited: Indicates whether inherited assignments or only + direct assignments are required. If None, then + both are required. + :param user_id: If not None, list only assignments that affect this + user. + :param group_ids: A list of groups required. Only one of user_id + and group_ids can be specified + :param project_id: If specified, only include those assignments + that affect this project + :param domain_id: If specified, only include those assignments + that affect this domain - by definition this will + not include any inherited assignments + + :returns: List of assignments matching the criteria. Any inherited + or group assignments that could affect the resulting + response are included. + + """ + + # List direct project role assignments + project_ids = [project_id] if project_id else None + + non_inherited_refs = [] + if inherited is False or inherited is None: + # Get non inherited assignments + non_inherited_refs = self.driver.list_role_assignments( + role_id=role_id, domain_id=domain_id, + project_ids=project_ids, user_id=user_id, + group_ids=group_ids, inherited_to_projects=False) + + inherited_refs = [] + if inherited is True or inherited is None: + # Get inherited assignments + if project_id: + # If we are filtering by a specific project, then we can + # only get inherited assignments from its domain or from + # any of its parents. + + # List inherited assignments from the project's domain + proj_domain_id = self.resource_api.get_project( + project_id)['domain_id'] + inherited_refs += self.driver.list_role_assignments( + role_id=role_id, domain_id=proj_domain_id, + user_id=user_id, group_ids=group_ids, + inherited_to_projects=True) + + # And those assignments that could be inherited from the + # project's parents. + parent_ids = [project['id'] for project in + self.resource_api.list_project_parents( + project_id)] + if parent_ids: + inherited_refs += self.driver.list_role_assignments( + role_id=role_id, project_ids=parent_ids, + user_id=user_id, group_ids=group_ids, + inherited_to_projects=True) + else: + # List inherited assignments without filtering by target + inherited_refs = self.driver.list_role_assignments( + role_id=role_id, user_id=user_id, group_ids=group_ids, + inherited_to_projects=True) + + return non_inherited_refs + inherited_refs + + # If filtering by group or inherited domain assignment the list is + # guranteed to be empty + if group_id or (domain_id and inherited): + return [] + + # If filtering by domain, then only non-inherited assignments are + # relevant, since domains don't inherit assignments + inherited = False if domain_id else inherited + + # List user assignments + direct_refs = list_role_assignments_for_actor( + role_id=role_id, user_id=user_id, project_id=project_id, + domain_id=domain_id, inherited=inherited) + + # And those from the user's groups + group_refs = [] + if user_id: + group_ids = self._get_group_ids_for_user_id(user_id) + if group_ids: + group_refs = list_role_assignments_for_actor( + role_id=role_id, project_id=project_id, + group_ids=group_ids, domain_id=domain_id, + inherited=inherited) + + # Expand grouping and inheritance on retrieved role assignments + refs = [] + for ref in (direct_refs + group_refs): + refs += self._expand_indirect_assignment(ref=ref, user_id=user_id, + project_id=project_id) + + return refs + + def _list_direct_role_assignments(self, role_id, user_id, group_id, + domain_id, project_id, inherited): + """List role assignments without applying expansion. + + Returns a list of direct role assignments, where their attributes match + the provided filters. + + """ + group_ids = [group_id] if group_id else None + project_ids = [project_id] if project_id else None + + return self.driver.list_role_assignments( + role_id=role_id, user_id=user_id, group_ids=group_ids, + domain_id=domain_id, project_ids=project_ids, + inherited_to_projects=inherited) + + def list_role_assignments(self, role_id=None, user_id=None, group_id=None, + domain_id=None, project_id=None, inherited=None, + effective=None): + """List role assignments, honoring effective mode and provided filters. + + Returns a list of role assignments, where their attributes match the + provided filters (role_id, user_id, group_id, domain_id, project_id and + inherited). The inherited filter defaults to None, meaning to get both + non-inherited and inherited role assignments. + + If effective mode is specified, this means that rather than simply + return the assignments that match the filters, any group or + inheritance assignments will be expanded. Group assignments will + become assignments for all the users in that group, and inherited + assignments will be shown on the projects below the assignment point. + Think of effective mode as being the list of assignments that actually + affect a user, for example the roles that would be placed in a token. + + If OS-INHERIT extension is disabled or the used driver does not support + inherited roles retrieval, inherited role assignments will be ignored. + + """ + + if not CONF.os_inherit.enabled: + if inherited: + return [] + inherited = False + + if effective: + return self._list_effective_role_assignments( + role_id, user_id, group_id, domain_id, project_id, inherited) + else: + return self._list_direct_role_assignments( + role_id, user_id, group_id, domain_id, project_id, inherited) def delete_tokens_for_role_assignments(self, role_id): assignments = self.list_role_assignments_for_role(role_id=role_id) @@ -532,98 +909,6 @@ class Manager(manager.Manager): # from persistence if persistence is enabled. pass - @deprecated_to_role_api - def create_role(self, role_id, role): - return self.role_api.create_role(role_id, role) - - @deprecated_to_role_api - def get_role(self, role_id): - return self.role_api.get_role(role_id) - - @deprecated_to_role_api - def update_role(self, role_id, role): - return self.role_api.update_role(role_id, role) - - @deprecated_to_role_api - def delete_role(self, role_id): - return self.role_api.delete_role(role_id) - - @deprecated_to_role_api - def list_roles(self, hints=None): - return self.role_api.list_roles(hints=hints) - - @deprecated_to_resource_api - def create_project(self, project_id, project): - return self.resource_api.create_project(project_id, project) - - @deprecated_to_resource_api - def get_project_by_name(self, tenant_name, domain_id): - return self.resource_api.get_project_by_name(tenant_name, domain_id) - - @deprecated_to_resource_api - def get_project(self, project_id): - return self.resource_api.get_project(project_id) - - @deprecated_to_resource_api - def update_project(self, project_id, project): - return self.resource_api.update_project(project_id, project) - - @deprecated_to_resource_api - def delete_project(self, project_id): - return self.resource_api.delete_project(project_id) - - @deprecated_to_resource_api - def list_projects(self, hints=None): - return self.resource_api.list_projects(hints=hints) - - @deprecated_to_resource_api - def list_projects_in_domain(self, domain_id): - return self.resource_api.list_projects_in_domain(domain_id) - - @deprecated_to_resource_api - def create_domain(self, domain_id, domain): - return self.resource_api.create_domain(domain_id, domain) - - @deprecated_to_resource_api - def get_domain_by_name(self, domain_name): - return self.resource_api.get_domain_by_name(domain_name) - - @deprecated_to_resource_api - def get_domain(self, domain_id): - return self.resource_api.get_domain(domain_id) - - @deprecated_to_resource_api - def update_domain(self, domain_id, domain): - return self.resource_api.update_domain(domain_id, domain) - - @deprecated_to_resource_api - def delete_domain(self, domain_id): - return self.resource_api.delete_domain(domain_id) - - @deprecated_to_resource_api - def list_domains(self, hints=None): - return self.resource_api.list_domains(hints=hints) - - @deprecated_to_resource_api - def assert_domain_enabled(self, domain_id, domain=None): - return self.resource_api.assert_domain_enabled(domain_id, domain) - - @deprecated_to_resource_api - def assert_project_enabled(self, project_id, project=None): - return self.resource_api.assert_project_enabled(project_id, project) - - @deprecated_to_resource_api - def is_leaf_project(self, project_id): - return self.resource_api.is_leaf_project(project_id) - - @deprecated_to_resource_api - def list_project_parents(self, project_id, user_id=None): - return self.resource_api.list_project_parents(project_id, user_id) - - @deprecated_to_resource_api - def list_projects_in_subtree(self, project_id, user_id=None): - return self.resource_api.list_projects_in_subtree(project_id, user_id) - @six.add_metaclass(abc.ABCMeta) class Driver(object): @@ -642,26 +927,6 @@ class Driver(object): role_list.append(d['id']) return role_list - def _add_role_to_role_dicts(self, role_id, inherited, dict_list, - allow_existing=True): - # There is a difference in error semantics when trying to - # assign a role that already exists between the coded v2 and v3 - # API calls. v2 will error if the assignment already exists, - # while v3 is silent. Setting the 'allow_existing' parameter - # appropriately lets this call be used for both. - role_set = set([frozenset(r.items()) for r in dict_list]) - key = frozenset(self._role_to_dict(role_id, inherited).items()) - if not allow_existing and key in role_set: - raise KeyError - role_set.add(key) - return [dict(r) for r in role_set] - - def _remove_role_from_role_dicts(self, role_id, inherited, dict_list): - role_set = set([frozenset(r.items()) for r in dict_list]) - role_set.remove(frozenset(self._role_to_dict(role_id, - inherited).items())) - return [dict(r) for r in role_set] - def _get_list_limit(self): return CONF.assignment.list_limit or CONF.list_limit @@ -740,8 +1005,16 @@ class Driver(object): raise exception.NotImplemented() # pragma: no cover @abc.abstractmethod - def list_role_assignments(self): + def list_role_assignments(self, role_id=None, + user_id=None, group_ids=None, + domain_id=None, project_ids=None, + inherited_to_projects=None): + """Returns a list of role assignments for actors on targets. + + Available parameters represent values in which the returned role + assignments attributes need to be filtered on. + """ raise exception.NotImplemented() # pragma: no cover @abc.abstractmethod @@ -866,12 +1139,8 @@ class Driver(object): raise exception.NotImplemented() # pragma: no cover - # TODO(henry-nash): Rename the following two methods to match the more - # meaningfully named ones above. - -# TODO(ayoung): determine what else these two functions raise @abc.abstractmethod - def delete_user(self, user_id): + def delete_user_assignments(self, user_id): """Deletes all assignments for a user. :raises: keystone.exception.RoleNotFound @@ -880,7 +1149,7 @@ class Driver(object): raise exception.NotImplemented() # pragma: no cover @abc.abstractmethod - def delete_group(self, group_id): + def delete_group_assignments(self, group_id): """Deletes all assignments for a group. :raises: keystone.exception.RoleNotFound @@ -894,6 +1163,8 @@ class Driver(object): class RoleManager(manager.Manager): """Default pivot point for the Role backend.""" + driver_namespace = 'keystone.role' + _ROLE = 'role' def __init__(self): @@ -902,9 +1173,8 @@ class RoleManager(manager.Manager): role_driver = CONF.role.driver if role_driver is None: - assignment_driver = ( - dependency.get_provider('assignment_api').driver) - role_driver = assignment_driver.default_role_driver() + assignment_manager = dependency.get_provider('assignment_api') + role_driver = assignment_manager.default_role_driver() super(RoleManager, self).__init__(role_driver) -- cgit 1.2.3-korg