summaryrefslogtreecommitdiffstats
path: root/keystone/identity/backends/sql.py
diff options
context:
space:
mode:
Diffstat (limited to 'keystone/identity/backends/sql.py')
-rw-r--r--keystone/identity/backends/sql.py632
1 files changed, 9 insertions, 623 deletions
diff --git a/keystone/identity/backends/sql.py b/keystone/identity/backends/sql.py
index f81feb1d..bff41106 100644
--- a/keystone/identity/backends/sql.py
+++ b/keystone/identity/backends/sql.py
@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from keystone import clean
+from keystone.common import dependency
from keystone.common import sql
from keystone.common.sql import migration
from keystone.common import utils
@@ -51,78 +51,6 @@ class Group(sql.ModelBase, sql.DictBase):
__table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {})
-class Domain(sql.ModelBase, sql.DictBase):
- __tablename__ = 'domain'
- attributes = ['id', 'name', 'enabled']
- id = sql.Column(sql.String(64), primary_key=True)
- name = sql.Column(sql.String(64), unique=True, nullable=False)
- enabled = sql.Column(sql.Boolean, default=True)
- extra = sql.Column(sql.JsonBlob())
-
-
-class Project(sql.ModelBase, sql.DictBase):
- __tablename__ = 'project'
- attributes = ['id', 'name', 'domain_id', 'description', 'enabled']
- id = sql.Column(sql.String(64), primary_key=True)
- name = sql.Column(sql.String(64), nullable=False)
- domain_id = sql.Column(sql.String(64), sql.ForeignKey('domain.id'),
- nullable=False)
- description = sql.Column(sql.Text())
- enabled = sql.Column(sql.Boolean)
- extra = sql.Column(sql.JsonBlob())
- # Unique constraint across two columns to create the separation
- # rather than just only 'name' being unique
- __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {})
-
-
-class Role(sql.ModelBase, sql.DictBase):
- __tablename__ = 'role'
- attributes = ['id', 'name']
- id = sql.Column(sql.String(64), primary_key=True)
- name = sql.Column(sql.String(64), unique=True, nullable=False)
- extra = sql.Column(sql.JsonBlob())
-
-
-class BaseGrant(sql.DictBase):
- def to_dict(self):
- """Override parent to_dict() method with a simpler implementation.
-
- Grant tables don't have non-indexed 'extra' attributes, so the
- parent implementation is not applicable.
- """
- return dict(self.iteritems())
-
-
-class UserProjectGrant(sql.ModelBase, BaseGrant):
- __tablename__ = 'user_project_metadata'
- user_id = sql.Column(sql.String(64),
- primary_key=True)
- project_id = sql.Column(sql.String(64),
- primary_key=True)
- data = sql.Column(sql.JsonBlob())
-
-
-class UserDomainGrant(sql.ModelBase, BaseGrant):
- __tablename__ = 'user_domain_metadata'
- user_id = sql.Column(sql.String(64), primary_key=True)
- domain_id = sql.Column(sql.String(64), primary_key=True)
- data = sql.Column(sql.JsonBlob())
-
-
-class GroupProjectGrant(sql.ModelBase, BaseGrant):
- __tablename__ = 'group_project_metadata'
- group_id = sql.Column(sql.String(64), primary_key=True)
- project_id = sql.Column(sql.String(64), primary_key=True)
- data = sql.Column(sql.JsonBlob())
-
-
-class GroupDomainGrant(sql.ModelBase, BaseGrant):
- __tablename__ = 'group_domain_metadata'
- group_id = sql.Column(sql.String(64), primary_key=True)
- domain_id = sql.Column(sql.String(64), primary_key=True)
- data = sql.Column(sql.JsonBlob())
-
-
class UserGroupMembership(sql.ModelBase, sql.DictBase):
"""Group membership join table."""
__tablename__ = 'user_group_membership'
@@ -134,7 +62,11 @@ class UserGroupMembership(sql.ModelBase, sql.DictBase):
primary_key=True)
+@dependency.requires('assignment_api')
class Identity(sql.Base, identity.Driver):
+ def default_assignment_driver(self):
+ return "keystone.assignment.backends.sql.Assignment"
+
# Internal interface to manage the database
def db_sync(self, version=None):
migration.db_sync(version=version)
@@ -154,7 +86,7 @@ class Identity(sql.Base, identity.Driver):
return utils.check_password(password, user_ref.password)
# Identity interface
- def authenticate_user(self, user_id=None, password=None):
+ def authenticate(self, user_id, password):
session = self.get_session()
user_ref = None
try:
@@ -163,464 +95,7 @@ class Identity(sql.Base, identity.Driver):
raise AssertionError('Invalid user / password')
if not self._check_password(password, user_ref):
raise AssertionError('Invalid user / password')
- return user_ref
-
- def authorize_for_project(self, user_ref, tenant_id=None):
- user_id = user_ref['id']
- tenant_ref = None
- metadata_ref = {}
- if tenant_id is not None:
- # FIXME(gyee): this should really be
- # get_roles_for_user_and_project() after the dusts settle
- if tenant_id not in self.get_projects_for_user(user_id):
- raise AssertionError('Invalid project')
- try:
- tenant_ref = self.get_project(tenant_id)
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.ProjectNotFound:
- tenant_ref = None
- metadata_ref = {}
- except exception.MetadataNotFound:
- metadata_ref = {}
- user_ref = identity.filter_user(user_ref.to_dict())
- return (user_ref, tenant_ref, metadata_ref)
-
- def _get_project(self, session, project_id):
- project_ref = session.query(Project).get(project_id)
- if project_ref is None:
- raise exception.ProjectNotFound(project_id=project_id)
- return project_ref
-
- def get_project(self, tenant_id):
- session = self.get_session()
- return self._get_project(session, tenant_id).to_dict()
-
- def get_project_by_name(self, tenant_name, domain_id):
- session = self.get_session()
- query = session.query(Project)
- query = query.filter_by(name=tenant_name)
- query = query.filter_by(domain_id=domain_id)
- try:
- project_ref = query.one()
- except sql.NotFound:
- raise exception.ProjectNotFound(project_id=tenant_name)
- return project_ref.to_dict()
-
- def get_project_user_ids(self, tenant_id):
- session = self.get_session()
- self.get_project(tenant_id)
- query = session.query(UserProjectGrant)
- query = query.filter(UserProjectGrant.project_id == tenant_id)
- project_refs = query.all()
- return [project_ref.user_id for project_ref in project_refs]
-
- def get_project_users(self, tenant_id):
- session = self.get_session()
- self.get_project(tenant_id)
- user_refs = []
- for user_id in self.get_project_user_ids(tenant_id):
- query = session.query(User)
- query = query.filter(User.id == user_id)
- user_ref = query.first()
- user_refs.append(identity.filter_user(user_ref.to_dict()))
- return user_refs
-
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
- session = self.get_session()
-
- if user_id:
- if tenant_id:
- q = session.query(UserProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- elif domain_id:
- q = session.query(UserDomainGrant)
- q = q.filter_by(domain_id=domain_id)
- q = q.filter_by(user_id=user_id)
- elif group_id:
- if tenant_id:
- q = session.query(GroupProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- elif domain_id:
- q = session.query(GroupDomainGrant)
- q = q.filter_by(domain_id=domain_id)
- q = q.filter_by(group_id=group_id)
- try:
- return q.one().data
- except sql.NotFound:
- raise exception.MetadataNotFound()
-
- def create_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- session = self.get_session()
- self._get_role(session, role_id)
- if user_id:
- self._get_user(session, user_id)
- if group_id:
- self._get_group(session, group_id)
- if domain_id:
- self._get_domain(session, domain_id)
- if project_id:
- self._get_project(session, project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- is_new = False
- except exception.MetadataNotFound:
- metadata_ref = {}
- is_new = True
- roles = set(metadata_ref.get('roles', []))
- roles.add(role_id)
- metadata_ref['roles'] = list(roles)
- if is_new:
- self.create_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
- else:
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
-
- def list_grants(self, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- session = self.get_session()
- if user_id:
- self._get_user(session, user_id)
- if group_id:
- self._get_group(session, group_id)
- if domain_id:
- self._get_domain(session, domain_id)
- if project_id:
- self._get_project(session, project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- return [self.get_role(x) for x in metadata_ref.get('roles', [])]
-
- def get_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- session = self.get_session()
- role_ref = self._get_role(session, role_id)
- if user_id:
- self._get_user(session, user_id)
- if group_id:
- self._get_group(session, group_id)
- if domain_id:
- self._get_domain(session, domain_id)
- if project_id:
- self._get_project(session, project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- role_ids = set(metadata_ref.get('roles', []))
- if role_id not in role_ids:
- raise exception.RoleNotFound(role_id=role_id)
- return role_ref.to_dict()
-
- def delete_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- session = self.get_session()
- self._get_role(session, role_id)
- if user_id:
- self._get_user(session, user_id)
- if group_id:
- self._get_group(session, group_id)
- if domain_id:
- self._get_domain(session, domain_id)
- if project_id:
- self._get_project(session, project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- is_new = False
- except exception.MetadataNotFound:
- metadata_ref = {}
- is_new = True
- roles = set(metadata_ref.get('roles', []))
- try:
- roles.remove(role_id)
- except KeyError:
- raise exception.RoleNotFound(role_id=role_id)
- metadata_ref['roles'] = list(roles)
- if is_new:
- self.create_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
- else:
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
-
- def list_projects(self):
- session = self.get_session()
- tenant_refs = session.query(Project).all()
- return [tenant_ref.to_dict() for tenant_ref in tenant_refs]
-
- def get_projects_for_user(self, user_id):
- session = self.get_session()
- self._get_user(session, user_id)
- query = session.query(UserProjectGrant)
- query = query.filter_by(user_id=user_id)
- membership_refs = query.all()
- return [x.project_id for x in membership_refs]
-
- def _get_user_group_project_roles(self, metadata_ref, user_id, project_id):
- group_refs = self.list_groups_for_user(user_id=user_id)
- for x in group_refs:
- try:
- metadata_ref.update(
- self.get_metadata(group_id=x['id'],
- tenant_id=project_id))
- except exception.MetadataNotFound:
- # no group grant, skip
- pass
-
- def _get_user_project_roles(self, metadata_ref, user_id, project_id):
- try:
- metadata_ref.update(self.get_metadata(user_id, project_id))
- except exception.MetadataNotFound:
- pass
-
- def get_roles_for_user_and_project(self, user_id, tenant_id):
- session = self.get_session()
- self._get_user(session, user_id)
- self._get_project(session, tenant_id)
- metadata_ref = {}
- self._get_user_project_roles(metadata_ref, user_id, tenant_id)
- self._get_user_group_project_roles(metadata_ref, user_id, tenant_id)
- return list(set(metadata_ref.get('roles', [])))
-
- def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
- session = self.get_session()
- self._get_user(session, user_id)
- self._get_project(session, tenant_id)
- self._get_role(session, role_id)
- try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
- is_new = False
- except exception.MetadataNotFound:
- metadata_ref = {}
- is_new = True
- roles = set(metadata_ref.get('roles', []))
- if role_id in roles:
- msg = ('User %s already has role %s in tenant %s'
- % (user_id, role_id, tenant_id))
- raise exception.Conflict(type='role grant', details=msg)
- roles.add(role_id)
- metadata_ref['roles'] = list(roles)
- if is_new:
- self.create_metadata(user_id, tenant_id, metadata_ref)
- else:
- self.update_metadata(user_id, tenant_id, metadata_ref)
-
- def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
- try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
- roles = set(metadata_ref.get('roles', []))
- if role_id not in roles:
- raise exception.RoleNotFound(message=_(
- 'Cannot remove role that has not been granted, %s') %
- role_id)
- roles.remove(role_id)
- metadata_ref['roles'] = list(roles)
- if len(roles):
- self.update_metadata(user_id, tenant_id, metadata_ref)
- else:
- session = self.get_session()
- q = session.query(UserProjectGrant)
- q = q.filter_by(user_id=user_id)
- q = q.filter_by(project_id=tenant_id)
- q.delete()
- except exception.MetadataNotFound:
- msg = 'Cannot remove role that has not been granted, %s' % role_id
- raise exception.RoleNotFound(message=msg)
-
- # CRUD
- @sql.handle_conflicts(type='project')
- def create_project(self, tenant_id, tenant):
- tenant['name'] = clean.project_name(tenant['name'])
- session = self.get_session()
- with session.begin():
- tenant_ref = Project.from_dict(tenant)
- session.add(tenant_ref)
- session.flush()
- return tenant_ref.to_dict()
-
- @sql.handle_conflicts(type='project')
- def update_project(self, tenant_id, tenant):
- session = self.get_session()
-
- if 'name' in tenant:
- tenant['name'] = clean.project_name(tenant['name'])
-
- with session.begin():
- tenant_ref = self._get_project(session, tenant_id)
- old_project_dict = tenant_ref.to_dict()
- for k in tenant:
- old_project_dict[k] = tenant[k]
- new_project = Project.from_dict(old_project_dict)
- for attr in Project.attributes:
- if attr != 'id':
- setattr(tenant_ref, attr, getattr(new_project, attr))
- tenant_ref.extra = new_project.extra
- session.flush()
- return tenant_ref.to_dict(include_extra_dict=True)
-
- @sql.handle_conflicts(type='project')
- def delete_project(self, tenant_id):
- session = self.get_session()
-
- with session.begin():
- tenant_ref = self._get_project(session, tenant_id)
-
- q = session.query(UserProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- q.delete(False)
-
- q = session.query(UserProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- q.delete(False)
-
- q = session.query(GroupProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- q.delete(False)
-
- session.delete(tenant_ref)
- session.flush()
-
- @sql.handle_conflicts(type='metadata')
- def create_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- session = self.get_session()
- with session.begin():
- if user_id:
- if tenant_id:
- session.add(UserProjectGrant(user_id=user_id,
- project_id=tenant_id,
- data=metadata))
- elif domain_id:
- session.add(UserDomainGrant(user_id=user_id,
- domain_id=domain_id,
- data=metadata))
- elif group_id:
- if tenant_id:
- session.add(GroupProjectGrant(group_id=group_id,
- project_id=tenant_id,
- data=metadata))
- elif domain_id:
- session.add(GroupDomainGrant(group_id=group_id,
- domain_id=domain_id,
- data=metadata))
- session.flush()
- return metadata
-
- @sql.handle_conflicts(type='metadata')
- def update_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- session = self.get_session()
- with session.begin():
- if user_id:
- if tenant_id:
- q = session.query(UserProjectGrant)
- q = q.filter_by(user_id=user_id)
- q = q.filter_by(project_id=tenant_id)
- elif domain_id:
- q = session.query(UserDomainGrant)
- q = q.filter_by(user_id=user_id)
- q = q.filter_by(domain_id=domain_id)
- elif group_id:
- if tenant_id:
- q = session.query(GroupProjectGrant)
- q = q.filter_by(group_id=group_id)
- q = q.filter_by(project_id=tenant_id)
- elif domain_id:
- q = session.query(GroupDomainGrant)
- q = q.filter_by(group_id=group_id)
- q = q.filter_by(domain_id=domain_id)
- metadata_ref = q.first()
- data = metadata_ref.data.copy()
- data.update(metadata)
- metadata_ref.data = data
- session.flush()
- return metadata_ref
-
- # domain crud
-
- @sql.handle_conflicts(type='domain')
- def create_domain(self, domain_id, domain):
- session = self.get_session()
- with session.begin():
- ref = Domain.from_dict(domain)
- session.add(ref)
- session.flush()
- return ref.to_dict()
-
- def list_domains(self):
- session = self.get_session()
- refs = session.query(Domain).all()
- return [ref.to_dict() for ref in refs]
-
- def _get_domain(self, session, domain_id):
- ref = session.query(Domain).get(domain_id)
- if ref is None:
- raise exception.DomainNotFound(domain_id=domain_id)
- return ref
-
- def get_domain(self, domain_id):
- session = self.get_session()
- return self._get_domain(session, domain_id).to_dict()
-
- def get_domain_by_name(self, domain_name):
- session = self.get_session()
- try:
- ref = session.query(Domain).filter_by(name=domain_name).one()
- except sql.NotFound:
- raise exception.DomainNotFound(domain_id=domain_name)
- return ref.to_dict()
-
- @sql.handle_conflicts(type='domain')
- def update_domain(self, domain_id, domain):
- session = self.get_session()
- with session.begin():
- ref = self._get_domain(session, domain_id)
- old_dict = ref.to_dict()
- for k in domain:
- old_dict[k] = domain[k]
- new_domain = Domain.from_dict(old_dict)
- for attr in Domain.attributes:
- if attr != 'id':
- setattr(ref, attr, getattr(new_domain, attr))
- ref.extra = new_domain.extra
- session.flush()
- return ref.to_dict()
-
- def delete_domain(self, domain_id):
- session = self.get_session()
- with session.begin():
- ref = self._get_domain(session, domain_id)
- session.delete(ref)
- session.flush()
-
- def list_user_projects(self, user_id):
- session = self.get_session()
- user = self.get_user(user_id)
- metadata_refs = session\
- .query(UserProjectGrant)\
- .filter_by(user_id=user_id)
- project_ids = set([x.project_id for x in metadata_refs
- if x.data.get('roles')])
- if user.get('project_id'):
- project_ids.add(user['project_id'])
-
- # FIXME(dolph): this should be removed with proper migrations
- if user.get('tenant_id'):
- project_ids.add(user['tenant_id'])
-
- return [self.get_project(x) for x in project_ids]
+ return identity.filter_user(user_ref.to_dict())
# user crud
@@ -742,20 +217,13 @@ class Identity(sql.Base, identity.Driver):
with session.begin():
ref = self._get_user(session, user_id)
- q = session.query(UserProjectGrant)
- q = q.filter_by(user_id=user_id)
- q.delete(False)
-
- q = session.query(UserDomainGrant)
- q = q.filter_by(user_id=user_id)
- q.delete(False)
-
q = session.query(UserGroupMembership)
q = q.filter_by(user_id=user_id)
q.delete(False)
session.delete(ref)
session.flush()
+ self.assignment_api.delete_user(user_id)
# group crud
@@ -806,92 +274,10 @@ class Identity(sql.Base, identity.Driver):
with session.begin():
ref = self._get_group(session, group_id)
- q = session.query(GroupProjectGrant)
- q = q.filter_by(group_id=group_id)
- q.delete(False)
-
- q = session.query(GroupDomainGrant)
- q = q.filter_by(group_id=group_id)
- q.delete(False)
-
q = session.query(UserGroupMembership)
q = q.filter_by(group_id=group_id)
q.delete(False)
session.delete(ref)
session.flush()
-
- # role crud
-
- @sql.handle_conflicts(type='role')
- def create_role(self, role_id, role):
- session = self.get_session()
- with session.begin():
- ref = Role.from_dict(role)
- session.add(ref)
- session.flush()
- return ref.to_dict()
-
- def list_roles(self):
- session = self.get_session()
- refs = session.query(Role).all()
- return [ref.to_dict() for ref in refs]
-
- def _get_role(self, session, role_id):
- ref = session.query(Role).get(role_id)
- if ref is None:
- raise exception.RoleNotFound(role_id=role_id)
- return ref
-
- def get_role(self, role_id):
- session = self.get_session()
- return self._get_role(session, role_id).to_dict()
-
- @sql.handle_conflicts(type='role')
- def update_role(self, role_id, role):
- session = self.get_session()
- with session.begin():
- ref = self._get_role(session, role_id)
- old_dict = ref.to_dict()
- for k in role:
- old_dict[k] = role[k]
- new_role = Role.from_dict(old_dict)
- for attr in Role.attributes:
- if attr != 'id':
- setattr(ref, attr, getattr(new_role, attr))
- ref.extra = new_role.extra
- session.flush()
- return ref.to_dict()
-
- def delete_role(self, role_id):
- session = self.get_session()
-
- with session.begin():
- ref = self._get_role(session, role_id)
- for metadata_ref in session.query(UserProjectGrant):
- try:
- self.delete_grant(role_id, user_id=metadata_ref.user_id,
- project_id=metadata_ref.project_id)
- except exception.RoleNotFound:
- pass
- for metadata_ref in session.query(UserDomainGrant):
- try:
- self.delete_grant(role_id, user_id=metadata_ref.user_id,
- domain_id=metadata_ref.domain_id)
- except exception.RoleNotFound:
- pass
- for metadata_ref in session.query(GroupProjectGrant):
- try:
- self.delete_grant(role_id, group_id=metadata_ref.group_id,
- project_id=metadata_ref.project_id)
- except exception.RoleNotFound:
- pass
- for metadata_ref in session.query(GroupDomainGrant):
- try:
- self.delete_grant(role_id, group_id=metadata_ref.group_id,
- domain_id=metadata_ref.domain_id)
- except exception.RoleNotFound:
- pass
-
- session.delete(ref)
- session.flush()
+ self.assignment_api.delete_group(group_id)