summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/keystone.conf.sample8
-rw-r--r--keystone/common/ldap/core.py7
-rw-r--r--keystone/config.py24
-rw-r--r--keystone/identity/backends/ldap/core.py29
-rw-r--r--tests/default_fixtures.py12
-rw-r--r--tests/test_backend_ldap.py122
6 files changed, 190 insertions, 12 deletions
diff --git a/etc/keystone.conf.sample b/etc/keystone.conf.sample
index c81d3b6c..2eabba41 100644
--- a/etc/keystone.conf.sample
+++ b/etc/keystone.conf.sample
@@ -108,12 +108,16 @@
# suffix = cn=example,cn=com
# use_dumb_member = False
# allow_subtree_delete = False
+# dumb_member = cn=dumb,dc=example,dc=com
# user_tree_dn = ou=Users,dc=example,dc=com
# user_filter =
# user_objectclass = inetOrgPerson
# user_id_attribute = cn
# user_name_attribute = sn
+# user_mail_attribute = email
+# user_pass_attribute = userPassword
+# user_attribute_ignore = tenant_id,enabled,tenants
# user_allow_create = True
# user_allow_update = True
# user_allow_delete = True
@@ -124,6 +128,8 @@
# tenant_id_attribute = cn
# tenant_member_attribute = member
# tenant_name_attribute = ou
+# tenant_desc_attribute = desc
+# tenant_attribute_ignore = enabled
# tenant_allow_create = True
# tenant_allow_update = True
# tenant_allow_delete = True
@@ -132,7 +138,9 @@
# role_filter =
# role_objectclass = organizationalRole
# role_id_attribute = cn
+# role_name_attribute = ou
# role_member_attribute = roleOccupant
+# role_attribute_ignore =
# role_allow_create = True
# role_allow_update = True
# role_allow_delete = True
diff --git a/keystone/common/ldap/core.py b/keystone/common/ldap/core.py
index 4a80d66a..53e20468 100644
--- a/keystone/common/ldap/core.py
+++ b/keystone/common/ldap/core.py
@@ -107,7 +107,10 @@ class BaseLdap(object):
self.allow_delete = getattr(conf.ldap, allow_delete)
self.structural_classes = self.DEFAULT_STRUCTURAL_CLASSES
- self.use_dumb_member = getattr(conf.ldap, 'use_dumb_member') or True
+ self.use_dumb_member = getattr(conf.ldap, 'use_dumb_member')
+ self.dumb_member = (getattr(conf.ldap, 'dumb_member') or
+ self.DUMB_MEMBER_DN)
+
self.subtree_delete_enabled = getattr(conf.ldap,
'allow_subtree_delete')
@@ -194,7 +197,7 @@ class BaseLdap(object):
attrs.append((attr_type, [v]))
if 'groupOfNames' in object_classes and self.use_dumb_member:
- attrs.append(('member', [self.DUMB_MEMBER_DN]))
+ attrs.append(('member', [self.dumb_member]))
conn.add_s(self._id_to_dn(values['id']), attrs)
return values
diff --git a/keystone/config.py b/keystone/config.py
index dc6c41d2..86a425ec 100644
--- a/keystone/config.py
+++ b/keystone/config.py
@@ -87,6 +87,18 @@ def register_cli_str(*args, **kw):
return conf.register_cli_opt(cfg.StrOpt(*args, **kw), group=group)
+def register_list(*args, **kw):
+ conf = kw.pop('conf', CONF)
+ group = kw.pop('group', None)
+ return conf.register_opt(cfg.ListOpt(*args, **kw), group=group)
+
+
+def register_cli_list(*args, **kw):
+ conf = kw.pop('conf', CONF)
+ group = kw.pop('group', None)
+ return conf.register_cli_opt(cfg.ListOpt(*args, **kw), group=group)
+
+
def register_bool(*args, **kw):
conf = kw.pop('conf', CONF)
group = kw.pop('group', None)
@@ -157,19 +169,25 @@ register_str('driver', group='ec2',
register_str('driver', group='stats',
default='keystone.contrib.stats.backends.kvs.Stats')
+
#ldap
register_str('url', group='ldap', default='ldap://localhost')
register_str('user', group='ldap', default='dc=Manager,dc=example,dc=com')
register_str('password', group='ldap', default='freeipa4all')
register_str('suffix', group='ldap', default='cn=example,cn=com')
register_bool('use_dumb_member', group='ldap', default=False)
-register_str('user_name_attribute', group='ldap', default='sn')
+register_str('dumb_member', group='ldap', default='cn=dumb,dc=nonexistent')
register_bool('allow_subtree_delete', group='ldap', default=False)
register_str('user_tree_dn', group='ldap', default=None)
register_str('user_filter', group='ldap', default=None)
register_str('user_objectclass', group='ldap', default='inetOrgPerson')
register_str('user_id_attribute', group='ldap', default='cn')
+register_str('user_name_attribute', group='ldap', default='sn')
+register_str('user_mail_attribute', group='ldap', default='email')
+register_str('user_pass_attribute', group='ldap', default='userPassword')
+register_list('user_attribute_ignore', group='ldap',
+ default='tenant_id,enable,tenants')
register_bool('user_allow_create', group='ldap', default=True)
register_bool('user_allow_update', group='ldap', default=True)
register_bool('user_allow_delete', group='ldap', default=True)
@@ -180,6 +198,8 @@ register_str('tenant_objectclass', group='ldap', default='groupOfNames')
register_str('tenant_id_attribute', group='ldap', default='cn')
register_str('tenant_member_attribute', group='ldap', default='member')
register_str('tenant_name_attribute', group='ldap', default='ou')
+register_str('tenant_desc_attribute', group='ldap', default='desc')
+register_list('tenant_attribute_ignore', group='ldap', default='enabled')
register_bool('tenant_allow_create', group='ldap', default=True)
register_bool('tenant_allow_update', group='ldap', default=True)
register_bool('tenant_allow_delete', group='ldap', default=True)
@@ -188,7 +208,9 @@ register_str('role_tree_dn', group='ldap', default=None)
register_str('role_filter', group='ldap', default=None)
register_str('role_objectclass', group='ldap', default='organizationalRole')
register_str('role_id_attribute', group='ldap', default='cn')
+register_str('role_name_attribute', group='ldap', default='ou')
register_str('role_member_attribute', group='ldap', default='roleOccupant')
+register_list('role_attribute_ignore', group='ldap', default='')
register_bool('role_allow_create', group='ldap', default=True)
register_bool('role_allow_update', group='ldap', default=True)
register_bool('role_allow_delete', group='ldap', default=True)
diff --git a/keystone/identity/backends/ldap/core.py b/keystone/identity/backends/ldap/core.py
index 540679c0..ebccde02 100644
--- a/keystone/identity/backends/ldap/core.py
+++ b/keystone/identity/backends/ldap/core.py
@@ -331,6 +331,7 @@ class UserApi(common_ldap.BaseLdap, ApiShimMixin):
DEFAULT_STRUCTURAL_CLASSES = ['person']
DEFAULT_ID_ATTR = 'cn'
DEFAULT_OBJECTCLASS = 'inetOrgPerson'
+ DEFAULT_ATTRIBUTE_IGNORE = ['tenant_id', 'enabled', 'tenants']
options_name = 'user'
attribute_mapping = {'password': 'userPassword',
'email': 'mail',
@@ -341,12 +342,15 @@ class UserApi(common_ldap.BaseLdap, ApiShimMixin):
# be part of any objectclass.
# in the future, we need to provide a way for the end user to
# indicate the field to use and what it indicates
- attribute_ignore = ['tenantId', 'enabled', 'tenants']
model = models.User
def __init__(self, conf):
super(UserApi, self).__init__(conf)
self.attribute_mapping['name'] = conf.ldap.user_name_attribute
+ self.attribute_mapping['email'] = conf.ldap.user_mail_attribute
+ self.attribute_mapping['password'] = conf.ldap.user_pass_attribute
+ self.attribute_ignore = (getattr(conf.ldap, 'user_attribute_ignore')
+ or self.DEFAULT_ATTRIBUTE_IGNORE)
self.api = ApiShim(conf)
def get(self, id, filter=None):
@@ -466,17 +470,20 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
DEFAULT_OBJECTCLASS = 'groupOfNames'
DEFAULT_ID_ATTR = 'cn'
DEFAULT_MEMBER_ATTRIBUTE = 'member'
+ DEFAULT_ATTRIBUTE_IGNORE = ['enabled']
options_name = 'tenant'
- attribute_mapping = {'name': 'ou', 'tenantId': 'cn'}
- attribute_ignore = ['enabled']
+ attribute_mapping = {'name': 'ou', 'description': 'desc', 'tenantId': 'cn'}
model = models.Tenant
def __init__(self, conf):
super(TenantApi, self).__init__(conf)
self.api = ApiShim(conf)
self.attribute_mapping['name'] = conf.ldap.tenant_name_attribute
+ self.attribute_mapping['description'] = conf.ldap.tenant_desc_attribute
self.member_attribute = (getattr(conf.ldap, 'tenant_member_attribute')
or self.DEFAULT_MEMBER_ATTRIBUTE)
+ self.attribute_ignore = (getattr(conf.ldap, 'tenant_attribute_ignore')
+ or self.DEFAULT_ATTRIBUTE_IGNORE)
def get(self, id, filter=None):
"""Replaces exception.NotFound with exception.TenantNotFound."""
@@ -523,7 +530,7 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
tenant = self._ldap_get(id)
members = tenant[1].get(self.member_attribute, [])
if self.use_dumb_member:
- empty = members == [self.DUMB_MEMBER_DN]
+ empty = members == [self.dumb_member]
else:
empty = len(members) == 0
return empty and len(self.role_api.get_role_assignments(id)) == 0
@@ -561,7 +568,7 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
if not role_id:
# Get users who have default tenant mapping
for user_dn in tenant[1].get(self.member_attribute, []):
- if self.use_dumb_member and user_dn == self.DUMB_MEMBER_DN:
+ if self.use_dumb_member and user_dn == self.dumb_member:
continue
res.add(self.user_api.get(self.user_api._dn_to_id(user_dn)))
@@ -607,6 +614,7 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
options_name = 'role'
DEFAULT_OBJECTCLASS = 'organizationalRole'
DEFAULT_MEMBER_ATTRIBUTE = 'roleOccupant'
+ DEFAULT_ATTRIBUTE_IGNORE = []
attribute_mapping = {'name': 'cn',
#'serviceId': 'service_id',
}
@@ -615,8 +623,11 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
def __init__(self, conf):
super(RoleApi, self).__init__(conf)
self.api = ApiShim(conf)
+ self.attribute_mapping['name'] = conf.ldap.role_name_attribute
self.member_attribute = (getattr(conf.ldap, 'role_member_attribute')
or self.DEFAULT_MEMBER_ATTRIBUTE)
+ self.attribute_ignore = (getattr(conf.ldap, 'role_attribute_ignore')
+ or self.DEFAULT_ATTRIBUTE_IGNORE)
@staticmethod
def _create_ref(role_id, tenant_id, user_id):
@@ -688,7 +699,7 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
(self.member_attribute, [user_dn])]
if self.use_dumb_member:
- attrs[1][1].append(self.DUMB_MEMBER_DN)
+ attrs[1][1].append(self.dumb_member)
try:
conn.add_s(role_dn, attrs)
except Exception as inst:
@@ -714,7 +725,7 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
(self.member_attribute, [user_dn])]
if self.use_dumb_member:
- attrs[1][1].append(self.DUMB_MEMBER_DN)
+ attrs[1][1].append(self.dumb_member)
try:
conn.add_s(role_dn, attrs)
except Exception as inst:
@@ -751,7 +762,7 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
except KeyError:
continue
for user_dn in user_dns:
- if self.use_dumb_member and user_dn == self.DUMB_MEMBER_DN:
+ if self.use_dumb_member and user_dn == self.dumb_member:
continue
user_id = self.user_api._dn_to_id(user_dn)
role_id = self._dn_to_id(role_dn)
@@ -884,7 +895,7 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
continue
for user_dn in user_dns:
- if self.use_dumb_member and user_dn == self.DUMB_MEMBER_DN:
+ if self.use_dumb_member and user_dn == self.dumb_member:
continue
user_id = self.user_api._dn_to_id(user_dn)
tenant_id = None
diff --git a/tests/default_fixtures.py b/tests/default_fixtures.py
index cb0d0e2e..8b5020ff 100644
--- a/tests/default_fixtures.py
+++ b/tests/default_fixtures.py
@@ -18,6 +18,10 @@ TENANTS = [
{'id': 'bar', 'name': 'BAR'},
{'id': 'baz', 'name': 'BAZ'},
{'id': 'tenent4add', 'name': 'tenant4add'},
+ {'id': 'attr',
+ 'name': 'attr_name',
+ 'description': 'description',
+ 'enabled': True},
]
# NOTE(ja): a role of keystone_admin and attribute "is_admin" is done in setUp
@@ -28,6 +32,13 @@ USERS = [
'name': 'NO_META',
'password': 'no_meta2',
'tenants': ['baz']},
+ {'id': 'attr',
+ 'name': 'attr',
+ 'email': 'attr@example.com',
+ 'enabled': True,
+ 'tenant_id': 'baz',
+ 'password': 'attr_passwd',
+ 'tenants': ['baz']},
]
METADATA = [
@@ -38,6 +49,7 @@ METADATA = [
ROLES = [
{'id': 'keystone_admin', 'name': 'Keystone Admin'},
{'id': 'useless', 'name': 'Useless'},
+ {'id': 'attr', 'name': 'attr'},
]
SERVICES = [
diff --git a/tests/test_backend_ldap.py b/tests/test_backend_ldap.py
index 1b3d4b90..cbb94e44 100644
--- a/tests/test_backend_ldap.py
+++ b/tests/test_backend_ldap.py
@@ -242,3 +242,125 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
self.assertRaises(exception.RoleNotFound,
self.identity_api.get_role,
self.role_useless['id'])
+
+ def test_dumb_member(self):
+ self.config([test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_ldap.conf')])
+ CONF.ldap.use_dumb_member = True
+ CONF.ldap.dumb_member = 'cn=dumb,cn=example,cn=com'
+ clear_database()
+ self.identity_api = identity_ldap.Identity()
+ self.load_fixtures(default_fixtures)
+ self.assertRaises(exception.UserNotFound,
+ self.identity_api.get_user,
+ 'dumb')
+
+ def test_user_attribute_mapping(self):
+ self.config([test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_ldap.conf')])
+ CONF.ldap.user_name_attribute = 'sn'
+ CONF.ldap.user_mail_attribute = 'email'
+ clear_database()
+ self.identity_api = identity_ldap.Identity()
+ self.load_fixtures(default_fixtures)
+ user_ref = self.identity_api.get_user(self.user_attr['id'])
+ self.assertEqual(user_ref['id'], self.user_attr['id'])
+ self.assertEqual(user_ref['name'], self.user_attr['name'])
+ self.assertEqual(user_ref['email'], self.user_attr['email'])
+
+ CONF.ldap.user_name_attribute = 'email'
+ CONF.ldap.user_mail_attribute = 'sn'
+ self.identity_api = identity_ldap.Identity()
+ user_ref = self.identity_api.get_user(self.user_attr['id'])
+ self.assertEqual(user_ref['id'], self.user_attr['id'])
+ self.assertEqual(user_ref['name'], self.user_attr['email'])
+ self.assertEqual(user_ref['email'], self.user_attr['name'])
+
+ def test_user_attribute_ignore(self):
+ self.config([test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_ldap.conf')])
+ CONF.ldap.user_attribute_ignore = ['name', 'email', 'password',
+ 'tenant_id', 'enabled', 'tenants']
+ clear_database()
+ self.identity_api = identity_ldap.Identity()
+ self.load_fixtures(default_fixtures)
+ user_ref = self.identity_api.get_user(self.user_attr['id'])
+ self.assertEqual(user_ref['id'], self.user_attr['id'])
+ self.assertNotIn('name', user_ref)
+ self.assertNotIn('email', user_ref)
+ self.assertNotIn('password', user_ref)
+ self.assertNotIn('tenant_id', user_ref)
+ self.assertNotIn('enabled', user_ref)
+ self.assertNotIn('tenants', user_ref)
+
+ def test_tenant_attribute_mapping(self):
+ self.config([test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_ldap.conf')])
+ CONF.ldap.tenant_name_attribute = 'ou'
+ CONF.ldap.tenant_desc_attribute = 'desc'
+ clear_database()
+ self.identity_api = identity_ldap.Identity()
+ self.load_fixtures(default_fixtures)
+ tenant_ref = self.identity_api.get_tenant(self.tenant_attr['id'])
+ self.assertEqual(tenant_ref['id'], self.tenant_attr['id'])
+ self.assertEqual(tenant_ref['name'], self.tenant_attr['name'])
+ self.assertEqual(tenant_ref['description'],
+ self.tenant_attr['description'])
+
+ CONF.ldap.tenant_name_attribute = 'desc'
+ CONF.ldap.tenant_desc_attribute = 'ou'
+ self.identity_api = identity_ldap.Identity()
+ tenant_ref = self.identity_api.get_tenant(self.tenant_attr['id'])
+ self.assertEqual(tenant_ref['id'], self.tenant_attr['id'])
+ self.assertEqual(tenant_ref['name'], self.tenant_attr['description'])
+ self.assertEqual(tenant_ref['description'], self.tenant_attr['name'])
+
+ def test_tenant_attribute_ignore(self):
+ self.config([test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_ldap.conf')])
+ CONF.ldap.tenant_attribute_ignore = ['name',
+ 'description',
+ 'enabled']
+ clear_database()
+ self.identity_api = identity_ldap.Identity()
+ self.load_fixtures(default_fixtures)
+ tenant_ref = self.identity_api.get_tenant(self.tenant_attr['id'])
+ self.assertEqual(tenant_ref['id'], self.tenant_attr['id'])
+ self.assertNotIn('name', tenant_ref)
+ self.assertNotIn('description', tenant_ref)
+ self.assertNotIn('enabled', tenant_ref)
+
+ def test_role_attribute_mapping(self):
+ self.config([test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_ldap.conf')])
+ CONF.ldap.role_name_attribute = 'ou'
+ clear_database()
+ self.identity_api = identity_ldap.Identity()
+ self.load_fixtures(default_fixtures)
+ role_ref = self.identity_api.get_role(self.role_attr['id'])
+ self.assertEqual(role_ref['id'], self.role_attr['id'])
+ self.assertEqual(role_ref['name'], self.role_attr['name'])
+
+ CONF.ldap.role_name_attribute = 'sn'
+ self.identity_api = identity_ldap.Identity()
+ role_ref = self.identity_api.get_role(self.role_attr['id'])
+ self.assertEqual(role_ref['id'], self.role_attr['id'])
+ self.assertNotIn('name', role_ref)
+
+ def test_role_attribute_ignore(self):
+ self.config([test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_ldap.conf')])
+ CONF.ldap.role_attribute_ignore = ['name']
+ clear_database()
+ self.identity_api = identity_ldap.Identity()
+ self.load_fixtures(default_fixtures)
+ role_ref = self.identity_api.get_role(self.role_attr['id'])
+ self.assertEqual(role_ref['id'], self.role_attr['id'])
+ self.assertNotIn('name', role_ref)