Skip to content

Commit aa0a07b

Browse files
committed
Make LDAPI optional
LDAPI is LDAP over Unix Domain Socket, also referred as LDAP IPC. AF_UNIX is only supported on POSIX compatible operating systems. Don't bind to LDAPI socket and skip LDAPI specific tests, e.g. SASL EXTERNAL with SO_PEERCRED. Signed-off-by: Christian Heimes <cheimes@redhat.com>
1 parent ab93063 commit aa0a07b

File tree

6 files changed

+55
-21
lines changed

6 files changed

+55
-21
lines changed

Lib/slapdtest/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
__version__ = '3.0.0b2'
99

1010
from slapdtest._slapdtest import SlapdObject, SlapdTestCase, SysLogHandler
11-
from slapdtest._slapdtest import skip_unless_ci, requires_sasl, requires_tls
11+
from slapdtest._slapdtest import requires_ldapi, requires_sasl, requires_tls
12+
from slapdtest._slapdtest import skip_unless_ci

Lib/slapdtest/_slapdtest.py

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@
5656

5757
LOCALHOST = '127.0.0.1'
5858

59+
CI_DISABLED = set(os.environ.get('CI_DISABLED', '').split(':'))
60+
if 'LDAPI' in CI_DISABLED:
61+
HAVE_LDAPI = False
62+
else:
63+
HAVE_LDAPI = hasattr(socket, 'AF_UNIX')
64+
5965

6066
def identity(test_item):
6167
"""Identity decorator
@@ -69,7 +75,7 @@ def skip_unless_ci(reason, feature=None):
6975
"""
7076
if not os.environ.get('CI', False):
7177
return unittest.skip(reason)
72-
elif feature in os.environ.get('CI_DISABLED', '').split(':'):
78+
elif feature in CI_DISABLED:
7379
return unittest.skip(reason)
7480
else:
7581
# Don't skip on Travis
@@ -95,6 +101,14 @@ def requires_sasl():
95101
return identity
96102

97103

