Skip to content

Commit cc95a2a

Browse files
committed
SlapdObject bind ldaps:// as well
Use a set() in _start_slapd() in case caller has somehow picked a duplicated the port.
1 parent 57493b1 commit cc95a2a

File tree

1 file changed

+59
-20
lines changed

1 file changed

+59
-20
lines changed

Lib/slapdtest/_slapdtest.py

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ class SlapdObject:
179179
.. versionchanged:: 3.1
180180
181181
Added context manager functionality
182+
183+
.. versionchanged:: UNRELEASED
184+
185+
Added ldaps_uri attribute
182186
"""
183187
slapd_conf_template = SLAPD_CONF_TEMPLATE
184188
database = 'mdb'
@@ -212,12 +216,13 @@ class SlapdObject:
212216

213217
def __init__(self):
214218
self._proc = None
215-
self._port = self._avail_tcp_port()
219+
self._port, self._tls_port = self._avail_tcp_ports(2)
216220
self.server_id = self._port % 4096
217221
self.testrundir = os.path.join(self.TMPDIR, 'python-ldap-test-%d' % self._port)
218222
self._slapd_conf = os.path.join(self.testrundir, 'slapd.d')
219223
self._db_directory = os.path.join(self.testrundir, "openldap-data")
220224
self.ldap_uri = "ldap://%s:%d/" % (self.local_host, self._port)
225+
self.ldaps_uri = "ldaps://%s:%d/" % (self.local_host, self._tls_port)
221226
if HAVE_LDAPI:
222227
ldapi_path = os.path.join(self.testrundir, 'ldapi')
223228
self.ldapi_uri = "ldapi://%s" % quote_plus(ldapi_path)
@@ -314,18 +319,26 @@ def _cleanup_rundir(self):
314319
os.rmdir(self.testrundir)
315320
self._log.info('cleaned-up %s', self.testrundir)
316321

322+
def _avail_tcp_ports(self, n):
323+
"""Return a list of currently unused TCP port numbers.
324+
"""
325+
ports = []
326+
socks = [socket.socket(socket.AF_INET, socket.SOCK_STREAM) for _i in range(n)]
327+
try:
328+
for sock in socks:
329+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
330+
sock.bind((self.local_host, 0))
331+
ports.append(sock.getsockname()[1])
332+
finally:
333+
[sock.close() for sock in socks]
334+
self._log.info('Found available port(s) %s', socks)
335+
return ports
336+
317337
def _avail_tcp_port(self):
318338
"""
319339
find an available port for TCP connection
320340
"""
321-
sock = socket.socket()
322-
try:
323-
sock.bind((self.local_host, 0))
324-
port = sock.getsockname()[1]
325-
finally:
326-
sock.close()
327-
self._log.info('Found available port %d', port)
328-
return port
341+
return self._avail_tcp_ports(1)
329342

330343
def gen_config(self):
331344
"""
@@ -399,7 +412,7 @@ def _start_slapd(self):
399412
"""
400413
Spawns/forks the slapd process
401414
"""
402-
urls = [self.ldap_uri]
415+
urls = [self.ldap_uri, self.ldaps_uri]
403416
if self.ldapi_uri:
404417
urls.append(self.ldapi_uri)
405418
slapd_args = [
@@ -425,13 +438,18 @@ def _start_slapd(self):
425438
self._log.debug(
426439
"slapd connection check to %s", self.default_ldap_uri
427440
)
428-
self.ldapwhoami()
441+
# try all bound sockets to make sure the daemon is ready to go.
442+
self.ldapwhoami(ldap_uri=self.ldap_uri)
443+
self.ldapwhoami(ldap_uri=self.ldaps_uri)
444+
if self.ldapi_uri:
445+
self.ldapwhoami(ldap_uri=self.ldapi_uri)
429446
except RuntimeError:
430447
if time.monotonic() >= deadline:
431448
break
432449
time.sleep(0.2)
433450
else:
434451
return
452+
self._proc.kill()
435453
raise RuntimeError("slapd did not start properly")
436454

437455
def start(self):
@@ -448,8 +466,8 @@ def start(self):
448466
self._test_config()
449467
self._start_slapd()
450468
self._log.debug(
451-
'slapd with pid=%d listening on %s and %s',
452-
self._proc.pid, self.ldap_uri, self.ldapi_uri
469+
'slapd with pid=%d listening on %s, %s and %s',
470+
self._proc.pid, self.ldap_uri, self.ldaps_uri, self.ldapi_uri
453471
)
454472

455473
def stop(self):
@@ -483,8 +501,8 @@ def _stopped(self):
483501
self._log.info('slapd[%d] terminated', self._proc.pid)
484502
self._proc = None
485503

486-
def _cli_auth_args(self):
487-
if self.cli_sasl_external:
504+
def _cli_remote_args(self, ldap_uri):
505+
if ldap_uri.startswith('ldapi://'):
488506
authc_args = [
489507
'-Y', 'EXTERNAL',
490508
]
@@ -496,16 +514,36 @@ def _cli_auth_args(self):
496514
'-D', self.root_dn,
497515
'-w', self.root_pw,
498516
]
499-
return authc_args
517+
return ['-H', ldap_uri] + authc_args
500518

