s4:provision Make setting the domain SID in the self join optional
[abartlet/samba.git/.git] / source4 / scripting / python / samba / provision.py
index 98f9298cf4ae86053cab17ee1446cf0b35ee4144..2e7843ac03a3716e1104330548443ce433224c88 100644 (file)
@@ -52,7 +52,8 @@ import urllib
 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
 from ms_display_specifiers import read_ms_ldif
 from schema import Schema
-from provisionbackend import ProvisionBackend
+from provisionbackend import LDBBackend, ExistingBackend, FDSBackend, OpenLDAPBackend
+from provisionexceptions import ProvisioningError, InvalidNetbiosName
 from signal import SIGTERM
 from dcerpc.misc import SEC_CHAN_BDC, SEC_CHAN_WKSTA
 
@@ -153,15 +154,6 @@ DEFAULTSITE = "Default-First-Site-Name"
 
 # Exception classes
 
-class ProvisioningError(Exception):
-    """A generic provision error."""
-
-class InvalidNetbiosName(Exception):
-    """A specified name was not a valid NetBIOS name."""
-    def __init__(self, name):
-        super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
-
-
 class ProvisionPaths(object):
     def __init__(self):
         self.shareconf = None
@@ -183,15 +175,6 @@ class ProvisionPaths(object):
         self.slapdconf = None
         self.modulesconf = None
         self.memberofconf = None
-        self.fedoradsinf = None
-        self.fedoradspartitions = None
-        self.fedoradssasl = None
-        self.fedoradsdna = None
-        self.fedoradspam = None
-        self.fedoradsrefint = None
-        self.fedoradslinkedattributes = None
-        self.fedoradsindex = None
-        self.fedoradssamba = None
         self.olmmron = None
         self.olmmrserveridsconf = None
         self.olmmrsyncreplconf = None
@@ -334,24 +317,6 @@ def provision_paths_from_lp(lp, dnsdomain):
                                      "modules.conf")
     paths.memberofconf = os.path.join(paths.ldapdir, 
                                       "memberof.conf")