104+
def requires_ldapi():
105+
if not HAVE_LDAPI:
106+
return skip_unless_ci(
107+
"test needs ldapi support (AF_UNIX)", feature='LDAPI')
108+
else:
109+
return identity
110+
111+
98112
def combined_logger(
99113
log_name,
100114
log_level=logging.WARN,
@@ -149,8 +163,6 @@ class SlapdObject(object):
149163
root_dn = 'cn=%s,%s' % (root_cn, suffix)
150164
root_pw = 'password'
151165
slapd_loglevel = 'stats stats2'
152-
# use SASL/EXTERNAL via LDAPI when invoking OpenLDAP CLI tools
153-
cli_sasl_external = True
154166
local_host = '127.0.0.1'
155167
testrunsubdirs = (
156168
'schema',
@@ -192,8 +204,17 @@ def __init__(self):
192204
self._slapd_conf = os.path.join(self.testrundir, 'slapd.conf')
193205
self._db_directory = os.path.join(self.testrundir, "openldap-data")
194206
self.ldap_uri = "ldap://%s:%d/" % (LOCALHOST, self._port)
195-
ldapi_path = os.path.join(self.testrundir, 'ldapi')
196-
self.ldapi_uri = "ldapi://%s" % quote_plus(ldapi_path)
207+
if HAVE_LDAPI:
208+
ldapi_path = os.path.join(self.testrundir, 'ldapi')
209+
self.ldapi_uri = "ldapi://%s" % quote_plus(ldapi_path)
210+
self.default_ldap_uri = self.ldapi_uri
211+
# use SASL/EXTERNAL via LDAPI when invoking OpenLDAP CLI tools
212+
self.cli_sasl_external = True
213+
else:
214+
self.ldapi_uri = None
215+
self.default_ldap_uri = self.ldap_uri
216+
# Use simple bind via LDAP uri
217+
self.cli_sasl_external = False
197218
# TLS certs
198219
self.cafile = os.path.join(HERE, 'certs/ca.pem')
199220
self.servercert = os.path.join(HERE, 'certs/server.pem')
@@ -331,11 +352,14 @@ def _start_slapd(self):
331352
"""
332353
Spawns/forks the slapd process
333354
"""
355+
urls = [self.ldap_uri]
356+
if self.ldapi_uri:
357+
urls.append(self.ldapi_uri)
334358
slapd_args = [
335359
self.PATH_SLAPD,
336360
'-f', self._slapd_conf,
337361
'-F', self.testrundir,
338-
'-h', '%s' % ' '.join((self.ldap_uri, self.ldapi_uri)),
362+
'-h', '%s' % ' '.join(urls),
339363
]
340364
if self._log.isEnabledFor(logging.DEBUG):
341365
slapd_args.extend(['-d', '-1'])
@@ -346,18 +370,21 @@ def _start_slapd(self):
346370
# Waits until the LDAP server socket is open, or slapd crashed
347371
# no cover to avoid spurious coverage changes, see
348372
# https://github.com/python-ldap/python-ldap/issues/127
349-
while 1: # pragma: no cover
373+
for _ in range(10): # pragma: no cover
350374
if self._proc.poll() is not None:
351375
self._stopped()
352376
raise RuntimeError("slapd exited before opening port")
353377
time.sleep(self._start_sleep)
354378
try:
355-
self._log.debug("slapd connection check to %s", self.ldapi_uri)
379+
self._log.debug(
380+
"slapd connection check to %s", self.default_ldap_uri
381+
)
356382
self.ldapwhoami()
357383
except RuntimeError:
358384
pass
359385
else:
360386
return
387+
raise RuntimeError("slapd did not start properly")
361388

362389
def start(self):
363390
"""
@@ -435,9 +462,11 @@ def _cli_auth_args(self):
435462
# no cover to avoid spurious coverage changes
436463
def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
437464
stdin_data=None): # pragma: no cover
465+
if ldap_uri is None:
466+
ldap_uri = self.default_ldap_uri
438467
args = [
439468
ldapcommand,
440-
'-H', ldap_uri or self.ldapi_uri,
469+
'-H', ldap_uri,
441470
] + self._cli_auth_args() + (extra_args or [])
442471
self._log.debug('Run command: %r', ' '.join(args))
443472
proc = subprocess.Popen(

Tests/t_ldap_sasl.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515
from ldap.ldapobject import SimpleLDAPObject
1616
import ldap.sasl
17-
from slapdtest import SlapdTestCase, requires_sasl, requires_tls
17+
from slapdtest import SlapdTestCase
18+
from slapdtest import requires_ldapi, requires_sasl, requires_tls
1819

1920

2021
LDIF = """
@@ -60,7 +61,7 @@ def setUpClass(cls):
6061
)
6162
cls.server.ldapadd(ldif)
6263

63-
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), "needs Unix socket")
64+
@requires_ldapi()
6465
def test_external_ldapi(self):
6566
# EXTERNAL authentication with LDAPI (AF_UNIX)
6667
ldap_conn = self.ldap_object_class(self.server.ldapi_uri)

Tests/t_ldap_schema_subentry.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from ldap.ldapobject import SimpleLDAPObject
1717
import ldap.schema
1818
from ldap.schema.models import ObjectClass
19-
from slapdtest import SlapdTestCase
19+
from slapdtest import SlapdTestCase, requires_ldapi
2020

2121
HERE = os.path.abspath(os.path.dirname(__file__))
2222

@@ -88,6 +88,7 @@ def test_urlfetch_ldap(self):
8888
dn, schema = ldap.schema.urlfetch(self.server.ldap_uri)
8989
self.assertSlapdSchema(dn, schema)
9090

91+
@requires_ldapi()
9192
def test_urlfetch_ldapi(self):
9293
dn, schema = ldap.schema.urlfetch(self.server.ldapi_uri)
9394
self.assertSlapdSchema(dn, schema)

