LDAP attribute names non-case-sensitive

keystone was not able to find any users while
the LDAP user name attribute was configured to
"samaccountname", but could find users when
reconfigured to use "sAMAccountName". LDAP is
not supposed to be case-sensitive, so either
should work.

This patch addresses the above problem by making
both the attributes into lower case. Also updated
the ldap_result example supporting python3.

Change-Id: I51813ac41489baed04f3cadbccd748e03025313e
Closes-Bug: #1753585
This commit is contained in:
Vishakha Agarwal 2018-09-18 15:17:07 +05:30 committed by Colleen Murphy
parent 50698fd128
commit 816b472a9d
3 changed files with 73 additions and 9 deletions

View File

@ -1402,20 +1402,31 @@ class BaseLdap(object):
raise ValueError('"%(attr)s" is not a valid value for'
' "%(attr_name)s"' % {'attr': attr,
'attr_name': attr_name})
# consider attr = "cn" and
# ldap_result = [{'uid': ['fake_id1']}, , 'cN': ["name"]}]
# doing lower case on both user_name_attribute and ldap users
# attribute
result = []
# consider attr = "cn" and
# ldap_result = [{'uid': ['fake_id1']},
# {'uid': ['fake_id2'], 'cn': [' ']},
# {'uid': ['fake_id3'], 'cn': ['']},
# {'uid': ['fake_id4'], 'cn': []},
# {'uid': ['fake_id5'], 'cn': ["name"]}]
# ldap_result = [(u'cn=fake1,o=ex_domain', {'uid': ['fake_id1']}),
# (u'cn=fake2,o=ex_domain', {'uid': ['fake_id2'],
# 'cn': [' ']}),
# (u'cn=fake3,o=ex_domain', {'uid': ['fake_id3'],
# 'cn': ['']}),
# (u'cn=fake4,o=ex_domain', {'uid': ['fake_id4'],
# 'cn': []}),
# (u'cn=fake5,o=ex_domain', {'uid': ['fake_id5'],
# 'cn': ["name"]})]
for obj in ldap_result:
# ignore ldap object(user/group entry) which has no attr set
# in it or whose value is empty list.
if obj[1].get(attr):
# ignore ldap object whose attr value has empty strings or
# contains only whitespaces.
if obj[1].get(attr)[0] and obj[1].get(attr)[0].strip():
ldap_res_low_keys_dict = {k.lower(): v for k, v in obj[1].items()}
result_attr_vals = ldap_res_low_keys_dict.get(attr.lower())
# ignore ldap object whose attr value has empty strings or
# contains only whitespaces.
if result_attr_vals:
if result_attr_vals[0] and result_attr_vals[0].strip():
result.append(obj)
# except {'uid': ['fake_id5'], 'cn': ["name"]}, all entries
# will be ignored in ldap_result

View File

@ -1308,6 +1308,53 @@ class LDAPIdentity(BaseLDAPIdentity):
self.assertEqual('junk1', user_refs[0]['name'])
self.assertEqual('sn=junk1,dc=example,dc=com', user_refs[0]['dn'])
@mock.patch.object(common_ldap.KeystoneLDAPHandler, 'connect')
@mock.patch.object(common_ldap.KeystoneLDAPHandler, 'search_s')
@mock.patch.object(common_ldap.KeystoneLDAPHandler, 'simple_bind_s')
def test_filter_ldap_result_with_case_sensitive_attr(self,
mock_simple_bind_s,
mock_search_s,
mock_connect):
# Mock the ldap search results to return user entries
# irrespective of lowercase and uppercase characters in
# ldap_result attribute keys e.g. {'Sn': ['junk1']} with
# user_name_attribute('sn')
mock_search_s.return_value = [(
'sn=junk1,dc=example,dc=com',
{
'cn': [uuid.uuid4().hex],
'email': [uuid.uuid4().hex],
'sN': ['junk1']
}
),
(
'sn=junk1,dc=example,dc=com',
{
'cn': [uuid.uuid4().hex],
'email': [uuid.uuid4().hex],
'Sn': ['junk1']
}
),
(
'sn=junk1,dc=example,dc=com',
{
'cn': [uuid.uuid4().hex],
'email': [uuid.uuid4().hex],
'sn': [' ']
}
)
]
user_api = identity.backends.ldap.UserApi(CONF)
user_refs = user_api.get_all()
# validate that keystone.identity.backends.ldap.common.BaseLdap.
# _filter_ldap_result_by_attr() method filtered the ldap query results
# whose name attribute keys having case insensitive characters.
self.assertEqual(2, len(user_refs))
self.assertEqual('junk1', user_refs[0]['name'])
self.assertEqual('sn=junk1,dc=example,dc=com', user_refs[0]['dn'])
@mock.patch.object(common_ldap.BaseLdap, '_ldap_get')
def test_user_enabled_attribute_handles_expired(self, mock_ldap_get):
# If using 'passwordisexpired' as enabled attribute, and inverting it,

View File

@ -0,0 +1,6 @@
---
fixes:
- |
['bug 1753585 <https://bugs.launchpad.net/keystone/+bug/1753585>'_]
LDAP attribute names are now matched case insensitively to comply with
LDAP implementations.