Remove hardcoded LDAP group schema from emulated enabled mix-in
The emulated enabled mix-in uses hard-coded LDAP schema for the group objectclass and membership attributes. This patch makes the mix-in optionally use the LDAP group configuration settings. Change-Id: I5ed9d552ec140f83578398fd29e2130ebf827662 Closes-Bug: #1515302
This commit is contained in:
parent
6500f81de2
commit
e465de5b44
|
@ -1637,9 +1637,9 @@ have been created. They are enabled by setting their respective flags to True.
|
||||||
Then the attributes ``user_enabled_emulation_dn`` and
|
Then the attributes ``user_enabled_emulation_dn`` and
|
||||||
``project_enabled_emulation_dn`` may be set to specify how the enabled users
|
``project_enabled_emulation_dn`` may be set to specify how the enabled users
|
||||||
and projects (tenants) are selected. These attributes work by using a
|
and projects (tenants) are selected. These attributes work by using a
|
||||||
``groupOfNames`` and adding whichever users or projects (tenants) that you want
|
``groupOfNames`` entry and adding whichever users or projects (tenants) that
|
||||||
enabled to the respective group. For example, this will mark any user who is a
|
you want enabled to the respective group with the ``member`` attribute. For
|
||||||
member of ``enabled_users`` as enabled:
|
example, this will mark any user who is a member of ``enabled_users`` as enabled:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
|
@ -1651,6 +1651,12 @@ The default values for user and project (tenant) enabled emulation DN is
|
||||||
``cn=enabled_users,$user_tree_dn`` and ``cn=enabled_tenants,$project_tree_dn``
|
``cn=enabled_users,$user_tree_dn`` and ``cn=enabled_tenants,$project_tree_dn``
|
||||||
respectively.
|
respectively.
|
||||||
|
|
||||||
|
If a different LDAP schema is used for group membership, it is possible to use
|
||||||
|
the ``group_objectclass`` and ``group_member_attribute`` attributes to
|
||||||
|
determine membership in the enabled emulation group by setting the
|
||||||
|
``user_enabled_emulation_use_group_config`` and
|
||||||
|
``project_enabled_emulation_use_group_config`` attributes to True.
|
||||||
|
|
||||||
Secure Connection
|
Secure Connection
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|
|
@ -1047,6 +1047,10 @@
|
||||||
# (string value)
|
# (string value)
|
||||||
#user_enabled_emulation_dn = <None>
|
#user_enabled_emulation_dn = <None>
|
||||||
|
|
||||||
|
# Use the "group_member_attribute" and "group_objectclass" settings to
|
||||||
|
# determine membership in the emulated enabled group. (boolean value)
|
||||||
|
#user_enabled_emulation_use_group_config = false
|
||||||
|
|
||||||
# List of additional LDAP attributes used for mapping additional attribute
|
# List of additional LDAP attributes used for mapping additional attribute
|
||||||
# mappings for users. Attribute mapping format is <ldap_attr>:<user_attr>,
|
# mappings for users. Attribute mapping format is <ldap_attr>:<user_attr>,
|
||||||
# where ldap_attr is the attribute in the LDAP entry and user_attr is the
|
# where ldap_attr is the attribute in the LDAP entry and user_attr is the
|
||||||
|
@ -1146,6 +1150,10 @@
|
||||||
# Its value may be silently ignored in the future.
|
# Its value may be silently ignored in the future.
|
||||||
#project_enabled_emulation_dn = <None>
|
#project_enabled_emulation_dn = <None>
|
||||||
|
|
||||||
|
# Use the "group_member_attribute" and "group_objectclass" settings to
|
||||||
|
# determine membership in the emulated enabled group. (boolean value)
|
||||||
|
#project_enabled_emulation_use_group_config = false
|
||||||
|
|
||||||
# Additional attribute mappings for projects. Attribute mapping format is
|
# Additional attribute mappings for projects. Attribute mapping format is
|
||||||
# <ldap_attr>:<user_attr>, where ldap_attr is the attribute in the LDAP entry
|
# <ldap_attr>:<user_attr>, where ldap_attr is the attribute in the LDAP entry
|
||||||
# and user_attr is the Identity API attribute. (list value)
|
# and user_attr is the Identity API attribute. (list value)
|
||||||
|
|
|
@ -593,6 +593,10 @@ FILE_OPTIONS = {
|
||||||
cfg.StrOpt('user_enabled_emulation_dn',
|
cfg.StrOpt('user_enabled_emulation_dn',
|
||||||
help='DN of the group entry to hold enabled users when '
|
help='DN of the group entry to hold enabled users when '
|
||||||
'using enabled emulation.'),
|
'using enabled emulation.'),
|
||||||
|
cfg.BoolOpt('user_enabled_emulation_use_group_config', default=False,
|
||||||
|
help='Use the "group_member_attribute" and '
|
||||||
|
'"group_objectclass" settings to determine '
|
||||||
|
'membership in the emulated enabled group.'),
|
||||||
cfg.ListOpt('user_additional_attribute_mapping',
|
cfg.ListOpt('user_additional_attribute_mapping',
|
||||||
default=[],
|
default=[],
|
||||||
help='List of additional LDAP attributes used for mapping '
|
help='List of additional LDAP attributes used for mapping '
|
||||||
|
@ -684,6 +688,11 @@ FILE_OPTIONS = {
|
||||||
deprecated_for_removal=True,
|
deprecated_for_removal=True,
|
||||||
help='DN of the group entry to hold enabled projects when '
|
help='DN of the group entry to hold enabled projects when '
|
||||||
'using enabled emulation.'),
|
'using enabled emulation.'),
|
||||||
|
cfg.BoolOpt('project_enabled_emulation_use_group_config',
|
||||||
|
default=False,
|
||||||
|
help='Use the "group_member_attribute" and '
|
||||||
|
'"group_objectclass" settings to determine '
|
||||||
|
'membership in the emulated enabled group.'),
|
||||||
cfg.ListOpt('project_additional_attribute_mapping',
|
cfg.ListOpt('project_additional_attribute_mapping',
|
||||||
deprecated_opts=[cfg.DeprecatedOpt(
|
deprecated_opts=[cfg.DeprecatedOpt(
|
||||||
'tenant_additional_attribute_mapping', group='ldap')],
|
'tenant_additional_attribute_mapping', group='ldap')],
|
||||||
|
|
|
@ -1773,19 +1773,23 @@ class BaseLdap(object):
|
||||||
class EnabledEmuMixIn(BaseLdap):
|
class EnabledEmuMixIn(BaseLdap):
|
||||||
"""Emulates boolean 'enabled' attribute if turned on.
|
"""Emulates boolean 'enabled' attribute if turned on.
|
||||||
|
|
||||||
Creates groupOfNames holding all enabled objects of this class, all missing
|
Creates a group holding all enabled objects of this class, all missing
|
||||||
objects are considered disabled.
|
objects are considered disabled.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
* $name_enabled_emulation - boolean, on/off
|
* $name_enabled_emulation - boolean, on/off
|
||||||
* $name_enabled_emulation_dn - DN of that groupOfNames, default is
|
* $name_enabled_emulation_dn - DN of that group, default is
|
||||||
cn=enabled_${name}s,${tree_dn}
|
cn=enabled_${name}s,${tree_dn}
|
||||||
|
* $name_enabled_emulation_use_group_config - boolean, on/off
|
||||||
|
|
||||||
Where ${name}s is the plural of self.options_name ('users' or 'tenants'),
|
Where ${name}s is the plural of self.options_name ('users' or 'tenants'),
|
||||||
${tree_dn} is self.tree_dn.
|
${tree_dn} is self.tree_dn.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
DEFAULT_GROUP_OBJECTCLASS = 'groupOfNames'
|
||||||
|
DEFAULT_MEMBER_ATTRIBUTE = 'member'
|
||||||
|
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
super(EnabledEmuMixIn, self).__init__(conf)
|
super(EnabledEmuMixIn, self).__init__(conf)
|
||||||
enabled_emulation = '%s_enabled_emulation' % self.options_name
|
enabled_emulation = '%s_enabled_emulation' % self.options_name
|
||||||
|
@ -1793,6 +1797,18 @@ class EnabledEmuMixIn(BaseLdap):
|
||||||
|
|
||||||
enabled_emulation_dn = '%s_enabled_emulation_dn' % self.options_name
|
enabled_emulation_dn = '%s_enabled_emulation_dn' % self.options_name
|
||||||
self.enabled_emulation_dn = getattr(conf.ldap, enabled_emulation_dn)
|
self.enabled_emulation_dn = getattr(conf.ldap, enabled_emulation_dn)
|
||||||
|
|
||||||
|
use_group_config = ('%s_enabled_emulation_use_group_config' %
|
||||||
|
self.options_name)
|
||||||
|
self.use_group_config = getattr(conf.ldap, use_group_config)
|
||||||
|
|
||||||
|
if not self.use_group_config:
|
||||||
|
self.member_attribute = self.DEFAULT_MEMBER_ATTRIBUTE
|
||||||
|
self.group_objectclass = self.DEFAULT_GROUP_OBJECTCLASS
|
||||||
|
else:
|
||||||
|
self.member_attribute = conf.ldap.group_member_attribute
|
||||||
|
self.group_objectclass = conf.ldap.group_objectclass
|
||||||
|
|
||||||
if not self.enabled_emulation_dn:
|
if not self.enabled_emulation_dn:
|
||||||
naming_attr_name = 'cn'
|
naming_attr_name = 'cn'
|
||||||
naming_attr_value = 'enabled_%ss' % self.options_name
|
naming_attr_value = 'enabled_%ss' % self.options_name
|
||||||
|
@ -1809,7 +1825,7 @@ class EnabledEmuMixIn(BaseLdap):
|
||||||
|
|
||||||
def _get_enabled(self, object_id, conn):
|
def _get_enabled(self, object_id, conn):
|
||||||
dn = self._id_to_dn(object_id)
|
dn = self._id_to_dn(object_id)
|
||||||
query = '(member=%s)' % dn
|
query = '(%s=%s)' % (self.member_attribute, dn)
|
||||||
try:
|
try:
|
||||||
enabled_value = conn.search_s(self.enabled_emulation_dn,
|
enabled_value = conn.search_s(self.enabled_emulation_dn,
|
||||||
ldap.SCOPE_BASE,
|
ldap.SCOPE_BASE,
|
||||||
|
@ -1823,13 +1839,14 @@ class EnabledEmuMixIn(BaseLdap):
|
||||||
with self.get_connection() as conn:
|
with self.get_connection() as conn:
|
||||||
if not self._get_enabled(object_id, conn):
|
if not self._get_enabled(object_id, conn):
|
||||||
modlist = [(ldap.MOD_ADD,
|
modlist = [(ldap.MOD_ADD,
|
||||||
'member',
|
self.member_attribute,
|
||||||
[self._id_to_dn(object_id)])]
|
[self._id_to_dn(object_id)])]
|
||||||
try:
|
try:
|
||||||
conn.modify_s(self.enabled_emulation_dn, modlist)
|
conn.modify_s(self.enabled_emulation_dn, modlist)
|
||||||
except ldap.NO_SUCH_OBJECT:
|
except ldap.NO_SUCH_OBJECT:
|
||||||
attr_list = [('objectClass', ['groupOfNames']),
|
attr_list = [('objectClass', [self.group_objectclass]),
|
||||||
('member', [self._id_to_dn(object_id)]),
|
(self.member_attribute,
|
||||||
|
[self._id_to_dn(object_id)]),
|
||||||
self.enabled_emulation_naming_attr]
|
self.enabled_emulation_naming_attr]
|
||||||
if self.use_dumb_member:
|
if self.use_dumb_member:
|
||||||
attr_list[1][1].append(self.dumb_member)
|
attr_list[1][1].append(self.dumb_member)
|
||||||
|
@ -1837,7 +1854,7 @@ class EnabledEmuMixIn(BaseLdap):
|
||||||
|
|
||||||
def _remove_enabled(self, object_id):
|
def _remove_enabled(self, object_id):
|
||||||
modlist = [(ldap.MOD_DELETE,
|
modlist = [(ldap.MOD_DELETE,
|
||||||
'member',
|
self.member_attribute,
|
||||||
[self._id_to_dn(object_id)])]
|
[self._id_to_dn(object_id)])]
|
||||||
with self.get_connection() as conn:
|
with self.get_connection() as conn:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -838,6 +838,7 @@ class DomainConfigManager(manager.Manager):
|
||||||
'user_attribute_ignore', 'user_default_project_id_attribute',
|
'user_attribute_ignore', 'user_default_project_id_attribute',
|
||||||
'user_allow_create', 'user_allow_update', 'user_allow_delete',
|
'user_allow_create', 'user_allow_update', 'user_allow_delete',
|
||||||
'user_enabled_emulation', 'user_enabled_emulation_dn',
|
'user_enabled_emulation', 'user_enabled_emulation_dn',
|
||||||
|
'user_enabled_emulation_use_group_config',
|
||||||
'user_additional_attribute_mapping', 'group_tree_dn',
|
'user_additional_attribute_mapping', 'group_tree_dn',
|
||||||
'group_filter', 'group_objectclass', 'group_id_attribute',
|
'group_filter', 'group_objectclass', 'group_id_attribute',
|
||||||
'group_name_attribute', 'group_member_attribute',
|
'group_name_attribute', 'group_member_attribute',
|
||||||
|
|
|
@ -2248,6 +2248,26 @@ class LDAPIdentityEnabledEmulation(LDAPIdentity):
|
||||||
self.skipTest(
|
self.skipTest(
|
||||||
"Enabled emulation conflicts with enabled mask")
|
"Enabled emulation conflicts with enabled mask")
|
||||||
|
|
||||||
|
def test_user_enabled_use_group_config(self):
|
||||||
|
self.config_fixture.config(
|
||||||
|
group='ldap',
|
||||||
|
user_enabled_emulation_use_group_config=True,
|
||||||
|
group_member_attribute='uniqueMember',
|
||||||
|
group_objectclass='groupOfUniqueNames')
|
||||||
|
self.ldapdb.clear()
|
||||||
|
self.load_backends()
|
||||||
|
self.load_fixtures(default_fixtures)
|
||||||
|
|
||||||
|
# Create a user and ensure they are enabled.
|
||||||
|
user1 = {'name': u'fäké1', 'enabled': True,
|
||||||
|
'domain_id': CONF.identity.default_domain_id}
|
||||||
|
user_ref = self.identity_api.create_user(user1)
|
||||||
|
self.assertIs(True, user_ref['enabled'])
|
||||||
|
|
||||||
|
# Get a user and ensure they are enabled.
|
||||||
|
user_ref = self.identity_api.get_user(user_ref['id'])
|
||||||
|
self.assertIs(True, user_ref['enabled'])
|
||||||
|
|
||||||
def test_user_enabled_invert(self):
|
def test_user_enabled_invert(self):
|
||||||
self.config_fixture.config(group='ldap', user_enabled_invert=True,
|
self.config_fixture.config(group='ldap', user_enabled_invert=True,
|
||||||
user_enabled_default=False)
|
user_enabled_default=False)
|
||||||
|
|
Loading…
Reference in New Issue