diff options
author | asteroide <thomas.duval@orange.com> | 2015-09-01 16:03:26 +0200 |
---|---|---|
committer | asteroide <thomas.duval@orange.com> | 2015-09-01 16:04:53 +0200 |
commit | 92fd2dbfb672d7b2b1cdfd5dd5cf89f7716b3e12 (patch) | |
tree | 7ba22297042019e7363fa1d4ad26d1c32c5908c6 /keystone-moon/keystone/assignment/backends | |
parent | 26e753254f3e43399cc76e62892908b7742415e8 (diff) |
Update Keystone code from official Github repository with branch Master on 09/01/2015.
Change-Id: I0ff6099e6e2580f87f502002a998bbfe12673498
Diffstat (limited to 'keystone-moon/keystone/assignment/backends')
-rw-r--r-- | keystone-moon/keystone/assignment/backends/ldap.py | 66 | ||||
-rw-r--r-- | keystone-moon/keystone/assignment/backends/sql.py | 108 |
2 files changed, 136 insertions, 38 deletions
diff --git a/keystone-moon/keystone/assignment/backends/ldap.py b/keystone-moon/keystone/assignment/backends/ldap.py index f93e989f..4ca66c4d 100644 --- a/keystone-moon/keystone/assignment/backends/ldap.py +++ b/keystone-moon/keystone/assignment/backends/ldap.py @@ -13,10 +13,10 @@ # under the License. from __future__ import absolute_import -import ldap as ldap import ldap.filter from oslo_config import cfg from oslo_log import log +from oslo_log import versionutils from keystone import assignment from keystone.assignment.role_backends import ldap as ldap_role @@ -25,7 +25,6 @@ from keystone.common import models from keystone import exception from keystone.i18n import _ from keystone.identity.backends import ldap as ldap_identity -from keystone.openstack.common import versionutils CONF = cfg.CONF @@ -36,7 +35,7 @@ class Assignment(assignment.Driver): @versionutils.deprecated( versionutils.deprecated.KILO, remove_in=+2, - what='keystone.assignment.backends.ldap.Assignment') + what='ldap') def __init__(self): super(Assignment, self).__init__() self.LDAP_URL = CONF.ldap.url @@ -54,10 +53,10 @@ class Assignment(assignment.Driver): self.role = RoleApi(CONF, self.user) def default_role_driver(self): - return 'keystone.assignment.role_backends.ldap.Role' + return 'ldap' def default_resource_driver(self): - return 'keystone.resource.backends.ldap.Resource' + return 'ldap' def list_role_ids_for_groups_on_project( self, groups, project_id, project_domain_id, project_parents): @@ -181,7 +180,7 @@ class Assignment(assignment.Driver): self.group._id_to_dn(group_id), role_id) # Bulk actions on User From identity - def delete_user(self, user_id): + def delete_user_assignments(self, user_id): user_dn = self.user._id_to_dn(user_id) for ref in self.role.list_global_roles_for_user(user_dn): self.role.delete_user(ref.role_dn, ref.user_dn, @@ -191,7 +190,7 @@ class Assignment(assignment.Driver): self.role.delete_user(ref.role_dn, ref.user_dn, self.role._dn_to_id(ref.role_dn)) - def delete_group(self, group_id): + def delete_group_assignments(self, group_id): """Called when the group was deleted. Any role assignments for the group should be cleaned up. @@ -277,20 +276,39 @@ class Assignment(assignment.Driver): return self._roles_from_role_dicts(metadata_ref.get('roles', []), inherited_to_projects) - 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): role_assignments = [] - for a in self.role.list_role_assignments(self.project.tree_dn): - if isinstance(a, UserRoleAssociation): - assignment = { - 'role_id': self.role._dn_to_id(a.role_dn), - 'user_id': self.user._dn_to_id(a.user_dn), - 'project_id': self.project._dn_to_id(a.project_dn)} - else: - assignment = { - 'role_id': self.role._dn_to_id(a.role_dn), - 'group_id': self.group._dn_to_id(a.group_dn), - 'project_id': self.project._dn_to_id(a.project_dn)} - role_assignments.append(assignment) + + # Since the LDAP backend does not support assignments to domains, if + # the request is to filter by domain, then the answer is guaranteed + # to be an empty list. + if not domain_id: + for a in self.role.list_role_assignments(self.project.tree_dn): + if isinstance(a, UserRoleAssociation): + assignment = { + 'role_id': self.role._dn_to_id(a.role_dn), + 'user_id': self.user._dn_to_id(a.user_dn), + 'project_id': self.project._dn_to_id(a.project_dn)} + else: + assignment = { + 'role_id': self.role._dn_to_id(a.role_dn), + 'group_id': self.group._dn_to_id(a.group_dn), + 'project_id': self.project._dn_to_id(a.project_dn)} + + if role_id and assignment['role_id'] != role_id: + continue + if user_id and assignment.get('user_id') != user_id: + continue + if group_ids and assignment.get('group_id') not in group_ids: + continue + if project_ids and assignment['project_id'] not in project_ids: + continue + + role_assignments.append(assignment) + return role_assignments def delete_project_assignments(self, project_id): @@ -313,9 +331,7 @@ class ProjectApi(common_ldap.ProjectLdapStructureMixin, or self.DEFAULT_MEMBER_ATTRIBUTE) def get_user_projects(self, user_dn, associations): - """Returns list of tenants a user has access to - """ - + """Returns the list of tenants to which a user has access.""" project_ids = set() for assoc in associations: project_ids.add(self._dn_to_id(assoc.project_dn)) @@ -497,9 +513,7 @@ class RoleApi(ldap_role.RoleLdapStructureMixin, common_ldap.BaseLdap): self.id_attr: role_id}) def list_role_assignments(self, project_tree_dn): - """Returns a list of all the role assignments linked to project_tree_dn - attribute. - """ + """List the role assignments linked to project_tree_dn attribute.""" try: roles = self._ldap_get_list(project_tree_dn, ldap.SCOPE_SUBTREE, attrlist=[self.member_attribute]) diff --git a/keystone-moon/keystone/assignment/backends/sql.py b/keystone-moon/keystone/assignment/backends/sql.py index 2de6ca60..89ff64b5 100644 --- a/keystone-moon/keystone/assignment/backends/sql.py +++ b/keystone-moon/keystone/assignment/backends/sql.py @@ -14,7 +14,6 @@ from oslo_config import cfg from oslo_log import log -import six import sqlalchemy from sqlalchemy.sql.expression import false @@ -53,10 +52,10 @@ class AssignmentType(object): class Assignment(keystone_assignment.Driver): def default_role_driver(self): - return "keystone.assignment.role_backends.sql.Role" + return 'sql' def default_resource_driver(self): - return 'keystone.resource.backends.sql.Resource' + return 'sql' def list_user_ids_for_project(self, tenant_id): with sql.transaction() as session: @@ -336,7 +335,62 @@ class Assignment(keystone_assignment.Driver): 'Cannot remove role that has not been granted, %s') % role_id) - def list_role_assignments(self): + def _get_user_assignment_types(self): + return [AssignmentType.USER_PROJECT, AssignmentType.USER_DOMAIN] + + def _get_group_assignment_types(self): + return [AssignmentType.GROUP_PROJECT, AssignmentType.GROUP_DOMAIN] + + def _get_project_assignment_types(self): + return [AssignmentType.USER_PROJECT, AssignmentType.GROUP_PROJECT] + + def _get_domain_assignment_types(self): + return [AssignmentType.USER_DOMAIN, AssignmentType.GROUP_DOMAIN] + + def _get_assignment_types(self, user, group, project, domain): + """Returns a list of role assignment types based on provided entities + + If one of user or group (the "actor") as well as one of project or + domain (the "target") are provided, the list will contain the role + assignment type for that specific pair of actor and target. + + If only an actor or target is provided, the list will contain the + role assignment types that satisfy the specified entity. + + For example, if user and project are provided, the return will be: + + [AssignmentType.USER_PROJECT] + + However, if only user was provided, the return would be: + + [AssignmentType.USER_PROJECT, AssignmentType.USER_DOMAIN] + + It is not expected that user and group (or project and domain) are + specified - but if they are, the most fine-grained value will be + chosen (i.e. user over group, project over domain). + + """ + actor_types = [] + if user: + actor_types = self._get_user_assignment_types() + elif group: + actor_types = self._get_group_assignment_types() + + target_types = [] + if project: + target_types = self._get_project_assignment_types() + elif domain: + target_types = self._get_domain_assignment_types() + + if actor_types and target_types: + return list(set(actor_types).intersection(target_types)) + + return actor_types or target_types + + def list_role_assignments(self, role_id=None, + user_id=None, group_ids=None, + domain_id=None, project_ids=None, + inherited_to_projects=None): def denormalize_role(ref): assignment = {} @@ -362,8 +416,35 @@ class Assignment(keystone_assignment.Driver): return assignment with sql.transaction() as session: - refs = session.query(RoleAssignment).all() - return [denormalize_role(ref) for ref in refs] + assignment_types = self._get_assignment_types( + user_id, group_ids, project_ids, domain_id) + + targets = None + if project_ids: + targets = project_ids + elif domain_id: + targets = [domain_id] + + actors = None + if group_ids: + actors = group_ids + elif user_id: + actors = [user_id] + + query = session.query(RoleAssignment) + + if role_id: + query = query.filter_by(role_id=role_id) + if actors: + query = query.filter(RoleAssignment.actor_id.in_(actors)) + if targets: + query = query.filter(RoleAssignment.target_id.in_(targets)) + if assignment_types: + query = query.filter(RoleAssignment.type.in_(assignment_types)) + if inherited_to_projects is not None: + query = query.filter_by(inherited=inherited_to_projects) + + return [denormalize_role(ref) for ref in query.all()] def delete_project_assignments(self, project_id): with sql.transaction() as session: @@ -377,13 +458,13 @@ class Assignment(keystone_assignment.Driver): q = q.filter_by(role_id=role_id) q.delete(False) - def delete_user(self, user_id): + def delete_user_assignments(self, user_id): with sql.transaction() as session: q = session.query(RoleAssignment) q = q.filter_by(actor_id=user_id) q.delete(False) - def delete_group(self, group_id): + def delete_group_assignments(self, group_id): with sql.transaction() as session: q = session.query(RoleAssignment) q = q.filter_by(actor_id=group_id) @@ -399,12 +480,15 @@ class RoleAssignment(sql.ModelBase, sql.DictBase): AssignmentType.USER_DOMAIN, AssignmentType.GROUP_DOMAIN, name='type'), nullable=False) - actor_id = sql.Column(sql.String(64), nullable=False, index=True) + actor_id = sql.Column(sql.String(64), nullable=False) target_id = sql.Column(sql.String(64), nullable=False) role_id = sql.Column(sql.String(64), nullable=False) inherited = sql.Column(sql.Boolean, default=False, nullable=False) - __table_args__ = (sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', - 'role_id'), {}) + __table_args__ = ( + sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id', + 'inherited'), + sql.Index('ix_actor_id', 'actor_id'), + ) def to_dict(self): """Override parent to_dict() method with a simpler implementation. @@ -412,4 +496,4 @@ class RoleAssignment(sql.ModelBase, sql.DictBase): RoleAssignment doesn't have non-indexed 'extra' attributes, so the parent implementation is not applicable. """ - return dict(six.iteritems(self)) + return dict(self.items()) |