[PATCH 7/7] s4:provision - Added support for external LDAP server.

Endi S. Dewata edewata at redhat.com
Sat Jan 30 06:09:27 MST 2010


---
 source4/scripting/python/samba/provision.py        |   91 ++++++------
 source4/scripting/python/samba/provisionbackend.py |  154 ++++++++++++--------
 source4/setup/fedorads-dna-modify.ldif             |   14 ++
 source4/setup/provision                            |    5 +-
 source4/setup/slapd.conf                           |    4 +
 5 files changed, 166 insertions(+), 102 deletions(-)
 create mode 100644 source4/setup/fedorads-dna-modify.ldif

diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py
index 2d7978d..c4a790f 100644
--- a/source4/scripting/python/samba/provision.py
+++ b/source4/scripting/python/samba/provision.py
@@ -50,7 +50,7 @@ from samba.ndr import ndr_pack,ndr_unpack
 from samba.schema import Schema
 from ms_display_specifiers import read_ms_ldif
 from samba.provisionutil import setup_add_ldif, setup_modify_ldif
-from samba.provisionbackend import LDBBackend, ExistingBackend, FDSBackend, OpenLDAPBackend
+from samba.provisionbackend import LDBBackend, FDSBackend, OpenLDAPBackend
 from provisionexceptions import ProvisioningError, InvalidNetbiosName
 
 __docformat__ = "restructuredText"
@@ -1060,7 +1060,8 @@ 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, backend_type=None, ldap_dir=None, ldap_uri=None,
+              ldap_backend_extra_port=None, backend_type=None,
+              ldap_action=None, ldap_dir=None, ldap_uri=None,
               sitename=None,
               ol_mmr_urls=None, ol_olc=None, 
               setup_ds_path=None, slapd_path=None, nosync=False,
