Ability to turn off ldap referral chasing

When getting an ldap connection, check a config property to see if
referral chasing should be turned off.

Co-Authored-By: Dolph Mathews <dolph.mathews@gmail.com>
Change-Id: I3bb5cc11b3c5c9108cfa656d5f5de1eaeb103fe5
Closes-Bug: 1233365
This commit is contained in:
Craig Jellick 2014-03-05 18:58:57 -07:00 committed by Dolph Mathews
parent 634243dece
commit 9c15b73f83
4 changed files with 76 additions and 3 deletions

@ -842,6 +842,9 @@
# Search base for users. (string value)
#user_tree_dn=<None>
# Override the system's default referral chasing behavior for queries.
#chase_referrals=<None>
# LDAP search filter for users. (string value)
#user_filter=<None>

@ -416,6 +416,9 @@ FILE_OPTIONS = {
'"finding" or "default". The "default" option falls '
'back to using default dereferencing configured by '
'your ldap.conf.'),
cfg.BoolOpt('chase_referrals', default=None,
help='Override the system\'s default referral chasing '
'behavior for queries.'),
cfg.StrOpt('user_tree_dn', default=None,
help='Search base for users.'),
cfg.StrOpt('user_filter', default=None,

@ -146,6 +146,7 @@ class BaseLdap(object):
self.tls_cacertdir = conf.ldap.tls_cacertdir
self.tls_req_cert = parse_tls_cert(conf.ldap.tls_req_cert)
self.attribute_mapping = {}
self.chase_referrals = conf.ldap.chase_referrals
if self.options_name is not None:
self.suffix = conf.ldap.suffix
@ -235,7 +236,8 @@ class BaseLdap(object):
use_tls=self.use_tls,
tls_cacertfile=self.tls_cacertfile,
tls_cacertdir=self.tls_cacertdir,
tls_req_cert=self.tls_req_cert)
tls_req_cert=self.tls_req_cert,
chase_referrals=self.chase_referrals)
if user is None:
user = self.LDAP_USER
@ -485,7 +487,7 @@ class BaseLdap(object):
class LdapWrapper(object):
def __init__(self, url, page_size, alias_dereferencing=None,
use_tls=False, tls_cacertfile=None, tls_cacertdir=None,
tls_req_cert='demand'):
tls_req_cert='demand', chase_referrals=None):
LOG.debug(_("LDAP init: url=%s"), url)
LOG.debug(_('LDAP init: use_tls=%(use_tls)s\n'
'tls_cacertfile=%(tls_cacertfile)s\n'
@ -552,6 +554,9 @@ class LdapWrapper(object):
if use_tls:
self.conn.start_tls_s()
if chase_referrals is not None:
self.conn.set_option(ldap.OPT_REFERRALS, int(chase_referrals))
def simple_bind_s(self, user, password):
LOG.debug(_("LDAP bind: dn=%s"), user)
return self.conn.simple_bind_s(user, password)
@ -591,9 +596,20 @@ class LdapWrapper(object):
res = self.conn.search_s(dn, scope, query, attrlist)
o = []
at_least_one_referral = False
for dn, attrs in res:
if dn is None:
# this is a Referral object, rather than an Entry object
at_least_one_referral = True
continue
o.append((dn, dict((kind, [ldap2py(x) for x in values])
for kind, values in six.iteritems(attrs))))
if at_least_one_referral:
LOG.debug(_('Referrals were returned and ignored. Enable referral '
'chasing in keystone.conf via [ldap] chase_referrals'))
return o
def paged_search_s(self, dn, scope, query, attrlist=None):

@ -874,11 +874,62 @@ class LDAPIdentity(BaseLDAPIdentity, tests.TestCase):
tls_cacertdir=None,
tls_cacertfile=None,
tls_req_cert=2,
use_tls=False).AndReturn(conn)
use_tls=False,
chase_referrals=None).AndReturn(conn)
self.mox.ReplayAll()
user_api.get_connection(user=None, password=None)
def test_chase_referrals_off(self):
self.config_fixture.config(
group='ldap',
url='fake://memory',
chase_referrals=False)
user_api = identity.backends.ldap.UserApi(CONF)
self.stubs.Set(fakeldap, 'FakeLdap',
self.mox.CreateMock(fakeldap.FakeLdap))
common_ldap.register_handler('fake://', fakeldap.FakeLdap)
user = uuid.uuid4().hex
password = uuid.uuid4().hex
conn = self.mox.CreateMockAnything()
conn = fakeldap.FakeLdap(CONF.ldap.url,
0,
alias_dereferencing=None,
tls_cacertdir=None,
tls_cacertfile=None,
tls_req_cert=2,
use_tls=False,
chase_referrals=False).AndReturn(conn)
conn.simple_bind_s(user, password).AndReturn(None)
self.mox.ReplayAll()
user_api.get_connection(user=user, password=password)
def test_chase_referrals_on(self):
self.config_fixture.config(
group='ldap',
url='fake://memory',
chase_referrals=True)
user_api = identity.backends.ldap.UserApi(CONF)
self.stubs.Set(fakeldap, 'FakeLdap',
self.mox.CreateMock(fakeldap.FakeLdap))
common_ldap.register_handler('fake://', fakeldap.FakeLdap)
user = uuid.uuid4().hex
password = uuid.uuid4().hex
conn = self.mox.CreateMockAnything()
conn = fakeldap.FakeLdap(CONF.ldap.url,
0,
alias_dereferencing=None,
tls_cacertdir=None,
tls_cacertfile=None,
tls_req_cert=2,
use_tls=False,
chase_referrals=True).AndReturn(conn)
conn.simple_bind_s(user, password).AndReturn(None)
self.mox.ReplayAll()
user_api.get_connection(user=user, password=password)
def test_wrong_ldap_scope(self):
CONF.ldap.query_scope = uuid.uuid4().hex
self.assertRaisesRegexp(