501519
# no cover to avoid spurious coverage changes
502520
def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
503521
stdin_data=None): # pragma: no cover
504522
if ldap_uri is None:
505523
ldap_uri = self.default_ldap_uri
506524

525+
environ = os.environ.copy()
526+
507527
if ldapcommand.split("/")[-1].startswith("ldap"):
508-
args = [ldapcommand, '-H', ldap_uri] + self._cli_auth_args()
528+
args = [ldapcommand] + self._cli_remote_args(ldap_uri)
529+
530+
# setting $LDAPNOINIT ignores all other environment and config files
531+
environ.pop('LDAPNOINIT', None)
532+
# we really only want to set the CA cert...
533+
environ['LDAPTLS_CACERT'] = self.cafile
534+
environ['LDAPTLS_REQCERT'] = 'demand'
535+
environ['LDAPTLS_REQSAN'] = 'demand'
536+
environ['LDAPTLS_CRLCHECK'] = 'none'
537+
environ['LDAPTLS_CRLFILE'] = ''
538+
# ... but need to provide more to override any system/user defaults.
539+
environ['LDAPVERSION'] = '3'
540+
environ['LDAPTIMEOUT'] = '5'
541+
environ['LDAPTIMELIMIT'] = '15'
542+
environ['LDAPSIZELIMIT'] = '12'
543+
environ['LDAPNETWORK_TIMEOUT'] = '5'
544+
environ['LDAPTLS_CERT'] = ''
545+
environ['LDAPTLS_KEY'] = ''
546+
509547
else:
510548
args = [ldapcommand, '-F', self._slapd_conf]
511549

@@ -514,7 +552,8 @@ def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
514552
self._log.debug('Run command: %r', ' '.join(args))
515553
proc = subprocess.Popen(
516554
args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
517-
stderr=subprocess.PIPE
555+
stderr=subprocess.PIPE,
556+
env=environ,
518557
)
519558
self._log.debug('stdin_data=%r', stdin_data)
520559
stdout_data, stderr_data = proc.communicate(stdin_data)
@@ -530,11 +569,11 @@ def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
530569
)
531570
return stdout_data, stderr_data
532571

533-
def ldapwhoami(self, extra_args=None):
572+
def ldapwhoami(self, extra_args=None, **kws):
534573
"""
535574
Runs ldapwhoami on this slapd instance
536575
"""
537-
self._cli_popen(self.PATH_LDAPWHOAMI, extra_args=extra_args)
576+
self._cli_popen(self.PATH_LDAPWHOAMI, extra_args=extra_args, **kws)
538577

539578
def ldapadd(self, ldif, extra_args=None):
540579
"""

0 commit comments

Comments
 (0)