Tests/t_ldapobject.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
import unittest
2323
import warnings
2424
import pickle
25-
import warnings
26-
from slapdtest import SlapdTestCase, requires_sasl, requires_tls
25+
from slapdtest import SlapdTestCase
26+
from slapdtest import requires_ldapi, requires_sasl, requires_tls
2727

2828
# Switch off processing .ldaprc or ldap.conf before importing _ldap
2929
os.environ['LDAPNOINIT'] = '1'
@@ -303,6 +303,7 @@ def test005_invalid_credentials(self):
303303
self.fail("expected INVALID_CREDENTIALS, got %r" % r)
304304

305305
@requires_sasl()
306+
@requires_ldapi()
306307
def test006_sasl_extenal_bind_s(self):
307308
l = self.ldap_object_class(self.server.ldapi_uri)
308309
l.sasl_external_bind_s()
@@ -441,6 +442,7 @@ class Test01_ReconnectLDAPObject(Test00_SimpleLDAPObject):
441442
ldap_object_class = ReconnectLDAPObject
442443

443444
@requires_sasl()
445+
@requires_ldapi()
444446
def test101_reconnect_sasl_external(self):
445447
l = self.ldap_object_class(self.server.ldapi_uri)
446448
l.sasl_external_bind_s()
@@ -450,15 +452,15 @@ def test101_reconnect_sasl_external(self):
450452
self.assertEqual(l.whoami_s(), authz_id)
451453

452454
def test102_reconnect_simple_bind(self):
453-
l = self.ldap_object_class(self.server.ldapi_uri)
455+
l = self.ldap_object_class(self.server.ldap_uri)
454456
bind_dn = 'cn=user1,'+self.server.suffix
455457
l.simple_bind_s(bind_dn, 'user1_pw')
456458
self.assertEqual(l.whoami_s(), 'dn:'+bind_dn)
457459
self.server.restart()
458460
self.assertEqual(l.whoami_s(), 'dn:'+bind_dn)
459461

460462
def test103_reconnect_get_state(self):
461-
l1 = self.ldap_object_class(self.server.ldapi_uri)
463+
l1 = self.ldap_object_class(self.server.ldap_uri)
462464
bind_dn = 'cn=user1,'+self.server.suffix
463465
l1.simple_bind_s(bind_dn, 'user1_pw')
464466
self.assertEqual(l1.whoami_s(), 'dn:'+bind_dn)
@@ -477,15 +479,15 @@ def test103_reconnect_get_state(self):
477479
str('_start_tls'): 0,
478480
str('_trace_level'): 0,
479481
str('_trace_stack_limit'): 5,
480-
str('_uri'): self.server.ldapi_uri,
482+
str('_uri'): self.server.ldap_uri,
481483
str('bytes_mode'): l1.bytes_mode,
482484
str('bytes_mode_hardfail'): l1.bytes_mode_hardfail,
483485
str('timeout'): -1,
484486
},
485487
)
486488

487489
def test104_reconnect_restore(self):
488-
l1 = self.ldap_object_class(self.server.ldapi_uri)
490+
l1 = self.ldap_object_class(self.server.ldap_uri)
489491
bind_dn = 'cn=user1,'+self.server.suffix
490492
l1.simple_bind_s(bind_dn, 'user1_pw')
491493
self.assertEqual(l1.whoami_s(), 'dn:'+bind_dn)

tox.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ basepython = python2
3333
deps = {[testenv]deps}
3434
passenv = {[testenv]passenv}
3535
setenv =
36-
CI_DISABLED=TLS:SASL
37-
# rebuild without SASL and TLS
36+
CI_DISABLED=LDAPI:SASL:TLS
37+
# rebuild without SASL and TLS, run without LDAPI
3838
commands = {envpython} \
3939
-m coverage run --parallel setup.py \
4040
clean --all \

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy