@@ -179,6 +179,10 @@ class SlapdObject:
179
179
.. versionchanged:: 3.1
180
180
181
181
Added context manager functionality
182
+
183
+ .. versionchanged:: UNRELEASED
184
+
185
+ Added ldaps_uri attribute
182
186
"""
183
187
slapd_conf_template = SLAPD_CONF_TEMPLATE
184
188
database = 'mdb'
@@ -212,12 +216,13 @@ class SlapdObject:
212
216
213
217
def __init__ (self ):
214
218
self ._proc = None
215
- self ._port = self ._avail_tcp_port ( )
219
+ self ._port , self . _tls_port = self ._avail_tcp_ports ( 2 )
216
220
self .server_id = self ._port % 4096
217
221
self .testrundir = os .path .join (self .TMPDIR , 'python-ldap-test-%d' % self ._port )
218
222
self ._slapd_conf = os .path .join (self .testrundir , 'slapd.d' )
219
223
self ._db_directory = os .path .join (self .testrundir , "openldap-data" )
220
224
self .ldap_uri = "ldap://%s:%d/" % (self .local_host , self ._port )
225
+ self .ldaps_uri = "ldaps://%s:%d/" % (self .local_host , self ._tls_port )
221
226
if HAVE_LDAPI :
222
227
ldapi_path = os .path .join (self .testrundir , 'ldapi' )
223
228
self .ldapi_uri = "ldapi://%s" % quote_plus (ldapi_path )
@@ -314,18 +319,26 @@ def _cleanup_rundir(self):
314
319
os .rmdir (self .testrundir )
315
320
self ._log .info ('cleaned-up %s' , self .testrundir )
316
321
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
+
317
337
def _avail_tcp_port (self ):
318
338
"""
319
339
find an available port for TCP connection
320
340
"""
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 )
329
342
330
343
def gen_config (self ):
331
344
"""
@@ -399,7 +412,7 @@ def _start_slapd(self):
399
412
"""
400
413
Spawns/forks the slapd process
401
414
"""
402
- urls = [self .ldap_uri ]
415
+ urls = [self .ldap_uri , self . ldaps_uri ]
403
416
if self .ldapi_uri :
404
417
urls .append (self .ldapi_uri )
405
418
slapd_args = [
@@ -425,13 +438,18 @@ def _start_slapd(self):
425
438
self ._log .debug (
426
439
"slapd connection check to %s" , self .default_ldap_uri
427
440
)
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 )
429
446
except RuntimeError :
430
447
if time .monotonic () >= deadline :
431
448
break
432
449
time .sleep (0.2 )
433
450
else :
434
451
return
452
+ self ._proc .kill ()
435
453
raise RuntimeError ("slapd did not start properly" )
436
454
437
455
def start (self ):
@@ -448,8 +466,8 @@ def start(self):
448
466
self ._test_config ()
449
467
self ._start_slapd ()
450
468
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
453
471
)
454
472
455
473
def stop (self ):
@@ -483,8 +501,8 @@ def _stopped(self):
483
501
self ._log .info ('slapd[%d] terminated' , self ._proc .pid )
484
502
self ._proc = None
485
503
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://' ) :
488
506
authc_args = [
489
507
'-Y' , 'EXTERNAL' ,
490
508
]
@@ -496,16 +514,36 @@ def _cli_auth_args(self):
496
514
'-D' , self .root_dn ,
497
515
'-w' , self .root_pw ,
498
516
]
499
- return authc_args
517
+ return [ '-H' , ldap_uri ] + authc_args
500
518
501
519
# no cover to avoid spurious coverage changes
502
520
def _cli_popen (self , ldapcommand , extra_args = None , ldap_uri = None ,
503
521
stdin_data = None ): # pragma: no cover
504
522
if ldap_uri is None :
505
523
ldap_uri = self .default_ldap_uri
506
524
525
+ environ = os .environ .copy ()
526
+
507
527
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
+
509
547
else :
510
548
args = [ldapcommand , '-F' , self ._slapd_conf ]
511
549
@@ -514,7 +552,8 @@ def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
514
552
self ._log .debug ('Run command: %r' , ' ' .join (args ))
515
553
proc = subprocess .Popen (
516
554
args , stdin = subprocess .PIPE , stdout = subprocess .PIPE ,
517
- stderr = subprocess .PIPE
555
+ stderr = subprocess .PIPE ,
556
+ env = environ ,
518
557
)
519
558
self ._log .debug ('stdin_data=%r' , stdin_data )
520
559
stdout_data , stderr_data = proc .communicate (stdin_data )
@@ -530,11 +569,11 @@ def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
530
569
)
531
570
return stdout_data , stderr_data
532
571
533
- def ldapwhoami (self , extra_args = None ):
572
+ def ldapwhoami (self , extra_args = None , ** kws ):
534
573
"""
535
574
Runs ldapwhoami on this slapd instance
536
575
"""
537
- self ._cli_popen (self .PATH_LDAPWHOAMI , extra_args = extra_args )
576
+ self ._cli_popen (self .PATH_LDAPWHOAMI , extra_args = extra_args , ** kws )
538
577
539
578
def ldapadd (self , ldif , extra_args = None ):
540
579
"""
0 commit comments