Use newer python-ldap paging control API
The API for using the LDAP simple paged results control changed
between python-ldap version 2.3 and 2.4. Our current implementation
fails with an AttributeError when trying to use paging with version
2.4 of python-ldap.
This patch detects the capabilities of the underlying python-ldap
version and uses the newer API in versions of python-ldap that have
removed the older API.
Change-Id: I2986e12daea3edf50f299af5927d2a05278e82f7
Closes-bug: #1381768
(cherry picked from commit 1be4a15454
)
This commit is contained in:
parent
e9cba76e8e
commit
db291b340e
|
@ -960,10 +960,24 @@ class KeystoneLDAPHandler(LDAPHandler):
|
|||
|
||||
def _paged_search_s(self, base, scope, filterstr, attrlist=None):
|
||||
res = []
|
||||
lc = ldap.controls.SimplePagedResultsControl(
|
||||
controlType=ldap.LDAP_CONTROL_PAGE_OID,
|
||||
criticality=True,
|
||||
controlValue=(self.page_size, ''))
|
||||
use_old_paging_api = False
|
||||
# The API for the simple paged results control changed between
|
||||
# python-ldap 2.3 and 2.4. We need to detect the capabilities
|
||||
# of the python-ldap version we are using.
|
||||
if hasattr(ldap, 'LDAP_CONTROL_PAGE_OID'):
|
||||
use_old_paging_api = True
|
||||
lc = ldap.controls.SimplePagedResultsControl(
|
||||
controlType=ldap.LDAP_CONTROL_PAGE_OID,
|
||||
criticality=True,
|
||||
controlValue=(self.page_size, ''))
|
||||
page_ctrl_oid = ldap.LDAP_CONTROL_PAGE_OID
|
||||
else:
|
||||
lc = ldap.controls.libldap.SimplePagedResultsControl(
|
||||
criticality=True,
|
||||
size=self.page_size,
|
||||
cookie='')
|
||||
page_ctrl_oid = ldap.controls.SimplePagedResultsControl.controlType
|
||||
|
||||
base_utf8 = utf8_encode(base)
|
||||
filterstr_utf8 = utf8_encode(filterstr)
|
||||
if attrlist is None:
|
||||
|
@ -983,14 +997,18 @@ class KeystoneLDAPHandler(LDAPHandler):
|
|||
# Receive the data
|
||||
res.extend(rdata)
|
||||
pctrls = [c for c in serverctrls
|
||||
if c.controlType == ldap.LDAP_CONTROL_PAGE_OID]
|
||||
if c.controlType == page_ctrl_oid]
|
||||
if pctrls:
|
||||
# LDAP server supports pagination
|
||||
est, cookie = pctrls[0].controlValue
|
||||
if use_old_paging_api:
|
||||
est, cookie = pctrls[0].controlValue
|
||||
lc.controlValue = (self.page_size, cookie)
|
||||
else:
|
||||
cookie = lc.cookie = pctrls[0].cookie
|
||||
|
||||
if cookie:
|
||||
# There is more data still on the server
|
||||
# so we request another page
|
||||
lc.controlValue = (self.page_size, cookie)
|
||||
msgid = self.conn.search_ext(base_utf8,
|
||||
scope,
|
||||
filterstr_utf8,
|
||||
|
|
|
@ -349,3 +349,45 @@ class SslTlsTest(tests.TestCase):
|
|||
|
||||
# Ensure the cert trust option is set.
|
||||
self.assertEqual(certdir, ldap.get_option(ldap.OPT_X_TLS_CACERTDIR))
|
||||
|
||||
|
||||
class LDAPPagedResultsTest(tests.TestCase):
|
||||
"""Tests the paged results functionality in keystone.common.ldap.core."""
|
||||
|
||||
def setUp(self):
|
||||
super(LDAPPagedResultsTest, self).setUp()
|
||||
self.clear_database()
|
||||
|
||||
ks_ldap.register_handler('fake://', fakeldap.FakeLdap)
|
||||
self.addCleanup(common_ldap_core._HANDLERS.clear)
|
||||
|
||||
self.load_backends()
|
||||
self.load_fixtures(default_fixtures)
|
||||
|
||||
def clear_database(self):
|
||||
for shelf in fakeldap.FakeShelves:
|
||||
fakeldap.FakeShelves[shelf].clear()
|
||||
|
||||
def config_overrides(self):
|
||||
super(LDAPPagedResultsTest, self).config_overrides()
|
||||
self.config_fixture.config(
|
||||
group='identity',
|
||||
driver='keystone.identity.backends.ldap.Identity')
|
||||
|
||||
def config_files(self):
|
||||
config_files = super(LDAPPagedResultsTest, self).config_files()
|
||||
config_files.append(tests.dirs.tests_conf('backend_ldap.conf'))
|
||||
return config_files
|
||||
|
||||
@mock.patch.object(fakeldap.FakeLdap, 'search_ext')
|
||||
@mock.patch.object(fakeldap.FakeLdap, 'result3')
|
||||
def test_paged_results_control_api(self, mock_result3, mock_search_ext):
|
||||
mock_result3.return_value = ('', [], 1, [])
|
||||
|
||||
self.config_fixture.config(group='ldap',
|
||||
page_size=1)
|
||||
|
||||
conn = self.identity_api.user.get_connection()
|
||||
conn._paged_search_s('dc=example,dc=test',
|
||||
ldap.SCOPE_SUBTREE,
|
||||
'objectclass=*')
|
||||
|
|
Loading…
Reference in New Issue