Skip to content
Permalink
Browse files

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
  • Loading branch information...
Craig Jellick and dolph committed Mar 6, 2014
1 parent 634243d commit 9c15b73f8361ce8606a531b5765c94b3927d99c4
Showing with 76 additions and 3 deletions.
  1. +3 −0 etc/keystone.conf.sample
  2. +3 −0 keystone/common/config.py
  3. +18 −2 keystone/common/ldap/core.py
  4. +52 −1 keystone/tests/test_backend_ldap.py
@@ -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 @@
'"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 @@ def __init__(self, conf):
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 @@ def get_connection(self, user=None, password=None):
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 @@ def deleteTree(self, object_id):
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 @@ def __init__(self, url, page_size, alias_dereferencing=None,
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 @@ def search_s(self, dn, scope, query, attrlist=None):
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 @@ def test_user_api_get_connection_no_user_password(self):
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(

0 comments on commit 9c15b73

Please sign in to comment.
You can’t perform that action at this time.