23
23
24
24
HERE = os .path .abspath (os .path .dirname (__file__ ))
25
25
26
- # a template string for generating simple slapd.conf file
27
- SLAPD_CONF_TEMPLATE = r"""
28
- serverID %(serverid)s
29
- moduleload back_%(database)s
30
- %(include_directives)s
31
- loglevel %(loglevel)s
32
- allow bind_v2
33
-
34
- authz-regexp
35
- "gidnumber=%(root_gid)s\\+uidnumber=%(root_uid)s,cn=peercred,cn=external,cn=auth"
36
- "%(rootdn)s"
37
-
38
- database %(database)s
39
- directory "%(directory)s"
40
- suffix "%(suffix)s"
41
- rootdn "%(rootdn)s"
42
- rootpw "%(rootpw)s"
43
-
44
- TLSCACertificateFile "%(cafile)s"
45
- TLSCertificateFile "%(servercert)s"
46
- TLSCertificateKeyFile "%(serverkey)s"
47
- # ignore missing client cert but fail with invalid client cert
48
- TLSVerifyClient try
49
-
50
- authz-regexp
51
- "C=DE, O=python-ldap, OU=slapd-test, CN=([A-Za-z]+)"
52
- "ldap://ou=people,dc=local???($1)"
53
-
26
+ # a template string for generating simple slapd.d file
27
+ SLAPD_CONF_TEMPLATE = r"""dn: cn=config
28
+ objectClass: olcGlobal
29
+ cn: config
30
+ olcServerID: %(serverid)s
31
+ olcLogLevel: %(loglevel)s
32
+ olcAllows: bind_v2
33
+ olcAuthzRegexp: {0}"gidnumber=%(root_gid)s\+uidnumber=%(root_uid)s,cn=peercred,cn=external,cn=auth" "%(rootdn)s"
34
+ olcAuthzRegexp: {1}"C=DE, O=python-ldap, OU=slapd-test, CN=([A-Za-z]+)" "ldap://ou=people,dc=local???($1)"
35
+ olcTLSCACertificateFile: %(cafile)s
36
+ olcTLSCertificateFile: %(servercert)s
37
+ olcTLSCertificateKeyFile: %(serverkey)s
38
+ olcTLSVerifyClient: try
39
+
40
+ dn: cn=module,cn=config
41
+ objectClass: olcModuleList
42
+ cn: module
43
+ olcModuleLoad: back_%(database)s
44
+
45
+ dn: olcDatabase=%(database)s,cn=config
46
+ objectClass: olcDatabaseConfig
47
+ objectClass: olcMdbConfig
48
+ olcDatabase: %(database)s
49
+ olcSuffix: %(suffix)s
50
+ olcRootDN: %(rootdn)s
51
+ olcRootPW: %(rootpw)s
52
+ olcDbDirectory: %(directory)s
54
53
"""
55
54
56
55
LOCALHOST = '127.0.0.1'
@@ -175,6 +174,9 @@ class SlapdObject(object):
175
174
manager, the slapd server is shut down and the temporary data store is
176
175
removed.
177
176
177
+ :param openldap_schema_files: A list of schema names or schema paths to
178
+ load at startup. By default this only contains `core`.
179
+
178
180
.. versionchanged:: 3.1
179
181
180
182
Added context manager functionality
@@ -187,10 +189,10 @@ class SlapdObject(object):
187
189
slapd_loglevel = 'stats stats2'
188
190
local_host = LOCALHOST
189
191
testrunsubdirs = (
190
- 'schema ' ,
192
+ 'slapd.d ' ,
191
193
)
192
194
openldap_schema_files = (
193
- 'core.schema ' ,
195
+ 'core.ldif ' ,
194
196
)
195
197
196
198
TMPDIR = os .environ .get ('TMP' , os .getcwd ())
@@ -217,8 +219,7 @@ def __init__(self):
217
219
self ._port = self ._avail_tcp_port ()
218
220
self .server_id = self ._port % 4096
219
221
self .testrundir = os .path .join (self .TMPDIR , 'python-ldap-test-%d' % self ._port )
220
- self ._schema_prefix = os .path .join (self .testrundir , 'schema' )
221
- self ._slapd_conf = os .path .join (self .testrundir , 'slapd.conf' )
222
+ self ._slapd_conf = os .path .join (self .testrundir , 'slapd.d' )
222
223
self ._db_directory = os .path .join (self .testrundir , "openldap-data" )
223
224
self .ldap_uri = "ldap://%s:%d/" % (self .local_host , self ._port )
224
225
if HAVE_LDAPI :
@@ -262,6 +263,7 @@ def _find_commands(self):
262
263
self .PATH_LDAPDELETE = self ._find_command ('ldapdelete' )
263
264
self .PATH_LDAPMODIFY = self ._find_command ('ldapmodify' )
264
265
self .PATH_LDAPWHOAMI = self ._find_command ('ldapwhoami' )
266
+ self .PATH_SLAPADD = self ._find_command ('slapadd' )
265
267
266
268
self .PATH_SLAPD = os .environ .get ('SLAPD' , None )
267
269
if not self .PATH_SLAPD :
@@ -292,7 +294,6 @@ def setup_rundir(self):
292
294
os .mkdir (self .testrundir )
293
295
os .mkdir (self ._db_directory )
294
296
self ._create_sub_dirs (self .testrunsubdirs )
295
- self ._ln_schema_files (self .openldap_schema_files , self .SCHEMADIR )
296
297
297
298
def _cleanup_rundir (self ):
298
299
"""
@@ -337,17 +338,8 @@ def gen_config(self):
337
338
for generating specific static configuration files you have to
338
339
override this method
339
340
"""
340
- include_directives = '\n ' .join (
341
- 'include "{schema_prefix}/{schema_file}"' .format (
342
- schema_prefix = self ._schema_prefix ,
343
- schema_file = schema_file ,
344
- )
345
- for schema_file in self .openldap_schema_files
346
- )
347
341
config_dict = {
348
342
'serverid' : hex (self .server_id ),
349
- 'schema_prefix' :self ._schema_prefix ,
350
- 'include_directives' : include_directives ,
351
343
'loglevel' : self .slapd_loglevel ,
352
344
'database' : self .database ,
353
345
'directory' : self ._db_directory ,
@@ -371,29 +363,28 @@ def _create_sub_dirs(self, dir_names):
371
363
self ._log .debug ('Create directory %s' , dir_name )
372
364
os .mkdir (dir_name )
373
365
374
- def _ln_schema_files (self , file_names , source_dir ):
375
- """
376
- write symbolic links to original schema files
377
- """
378
- for fname in file_names :
379
- ln_source = os .path .join (source_dir , fname )
380
- ln_target = os .path .join (self ._schema_prefix , fname )
381
- self ._log .debug ('Create symlink %s -> %s' , ln_source , ln_target )
382
- os .symlink (ln_source , ln_target )
383
-
384
366
def _write_config (self ):
385
- """Writes the slapd.conf file out, and returns the path to it."""
386
- self ._log .debug ('Writing config to %s' , self ._slapd_conf )
387
- with open (self ._slapd_conf , 'w' ) as config_file :
388
- config_file .write (self .gen_config ())
389
- self ._log .info ('Wrote config to %s' , self ._slapd_conf )
367
+ """Loads the slapd.d configuration."""
368
+ self ._log .debug ("importing configuration: %s" , self ._slapd_conf )
369
+
370
+ self .slapadd (self .gen_config (), ["-n0" ])
371
+ ldif_paths = [
372
+ schema
373
+ if os .path .exists (schema )
374
+ else os .path .join (self .SCHEMADIR , schema )
375
+ for schema in self .openldap_schema_files
376
+ ]
377
+ for ldif_path in ldif_paths :
378
+ self .slapadd (None , ["-n0" , "-l" , ldif_path ])
379
+
380
+ self ._log .debug ("import ok: %s" , self ._slapd_conf )
390
381
391
382
def _test_config (self ):
392
383
self ._log .debug ('testing config %s' , self ._slapd_conf )
393
384
popen_list = [
394
385
self .PATH_SLAPD ,
395
386
"-Ttest" ,
396
- "-f " , self ._slapd_conf ,
387
+ "-F " , self ._slapd_conf ,
397
388
"-u" ,
398
389
"-v" ,
399
390
"-d" , "config"
@@ -417,8 +408,7 @@ def _start_slapd(self):
417
408
urls .append (self .ldapi_uri )
418
409
slapd_args = [
419
410
self .PATH_SLAPD ,
420
- '-f' , self ._slapd_conf ,
421
- '-F' , self .testrundir ,
411
+ '-F' , self ._slapd_conf ,
422
412
'-h' , ' ' .join (urls ),
423
413
]
424
414
if self ._log .isEnabledFor (logging .DEBUG ):
@@ -523,10 +513,14 @@ def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
523
513
stdin_data = None ): # pragma: no cover
524
514
if ldap_uri is None :
525
515
ldap_uri = self .default_ldap_uri
526
- args = [
527
- ldapcommand ,
528
- '-H' , ldap_uri ,
529
- ] + self ._cli_auth_args () + (extra_args or [])
516
+
517
+ if ldapcommand .split ("/" )[- 1 ].startswith ("ldap" ):
518
+ args = [ldapcommand , '-H' , ldap_uri ] + self ._cli_auth_args ()
519
+ else :
520
+ args = [ldapcommand , '-F' , self ._slapd_conf ]
521
+
522
+ args += (extra_args or [])
523
+
530
524
self ._log .debug ('Run command: %r' , ' ' .join (args ))
531
525
proc = subprocess .Popen (
532
526
args , stdin = subprocess .PIPE , stdout = subprocess .PIPE ,
@@ -577,6 +571,16 @@ def ldapdelete(self, dn, recursive=False, extra_args=None):
577
571
extra_args .append (dn )
578
572
self ._cli_popen (self .PATH_LDAPDELETE , extra_args = extra_args )
579
573
574
+ def slapadd (self , ldif , extra_args = None ):
575
+ """
576
+ Runs slapadd on this slapd instance, passing it the ldif content
577
+ """
578
+ self ._cli_popen (
579
+ self .PATH_SLAPADD ,
580
+ stdin_data = ldif .encode ("utf-8" ) if ldif else None ,
581
+ extra_args = extra_args ,
582
+ )
583
+
580
584
def __enter__ (self ):
581
585
self .start ()
582
586
return self
0 commit comments