-    paths.fedoradsinf = os.path.join(paths.ldapdir, 
-                                     "fedorads.inf")
-    paths.fedoradspartitions = os.path.join(paths.ldapdir, 
-                                            "fedorads-partitions.ldif")
-    paths.fedoradssasl = os.path.join(paths.ldapdir, 
-                                      "fedorads-sasl.ldif")
-    paths.fedoradsdna = os.path.join(paths.ldapdir, 
-                                     "fedorads-dna.ldif")
-    paths.fedoradspam = os.path.join(paths.ldapdir,
-                                     "fedorads-pam.ldif")
-    paths.fedoradsrefint = os.path.join(paths.ldapdir,
-                                        "fedorads-refint.ldif")
-    paths.fedoradslinkedattributes = os.path.join(paths.ldapdir,
-                                                  "fedorads-linked-attributes.ldif")
-    paths.fedoradsindex = os.path.join(paths.ldapdir,
-                                       "fedorads-index.ldif")
-    paths.fedoradssamba = os.path.join(paths.ldapdir, 
-                                       "fedorads-samba.ldif")
     paths.olmmrserveridsconf = os.path.join(paths.ldapdir, 
                                             "mmr_serverids.conf")
     paths.olmmrsyncreplconf = os.path.join(paths.ldapdir, 
@@ -576,89 +541,25 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
     samdb = Ldb(url=samdb_path, session_info=session_info, 
                 lp=lp, options=["modules:"])
 
-    #Add modules to the list to activate them by default
-    #beware often order is important
-    #
-    # Some Known ordering constraints:
-    # - rootdse must be first, as it makes redirects from "" -> cn=rootdse
-    # - objectclass must be before password_hash, because password_hash checks
-    #   that the objectclass is of type person (filled in by objectclass
-    #   module when expanding the objectclass list)
-    # - partition must be last
-    # - each partition has its own module list then
-    modules_list = ["resolve_oids",
-                    "rootdse",
-                    "lazy_commit",
-                    "paged_results",
-                    "ranged_results",
-                    "anr",
-                    "server_sort",
-                    "asq",
-                    "extended_dn_store",
-                    "extended_dn_in",
-                    "rdn_name",
-                    "objectclass",
-                    "descriptor",
-                    "acl",
-                    "samldb",
-                    "password_hash",
-                    "operational",
-                    "kludge_acl", 
-                    "instancetype"]
-    tdb_modules_list = [
-                    "subtree_rename",
-                    "subtree_delete",
-                    "linked_attributes",
-                    "extended_dn_out_ldb"]
-    modules_list2 = ["show_deleted",
-                     "schema_load",
-                     "new_partition",
-                     "partition"]
-
     ldap_backend_line = "# No LDAP backend"
     if provision_backend.type is not "ldb":
         ldap_backend_line = "ldapBackend: %s" % provision_backend.ldapi_uri
-        
-        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"]
-        elif ldap_backend.ldap_backend_type == "openldap":
-            backend_modules = ["entryuuid", "paged_searches"]
-            # OpenLDAP handles subtree renames, so we don't want to do any of these things
-            tdb_modules_list = ["extended_dn_out_openldap"]
-
-    elif serverrole == "domain controller":
-        tdb_modules_list.insert(0, "repl_meta_data")
-        backend_modules = []
-    else:
-        backend_modules = ["objectguid"]
 
-    if tdb_modules_list is None:
-        tdb_modules_list_as_string = ""
-    else:
-        tdb_modules_list_as_string = ","+",".join(tdb_modules_list)
-        
     samdb.transaction_start()
     try:
         message("Setting up sam.ldb partitions and settings")
         setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
                 "SCHEMADN": ldb.Dn(schema.ldb, names.schemadn).get_casefold(), 
-                "SCHEMADN_MOD2": ",objectguid",
                 "CONFIGDN": ldb.Dn(schema.ldb, names.configdn).get_casefold(),
                 "DOMAINDN": ldb.Dn(schema.ldb, names.domaindn).get_casefold(),
-                "SCHEMADN_MOD": "schema_data",
-                "CONFIGDN_MOD": "naming_fsmo",
-                "DOMAINDN_MOD": "pdc_fsmo",
-                "MODULES_LIST": ",".join(modules_list),
-                "TDB_MODULES_LIST": tdb_modules_list_as_string,
-                "MODULES_LIST2": ",".join(modules_list2),
-                "BACKEND_MOD": ",".join(backend_modules),
                 "LDAP_BACKEND_LINE": ldap_backend_line,
         })
 
         
-        samdb.load_ldif_file_add(setup_path("provision_init.ldif"))
+        setup_add_ldif(samdb, setup_path("provision_init.ldif"), {
+                "BACKEND_TYPE": provision_backend.type,
+                "SERVER_ROLE": serverrole
+                })
 
         message("Setting up sam.ldb rootDSE")
         setup_samdb_rootdse(samdb, setup_path, names)
@@ -671,7 +572,7 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
 
         
 def secretsdb_self_join(secretsdb, domain, 
-                        netbiosname, domainsid, machinepass, 
+                        netbiosname, machinepass, domainsid=None,
                         realm=None, dnsdomain=None,
                         keytab_path=None, 
                         key_version_number=1,
@@ -706,7 +607,8 @@ def secretsdb_self_join(secretsdb, domain,
     msg["secret"] = [machinepass]
     msg["samAccountName"] = ["%s$" % netbiosname]
     msg["secureChannelType"] = [str(secure_channel_type)]
-    msg["objectSid"] = [ndr_pack(domainsid)]
+    if domainsid is not None:
+        msg["objectSid"] = [ndr_pack(domainsid)]
     
     res = secretsdb.search(base="cn=Primary Domains", 
                            attrs=attrs, 
@@ -1023,11 +925,6 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
             "CONFIGDN": names.configdn, 
             "DESCRIPTOR": descr,
             })
-        message("Modifying configuration container")
-        setup_modify_ldif(samdb, setup_path("provision_configuration_basedn_modify.ldif"), {
-            "CONFIGDN": names.configdn, 
-            "SCHEMADN": names.schemadn,
-            })
 
         # The LDIF here was created when the Schema object was constructed
         message("Setting up sam.ldb schema")
@@ -1080,6 +977,12 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
             "POLICYGUID_DC": policyguid_dc
             })
 
