1
0
mirror of https://github.com/samba-team/samba.git synced 2025-07-15 16:59:09 +03:00

s4:provision Rework provision to always have a ProvisionBackend

Rather than treat the LDAP backend as a special case, treat all
backends the same, with different callbacks.

Andrew Bartlett
This commit is contained in:
Andrew Bartlett
2009-10-30 13:16:10 +11:00
parent e035433bab
commit 350e963545
2 changed files with 189 additions and 166 deletions

View File

@ -184,7 +184,7 @@ class ProvisionResult(object):
class Schema(object):
def __init__(self, setup_path, domain_sid, schemadn=None,
serverdn=None, sambadn=None, ldap_backend_type=None):
serverdn=None, sambadn=None):
"""Load schema for the SamDB from the AD schema files and samba4_schema.ldif
:param samdb: Load a schema into a SamDB.
@ -604,8 +604,8 @@ def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid,
idmap.setup_name_mapping(sid + "-513", idmap.TYPE_GID, users_gid)
def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
credentials, names, schema,
serverrole, ldap_backend=None,
provision_backend, names, schema,
serverrole,
erase=False):
"""Setup the partitions for the SAM database.
@ -628,7 +628,7 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
try:
samdb = Ldb(url=samdb_path, session_info=session_info,
credentials=credentials, lp=lp, options=["modules:"])
lp=lp, options=["modules:"])
res = samdb.search(base="@PARTITION", scope=SCOPE_BASE, attrs=["partition"], expression="partition=*")
if len(res) == 1:
try:
@ -651,7 +651,7 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
except LdbError:
os.unlink(samdb_path)
samdb = Ldb(url=samdb_path, session_info=session_info,
credentials=credentials, lp=lp, options=["modules:"])
lp=lp, options=["modules:"])
# Wipes the database
samdb.erase_except_schema_controlled()
@ -693,11 +693,12 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
"schema_load",
"new_partition",
"partition"]
ldap_backend_line = "# No LDAP backend"
if ldap_backend is not None:
ldap_backend_line = "ldapBackend: %s" % ldap_backend.ldapi_uri
if provision_backend.type is not "ldb":
ldap_backend_line = "ldapBackend: %s" % provision_backend.ldapi_uri
if ldap_backend.ldap_backend_type == "fedora-ds":
if provision_backend.ldap_backend_type == "fedora-ds":
backend_modules = ["nsuniqueid", "paged_searches"]
# We can handle linked attributes here, as we don't have directory-side subtree operations
tdb_modules_list = ["extended_dn_out_fds"]
@ -837,7 +838,7 @@ def secretsdb_setup_dns(secretsdb, setup_path, realm, dnsdomain,
})
def setup_secretsdb(path, setup_path, session_info, credentials, lp):
def setup_secretsdb(path, setup_path, session_info, backend_credentials, lp):
"""Setup the secrets database.
:param path: Path to the secrets database.
@ -849,26 +850,26 @@ def setup_secretsdb(path, setup_path, session_info, credentials, lp):
"""
if os.path.exists(path):
os.unlink(path)
secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
secrets_ldb = Ldb(path, session_info=session_info,
lp=lp)
secrets_ldb.erase()
secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif"))
secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
secrets_ldb = Ldb(path, session_info=session_info,
lp=lp)
secrets_ldb.transaction_start()
secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif"))
if credentials is not None and credentials.authentication_requested():
if credentials.get_bind_dn() is not None:
if backend_credentials is not None and backend_credentials.authentication_requested():
if backend_credentials.get_bind_dn() is not None:
setup_add_ldif(secrets_ldb, setup_path("secrets_simple_ldap.ldif"), {
"LDAPMANAGERDN": credentials.get_bind_dn(),
"LDAPMANAGERPASS_B64": b64encode(credentials.get_password())
"LDAPMANAGERDN": backend_credentials.get_bind_dn(),
"LDAPMANAGERPASS_B64": b64encode(backend_credentials.get_password())
})
else:
setup_add_ldif(secrets_ldb, setup_path("secrets_sasl_ldap.ldif"), {
"LDAPADMINUSER": credentials.get_username(),
"LDAPADMINREALM": credentials.get_realm(),
"LDAPADMINPASS_B64": b64encode(credentials.get_password())
"LDAPADMINUSER": backend_credentials.get_username(),
"LDAPADMINREALM": backend_credentials.get_realm(),
"LDAPADMINPASS_B64": b64encode(backend_credentials.get_password())
})
return secrets_ldb
@ -1003,13 +1004,13 @@ def setup_self_join(samdb, names,
})
def setup_samdb(path, setup_path, session_info, credentials, lp,
def setup_samdb(path, setup_path, session_info, provision_backend, lp,
names, message,
domainsid, domainguid, policyguid, policyguid_dc,
fill, adminpass, krbtgtpass,
machinepass, invocationid, dnspass, ntdsguid,
serverrole, dom_for_fun_level=None,
schema=None, ldap_backend=None):
schema=None):
"""Setup a complete SAM Database.
:note: This will wipe the main SAM database file!
@ -1032,17 +1033,17 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
# Also wipes the database
setup_samdb_partitions(path, setup_path, message=message, lp=lp,
credentials=credentials, session_info=session_info,
names=names, ldap_backend=ldap_backend,
provision_backend=provision_backend, session_info=session_info,
names=names,
serverrole=serverrole, schema=schema)
if (schema == None):
schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn,
sambadn=names.sambadn, ldap_backend_type=ldap_backend.ldap_backend_type)
sambadn=names.sambadn)
# Load the database, but importantly, use Ldb not SamDB as we don't want to load the global schema
samdb = Ldb(session_info=session_info,
credentials=credentials, lp=lp)
credentials=provision_backend.credentials, lp=lp)
message("Pre-loading the Samba 4 and AD schema")
@ -1222,7 +1223,7 @@ def provision(setup_dir, message, session_info,
dnspass=None, root=None, nobody=None, users=None,
wheel=None, backup=None, aci=None, serverrole=None,
dom_for_fun_level=None,
ldap_backend_extra_port=None, ldap_backend_type=None,
ldap_backend_extra_port=None, backend_type=None,
sitename=None,
ol_mmr_urls=None, ol_olc=None,
setup_ds_path=None, slapd_path=None, nosync=False,
@ -1260,8 +1261,11 @@ def provision(setup_dir, message, session_info,
#Make a new, random password between Samba and it's LDAP server
ldapadminpass=glue.generate_random_str(12)
if backend_type is None:
backend_type = "ldb"
sid_generator = "internal"
if ldap_backend_type == "fedora-ds":
if backend_type == "fedora-ds":
sid_generator = "backend"
root_uid = findnss_uid([root or "root"])
@ -1319,44 +1323,34 @@ def provision(setup_dir, message, session_info,
ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn,
sambadn=names.sambadn, ldap_backend_type=ldap_backend_type)
sambadn=names.sambadn)
secrets_credentials = credentials
provision_backend = None
if ldap_backend_type:
# We only support an LDAP backend over ldapi://
provision_backend = ProvisionBackend(paths=paths, setup_path=setup_path,
lp=lp, credentials=credentials,
names=names,
message=message, hostname=hostname,
root=root, schema=schema,
ldap_backend_type=ldap_backend_type,
ldapadminpass=ldapadminpass,
ldap_backend_extra_port=ldap_backend_extra_port,
ol_mmr_urls=ol_mmr_urls,
slapd_path=slapd_path,
setup_ds_path=setup_ds_path,
ldap_dryrun_mode=ldap_dryrun_mode,
domainsid=domainsid)
# Now use the backend credentials to access the databases
credentials = provision_backend.credentials
secrets_credentials = provision_backend.adminCredentials
ldapi_url = provision_backend.ldapi_uri
provision_backend = ProvisionBackend(backend_type,
paths=paths, setup_path=setup_path,
lp=lp, credentials=credentials,
names=names,
message=message, hostname=hostname,
root=root, schema=schema,
ldapadminpass=ldapadminpass,
ldap_backend_extra_port=ldap_backend_extra_port,
ol_mmr_urls=ol_mmr_urls,
slapd_path=slapd_path,
setup_ds_path=setup_ds_path,
ldap_dryrun_mode=ldap_dryrun_mode,
domainsid=domainsid)
# only install a new shares config db if there is none
if not os.path.exists(paths.shareconf):
message("Setting up share.ldb")
share_ldb = Ldb(paths.shareconf, session_info=session_info,
credentials=credentials, lp=lp)
lp=lp)
share_ldb.load_ldif_file_add(setup_path("share.ldif"))
message("Setting up secrets.ldb")
secrets_ldb = setup_secretsdb(paths.secrets, setup_path,
session_info=session_info,
credentials=secrets_credentials, lp=lp)
backend_credentials=provision_backend.secrets_credentials, lp=lp)
message("Setting up the registry")
setup_registry(paths.hklm, setup_path, session_info,
@ -1370,9 +1364,9 @@ def provision(setup_dir, message, session_info,
lp=lp)
message("Setting up SAM db")
samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info,
credentials=credentials, lp=lp, names=names,
message=message,
samdb = setup_samdb(paths.samdb, setup_path, session_info,
provision_backend, lp, names,
message,
domainsid=domainsid,
schema=schema, domainguid=domainguid,
policyguid=policyguid, policyguid_dc=policyguid_dc,
@ -1381,8 +1375,7 @@ def provision(setup_dir, message, session_info,
invocationid=invocationid,
machinepass=machinepass, dnspass=dnspass,
ntdsguid=ntdsguid, serverrole=serverrole,
dom_for_fun_level=dom_for_fun_level,
ldap_backend=provision_backend)
dom_for_fun_level=dom_for_fun_level)
if serverrole == "domain controller":
if paths.netlogon is None:
@ -1464,61 +1457,18 @@ def provision(setup_dir, message, session_info,
realm=names.realm)
message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf)
#Now commit the secrets.ldb to disk
secrets_ldb.transaction_commit()
if provision_backend is not None:
if ldap_backend_type == "fedora-ds":
ldapi_db = Ldb(provision_backend.ldapi_uri, lp=lp, credentials=credentials)
# delete default SASL mappings
res = ldapi_db.search(expression="(!(cn=samba-admin mapping))", base="cn=mapping,cn=sasl,cn=config", scope=SCOPE_ONELEVEL, attrs=["dn"])
# configure in-directory access control on Fedora DS via the aci attribute (over a direct ldapi:// socket)
for i in range (0, len(res)):
dn = str(res[i]["dn"])
ldapi_db.delete(dn)
aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % names.sambadn
m = ldb.Message()
m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci")
m.dn = ldb.Dn(1, names.domaindn)
ldapi_db.modify(m)
m.dn = ldb.Dn(1, names.configdn)
ldapi_db.modify(m)
m.dn = ldb.Dn(1, names.schemadn)
ldapi_db.modify(m)
# if an LDAP backend is in use, terminate slapd after final provision and check its proper termination
if provision_backend.slapd.poll() is None:
#Kill the slapd
if hasattr(provision_backend.slapd, "terminate"):
provision_backend.slapd.terminate()
else:
# Older python versions don't have .terminate()
import signal
os.kill(provision_backend.slapd.pid, signal.SIGTERM)
#and now wait for it to die
provision_backend.slapd.communicate()
# now display slapd_command_file.txt to show how slapd must be started next time
message("Use later the following commandline to start slapd, then Samba:")
slapd_command = "\'" + "\' \'".join(provision_backend.slapd_command) + "\'"
message(slapd_command)
message("This slapd-Commandline is also stored under: " + paths.ldapdir + "/ldap_backend_startup.sh")
setup_file(setup_path("ldap_backend_startup.sh"), paths.ldapdir + "/ldap_backend_startup.sh", {
"SLAPD_COMMAND" : slapd_command})
if provision_backend.post_setup is not None:
provision_backend.post_setup()
if provision_backend.shutdown is not None:
provision_backend.shutdown()
create_phpldapadmin_config(paths.phpldapadminconfig, setup_path,
ldapi_url)
#Now commit the secrets.ldb to disk
secrets_ldb.transaction_commit()
message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
message("Once the above files are installed, your Samba4 server will be ready to use")
@ -1529,14 +1479,21 @@ def provision(setup_dir, message, session_info,
message("DOMAIN SID: %s" % str(domainsid))
if samdb_fill == FILL_FULL:
message("Admin password: %s" % adminpass)
if provision_backend:
if provision_backend.type is not "ldb":
if provision_backend.credentials.get_bind_dn() is not None:
message("LDAP Backend Admin DN: %s" % provision_backend.credentials.get_bind_dn())
else:
message("LDAP Admin User: %s" % provision_backend.credentials.get_username())
message("LDAP Admin Password: %s" % provision_backend.credentials.get_password())
if provision_backend.slapd_command_escaped is not None:
# now display slapd_command_file.txt to show how slapd must be started next time
message("Use later the following commandline to start slapd, then Samba:")
message(provision_backend.slapd_command_escaped)
message("This slapd-Commandline is also stored under: " + paths.ldapdir + "/ldap_backend_startup.sh")
result = ProvisionResult()
result.domaindn = domaindn
result.paths = paths
@ -1586,13 +1543,28 @@ def setup_db_config(setup_path, dbdir):
setup_file(setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"),
{"LDAPDBDIR": dbdir})
def ldap_backend_shutdown(self):
# if an LDAP backend is in use, terminate slapd after final provision and check its proper termination
if self.slapd.poll() is None:
#Kill the slapd
if hasattr(self.slapd, "terminate"):
self.slapd.terminate()
else:
# Older python versions don't have .terminate()
import signal
os.kill(self.slapd.pid, signal.SIGTERM)
#and now wait for it to die
self.slapd.communicate()
class ProvisionBackend(object):
def __init__(self, paths=None, setup_path=None, lp=None, credentials=None,
def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
names=None, message=None,
hostname=None, root=None,
schema=None, ldapadminpass=None,
ldap_backend_type=None, ldap_backend_extra_port=None,
ldap_backend_extra_port=None,
ol_mmr_urls=None,
setup_ds_path=None, slapd_path=None,
nosync=False, ldap_dryrun_mode=False,
@ -1601,21 +1573,36 @@ class ProvisionBackend(object):
This works for OpenLDAP and Fedora DS
"""
self.paths = paths
self.slapd_command = None
self.slapd_command_escaped = None
self.type = backend_type
# Set a default - the code for "existing" below replaces this
self.ldap_backend_type = backend_type
self.post_setup = None
self.shutdown = None
if self.type is "ldb":
self.credentials = None
self.secrets_credentials = None
return
self.ldapi_uri = "ldapi://" + urllib.quote(os.path.join(paths.ldapdir, "ldapi"), safe="")
if not os.path.isdir(paths.ldapdir):
os.makedirs(paths.ldapdir, 0700)
if ldap_backend_type == "existing":
if self.type == "existing":
#Check to see that this 'existing' LDAP backend in fact exists
ldapi_db = Ldb(self.ldapi_uri, credentials=credentials)
search_ol_rootdse = ldapi_db.search(base="", scope=SCOPE_BASE,
expression="(objectClass=OpenLDAProotDSE)")
# If we have got here, then we must have a valid connection to the LDAP server, with valid credentials supplied
# This caused them to be set into the long-term database later in the script.
self.credentials = credentials
# This caused them to be set into the long-term database later in the script.
self.secrets_credentials = credentials
self.ldap_backend_type = "openldap" #For now, assume existing backends at least emulate OpenLDAP
return
@ -1645,13 +1632,16 @@ class ProvisionBackend(object):
message (slapd_path)
raise ProvisioningError("Warning: Given Path to slapd does not exist!")
if not os.path.isdir(paths.ldapdir):
os.makedirs(paths.ldapdir, 0700)
schemadb_path = os.path.join(paths.ldapdir, "schema-tmp.ldb")
try:
os.unlink(schemadb_path)
except OSError:
pass
# Put the LDIF of the schema into a database so we can search on
# it to generate schema-dependent configurations in Fedora DS and
# OpenLDAP
@ -1670,15 +1660,15 @@ class ProvisionBackend(object):
#Kerberos to an ldapi:// backend makes no sense
self.credentials.set_kerberos_state(DONT_USE_KERBEROS)
self.adminCredentials = Credentials()
self.adminCredentials.guess(lp)
self.secrets_credentials = Credentials()
self.secrets_credentials.guess(lp)
#Kerberos to an ldapi:// backend makes no sense
self.adminCredentials.set_kerberos_state(DONT_USE_KERBEROS)
self.secrets_credentials.set_kerberos_state(DONT_USE_KERBEROS)
self.ldap_backend_type = ldap_backend_type
self.shutdown = ldap_backend_shutdown
if ldap_backend_type == "fedora-ds":
provision_fds_backend(self, paths=paths, setup_path=setup_path,
if self.type == "fedora-ds":
provision_fds_backend(self, setup_path=setup_path,
names=names, message=message,
hostname=hostname,
ldapadminpass=ldapadminpass, root=root,
@ -1690,8 +1680,8 @@ class ProvisionBackend(object):
ldap_dryrun_mode=ldap_dryrun_mode,
domainsid=domainsid)
elif ldap_backend_type == "openldap":
provision_openldap_backend(self, paths=paths, setup_path=setup_path,
elif self.type == "openldap":
provision_openldap_backend(self, setup_path=setup_path,
names=names, message=message,
hostname=hostname,
ldapadminpass=ldapadminpass, root=root,
@ -1705,8 +1695,12 @@ class ProvisionBackend(object):
raise ProvisioningError("Unknown LDAP backend type selected")
self.credentials.set_password(ldapadminpass)
self.adminCredentials.set_username("samba-admin")
self.adminCredentials.set_password(ldapadminpass)
self.secrets_credentials.set_username("samba-admin")
self.secrets_credentials.set_password(ldapadminpass)
self.slapd_command_escaped = "\'" + "\' \'".join(self.slapd_command) + "\'"
setup_file(setup_path("ldap_backend_startup.sh"), paths.ldapdir + "/ldap_backend_startup.sh", {
"SLAPD_COMMAND" : slapd_command})
# Now start the slapd, so we can provision onto it. We keep the
# subprocess context around, to kill this off at the successful
@ -1728,7 +1722,7 @@ class ProvisionBackend(object):
raise ProvisioningError("slapd died before we could make a connection to it")
def provision_openldap_backend(result, paths=None, setup_path=None, names=None,
def provision_openldap_backend(result, setup_path=None, names=None,
message=None,
hostname=None, ldapadminpass=None, root=None,
schema=None,
@ -1840,15 +1834,15 @@ def provision_openldap_backend(result, paths=None, setup_path=None, names=None,
{ "RID" : str(rid),
"LDAPSERVER" : url})
setup_file(setup_path("olc_seed.ldif"), paths.olcseedldif,
setup_file(setup_path("olc_seed.ldif"), result.paths.olcseedldif,
{"OLC_SERVER_ID_CONF": olc_serverids_config,
"OLC_PW": ldapadminpass,
"OLC_SYNCREPL_CONF": olc_syncrepl_seed_config})
# end olc
setup_file(setup_path("slapd.conf"), paths.slapdconf,
setup_file(setup_path("slapd.conf"), result.paths.slapdconf,
{"DNSDOMAIN": names.dnsdomain,
"LDAPDIR": paths.ldapdir,
"LDAPDIR": result.paths.ldapdir,
"DOMAINDN": names.domaindn,
"CONFIGDN": names.configdn,
"SCHEMADN": names.schemadn,
@ -1865,26 +1859,26 @@ def provision_openldap_backend(result, paths=None, setup_path=None, names=None,
"INDEX_CONFIG": index_config,
"NOSYNC": nosync_config})
setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "user"))
setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "config"))
setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "schema"))
setup_db_config(setup_path, os.path.join(result.paths.ldapdir, "db", "user"))
setup_db_config(setup_path, os.path.join(result.paths.ldapdir, "db", "config"))
setup_db_config(setup_path, os.path.join(result.paths.ldapdir, "db", "schema"))
if not os.path.exists(os.path.join(paths.ldapdir, "db", "samba", "cn=samba")):
os.makedirs(os.path.join(paths.ldapdir, "db", "samba", "cn=samba"), 0700)
if not os.path.exists(os.path.join(result.paths.ldapdir, "db", "samba", "cn=samba")):
os.makedirs(os.path.join(result.paths.ldapdir, "db", "samba", "cn=samba"), 0700)
setup_file(setup_path("cn=samba.ldif"),
os.path.join(paths.ldapdir, "db", "samba", "cn=samba.ldif"),
os.path.join(result.paths.ldapdir, "db", "samba", "cn=samba.ldif"),
{ "UUID": str(uuid.uuid4()),
"LDAPTIME": timestring(int(time.time()))} )
setup_file(setup_path("cn=samba-admin.ldif"),
os.path.join(paths.ldapdir, "db", "samba", "cn=samba", "cn=samba-admin.ldif"),
os.path.join(result.paths.ldapdir, "db", "samba", "cn=samba", "cn=samba-admin.ldif"),
{"LDAPADMINPASS_B64": b64encode(ldapadminpass),
"UUID": str(uuid.uuid4()),
"LDAPTIME": timestring(int(time.time()))} )
if ol_mmr_urls is not None:
setup_file(setup_path("cn=replicator.ldif"),
os.path.join(paths.ldapdir, "db", "samba", "cn=samba", "cn=replicator.ldif"),
os.path.join(result.paths.ldapdir, "db", "samba", "cn=samba", "cn=replicator.ldif"),
{"MMR_PASSWORD_B64": b64encode(mmr_pass),
"UUID": str(uuid.uuid4()),
"LDAPTIME": timestring(int(time.time()))} )
@ -1895,7 +1889,7 @@ def provision_openldap_backend(result, paths=None, setup_path=None, names=None,
backend_schema_data = schema.ldb.convert_schema_to_openldap("openldap", open(setup_path(mapping), 'r').read())
assert backend_schema_data is not None
open(os.path.join(paths.ldapdir, backend_schema), 'w').write(backend_schema_data)
open(os.path.join(result.paths.ldapdir, backend_schema), 'w').write(backend_schema_data)
# now we generate the needed strings to start slapd automatically,
# first ldapi_uri...
@ -1913,7 +1907,7 @@ def provision_openldap_backend(result, paths=None, setup_path=None, names=None,
# Prepare the 'result' information - the commands to return in particular
result.slapd_provision_command = [slapd_path]
result.slapd_provision_command.append("-F" + paths.olcdir)
result.slapd_provision_command.append("-F" + result.paths.olcdir)
result.slapd_provision_command.append("-h")
@ -1939,10 +1933,10 @@ def provision_openldap_backend(result, paths=None, setup_path=None, names=None,
sys.exit(0)
# Finally, convert the configuration into cn=config style!
if not os.path.isdir(paths.olcdir):
os.makedirs(paths.olcdir, 0770)
if not os.path.isdir(result.paths.olcdir):
os.makedirs(result.paths.olcdir, 0770)
retcode = subprocess.call([slapd_path, "-Ttest", "-f", paths.slapdconf, "-F", paths.olcdir], close_fds=True, shell=False)
retcode = subprocess.call([slapd_path, "-Ttest", "-f", result.paths.slapdconf, "-F", result.paths.olcdir], close_fds=True, shell=False)
# We can't do this, as OpenLDAP is strange. It gives an error
# output to the above, but does the conversion sucessfully...
@ -1950,14 +1944,14 @@ def provision_openldap_backend(result, paths=None, setup_path=None, names=None,
# if retcode != 0:
# raise ProvisioningError("conversion from slapd.conf to cn=config failed")
if not os.path.exists(os.path.join(paths.olcdir, "cn=config.ldif")):
if not os.path.exists(os.path.join(result.paths.olcdir, "cn=config.ldif")):
raise ProvisioningError("conversion from slapd.conf to cn=config failed")
# Don't confuse the admin by leaving the slapd.conf around
os.remove(paths.slapdconf)
os.remove(result.paths.slapdconf)
def provision_fds_backend(result, paths=None, setup_path=None, names=None,
def provision_fds_backend(result, setup_path=None, names=None,
message=None,
hostname=None, ldapadminpass=None, root=None,
schema=None,
@ -1973,33 +1967,33 @@ def provision_fds_backend(result, paths=None, setup_path=None, names=None,
else:
serverport = ""
setup_file(setup_path("fedorads.inf"), paths.fedoradsinf,
setup_file(setup_path("fedorads.inf"), result.paths.fedoradsinf,
{"ROOT": root,
"HOSTNAME": hostname,
"DNSDOMAIN": names.dnsdomain,
"LDAPDIR": paths.ldapdir,
"LDAPDIR": result.paths.ldapdir,
"DOMAINDN": names.domaindn,
"LDAPMANAGERDN": names.ldapmanagerdn,
"LDAPMANAGERPASS": ldapadminpass,
"SERVERPORT": serverport})
setup_file(setup_path("fedorads-partitions.ldif"), paths.fedoradspartitions,
setup_file(setup_path("fedorads-partitions.ldif"), result.paths.fedoradspartitions,
{"CONFIGDN": names.configdn,
"SCHEMADN": names.schemadn,
"SAMBADN": names.sambadn,
})
setup_file(setup_path("fedorads-sasl.ldif"), paths.fedoradssasl,
setup_file(setup_path("fedorads-sasl.ldif"), result.paths.fedoradssasl,
{"SAMBADN": names.sambadn,
})
setup_file(setup_path("fedorads-dna.ldif"), paths.fedoradsdna,
setup_file(setup_path("fedorads-dna.ldif"), result.paths.fedoradsdna,
{"DOMAINDN": names.domaindn,
"SAMBADN": names.sambadn,
"DOMAINSID": str(domainsid),
})
setup_file(setup_path("fedorads-pam.ldif"), paths.fedoradspam)
setup_file(setup_path("fedorads-pam.ldif"), result.paths.fedoradspam)
lnkattr = get_linked_attributes(names.schemadn,schema.ldb)
@ -2020,8 +2014,8 @@ def provision_fds_backend(result, paths=None, setup_path=None, names=None,
{ "ATTR" : attr })
argnum += 1
open(paths.fedoradsrefint, 'w').write(refint_config)
open(paths.fedoradslinkedattributes, 'w').write(memberof_config)
open(result.paths.fedoradsrefint, 'w').write(refint_config)
open(result.paths.fedoradslinkedattributes, 'w').write(memberof_config)
attrs = ["lDAPDisplayName"]
res = schema.ldb.search(expression="(&(objectclass=attributeSchema)(searchFlags:1.2.840.113556.1.4.803:=1))", base=names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs)
@ -2035,9 +2029,9 @@ def provision_fds_backend(result, paths=None, setup_path=None, names=None,
index_config += read_and_sub_file(setup_path("fedorads-index.ldif"),
{ "ATTR" : attr })
open(paths.fedoradsindex, 'w').write(index_config)
open(result.paths.fedoradsindex, 'w').write(index_config)
setup_file(setup_path("fedorads-samba.ldif"), paths.fedoradssamba,
setup_file(setup_path("fedorads-samba.ldif"), result.paths.fedoradssamba,
{"SAMBADN": names.sambadn,
"LDAPADMINPASS": ldapadminpass
})
@ -2048,20 +2042,20 @@ def provision_fds_backend(result, paths=None, setup_path=None, names=None,
# Build a schema file in Fedora DS format
backend_schema_data = schema.ldb.convert_schema_to_openldap("fedora-ds", open(setup_path(mapping), 'r').read())
assert backend_schema_data is not None
open(os.path.join(paths.ldapdir, backend_schema), 'w').write(backend_schema_data)
open(os.path.join(result.paths.ldapdir, backend_schema), 'w').write(backend_schema_data)
result.credentials.set_bind_dn(names.ldapmanagerdn)
# Destory the target directory, or else setup-ds.pl will complain
fedora_ds_dir = os.path.join(paths.ldapdir, "slapd-samba4")
fedora_ds_dir = os.path.join(result.paths.ldapdir, "slapd-samba4")
shutil.rmtree(fedora_ds_dir, True)
result.slapd_provision_command = [slapd_path, "-D", fedora_ds_dir, "-i", paths.slapdpid];
result.slapd_provision_command = [slapd_path, "-D", fedora_ds_dir, "-i", result.paths.slapdpid];
#In the 'provision' command line, stay in the foreground so we can easily kill it
result.slapd_provision_command.append("-d0")
#the command for the final run is the normal script
result.slapd_command = [os.path.join(paths.ldapdir, "slapd-samba4", "start-slapd")]
result.slapd_command = [os.path.join(result.paths.ldapdir, "slapd-samba4", "start-slapd")]
# If we were just looking for crashes up to this point, it's a
# good time to exit before we realise we don't have Fedora DS on
@ -2076,17 +2070,46 @@ def provision_fds_backend(result, paths=None, setup_path=None, names=None,
raise ProvisioningError("Warning: Given Path to slapd does not exist!")
# Run the Fedora DS setup utility
retcode = subprocess.call([setup_ds_path, "--silent", "--file", paths.fedoradsinf], close_fds=True, shell=False)
retcode = subprocess.call([setup_ds_path, "--silent", "--file", result.paths.fedoradsinf], close_fds=True, shell=False)
if retcode != 0:
raise ProvisioningError("setup-ds failed")
# Load samba-admin
retcode = subprocess.call([
os.path.join(paths.ldapdir, "slapd-samba4", "ldif2db"), "-s", names.sambadn, "-i", paths.fedoradssamba],
os.path.join(result.paths.ldapdir, "slapd-samba4", "ldif2db"), "-s", names.sambadn, "-i", result.paths.fedoradssamba],
close_fds=True, shell=False)
if retcode != 0:
raise("ldib2db failed")
# Leave a hook to do the 'post initilisation' setup
def fds_post_setup(self):
ldapi_db = Ldb(self.ldapi_uri, credentials=self.credentials)
# delete default SASL mappings
res = ldapi_db.search(expression="(!(cn=samba-admin mapping))", base="cn=mapping,cn=sasl,cn=config", scope=SCOPE_ONELEVEL, attrs=["dn"])
# configure in-directory access control on Fedora DS via the aci attribute (over a direct ldapi:// socket)
for i in range (0, len(res)):
dn = str(res[i]["dn"])
ldapi_db.delete(dn)
aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % names.sambadn
m = ldb.Message()
m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci")
m.dn = ldb.Dn(1, names.domaindn)
ldapi_db.modify(m)
m.dn = ldb.Dn(1, names.configdn)
ldapi_db.modify(m)
m.dn = ldb.Dn(1, names.schemadn)
ldapi_db.modify(m)
result.post_setup = fds_post_setup
def create_phpldapadmin_config(path, setup_path, ldapi_uri):
"""Create a PHP LDAP admin configuration file.