summaryrefslogtreecommitdiffstats
path: root/keystone-moon/keystone/assignment/role_backends
diff options
context:
space:
mode:
Diffstat (limited to 'keystone-moon/keystone/assignment/role_backends')
-rw-r--r--keystone-moon/keystone/assignment/role_backends/__init__.py0
-rw-r--r--keystone-moon/keystone/assignment/role_backends/ldap.py125
-rw-r--r--keystone-moon/keystone/assignment/role_backends/sql.py80
3 files changed, 205 insertions, 0 deletions
diff --git a/keystone-moon/keystone/assignment/role_backends/__init__.py b/keystone-moon/keystone/assignment/role_backends/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone-moon/keystone/assignment/role_backends/__init__.py
diff --git a/keystone-moon/keystone/assignment/role_backends/ldap.py b/keystone-moon/keystone/assignment/role_backends/ldap.py
new file mode 100644
index 00000000..d5a06a4c
--- /dev/null
+++ b/keystone-moon/keystone/assignment/role_backends/ldap.py
@@ -0,0 +1,125 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from __future__ import absolute_import
+
+from oslo_config import cfg
+from oslo_log import log
+
+from keystone import assignment
+from keystone.common import ldap as common_ldap
+from keystone.common import models
+from keystone import exception
+from keystone.i18n import _
+from keystone.identity.backends import ldap as ldap_identity
+
+
+CONF = cfg.CONF
+LOG = log.getLogger(__name__)
+
+
+class Role(assignment.RoleDriver):
+
+ def __init__(self):
+ super(Role, self).__init__()
+ self.LDAP_URL = CONF.ldap.url
+ self.LDAP_USER = CONF.ldap.user
+ self.LDAP_PASSWORD = CONF.ldap.password
+ self.suffix = CONF.ldap.suffix
+
+ # This is the only deep dependency from resource back
+ # to identity. The assumption is that if you are using
+ # LDAP for resource, you are using it for identity as well.
+ self.user = ldap_identity.UserApi(CONF)
+ self.role = RoleApi(CONF, self.user)
+
+ def get_role(self, role_id):
+ return self.role.get(role_id)
+
+ def list_roles(self, hints):
+ return self.role.get_all()
+
+ def list_roles_from_ids(self, ids):
+ return [self.get_role(id) for id in ids]
+
+ def create_role(self, role_id, role):
+ self.role.check_allow_create()
+ try:
+ self.get_role(role_id)
+ except exception.NotFound:
+ pass
+ else:
+ msg = _('Duplicate ID, %s.') % role_id
+ raise exception.Conflict(type='role', details=msg)
+
+ try:
+ self.role.get_by_name(role['name'])
+ except exception.NotFound:
+ pass
+ else:
+ msg = _('Duplicate name, %s.') % role['name']
+ raise exception.Conflict(type='role', details=msg)
+
+ return self.role.create(role)
+
+ def delete_role(self, role_id):
+ self.role.check_allow_delete()
+ return self.role.delete(role_id)
+
+ def update_role(self, role_id, role):
+ self.role.check_allow_update()
+ self.get_role(role_id)
+ return self.role.update(role_id, role)
+
+
+# NOTE(heny-nash): A mixin class to enable the sharing of the LDAP structure
+# between here and the assignment LDAP.
+class RoleLdapStructureMixin(object):
+ DEFAULT_OU = 'ou=Roles'
+ DEFAULT_STRUCTURAL_CLASSES = []
+ DEFAULT_OBJECTCLASS = 'organizationalRole'
+ DEFAULT_MEMBER_ATTRIBUTE = 'roleOccupant'
+ NotFound = exception.RoleNotFound
+ options_name = 'role'
+ attribute_options_names = {'name': 'name'}
+ immutable_attrs = ['id']
+ model = models.Role
+
+
+# TODO(termie): turn this into a data object and move logic to driver
+class RoleApi(RoleLdapStructureMixin, common_ldap.BaseLdap):
+
+ def __init__(self, conf, user_api):
+ super(RoleApi, self).__init__(conf)
+ self._user_api = user_api
+
+ def get(self, role_id, role_filter=None):
+ model = super(RoleApi, self).get(role_id, role_filter)
+ return model
+
+ def create(self, values):
+ return super(RoleApi, self).create(values)
+
+ def update(self, role_id, role):
+ new_name = role.get('name')
+ if new_name is not None:
+ try:
+ old_role = self.get_by_name(new_name)
+ if old_role['id'] != role_id:
+ raise exception.Conflict(
+ _('Cannot duplicate name %s') % old_role)
+ except exception.NotFound:
+ pass
+ return super(RoleApi, self).update(role_id, role)
+
+ def delete(self, role_id):
+ super(RoleApi, self).delete(role_id)
diff --git a/keystone-moon/keystone/assignment/role_backends/sql.py b/keystone-moon/keystone/assignment/role_backends/sql.py
new file mode 100644
index 00000000..f19d1827
--- /dev/null
+++ b/keystone-moon/keystone/assignment/role_backends/sql.py
@@ -0,0 +1,80 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from keystone import assignment
+from keystone.common import sql
+from keystone import exception
+
+
+class Role(assignment.RoleDriver):
+
+ @sql.handle_conflicts(conflict_type='role')
+ def create_role(self, role_id, role):
+ with sql.transaction() as session:
+ ref = RoleTable.from_dict(role)
+ session.add(ref)
+ return ref.to_dict()
+
+ @sql.truncated
+ def list_roles(self, hints):
+ with sql.transaction() as session:
+ query = session.query(RoleTable)
+ refs = sql.filter_limit_query(RoleTable, query, hints)
+ return [ref.to_dict() for ref in refs]
+
+ def list_roles_from_ids(self, ids):
+ if not ids:
+ return []
+ else:
+ with sql.transaction() as session:
+ query = session.query(RoleTable)
+ query = query.filter(RoleTable.id.in_(ids))
+ role_refs = query.all()
+ return [role_ref.to_dict() for role_ref in role_refs]
+
+ def _get_role(self, session, role_id):
+ ref = session.query(RoleTable).get(role_id)
+ if ref is None:
+ raise exception.RoleNotFound(role_id=role_id)
+ return ref
+
+ def get_role(self, role_id):
+ with sql.transaction() as session:
+ return self._get_role(session, role_id).to_dict()
+
+ @sql.handle_conflicts(conflict_type='role')
+ def update_role(self, role_id, role):
+ with sql.transaction() as session:
+ ref = self._get_role(session, role_id)
+ old_dict = ref.to_dict()
+ for k in role:
+ old_dict[k] = role[k]
+ new_role = RoleTable.from_dict(old_dict)
+ for attr in RoleTable.attributes:
+ if attr != 'id':
+ setattr(ref, attr, getattr(new_role, attr))
+ ref.extra = new_role.extra
+ return ref.to_dict()
+
+ def delete_role(self, role_id):
+ with sql.transaction() as session:
+ ref = self._get_role(session, role_id)
+ session.delete(ref)
+
+
+class RoleTable(sql.ModelBase, sql.DictBase):
+ __tablename__ = 'role'
+ attributes = ['id', 'name']
+ id = sql.Column(sql.String(64), primary_key=True)
+ name = sql.Column(sql.String(255), unique=True, nullable=False)
+ extra = sql.Column(sql.JsonBlob())
+ __table_args__ = (sql.UniqueConstraint('name'), {})