+        setup_modify_ldif(samdb, setup_path("provision_basedn_references.ldif"), {
+                "DOMAINDN": names.domaindn})
+
+        setup_modify_ldif(samdb, setup_path("provision_configuration_references.ldif"), {
+                "CONFIGDN": names.configdn,
+                "SCHEMADN": names.schemadn})
         if fill == FILL_FULL:
             message("Setting up sam.ldb users and groups")
             setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
@@ -1228,24 +1131,60 @@ def provision(setup_dir, message, session_info,
 
     if not os.path.exists(paths.private_dir):
         os.mkdir(paths.private_dir)
+    if not os.path.exists(os.path.join(paths.private_dir,"tls")):
+        os.mkdir(os.path.join(paths.private_dir,"tls"))
 
     ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
     
     schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn)
     
-    provision_backend = ProvisionBackend(backend_type,
+    if backend_type == "ldb":
+        provision_backend = LDBBackend(backend_type,
                                          paths=paths, setup_path=setup_path,
                                          lp=lp, credentials=credentials, 
                                          names=names,
-                                         message=message, hostname=hostname,
-                                         root=root, schema=schema,
+                                         message=message)
+    elif backend_type == "existing":
+        provision_backend = ExistingBackend(backend_type,
+                                         paths=paths, setup_path=setup_path,
+                                         lp=lp, credentials=credentials, 
+                                         names=names,
+                                         message=message)
+    elif backend_type == "fedora-ds":
+        provision_backend = FDSBackend(backend_type,
+                                         paths=paths, setup_path=setup_path,
+                                         lp=lp, credentials=credentials, 
+                                         names=names,
+                                         message=message,
+                                         domainsid=domainsid,
+                                         schema=schema,
+                                         hostname=hostname,
                                          ldapadminpass=ldapadminpass,
+                                         slapd_path=slapd_path,
                                          ldap_backend_extra_port=ldap_backend_extra_port,
-                                         ol_mmr_urls=ol_mmr_urls, 
+                                         ldap_dryrun_mode=ldap_dryrun_mode,
+                                         root=root,
+                                         setup_ds_path=setup_ds_path)
+    elif backend_type == "openldap":
+        provision_backend = OpenLDAPBackend(backend_type,
+                                         paths=paths, setup_path=setup_path,
+                                         lp=lp, credentials=credentials, 
+                                         names=names,
+                                         message=message,
+                                         domainsid=domainsid,
+                                         schema=schema,
+                                         hostname=hostname,
+                                         ldapadminpass=ldapadminpass,
                                          slapd_path=slapd_path,
-                                         setup_ds_path=setup_ds_path,
+                                         ldap_backend_extra_port=ldap_backend_extra_port,
                                          ldap_dryrun_mode=ldap_dryrun_mode,
-                                         domainsid=domainsid)
+                                         ol_mmr_urls=ol_mmr_urls, 
+                                         nosync=nosync)
+    else:
+        raise ProvisioningError("Unknown LDAP backend type selected")
+
+    provision_backend.init()
+    provision_backend.start()
 
     # only install a new shares config db if there is none
     if not os.path.exists(paths.shareconf):
@@ -1329,7 +1268,7 @@ def provision(setup_dir, message, session_info,
 
         # Only make a zone file on the first DC, it should be replicated with DNS replication
         if serverrole == "domain controller":
-            secretsdb_self_join(secrets_ldb, domain=domain,
+            secretsdb_self_join(secrets_ldb, domain=names.domain,
                                 realm=names.realm,
                                 dnsdomain=names.dnsdomain,
                                 netbiosname=names.netbiosname,
@@ -1365,11 +1304,8 @@ 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)
 
-    if provision_backend.post_setup is not None:
-        provision_backend.post_setup()
-
-    if provision_backend.shutdown is not None:
-        provision_backend.shutdown()
+    provision_backend.post_setup()
+    provision_backend.shutdown()
     
     create_phpldapadmin_config(paths.phpldapadminconfig, setup_path, 
                                ldapi_url)