@@ -1163,13 +1164,6 @@ def provision(setup_dir, message, session_info,
                                          lp=lp, credentials=credentials, 
                                          names=names,
                                          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,
-                                         ldapi_url=ldapi_url)
     elif backend_type == "fedora-ds":
         provision_backend = FDSBackend(backend_type,
                                          paths=paths, setup_path=setup_path,
@@ -1207,43 +1201,56 @@ def provision(setup_dir, message, session_info,
     else:
         raise ProvisioningError("Unknown LDAP backend type selected")
 
-    provision_backend.init()
-    provision_backend.start()
-
-    provision_samba(result=result, paths=paths, message=message,
-            session_info=session_info, lp=lp, names=names, setup_path=setup_path,
-            provision_backend=provision_backend,
-            domainsid=domainsid, schema=schema, domainguid=domainguid,
-            policyguid=policyguid, policyguid_dc=policyguid_dc,
-            samdb_fill=samdb_fill,
-            adminpass=adminpass, krbtgtpass=krbtgtpass,
-            invocationid=invocationid,
-            machinepass=machinepass, dnspass=dnspass,
-            ntdsguid=ntdsguid, serverrole=serverrole,
-            dom_for_fun_level=dom_for_fun_level,
-            root=root, nobody=nobody, users=users, wheel=wheel,
-            domaindn=domaindn, hostip=hostip, hostip6=hostip6)
-
-    provision_backend.post_setup()
-    provision_backend.shutdown()
-    
-    create_phpldapadmin_config(paths.phpldapadminconfig, setup_path, 
+    if ldap_action is None or ldap_action == "create":
+        provision_backend.create()
+
+    if ldap_action is None:
+        provision_backend.start()
+
+    if ldap_action == "setup":
+        provision_backend.reset()
+
+    if ldap_action is None or ldap_action == "setup":
+        provision_samba(result=result, paths=paths, message=message,
+                session_info=session_info, lp=lp, names=names, setup_path=setup_path,
+                provision_backend=provision_backend,
+                domainsid=domainsid, schema=schema, domainguid=domainguid,
+                policyguid=policyguid, policyguid_dc=policyguid_dc,
+                samdb_fill=samdb_fill,
+                adminpass=adminpass, krbtgtpass=krbtgtpass,
+                invocationid=invocationid,
+                machinepass=machinepass, dnspass=dnspass,
+                ntdsguid=ntdsguid, serverrole=serverrole,
+                dom_for_fun_level=dom_for_fun_level,
+                root=root, nobody=nobody, users=users, wheel=wheel,
+                domaindn=domaindn, hostip=hostip, hostip6=hostip6)
+
+        provision_backend.post_setup()
+
+    if ldap_action is None:
+        provision_backend.shutdown()
+
+    if ldap_action == "create":
+        message("An empty LDAP server has been created in %s" % provision_backend.ldapdir)
+        message("Please provision Samba using LDAP URI %s" % provision_backend.ldap_uri)
+    else:
+        create_phpldapadmin_config(paths.phpldapadminconfig, setup_path,
                                ldapi_url)
 
-    #Now commit the secrets.ldb to disk
-    result.secrets_ldb.transaction_commit()
+        #Now commit the secrets.ldb to disk
+        result.secrets_ldb.transaction_commit()
 
-    message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
+        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")
-    message("Server Role:           %s" % serverrole)
-    message("Hostname:              %s" % names.hostname)
-    message("NetBIOS Domain:        %s" % names.domain)
-    message("DNS Domain:            %s" % names.dnsdomain)
-    message("DOMAIN SID:            %s" % str(domainsid))
+        message("Once the above files are installed, your Samba4 server will be ready to use")
+        message("Server Role:           %s" % serverrole)
+        message("Hostname:              %s" % names.hostname)
+        message("NetBIOS Domain:        %s" % names.domain)
+        message("DNS Domain:            %s" % names.dnsdomain)
+        message("DOMAIN SID:            %s" % str(domainsid))
 
-    if samdb_fill == FILL_FULL:
-        message("Admin password:        %s" % adminpass)
+        if samdb_fill == FILL_FULL:
+            message("Admin password:        %s" % adminpass)
 
     if provision_backend.type is not "ldb":
         if provision_backend.credentials.get_bind_dn() is not None:
@@ -1253,7 +1260,7 @@ def provision(setup_dir, message, session_info,
 
         message("LDAP Admin Password:   %s" % provision_backend.credentials.get_password())
 
-        if provision_backend.slapd_command_escaped is not None:
+        if (ldap_action is None or ldap_action == "create") and 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)
diff --git a/source4/scripting/python/samba/provisionbackend.py b/source4/scripting/python/samba/provisionbackend.py
index db9436d..22b1eed 100644
--- a/source4/scripting/python/samba/provisionbackend.py
+++ b/source4/scripting/python/samba/provisionbackend.py
@@ -40,6 +40,7 @@ from ldb import SCOPE_BASE, SCOPE_ONELEVEL, LdbError, timestring
 from samba import Ldb, read_and_sub_file, setup_file
 from samba.credentials import Credentials, DONT_USE_KERBEROS
 from samba.schema import Schema
+from samba.provisionutil import setup_add_ldif, setup_modify_ldif
 from samba.provisionexceptions import ProvisioningError
 
 class ProvisionBackend(object):
@@ -58,7 +59,7 @@ class ProvisionBackend(object):
         # Set a default - the code for "existing" below replaces this
         self.ldap_backend_type = backend_type
 
-    def init(self):
+    def create(self):
         pass
 
     def start(self):
@@ -67,6 +68,9 @@ class ProvisionBackend(object):
     def shutdown(self):
         pass
 
+    def reset(self):
+        pass
+
     def post_setup(self):
         pass
 
@@ -82,7 +86,7 @@ class LDBBackend(ProvisionBackend):
                 names=names,
                 message=message)
 
-    def init(self):
+    def create(self):
         self.credentials = None
         self.secrets_credentials = None
     
@@ -90,33 +94,6 @@ class LDBBackend(ProvisionBackend):
         shutil.rmtree(self.paths.samdb + ".d", True)
 
 
-class ExistingBackend(ProvisionBackend):
-    def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None, 
-                 names=None, message=None,
-                 ldap_uri=None):
-
-        super(ExistingBackend, self).__init__(
-                backend_type=backend_type,
-                paths=paths, setup_path=setup_path,
-                lp=lp, credentials=credentials,
-                names=names,
-                message=message)
-
-        self.ldap_uri = ldap_uri
-
-    def init(self):
-        #Check to see that this 'existing' LDAP backend in fact exists
-        ldapi_db = Ldb(self.ldap_uri, credentials=self.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.secrets_credentials = self.credentials
-
-        self.ldap_backend_type = "openldap" #For now, assume existing backends at least emulate OpenLDAP
-
-
 class LDAPBackend(ProvisionBackend):
     def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
                  names=None, message=None,
@@ -164,13 +141,27 @@ class LDAPBackend(ProvisionBackend):
         self.ldap_backend_extra_port = ldap_backend_extra_port
         self.ldap_dryrun_mode = ldap_dryrun_mode
 
-    def init(self):
+        # Credentials for provisioning
+        self.credentials = Credentials()
+        self.credentials.guess(self.lp)
+        #Kerberos to an ldapi:// backend makes no sense
+        self.credentials.set_kerberos_state(DONT_USE_KERBEROS)
+        self.credentials.set_password(self.ldapadminpass)
+
+        # Credentials for Samba
+        self.secrets_credentials = Credentials()
+        self.secrets_credentials.guess(self.lp)
+        #Kerberos to an ldapi:// backend makes no sense
+        self.secrets_credentials.set_kerberos_state(DONT_USE_KERBEROS)
+        self.secrets_credentials.set_username("samba-admin")
+        self.secrets_credentials.set_password(self.ldapadminpass)
+
+    def create(self):
         # we will shortly start slapd with ldapi for final provisioning. first check with ldapsearch -> rootDSE via self.ldap_uri
         # if another instance of slapd is already running 
         try:
             ldapi_db = Ldb(self.ldap_uri)
-            search_ol_rootdse = ldapi_db.search(base="", scope=SCOPE_BASE,
-                                                expression="(objectClass=OpenLDAProotDSE)");
+            search_rootdse = ldapi_db.search(base="", scope=SCOPE_BASE)
             try:
                 f = open(self.slapd_pid, "r")
                 p = f.read()
@@ -206,24 +197,6 @@ class LDAPBackend(ProvisionBackend):
 
         self.schema.write_to_tmp_ldb(schemadb_path);
 
-        self.credentials = Credentials()
-        self.credentials.guess(self.lp)
-        #Kerberos to an ldapi:// backend makes no sense
-        self.credentials.set_kerberos_state(DONT_USE_KERBEROS)
-        self.credentials.set_password(self.ldapadminpass)
-
-        self.secrets_credentials = Credentials()
-        self.secrets_credentials.guess(self.lp)
-        #Kerberos to an ldapi:// backend makes no sense
-        self.secrets_credentials.set_kerberos_state(DONT_USE_KERBEROS)
-        self.secrets_credentials.set_username("samba-admin")
-        self.secrets_credentials.set_password(self.ldapadminpass)
-
-        self.provision()
-
-    def provision(self):
-        pass
-
     def start(self):
         self.slapd_command_escaped = "\'" + "\' \'".join(self.slapd_command) + "\'"
         open(self.ldapdir + "/ldap_backend_startup.sh", 'w').write("#!/bin/sh\n" + self.slapd_command_escaped + "\n")
@@ -237,8 +210,7 @@ class LDAPBackend(ProvisionBackend):
             # Wait until the socket appears
             try:
                 ldapi_db = Ldb(self.ldap_uri, lp=self.lp, credentials=self.credentials)
-                search_ol_rootdse = ldapi_db.search(base="", scope=SCOPE_BASE,
-                                                    expression="(objectClass=OpenLDAProotDSE)")
+                search_rootdse = ldapi_db.search(base="", scope=SCOPE_BASE)
                 # If we have got here, then we must have a valid connection to the LDAP server!
                 return
             except LdbError, e:
@@ -261,6 +233,25 @@ class LDAPBackend(ProvisionBackend):
             #and now wait for it to die
             self.slapd.communicate()
 
+    def delete(self, ldap_db, dn):
+
+        self.deleteChildren(ldap_db, dn)
+
+        try:
+            ldap_db.delete(dn)
+        except ldb.LdbError, (ldb.ERR_NO_SUCH_OBJECT, _):
+            pass
+
+    def deleteChildren(self, ldap_db, dn):
+
+        try:
+            res = ldap_db.search(base=dn, scope=ldb.SCOPE_ONELEVEL, attrs=[])
+        except ldb.LdbError, (ldb.ERR_NO_SUCH_OBJECT, _):
+            return
+
+        for msg in res:
+            self.delete(ldap_db, msg.dn)
+
 
 class OpenLDAPBackend(LDAPBackend):
     def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
@@ -311,6 +302,8 @@ class OpenLDAPBackend(LDAPBackend):
                 serverdn=self.names.serverdn,
                 files=[setup_path("schema_samba4.ldif")]);
 
+        self.credentials.set_username("samba-admin")
+
     def setup_db_config(self, dbdir):
         """Setup a Berkeley database.
     
@@ -324,7 +317,11 @@ class OpenLDAPBackend(LDAPBackend):
         setup_file(self.setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"),
                    {"LDAPDBDIR": dbdir})
 
-    def provision(self):
+    def create(self):
+
+        super(OpenLDAPBackend, self).create()
+
+
         # Wipe the directories so we can start
         shutil.rmtree(os.path.join(self.ldapdir, "db"), True)
 
@@ -440,6 +437,7 @@ class OpenLDAPBackend(LDAPBackend):
         setup_file(self.setup_path("slapd.conf"), self.slapdconf,
                    {"DNSDOMAIN": self.names.dnsdomain,
                     "LDAPDIR": self.ldapdir,
+                    "LDAPADMINPASS": self.ldapadminpass,
                     "DOMAINDN": self.names.domaindn,
                     "CONFIGDN": self.names.configdn,
                     "SCHEMADN": self.names.schemadn,
@@ -520,9 +518,6 @@ class OpenLDAPBackend(LDAPBackend):
 
         self.slapd_command.append(uris)
 
-        # Set the username - done here because Fedora DS still uses the admin DN and simple bind
-        self.credentials.set_username("samba-admin")
-    
         # 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 OpenLDAP on
         # this system
@@ -547,6 +542,22 @@ class OpenLDAPBackend(LDAPBackend):
             # Don't confuse the admin by leaving the slapd.conf around
             os.remove(self.slapdconf)        
 
+    def reset(self):
+
+        # Delete each partition as partition's Manager
+        for basedn in [self.names.schemadn, self.names.configdn, self.names.domaindn]:
+
+            self.message("Erasing " + basedn)
+
+            credentials = Credentials()
+            credentials.set_kerberos_state(DONT_USE_KERBEROS)
+            credentials.set_bind_dn("CN=Manager," + basedn)
+            credentials.set_password(self.ldapadminpass)
+
+            ldap_db = Ldb(self.ldap_uri, lp=self.lp, credentials=credentials)
+
+            self.delete(ldap_db, basedn)
+
 
 class FDSBackend(LDAPBackend):
     def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
@@ -584,6 +595,8 @@ class FDSBackend(LDAPBackend):
         self.ldap_instance = self.names.netbiosname.lower()
 
         self.sambadn = "CN=Samba"
+        self.dnadn = "cn=Samba SIDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config"
+        self.rangesdn = "cn=Samba SIDs,ou=Ranges," + self.sambadn
 
         self.fedoradsinf = os.path.join(self.ldapdir, "fedorads.inf")
         self.partitions_ldif = os.path.join(self.ldapdir, "fedorads-partitions.ldif")
@@ -615,7 +628,12 @@ class FDSBackend(LDAPBackend):
                 files=[setup_path("schema_samba4.ldif"), self.samba3_ldif],
                 prefixmap=["1000:1.3.6.1.4.1.7165.2.1", "1001:1.3.6.1.4.1.7165.2.2"])
 
-    def provision(self):
+        self.credentials.set_bind_dn(self.names.ldapmanagerdn)
+
+    def create(self):
+
+        super(FDSBackend, self).create()
+
         if self.ldap_backend_extra_port is not None:
             serverport = "ServerPort=%d" % self.ldap_backend_extra_port
         else:
@@ -699,8 +717,6 @@ class FDSBackend(LDAPBackend):
         assert backend_schema_data is not None
         open(os.path.join(self.ldapdir, backend_schema), 'w').write(backend_schema_data)
 
-        self.credentials.set_bind_dn(self.names.ldapmanagerdn)
-
         # Destory the target directory, or else setup-ds.pl will complain
         fedora_ds_dir = os.path.join(self.ldapdir, "slapd-" + self.ldap_instance)
         shutil.rmtree(fedora_ds_dir, True)
@@ -736,6 +752,26 @@ class FDSBackend(LDAPBackend):
         if retcode != 0:
             raise ProvisioningError("ldif2db failed")
 
+    def reset(self):
+
+        self.ldap_db = Ldb(self.ldap_uri, lp=self.lp, credentials=self.credentials)
+
+        # Erasing all partitions
+        for basedn in [self.names.schemadn, self.names.configdn, self.names.domaindn]:
+
+            self.message("Erasing " + basedn)
+            self.delete(self.ldap_db, basedn)
+
+        self.message("Erasing " + self.rangesdn)
+        self.deleteChildren(self.ldap_db, self.rangesdn)
+
+        # Updating DNA configuration
+        setup_modify_ldif(self.ldap_db, self.setup_path("fedorads-dna-modify.ldif"),
+                   {"DOMAINDN": self.names.domaindn,
+                    "SAMBADN": self.sambadn,
+                    "DOMAINSID": str(self.domainsid),
+                    })
+
     def post_setup(self):
         ldapi_db = Ldb(self.ldap_uri, credentials=self.credentials)
 
diff --git a/source4/setup/fedorads-dna-modify.ldif b/source4/setup/fedorads-dna-modify.ldif
new file mode 100644
index 0000000..52281a7
--- /dev/null
+++ b/source4/setup/fedorads-dna-modify.ldif
@@ -0,0 +1,14 @@
+dn: cn=Samba SIDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
+changetype: modify
+replace: dnaScope
+dnaScope: ${DOMAINDN}
+-
+replace: dnaNextValue
+dnaNextValue: 1000
+-
+replace: dnaSharedCfgDn
+dnaSharedCfgDn: cn=Samba SIDs,ou=Ranges,${SAMBADN}
+-
+replace: dnaPrefix
+dnaPrefix: ${DOMAINSID}-
+-
diff --git a/source4/setup/provision b/source4/setup/provision
index 5377a2e..80f3153 100755
--- a/source4/setup/provision
+++ b/source4/setup/provision
@@ -95,6 +95,9 @@ parser.add_option("--ldap-backend-extra-port", type="int", metavar="LDAP-BACKEND
 parser.add_option("--ldap-backend-type", type="choice", metavar="LDAP-BACKEND-TYPE", 
 		help="LDAP backend type (fedora-ds or openldap)",
 		choices=["fedora-ds", "openldap"])
+parser.add_option("--ldap-action", type="choice", metavar="LDAP-ACTION",
+               help="LDAP backend action (create or setup)",
+               choices=["create", "setup"])
 parser.add_option("--ldap-dir", type="string", metavar="LDAP-DIR", 
 		help="LDAP backend directory")
 parser.add_option("--ldap-uri", type="string", metavar="LDAP-URI",
@@ -243,7 +246,7 @@ provision(setup_dir, message,
           serverrole=server_role, dom_for_fun_level=dom_for_fun_level,
           ldap_backend_extra_port=opts.ldap_backend_extra_port, 
           backend_type=opts.ldap_backend_type,
-          ldap_dir=opts.ldap_dir, ldap_uri=opts.ldap_uri,
+          ldap_action=opts.ldap_action, ldap_dir=opts.ldap_dir, ldap_uri=opts.ldap_uri,
           ldapadminpass=opts.ldapadminpass, ol_mmr_urls=opts.ol_mmr_urls,
           slapd_path=opts.slapd_path, setup_ds_path=opts.setup_ds_path,
           nosync=opts.nosync,ldap_dryrun_mode=opts.ldap_dryrun_mode,useeadb=eadb)
diff --git a/source4/setup/slapd.conf b/source4/setup/slapd.conf
index 0077a22..70cec60 100644
--- a/source4/setup/slapd.conf
+++ b/source4/setup/slapd.conf
@@ -58,6 +58,7 @@ database	ldif
 suffix		cn=Samba
 directory       ${LDAPDIR}/db/samba
 rootdn          cn=Manager,cn=Samba
+rootpw          ${LDAPADMINPASS}
 
 ########################################
 ## olc - configuration ###
@@ -77,6 +78,7 @@ access to dn.sub="cn=config"
 database        hdb
 suffix		${SCHEMADN}
 rootdn          cn=Manager,${SCHEMADN}
+rootpw          ${LDAPADMINPASS}
 directory	${LDAPDIR}/db/schema
 ${NOSYNC}
 ${INDEX_CONFIG}
@@ -97,6 +99,7 @@ ${MIRRORMODE}
 database        hdb
 suffix		${CONFIGDN}
 rootdn          cn=Manager,${CONFIGDN}
+rootpw          ${LDAPADMINPASS}
 directory	${LDAPDIR}/db/config
 ${NOSYNC}
 ${INDEX_CONFIG}
@@ -116,6 +119,7 @@ ${MIRRORMODE}
 database        hdb
 suffix		${DOMAINDN}
 rootdn          cn=Manager,${DOMAINDN}
+rootpw          ${LDAPADMINPASS}
 directory	${LDAPDIR}/db/user
 ${NOSYNC}
 ${INDEX_CONFIG}
-- 
1.6.6


------=_Part_68415_58125355.1265837901273--


More information about the samba-technical mailing list