Support for LDAP groups (bug #1092187)
Also covers Domain CRUD. Fixes Bug #1092187 Change-Id: If2266ed382edfedfad3eef450ce58640ca4b4657
This commit is contained in:
parent
a066b69fbe
commit
5cb8e1f2e5
@ -116,7 +116,7 @@ class Group(Model):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
required_keys = ('id', 'name', 'domain_id')
|
required_keys = ('id', 'name', 'domain_id')
|
||||||
optional_keys = ('description')
|
optional_keys = ('description',)
|
||||||
|
|
||||||
|
|
||||||
class Project(Model):
|
class Project(Model):
|
||||||
@ -162,3 +162,21 @@ class Trust(Model):
|
|||||||
|
|
||||||
required_keys = ('id', 'trustor_user_id', 'trustee_user_id', 'project_id')
|
required_keys = ('id', 'trustor_user_id', 'trustee_user_id', 'project_id')
|
||||||
optional_keys = tuple('expires_at')
|
optional_keys = tuple('expires_at')
|
||||||
|
|
||||||
|
|
||||||
|
class Domain(Model):
|
||||||
|
"""Domain object.
|
||||||
|
|
||||||
|
Required keys:
|
||||||
|
id
|
||||||
|
name
|
||||||
|
|
||||||
|
Optional keys:
|
||||||
|
|
||||||
|
description
|
||||||
|
enabled (bool, default True)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
required_keys = ('id', 'name')
|
||||||
|
optional_keys = ('description', 'enabled')
|
||||||
|
@ -310,12 +310,26 @@ register_str('group_id_attribute', group='ldap', default='cn')
|
|||||||
register_str('group_name_attribute', group='ldap', default='ou')
|
register_str('group_name_attribute', group='ldap', default='ou')
|
||||||
register_str('group_member_attribute', group='ldap', default='member')
|
register_str('group_member_attribute', group='ldap', default='member')
|
||||||
register_str('group_desc_attribute', group='ldap', default='description')
|
register_str('group_desc_attribute', group='ldap', default='description')
|
||||||
register_str('group_domain_id_attribute', group='ldap', default='domain_id')
|
register_str('group_domain_id_attribute', group='ldap',
|
||||||
|
default='businessCategory')
|
||||||
register_list('group_attribute_ignore', group='ldap', default='')
|
register_list('group_attribute_ignore', group='ldap', default='')
|
||||||
register_bool('group_allow_create', group='ldap', default=True)
|
register_bool('group_allow_create', group='ldap', default=True)
|
||||||
register_bool('group_allow_update', group='ldap', default=True)
|
register_bool('group_allow_update', group='ldap', default=True)
|
||||||
register_bool('group_allow_delete', group='ldap', default=True)
|
register_bool('group_allow_delete', group='ldap', default=True)
|
||||||
|
|
||||||
|
register_str('domain_tree_dn', group='ldap', default=None)
|
||||||
|
register_str('domain_filter', group='ldap', default=None)
|
||||||
|
register_str('domain_objectclass', group='ldap', default='groupOfNames')
|
||||||
|
register_str('domain_id_attribute', group='ldap', default='cn')
|
||||||
|
register_str('domain_name_attribute', group='ldap', default='ou')
|
||||||
|
register_str('domain_member_attribute', group='ldap', default='member')
|
||||||
|
register_str('domain_desc_attribute', group='ldap', default='description')
|
||||||
|
register_str('domain_enabled_attribute', group='ldap', default='enabled')
|
||||||
|
register_list('domain_attribute_ignore', group='ldap', default='')
|
||||||
|
register_bool('domain_allow_create', group='ldap', default=True)
|
||||||
|
register_bool('domain_allow_update', group='ldap', default=True)
|
||||||
|
register_bool('domain_allow_delete', group='ldap', default=True)
|
||||||
|
|
||||||
# pam
|
# pam
|
||||||
register_str('url', group='pam', default=None)
|
register_str('url', group='pam', default=None)
|
||||||
register_str('userid', group='pam', default=None)
|
register_str('userid', group='pam', default=None)
|
||||||
|
@ -28,7 +28,6 @@ from keystone import config
|
|||||||
from keystone import exception
|
from keystone import exception
|
||||||
from keystone import identity
|
from keystone import identity
|
||||||
|
|
||||||
|
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +43,7 @@ class Identity(identity.Driver):
|
|||||||
self.project = ProjectApi(CONF)
|
self.project = ProjectApi(CONF)
|
||||||
self.role = RoleApi(CONF)
|
self.role = RoleApi(CONF)
|
||||||
self.group = GroupApi(CONF)
|
self.group = GroupApi(CONF)
|
||||||
|
self.domain = DomainApi(CONF)
|
||||||
|
|
||||||
def get_connection(self, user=None, password=None):
|
def get_connection(self, user=None, password=None):
|
||||||
if self.LDAP_URL.startswith('fake://'):
|
if self.LDAP_URL.startswith('fake://'):
|
||||||
@ -238,6 +238,62 @@ class Identity(identity.Driver):
|
|||||||
def delete_group(self, group_id):
|
def delete_group(self, group_id):
|
||||||
return self.group.delete(group_id)
|
return self.group.delete(group_id)
|
||||||
|
|
||||||
|
def add_user_to_group(self, user_id, group_id):
|
||||||
|
self.get_user(user_id)
|
||||||
|
self.get_group(group_id)
|
||||||
|
self.group.add_user(user_id, group_id)
|
||||||
|
|
||||||
|
def remove_user_from_group(self, user_id, group_id):
|
||||||
|
self.get_user(user_id)
|
||||||
|
self.get_group(group_id)
|
||||||
|
self.group.remove_user(user_id, group_id)
|
||||||
|
|
||||||
|
def list_groups_for_user(self, user_id):
|
||||||
|
self.get_user(user_id)
|
||||||
|
return self.group.list_user_groups(user_id)
|
||||||
|
|
||||||
|
def list_groups(self):
|
||||||
|
return self.group.get_all()
|
||||||
|
|
||||||
|
def list_users_in_group(self, group_id):
|
||||||
|
self.get_group(group_id)
|
||||||
|
return self.group.list_group_users(group_id)
|
||||||
|
|
||||||
|
def check_user_in_group(self, user_id, group_id):
|
||||||
|
self.get_user(user_id)
|
||||||
|
self.get_group(group_id)
|
||||||
|
user_refs = self.list_users_in_group(group_id)
|
||||||
|
found = False
|
||||||
|
for x in user_refs:
|
||||||
|
if x['id'] == user_id:
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
return found
|
||||||
|
|
||||||
|
def create_domain(self, domain_id, domain):
|
||||||
|
domain['name'] = clean.domain_name(domain['name'])
|
||||||
|
return self.domain.create(domain)
|
||||||
|
|
||||||
|
def get_domain(self, domain_id):
|
||||||
|
try:
|
||||||
|
return self.domain.get(domain_id)
|
||||||
|
except exception.NotFound:
|
||||||
|
raise exception.DomainNotFound(domain_id=domain_id)
|
||||||
|
|
||||||
|
def update_domain(self, domain_id, domain):
|
||||||
|
if 'name' in domain:
|
||||||
|
domain['name'] = clean.domain_name(domain['name'])
|
||||||
|
return self.domain.update(domain_id, domain)
|
||||||
|
|
||||||
|
def delete_domain(self, domain_id):
|
||||||
|
try:
|
||||||
|
return self.domain.delete(domain_id)
|
||||||
|
except ldap.NO_SUCH_OBJECT:
|
||||||
|
raise exception.DomainNotFound(domain_id=domain_id)
|
||||||
|
|
||||||
|
def list_domains(self):
|
||||||
|
return self.domain.get_all()
|
||||||
|
|
||||||
|
|
||||||
# TODO(termie): remove this and move cross-api calls into driver
|
# TODO(termie): remove this and move cross-api calls into driver
|
||||||
class ApiShim(object):
|
class ApiShim(object):
|
||||||
@ -251,6 +307,7 @@ class ApiShim(object):
|
|||||||
_project = None
|
_project = None
|
||||||
_user = None
|
_user = None
|
||||||
_group = None
|
_group = None
|
||||||
|
_domain = None
|
||||||
|
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
@ -275,9 +332,15 @@ class ApiShim(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def group(self):
|
def group(self):
|
||||||
if not self.group:
|
if not self._group:
|
||||||
self.group = GroupApi(self.conf)
|
self._group = GroupApi(self.conf)
|
||||||
return self.group
|
return self._group
|
||||||
|
|
||||||
|
@property
|
||||||
|
def domain(self):
|
||||||
|
if not self._domain:
|
||||||
|
self._domain = DomainApi(self.conf)
|
||||||
|
return self._domain
|
||||||
|
|
||||||
|
|
||||||
# TODO(termie): remove this and move cross-api calls into driver
|
# TODO(termie): remove this and move cross-api calls into driver
|
||||||
@ -300,6 +363,10 @@ class ApiShimMixin(object):
|
|||||||
def group_api(self):
|
def group_api(self):
|
||||||
return self.api.group
|
return self.api.group
|
||||||
|
|
||||||
|
@property
|
||||||
|
def domain_api(self):
|
||||||
|
return self.api.domain
|
||||||
|
|
||||||
|
|
||||||
# TODO(termie): turn this into a data object and move logic to driver
|
# TODO(termie): turn this into a data object and move logic to driver
|
||||||
class UserApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap, ApiShimMixin):
|
class UserApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap, ApiShimMixin):
|
||||||
@ -569,7 +636,6 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
|
|||||||
def create(self, values):
|
def create(self, values):
|
||||||
#values['id'] = values['name']
|
#values['id'] = values['name']
|
||||||
#delattr(values, 'name')
|
#delattr(values, 'name')
|
||||||
|
|
||||||
return super(RoleApi, self).create(values)
|
return super(RoleApi, self).create(values)
|
||||||
|
|
||||||
def add_user(self, role_id, user_id, tenant_id=None):
|
def add_user(self, role_id, user_id, tenant_id=None):
|
||||||
@ -736,9 +802,29 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
|
|||||||
pass
|
pass
|
||||||
super(RoleApi, self).delete(id)
|
super(RoleApi, self).delete(id)
|
||||||
|
|
||||||
|
# TODO (spzala) - this is only placeholder for group and domain role support
|
||||||
|
# which will be added under bug 1101287
|
||||||
|
def roles_delete_subtree_by_type(self, id, type):
|
||||||
|
conn = self.get_connection()
|
||||||
|
query = '(objectClass=%s)' % self.object_class
|
||||||
|
dn = None
|
||||||
|
if type == 'Group':
|
||||||
|
dn = self.group_api._id_to_dn(id)
|
||||||
|
if type == 'Domain':
|
||||||
|
dn = self.domain_api._id_to_dn(id)
|
||||||
|
if dn:
|
||||||
|
try:
|
||||||
|
roles = conn.search_s(dn, ldap.SCOPE_ONELEVEL,
|
||||||
|
query, ['%s' % '1.1'])
|
||||||
|
for role_dn, _ in roles:
|
||||||
|
try:
|
||||||
|
conn.delete_s(role_dn)
|
||||||
|
except:
|
||||||
|
raise Exception
|
||||||
|
except ldap.NO_SUCH_OBJECT:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# TODO (henry-nash) This is a placeholder for the full LDPA implementation
|
|
||||||
# This needs to be completed (see Bug #1092187)
|
|
||||||
class GroupApi(common_ldap.BaseLdap, ApiShimMixin):
|
class GroupApi(common_ldap.BaseLdap, ApiShimMixin):
|
||||||
DEFAULT_OU = 'ou=UserGroups'
|
DEFAULT_OU = 'ou=UserGroups'
|
||||||
DEFAULT_STRUCTURAL_CLASSES = []
|
DEFAULT_STRUCTURAL_CLASSES = []
|
||||||
@ -771,13 +857,15 @@ class GroupApi(common_ldap.BaseLdap, ApiShimMixin):
|
|||||||
data = values.copy()
|
data = values.copy()
|
||||||
if data.get('id') is None:
|
if data.get('id') is None:
|
||||||
data['id'] = uuid.uuid4().hex
|
data['id'] = uuid.uuid4().hex
|
||||||
|
if 'description' in data and data['description'] in ['', None]:
|
||||||
|
data.pop('description')
|
||||||
return super(GroupApi, self).create(data)
|
return super(GroupApi, self).create(data)
|
||||||
|
|
||||||
def delete(self, id):
|
def delete(self, id):
|
||||||
if self.subtree_delete_enabled:
|
if self.subtree_delete_enabled:
|
||||||
super(GroupApi, self).deleteTree(id)
|
super(GroupApi, self).deleteTree(id)
|
||||||
else:
|
else:
|
||||||
self.role_api.roles_delete_subtree_by_group(id)
|
self.role_api.roles_delete_subtree_by_type(id, 'Group')
|
||||||
super(GroupApi, self).delete(id)
|
super(GroupApi, self).delete(id)
|
||||||
|
|
||||||
def update(self, id, values):
|
def update(self, id, values):
|
||||||
@ -786,3 +874,112 @@ class GroupApi(common_ldap.BaseLdap, ApiShimMixin):
|
|||||||
msg = _('Changing Name not supported by LDAP')
|
msg = _('Changing Name not supported by LDAP')
|
||||||
raise exception.NotImplemented(message=msg)
|
raise exception.NotImplemented(message=msg)
|
||||||
super(GroupApi, self).update(id, values, old_obj)
|
super(GroupApi, self).update(id, values, old_obj)
|
||||||
|
|
||||||
|
def add_user(self, user_id, group_id):
|
||||||
|
conn = self.get_connection()
|
||||||
|
try:
|
||||||
|
conn.modify_s(
|
||||||
|
self._id_to_dn(group_id),
|
||||||
|
[(ldap.MOD_ADD,
|
||||||
|
self.member_attribute,
|
||||||
|
self.user_api._id_to_dn(user_id))])
|
||||||
|
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||||
|
msg = _('User %s is already a member of group %s'
|
||||||
|
% (user_id, group_id))
|
||||||
|
raise exception.Conflict(msg)
|
||||||
|
|
||||||
|
def remove_user(self, user_id, group_id):
|
||||||
|
conn = self.get_connection()
|
||||||
|
try:
|
||||||
|
conn.modify_s(
|
||||||
|
self._id_to_dn(group_id),
|
||||||
|
[(ldap.MOD_DELETE,
|
||||||
|
self.member_attribute,
|
||||||
|
self.user_api._id_to_dn(user_id))])
|
||||||
|
except ldap.NO_SUCH_ATTRIBUTE:
|
||||||
|
raise exception.UserNotFound(user_id=user_id)
|
||||||
|
|
||||||
|
def list_user_groups(self, user_id):
|
||||||
|
"""Returns a list of groups a user has access to"""
|
||||||
|
user_dn = self.user_api._id_to_dn(user_id)
|
||||||
|
query = '(%s=%s)' % (self.member_attribute, user_dn)
|
||||||
|
memberships = self.get_all(query)
|
||||||
|
return memberships
|
||||||
|
|
||||||
|
def list_group_users(self, group_id):
|
||||||
|
"""Returns a list of users that belong to a group"""
|
||||||
|
query = '(objectClass=%s)' % self.object_class
|
||||||
|
conn = self.get_connection()
|
||||||
|
group_dn = self._id_to_dn(group_id)
|
||||||
|
try:
|
||||||
|
attrs = conn.search_s(group_dn,
|
||||||
|
ldap.SCOPE_BASE,
|
||||||
|
query, ['%s' % self.member_attribute])
|
||||||
|
except ldap.NO_SUCH_OBJECT:
|
||||||
|
return []
|
||||||
|
users = []
|
||||||
|
for dn, member in attrs:
|
||||||
|
user_dns = member[self.member_attribute]
|
||||||
|
for user_dn in user_dns:
|
||||||
|
if self.use_dumb_member and user_dn == self.dumb_member:
|
||||||
|
continue
|
||||||
|
user_id = self.user_api._dn_to_id(user_dn)
|
||||||
|
users.append(self.user_api.get(user_id))
|
||||||
|
return users
|
||||||
|
|
||||||
|
|
||||||
|
class DomainApi(common_ldap.BaseLdap, ApiShimMixin):
|
||||||
|
DEFAULT_OU = 'ou=Domains'
|
||||||
|
DEFAULT_STRUCTURAL_CLASSES = []
|
||||||
|
DEFAULT_OBJECTCLASS = 'groupOfNames'
|
||||||
|
DEFAULT_ID_ATTR = 'cn'
|
||||||
|
DEFAULT_MEMBER_ATTRIBUTE = 'member'
|
||||||
|
DEFAULT_ATTRIBUTE_IGNORE = []
|
||||||
|
options_name = 'domain'
|
||||||
|
attribute_mapping = {'name': 'ou',
|
||||||
|
'description': 'description',
|
||||||
|
'domainId': 'cn',
|
||||||
|
'enabled': 'enabled'}
|
||||||
|
model = models.Domain
|
||||||
|
|
||||||
|
def __init__(self, conf):
|
||||||
|
super(DomainApi, self).__init__(conf)
|
||||||
|
self.api = ApiShim(conf)
|
||||||
|
self.attribute_mapping['name'] = conf.ldap.domain_name_attribute
|
||||||
|
self.attribute_mapping['description'] = conf.ldap.domain_desc_attribute
|
||||||
|
self.attribute_mapping['enabled'] = conf.ldap.tenant_enabled_attribute
|
||||||
|
self.member_attribute = (getattr(conf.ldap, 'domain_member_attribute')
|
||||||
|
or self.DEFAULT_MEMBER_ATTRIBUTE)
|
||||||
|
self.attribute_ignore = (getattr(conf.ldap, 'domain_attribute_ignore')
|
||||||
|
or self.DEFAULT_ATTRIBUTE_IGNORE)
|
||||||
|
|
||||||
|
def get(self, id, filter=None):
|
||||||
|
"""Replaces exception.NotFound with exception.DomainNotFound."""
|
||||||
|
try:
|
||||||
|
return super(DomainApi, self).get(id, filter)
|
||||||
|
except exception.NotFound:
|
||||||
|
raise exception.DomainNotFound(domain_id=id)
|
||||||
|
|
||||||
|
def create(self, values):
|
||||||
|
self.affirm_unique(values)
|
||||||
|
data = values.copy()
|
||||||
|
if data.get('id') is None:
|
||||||
|
data['id'] = uuid.uuid4().hex
|
||||||
|
return super(DomainApi, self).create(data)
|
||||||
|
|
||||||
|
def delete(self, id):
|
||||||
|
if self.subtree_delete_enabled:
|
||||||
|
super(DomainApi, self).deleteTree(id)
|
||||||
|
else:
|
||||||
|
self.role_api.roles_delete_subtree_by_type(id, 'Domain')
|
||||||
|
super(DomainApi, self).delete(id)
|
||||||
|
|
||||||
|
def update(self, id, values):
|
||||||
|
try:
|
||||||
|
old_obj = self.get(id)
|
||||||
|
except exception.NotFound:
|
||||||
|
raise exception.DomainNotFound(domain_id=id)
|
||||||
|
if old_obj['name'] != values['name']:
|
||||||
|
msg = _('Changing Name not supported by LDAP')
|
||||||
|
raise exception.NotImplemented(message=msg)
|
||||||
|
super(DomainApi, self).update(id, values, old_obj)
|
||||||
|
@ -41,6 +41,7 @@ def filter_user(user_ref):
|
|||||||
user_ref.pop('password', None)
|
user_ref.pop('password', None)
|
||||||
user_ref.pop('tenants', None)
|
user_ref.pop('tenants', None)
|
||||||
user_ref.pop('groups', None)
|
user_ref.pop('groups', None)
|
||||||
|
user_ref.pop('domains', None)
|
||||||
try:
|
try:
|
||||||
user_ref['extra'].pop('password', None)
|
user_ref['extra'].pop('password', None)
|
||||||
user_ref['extra'].pop('tenants', None)
|
user_ref['extra'].pop('tenants', None)
|
||||||
|
@ -67,11 +67,12 @@ class LiveLDAPIdentity(test_backend_ldap.LDAPIdentity):
|
|||||||
create_object(CONF.ldap.tenant_tree_dn,
|
create_object(CONF.ldap.tenant_tree_dn,
|
||||||
{'objectclass': 'organizationalUnit',
|
{'objectclass': 'organizationalUnit',
|
||||||
'ou': 'Projects'})
|
'ou': 'Projects'})
|
||||||
|
create_object(CONF.ldap.domain_tree_dn,
|
||||||
# NOTE(crazed): This feature is currently being added
|
|
||||||
create_object("ou=Groups,%s" % CONF.ldap.suffix,
|
|
||||||
{'objectclass': 'organizationalUnit',
|
{'objectclass': 'organizationalUnit',
|
||||||
'ou': 'Groups'})
|
'ou': 'Domain'})
|
||||||
|
create_object(CONF.ldap.group_tree_dn,
|
||||||
|
{'objectclass': 'organizationalUnit',
|
||||||
|
'ou': 'UserGroups'})
|
||||||
|
|
||||||
def _set_config(self):
|
def _set_config(self):
|
||||||
self.config([test.etcdir('keystone.conf.sample'),
|
self.config([test.etcdir('keystone.conf.sample'),
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
url = fake://memory
|
url = fake://memory
|
||||||
user = cn=Admin
|
user = cn=Admin
|
||||||
password = password
|
password = password
|
||||||
backend_entities = ['Tenant', 'User', 'UserRoleAssociation', 'Role']
|
backend_entities = ['Tenant', 'User', 'UserRoleAssociation', 'Role', 'Group', 'Domain']
|
||||||
suffix = cn=example,cn=com
|
suffix = cn=example,cn=com
|
||||||
|
|
||||||
[identity]
|
[identity]
|
||||||
|
@ -3,8 +3,10 @@ url = ldap://localhost
|
|||||||
user = dc=Manager,dc=openstack,dc=org
|
user = dc=Manager,dc=openstack,dc=org
|
||||||
password = test
|
password = test
|
||||||
suffix = dc=openstack,dc=org
|
suffix = dc=openstack,dc=org
|
||||||
|
group_tree_dn = ou=UserGroups,dc=openstack,dc=org
|
||||||
role_tree_dn = ou=Roles,dc=openstack,dc=org
|
role_tree_dn = ou=Roles,dc=openstack,dc=org
|
||||||
tenant_tree_dn = ou=Projects,dc=openstack,dc=org
|
tenant_tree_dn = ou=Projects,dc=openstack,dc=org
|
||||||
|
domain_tree_dn = ou=Domains,dc=openstack,dc=org
|
||||||
user_tree_dn = ou=Users,dc=openstack,dc=org
|
user_tree_dn = ou=Users,dc=openstack,dc=org
|
||||||
tenant_enabled_emulation = True
|
tenant_enabled_emulation = True
|
||||||
user_enabled_emulation = True
|
user_enabled_emulation = True
|
||||||
|
@ -359,29 +359,43 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
|
|||||||
|
|
||||||
# TODO (henry-nash) These need to be removed when the full LDAP implementation
|
# TODO (henry-nash) These need to be removed when the full LDAP implementation
|
||||||
# is submitted - see Bugs 1092187, 1101287, 1101276, 1101289
|
# is submitted - see Bugs 1092187, 1101287, 1101276, 1101289
|
||||||
|
|
||||||
|
# (spzala)The group and domain crud tests below override the standard ones
|
||||||
|
# in test_backend.py so that we can exclude the update name test, since we
|
||||||
|
# do not yet support the update of either group or domain names with LDAP.
|
||||||
|
# In the tests below, the update is demonstrated by updating description.
|
||||||
|
# Refer to bug 1136403 for more detail.
|
||||||
def test_group_crud(self):
|
def test_group_crud(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
group = {'id': uuid.uuid4().hex, 'domain_id': uuid.uuid4().hex,
|
||||||
|
'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex}
|
||||||
|
self.identity_api.create_group(group['id'], group)
|
||||||
|
group_ref = self.identity_api.get_group(group['id'])
|
||||||
|
self.assertDictEqual(group_ref, group)
|
||||||
|
group['description'] = uuid.uuid4().hex
|
||||||
|
self.identity_api.update_group(group['id'], group)
|
||||||
|
group_ref = self.identity_api.get_group(group['id'])
|
||||||
|
self.assertDictEqual(group_ref, group)
|
||||||
|
|
||||||
def test_add_user_to_group(self):
|
self.identity_api.delete_group(group['id'])
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
self.assertRaises(exception.GroupNotFound,
|
||||||
|
self.identity_api.get_group,
|
||||||
|
group['id'])
|
||||||
|
|
||||||
def test_add_user_to_group_404(self):
|
def test_domain_crud(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
|
||||||
|
'enabled': True, 'description': uuid.uuid4().hex}
|
||||||
|
self.identity_api.create_domain(domain['id'], domain)
|
||||||
|
domain_ref = self.identity_api.get_domain(domain['id'])
|
||||||
|
self.assertDictEqual(domain_ref, domain)
|
||||||
|
domain['description'] = uuid.uuid4().hex
|
||||||
|
self.identity_api.update_domain(domain['id'], domain)
|
||||||
|
domain_ref = self.identity_api.get_domain(domain['id'])
|
||||||
|
self.assertDictEqual(domain_ref, domain)
|
||||||
|
|
||||||
def test_check_user_in_group(self):
|
self.identity_api.delete_domain(domain['id'])
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
self.assertRaises(exception.DomainNotFound,
|
||||||
|
self.identity_api.get_domain,
|
||||||
def test_check_user_not_in_group(self):
|
domain['id'])
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
|
||||||
|
|
||||||
def test_list_users_in_group(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
|
||||||
|
|
||||||
def test_remove_user_from_group(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
|
||||||
|
|
||||||
def test_remove_user_from_group_404(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
|
||||||
|
|
||||||
def test_get_role_grant_by_user_and_project(self):
|
def test_get_role_grant_by_user_and_project(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
||||||
@ -407,15 +421,6 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
|
|||||||
def test_get_and_remove_correct_role_grant_from_a_mix(self):
|
def test_get_and_remove_correct_role_grant_from_a_mix(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
||||||
|
|
||||||
def test_get_roles_for_user_and_domain(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
|
||||||
|
|
||||||
def test_get_roles_for_user_and_domain_404(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
|
||||||
|
|
||||||
def test_domain_crud(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
|
||||||
|
|
||||||
def test_project_crud(self):
|
def test_project_crud(self):
|
||||||
# NOTE(topol): LDAP implementation does not currently support the
|
# NOTE(topol): LDAP implementation does not currently support the
|
||||||
# updating of a project name so this method override
|
# updating of a project name so this method override
|
||||||
@ -467,12 +472,6 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
|
|||||||
def test_delete_group_with_user_project_domain_links(self):
|
def test_delete_group_with_user_project_domain_links(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
||||||
|
|
||||||
def test_list_groups(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
|
||||||
|
|
||||||
def test_list_domains(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
|
||||||
|
|
||||||
def test_list_user_projects(self):
|
def test_list_user_projects(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
||||||
|
|
||||||
@ -485,9 +484,6 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
|
|||||||
def test_create_duplicate_project_name_in_different_domains(self):
|
def test_create_duplicate_project_name_in_different_domains(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
||||||
|
|
||||||
def test_create_duplicate_group_name_fails(self):
|
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1092187')
|
|
||||||
|
|
||||||
def test_create_duplicate_group_name_in_different_domains(self):
|
def test_create_duplicate_group_name_in_different_domains(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
||||||
|
|
||||||
@ -509,6 +505,9 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
|
|||||||
def test_move_project_between_domains_with_clashing_names_fails(self):
|
def test_move_project_between_domains_with_clashing_names_fails(self):
|
||||||
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
raise nose.exc.SkipTest('Blocked by bug 1101276')
|
||||||
|
|
||||||
|
def test_get_roles_for_user_and_domain(self):
|
||||||
|
raise nose.exc.SkipTest('Blocked by bug 1101287')
|
||||||
|
|
||||||
|
|
||||||
class LDAPIdentityEnabledEmulation(LDAPIdentity):
|
class LDAPIdentityEnabledEmulation(LDAPIdentity):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user