def create_zone_file(lp, logger, paths, targetdir, dnsdomain, hostip, hostip6, hostname, realm, domainguid, ntdsguid, site): """Write out a DNS zone file, from the info in the current database. :param paths: paths object :param dnsdomain: DNS Domain name :param domaindn: DN of the Domain :param hostip: Local IPv4 IP :param hostip6: Local IPv6 IP :param hostname: Local hostname :param realm: Realm name :param domainguid: GUID of the domain. :param ntdsguid: GUID of the hosts nTDSDSA record. """ assert isinstance(domainguid, str) if hostip6 is not None: hostip6_base_line = " IN AAAA " + hostip6 hostip6_host_line = hostname + " IN AAAA " + hostip6 gc_msdcs_ip6_line = "gc._msdcs IN AAAA " + hostip6 else: hostip6_base_line = "" hostip6_host_line = "" gc_msdcs_ip6_line = "" if hostip is not None: hostip_base_line = " IN A " + hostip hostip_host_line = hostname + " IN A " + hostip gc_msdcs_ip_line = "gc._msdcs IN A " + hostip else: hostip_base_line = "" hostip_host_line = "" gc_msdcs_ip_line = "" setup_file(setup_path("provision.zone"), paths.dns, { "HOSTNAME": hostname, "DNSDOMAIN": dnsdomain, "REALM": realm, "HOSTIP_BASE_LINE": hostip_base_line, "HOSTIP_HOST_LINE": hostip_host_line, "DOMAINGUID": domainguid, "DATESTRING": time.strftime("%Y%m%d%H"), "DEFAULTSITE": site, "NTDSGUID": ntdsguid, "HOSTIP6_BASE_LINE": hostip6_base_line, "HOSTIP6_HOST_LINE": hostip6_host_line, "GC_MSDCS_IP_LINE": gc_msdcs_ip_line, "GC_MSDCS_IP6_LINE": gc_msdcs_ip6_line, }) if paths.bind_gid is not None: try: os.chown(paths.dns, -1, paths.bind_gid) # chmod needed to cope with umask os.chmod(paths.dns, 0o664) except OSError: if 'SAMBA_SELFTEST' not in os.environ: logger.error("Failed to chown %s to bind gid %u" % ( paths.dns, paths.bind_gid))
def setup_db_config(setup_path, dbdir): """Setup a Berkeley database. :param setup_path: Setup path function. :param dbdir: Database directory.""" if not os.path.isdir(os.path.join(dbdir, "bdb-logs")): os.makedirs(os.path.join(dbdir, "bdb-logs"), 0700) if not os.path.isdir(os.path.join(dbdir, "tmp")): os.makedirs(os.path.join(dbdir, "tmp"), 0700) setup_file(setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"), {"LDAPDBDIR": dbdir})
def create_named_txt(path, realm, dnsdomain, dnsname, private_dir, keytab_name): """Write out a file containing zone statements suitable for inclusion in a named.conf file (including GSS-TSIG configuration). :param path: Path of the new named.conf file. :param realm: Realm name :param dnsdomain: DNS Domain name :param private_dir: Path to private directory :param keytab_name: File name of DNS keytab file """ setup_file(setup_path("named.txt"), path, { "DNSDOMAIN": dnsdomain, "DNSNAME" : dnsname, "REALM": realm, "DNS_KEYTAB": keytab_name, "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name), "PRIVATE_DIR": private_dir })
def create_named_conf(paths, realm, dnsdomain, dns_backend): """Write out a file containing zone statements suitable for inclusion in a named.conf file (including GSS-TSIG configuration). :param paths: all paths :param realm: Realm name :param dnsdomain: DNS Domain name :param dns_backend: DNS backend type :param keytab_name: File name of DNS keytab file """ if dns_backend == "BIND9_FLATFILE": setup_file(setup_path("named.conf"), paths.namedconf, { "DNSDOMAIN": dnsdomain, "REALM": realm, "ZONE_FILE": paths.dns, "REALM_WC": "*." + ".".join(realm.split(".")[1:]), "NAMED_CONF": paths.namedconf, "NAMED_CONF_UPDATE": paths.namedconf_update }) setup_file(setup_path("named.conf.update"), paths.namedconf_update) elif dns_backend == "BIND9_DLZ": setup_file(setup_path("named.conf.dlz"), paths.namedconf, { "NAMED_CONF": paths.namedconf, "MODULESDIR" : samba.param.modules_dir(), })
def create_named_conf(paths, realm, dnsdomain, dns_backend, logger): """Write out a file containing zone statements suitable for inclusion in a named.conf file (including GSS-TSIG configuration). :param paths: all paths :param realm: Realm name :param dnsdomain: DNS Domain name :param dns_backend: DNS backend type :param keytab_name: File name of DNS keytab file :param logger: Logger object """ # TODO: This really should have been done as a top level import. # It is done here to avoid a depencency loop. That is, we move # ProvisioningError to another file, and have all the provision # scripts import it from there. from samba.provision import ProvisioningError if dns_backend == "BIND9_FLATFILE": setup_file(setup_path("named.conf"), paths.namedconf, { "DNSDOMAIN": dnsdomain, "REALM": realm, "ZONE_FILE": paths.dns, "REALM_WC": "*." + ".".join(realm.split(".")[1:]), "NAMED_CONF": paths.namedconf, "NAMED_CONF_UPDATE": paths.namedconf_update }) setup_file(setup_path("named.conf.update"), paths.namedconf_update) elif dns_backend == "BIND9_DLZ": bind_info = subprocess.Popen(['named -V'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd='.').communicate()[0] bind9_8 = '#' bind9_9 = '#' bind9_10 = '#' bind9_11 = '#' if bind_info.upper().find('BIND 9.8') != -1: bind9_8 = '' elif bind_info.upper().find('BIND 9.9') != -1: bind9_9 = '' elif bind_info.upper().find('BIND 9.10') != -1: bind9_10 = '' elif bind_info.upper().find('BIND 9.11') != -1: bind9_11 = '' elif bind_info.upper().find('BIND 9.7') != -1: raise ProvisioningError("DLZ option incompatible with BIND 9.7.") else: logger.warning("BIND version unknown, please modify %s manually." % paths.namedconf) setup_file(setup_path("named.conf.dlz"), paths.namedconf, { "NAMED_CONF": paths.namedconf, "MODULESDIR" : samba.param.modules_dir(), "BIND9_8" : bind9_8, "BIND9_9" : bind9_9, "BIND9_10" : bind9_10, "BIND9_11" : bind9_11 })
def create_named_conf(paths, realm, dnsdomain, dns_backend): """Write out a file containing zone statements suitable for inclusion in a named.conf file (including GSS-TSIG configuration). :param paths: all paths :param realm: Realm name :param dnsdomain: DNS Domain name :param dns_backend: DNS backend type :param keytab_name: File name of DNS keytab file """ if dns_backend == "BIND9_FLATFILE": setup_file( setup_path("named.conf"), paths.namedconf, { "DNSDOMAIN": dnsdomain, "REALM": realm, "ZONE_FILE": paths.dns, "REALM_WC": "*." + ".".join(realm.split(".")[1:]), "NAMED_CONF": paths.namedconf, "NAMED_CONF_UPDATE": paths.namedconf_update }) setup_file(setup_path("named.conf.update"), paths.namedconf_update) elif dns_backend == "BIND9_DLZ": setup_file( setup_path("named.conf.dlz"), paths.namedconf, { "NAMED_CONF": paths.namedconf, "MODULESDIR": samba.param.modules_dir(), })
def provision(self): from samba.provision import ProvisioningError, setup_path # Wipe the directories so we can start shutil.rmtree(os.path.join(self.ldapdir, "db"), True) # Allow the test scripts to turn off fsync() for OpenLDAP as for TDB # and LDB nosync_config = "" if self.nosync: nosync_config = "dbnosync" lnkattr = self.schema.linked_attributes() refint_attributes = "" memberof_config = "# Generated from Samba4 schema\n" for att in lnkattr.keys(): if lnkattr[att] is not None: refint_attributes = refint_attributes + " " + att memberof_config += read_and_sub_file( setup_path("memberof.conf"), { "MEMBER_ATTR": att, "MEMBEROF_ATTR": lnkattr[att]}) refint_config = read_and_sub_file( setup_path("refint.conf"), {"LINK_ATTRS": refint_attributes}) attrs = ["linkID", "lDAPDisplayName"] res = self.schema.ldb.search( expression="(&(objectclass=attributeSchema)" "(searchFlags:1.2.840.113556.1.4.803:=1))", base=self.names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs) index_config = "" for i in range(0, len(res)): index_attr = res[i]["lDAPDisplayName"][0] if index_attr == "objectGUID": index_attr = "entryUUID" index_config += "index " + index_attr + " eq\n" # generate serverids, ldap-urls and syncrepl-blocks for mmr hosts mmr_on_config = "" mmr_replicator_acl = "" mmr_serverids_config = "" mmr_syncrepl_schema_config = "" mmr_syncrepl_config_config = "" mmr_syncrepl_domaindns_config = "" mmr_syncrepl_forestdns_config = "" mmr_syncrepl_user_config = "" mmr_pass = "" if self.ol_mmr_urls is not None: # For now, make these equal mmr_pass = self.ldapadminpass url_list = filter(None,self.ol_mmr_urls.split(',')) for url in url_list: self.logger.info("Using LDAP-URL: "+url) if len(url_list) == 1: raise ProvisioningError("At least 2 LDAP-URLs needed for MMR!") mmr_on_config = "MirrorMode On" mmr_replicator_acl = " by dn=cn=replicator,cn=samba read" serverid = 0 for url in url_list: serverid = serverid + 1 mmr_serverids_config += read_and_sub_file( setup_path("mmr_serverids.conf"), { "SERVERID": str(serverid), "LDAPSERVER": url }) rid = serverid * 10 rid = rid + 1 mmr_syncrepl_schema_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), "MMRDN": self.names.schemadn, "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) rid = rid + 1 mmr_syncrepl_config_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), "MMRDN": self.names.configdn, "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) rid = rid + 1 mmr_syncrepl_domaindns_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), "MMRDN": "dc=DomainDNSZones," + self.names.domaindn, "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) rid = rid + 1 mmr_syncrepl_forestdns_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), "MMRDN": "dc=ForestDNSZones," + self.names.domaindn, "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) rid = rid + 1 mmr_syncrepl_user_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), "MMRDN": self.names.domaindn, "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass }) # OpenLDAP cn=config initialisation olc_syncrepl_config = "" olc_mmr_config = "" # if mmr = yes, generate cn=config-replication directives # and olc_seed.lif for the other mmr-servers if self.ol_mmr_urls is not None: serverid = 0 olc_serverids_config = "" olc_syncrepl_seed_config = "" olc_mmr_config += read_and_sub_file( setup_path("olc_mmr.conf"), {}) rid = 500 for url in url_list: serverid = serverid + 1 olc_serverids_config += read_and_sub_file( setup_path("olc_serverid.conf"), { "SERVERID" : str(serverid), "LDAPSERVER" : url }) rid = rid + 1 olc_syncrepl_config += read_and_sub_file( setup_path("olc_syncrepl.conf"), { "RID" : str(rid), "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) olc_syncrepl_seed_config += read_and_sub_file( setup_path("olc_syncrepl_seed.conf"), { "RID" : str(rid), "LDAPSERVER" : url}) setup_file(setup_path("olc_seed.ldif"), self.olcseedldif, {"OLC_SERVER_ID_CONF": olc_serverids_config, "OLC_PW": self.ldapadminpass, "OLC_SYNCREPL_CONF": olc_syncrepl_seed_config}) # end olc setup_file(setup_path("slapd.conf"), self.slapdconf, {"DNSDOMAIN": self.names.dnsdomain, "LDAPDIR": self.ldapdir, "DOMAINDN": self.names.domaindn, "CONFIGDN": self.names.configdn, "SCHEMADN": self.names.schemadn, "MEMBEROF_CONFIG": memberof_config, "MIRRORMODE": mmr_on_config, "REPLICATOR_ACL": mmr_replicator_acl, "MMR_SERVERIDS_CONFIG": mmr_serverids_config, "MMR_SYNCREPL_SCHEMA_CONFIG": mmr_syncrepl_schema_config, "MMR_SYNCREPL_CONFIG_CONFIG": mmr_syncrepl_config_config, "MMR_SYNCREPL_DOMAINDNS_CONFIG": mmr_syncrepl_domaindns_config, "MMR_SYNCREPL_FORESTDNS_CONFIG": mmr_syncrepl_forestdns_config, "MMR_SYNCREPL_USER_CONFIG": mmr_syncrepl_user_config, "OLC_SYNCREPL_CONFIG": olc_syncrepl_config, "OLC_MMR_CONFIG": olc_mmr_config, "REFINT_CONFIG": refint_config, "INDEX_CONFIG": index_config, "ADMIN_UID": str(os.getuid()), "NOSYNC": nosync_config,}) self.setup_db_dir(os.path.join(self.ldapdir, "db", "forestdns")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "domaindns")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "user")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "config")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "schema")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "samba")) if self.ol_mmr_urls is not None: mmr = "" else: mmr = "#" cn_samba = read_and_sub_file( setup_path("cn=samba.ldif"), { "LDAPADMINPASS": self.ldapadminpass, "MMR_PASSWORD": mmr_pass, "MMR": mmr }) mapping = "schema-map-openldap-2.3" backend_schema = "backend-schema.schema" f = open(setup_path(mapping), 'r') try: backend_schema_data = self.schema.convert_to_openldap( "openldap", f.read()) finally: f.close() assert backend_schema_data is not None f = open(os.path.join(self.ldapdir, backend_schema), 'w') try: f.write(backend_schema_data) finally: f.close() # now we generate the needed strings to start slapd automatically, if self.ldap_backend_extra_port is not None: # When we use MMR, we can't use 0.0.0.0 as it uses the name # specified there as part of it's clue as to it's own name, # and not to replicate to itself if self.ol_mmr_urls is None: server_port_string = "ldap://0.0.0.0:%d" % self.ldap_backend_extra_port else: server_port_string = "ldap://%s.%s:%d" (self.names.hostname, self.names.dnsdomain, self.ldap_backend_extra_port) else: server_port_string = "" # Prepare the 'result' information - the commands to return in # particular self.slapd_provision_command = [self.slapd_path, "-F" + self.olcdir, "-h"] # copy this command so we have two version, one with -d0 and only # ldapi (or the forced ldap_uri), and one with all the listen commands self.slapd_command = list(self.slapd_provision_command) self.slapd_provision_command.extend([self.ldap_uri, "-d0"]) uris = self.ldap_uri if server_port_string is not "": uris = uris + " " + server_port_string self.slapd_command.append(uris) # Wipe the old sam.ldb databases away shutil.rmtree(self.olcdir, True) os.makedirs(self.olcdir, 0o770) # 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 if self.ldap_dryrun_mode: sys.exit(0) slapd_cmd = [self.slapd_path, "-Ttest", "-n", "0", "-f", self.slapdconf, "-F", self.olcdir] retcode = subprocess.call(slapd_cmd, close_fds=True, shell=False) if retcode != 0: self.logger.error("conversion from slapd.conf to cn=config failed slapd started with: %s" % "\'" + "\' \'".join(slapd_cmd) + "\'") raise ProvisioningError("conversion from slapd.conf to cn=config failed") if not os.path.exists(os.path.join(self.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(self.slapdconf) cn_samba_cmd = [self.slapd_path, "-Tadd", "-b", "cn=samba", "-F", self.olcdir] p = subprocess.Popen(cn_samba_cmd, stdin=subprocess.PIPE, shell=False) p.stdin.write(cn_samba) p.communicate()
def create_dns_update_list(lp, logger, paths): """Write out a dns_update_list file""" # note that we use no variable substitution on this file # the substitution is done at runtime by samba_dnsupdate, samba_spnupdate setup_file(setup_path("dns_update_list"), paths.dns_update_list, None) setup_file(setup_path("spn_update_list"), paths.spn_update_list, None)
def create_zone_file(lp, logger, paths, targetdir, dnsdomain, hostip, hostip6, hostname, realm, domainguid, ntdsguid, site): """Write out a DNS zone file, from the info in the current database. :param paths: paths object :param dnsdomain: DNS Domain name :param domaindn: DN of the Domain :param hostip: Local IPv4 IP :param hostip6: Local IPv6 IP :param hostname: Local hostname :param realm: Realm name :param domainguid: GUID of the domain. :param ntdsguid: GUID of the hosts nTDSDSA record. """ assert isinstance(domainguid, str) if hostip6 is not None: hostip6_base_line = " IN AAAA " + hostip6 hostip6_host_line = hostname + " IN AAAA " + hostip6 gc_msdcs_ip6_line = "gc._msdcs IN AAAA " + hostip6 else: hostip6_base_line = "" hostip6_host_line = "" gc_msdcs_ip6_line = "" if hostip is not None: hostip_base_line = " IN A " + hostip hostip_host_line = hostname + " IN A " + hostip gc_msdcs_ip_line = "gc._msdcs IN A " + hostip else: hostip_base_line = "" hostip_host_line = "" gc_msdcs_ip_line = "" # we need to freeze the zone while we update the contents if targetdir is None: rndc = ' '.join(lp.get("rndc command")) os.system(rndc + " freeze " + lp.get("realm")) setup_file(setup_path("provision.zone"), paths.dns, { "HOSTNAME": hostname, "DNSDOMAIN": dnsdomain, "REALM": realm, "HOSTIP_BASE_LINE": hostip_base_line, "HOSTIP_HOST_LINE": hostip_host_line, "DOMAINGUID": domainguid, "DATESTRING": time.strftime("%Y%m%d%H"), "DEFAULTSITE": site, "NTDSGUID": ntdsguid, "HOSTIP6_BASE_LINE": hostip6_base_line, "HOSTIP6_HOST_LINE": hostip6_host_line, "GC_MSDCS_IP_LINE": gc_msdcs_ip_line, "GC_MSDCS_IP6_LINE": gc_msdcs_ip6_line, }) if paths.bind_gid is not None: try: os.chown(paths.dns, -1, paths.bind_gid) # chmod needed to cope with umask os.chmod(paths.dns, 0664) except OSError: if not os.environ.has_key('SAMBA_SELFTEST'): logger.error("Failed to chown %s to bind gid %u" % ( paths.dns, paths.bind_gid)) if targetdir is None: os.system(rndc + " unfreeze " + lp.get("realm"))
def provision(self): from samba.provision import ProvisioningError, setup_path if self.ldap_backend_extra_port is not None: serverport = "ServerPort=%d" % self.ldap_backend_extra_port else: serverport = "" setup_file( setup_path("fedorads.inf"), self.fedoradsinf, { "ROOT": self.root, "HOSTNAME": self.hostname, "DNSDOMAIN": self.names.dnsdomain, "LDAPDIR": self.ldapdir, "DOMAINDN": self.names.domaindn, "LDAP_INSTANCE": self.ldap_instance, "LDAPMANAGERDN": self.names.ldapmanagerdn, "LDAPMANAGERPASS": self.ldapadminpass, "SERVERPORT": serverport }) setup_file( setup_path("fedorads-partitions.ldif"), self.partitions_ldif, { "CONFIGDN": self.names.configdn, "SCHEMADN": self.names.schemadn, "SAMBADN": self.sambadn, }) setup_file(setup_path("fedorads-sasl.ldif"), self.sasl_ldif, { "SAMBADN": self.sambadn, }) setup_file( setup_path("fedorads-dna.ldif"), self.dna_ldif, { "DOMAINDN": self.names.domaindn, "SAMBADN": self.sambadn, "DOMAINSID": str(self.domainsid), }) setup_file(setup_path("fedorads-pam.ldif"), self.pam_ldif) lnkattr = self.schema.linked_attributes() f = open(setup_path("fedorads-refint-delete.ldif"), 'r') try: refint_config = f.read() finally: f.close() memberof_config = "" index_config = "" argnum = 3 for attr in lnkattr.keys(): if lnkattr[attr] is not None: refint_config += read_and_sub_file( setup_path("fedorads-refint-add.ldif"), { "ARG_NUMBER": str(argnum), "LINK_ATTR": attr }) memberof_config += read_and_sub_file( setup_path("fedorads-linked-attributes.ldif"), { "MEMBER_ATTR": attr, "MEMBEROF_ATTR": lnkattr[attr] }) index_config += read_and_sub_file( setup_path("fedorads-index.ldif"), {"ATTR": attr}) argnum += 1 f = open(self.refint_ldif, 'w') try: f.write(refint_config) finally: f.close() f = open(self.linked_attrs_ldif, 'w') try: f.write(memberof_config) finally: f.close() attrs = ["lDAPDisplayName"] res = self.schema.ldb.search( expression="(&(objectclass=attributeSchema)" "(searchFlags:1.2.840.113556.1.4.803:=1))", base=self.names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs) for i in range(0, len(res)): attr = res[i]["lDAPDisplayName"][0] if attr == "objectGUID": attr = "nsUniqueId" index_config += read_and_sub_file( setup_path("fedorads-index.ldif"), {"ATTR": attr}) f = open(self.index_ldif, 'w') try: f.write(index_config) finally: f.close() setup_file(setup_path("fedorads-samba.ldif"), self.samba_ldif, { "SAMBADN": self.sambadn, "LDAPADMINPASS": self.ldapadminpass }) mapping = "schema-map-fedora-ds-1.0" backend_schema = "99_ad.ldif" # Build a schema file in Fedora DS format f = open(setup_path(mapping), 'r') try: backend_schema_data = self.schema.convert_to_openldap( "fedora-ds", f.read()) finally: f.close() assert backend_schema_data is not None f = open(os.path.join(self.ldapdir, backend_schema), 'w') try: f.write(backend_schema_data) finally: f.close() 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) self.slapd_provision_command = [ self.slapd_path, "-D", fedora_ds_dir, "-i", self.slapd_pid ] # In the 'provision' command line, stay in the foreground so we can # easily kill it self.slapd_provision_command.append("-d0") # the command for the final run is the normal script self.slapd_command = \ [os.path.join(self.ldapdir, "slapd-" + self.ldap_instance, "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 if self.ldap_dryrun_mode: sys.exit(0) # Try to print helpful messages when the user has not specified the # path to the setup-ds tool if self.setup_ds_path is None: raise ProvisioningError( "Fedora DS LDAP-Backend must be setup with path to setup-ds, e.g. --setup-ds-path=\"/usr/sbin/setup-ds.pl\"!" ) if not os.path.exists(self.setup_ds_path): self.logger.warning("Path (%s) to slapd does not exist!", self.setup_ds_path) # Run the Fedora DS setup utility retcode = subprocess.call( [self.setup_ds_path, "--silent", "--file", self.fedoradsinf], close_fds=True, shell=False) if retcode != 0: raise ProvisioningError("setup-ds failed") # Load samba-admin retcode = subprocess.call([ os.path.join(self.ldapdir, "slapd-" + self.ldap_instance, "ldif2db"), "-s", self.sambadn, "-i", self.samba_ldif ], close_fds=True, shell=False) if retcode != 0: raise ProvisioningError("ldif2db failed")
def provision(self): from samba.provision import ProvisioningError, setup_path # Wipe the directories so we can start shutil.rmtree(os.path.join(self.ldapdir, "db"), True) # Allow the test scripts to turn off fsync() for OpenLDAP as for TDB # and LDB nosync_config = "" if self.nosync: nosync_config = "dbnosync" lnkattr = self.schema.linked_attributes() refint_attributes = "" memberof_config = "# Generated from Samba4 schema\n" for att in lnkattr.keys(): if lnkattr[att] is not None: refint_attributes = refint_attributes + " " + att memberof_config += read_and_sub_file( setup_path("memberof.conf"), { "MEMBER_ATTR": att, "MEMBEROF_ATTR": lnkattr[att] }) refint_config = read_and_sub_file(setup_path("refint.conf"), {"LINK_ATTRS": refint_attributes}) attrs = ["linkID", "lDAPDisplayName"] res = self.schema.ldb.search( expression="(&(objectclass=attributeSchema)" "(searchFlags:1.2.840.113556.1.4.803:=1))", base=self.names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs) index_config = "" for i in range(0, len(res)): index_attr = res[i]["lDAPDisplayName"][0] if index_attr == "objectGUID": index_attr = "entryUUID" index_config += "index " + index_attr + " eq\n" # generate serverids, ldap-urls and syncrepl-blocks for mmr hosts mmr_on_config = "" mmr_replicator_acl = "" mmr_serverids_config = "" mmr_syncrepl_schema_config = "" mmr_syncrepl_config_config = "" mmr_syncrepl_domaindns_config = "" mmr_syncrepl_forestdns_config = "" mmr_syncrepl_user_config = "" mmr_pass = "" if self.ol_mmr_urls is not None: # For now, make these equal mmr_pass = self.ldapadminpass url_list = filter(None, self.ol_mmr_urls.split(',')) for url in url_list: self.logger.info("Using LDAP-URL: " + url) if len(url_list) == 1: raise ProvisioningError("At least 2 LDAP-URLs needed for MMR!") mmr_on_config = "MirrorMode On" mmr_replicator_acl = " by dn=cn=replicator,cn=samba read" serverid = 0 for url in url_list: serverid = serverid + 1 mmr_serverids_config += read_and_sub_file( setup_path("mmr_serverids.conf"), { "SERVERID": str(serverid), "LDAPSERVER": url }) rid = serverid * 10 rid = rid + 1 mmr_syncrepl_schema_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID": str(rid), "MMRDN": self.names.schemadn, "LDAPSERVER": url, "MMR_PASSWORD": mmr_pass }) rid = rid + 1 mmr_syncrepl_config_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID": str(rid), "MMRDN": self.names.configdn, "LDAPSERVER": url, "MMR_PASSWORD": mmr_pass }) rid = rid + 1 mmr_syncrepl_domaindns_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID": str(rid), "MMRDN": "dc=DomainDNSZones," + self.names.domaindn, "LDAPSERVER": url, "MMR_PASSWORD": mmr_pass }) rid = rid + 1 mmr_syncrepl_forestdns_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID": str(rid), "MMRDN": "dc=ForestDNSZones," + self.names.domaindn, "LDAPSERVER": url, "MMR_PASSWORD": mmr_pass }) rid = rid + 1 mmr_syncrepl_user_config += read_and_sub_file( setup_path("mmr_syncrepl.conf"), { "RID": str(rid), "MMRDN": self.names.domaindn, "LDAPSERVER": url, "MMR_PASSWORD": mmr_pass }) # OpenLDAP cn=config initialisation olc_syncrepl_config = "" olc_mmr_config = "" # if mmr = yes, generate cn=config-replication directives # and olc_seed.lif for the other mmr-servers if self.ol_mmr_urls is not None: serverid = 0 olc_serverids_config = "" olc_syncrepl_seed_config = "" olc_mmr_config += read_and_sub_file(setup_path("olc_mmr.conf"), {}) rid = 500 for url in url_list: serverid = serverid + 1 olc_serverids_config += read_and_sub_file( setup_path("olc_serverid.conf"), { "SERVERID": str(serverid), "LDAPSERVER": url }) rid = rid + 1 olc_syncrepl_config += read_and_sub_file( setup_path("olc_syncrepl.conf"), { "RID": str(rid), "LDAPSERVER": url, "MMR_PASSWORD": mmr_pass }) olc_syncrepl_seed_config += read_and_sub_file( setup_path("olc_syncrepl_seed.conf"), { "RID": str(rid), "LDAPSERVER": url }) setup_file( setup_path("olc_seed.ldif"), self.olcseedldif, { "OLC_SERVER_ID_CONF": olc_serverids_config, "OLC_PW": self.ldapadminpass, "OLC_SYNCREPL_CONF": olc_syncrepl_seed_config }) # end olc setup_file( setup_path("slapd.conf"), self.slapdconf, { "DNSDOMAIN": self.names.dnsdomain, "LDAPDIR": self.ldapdir, "DOMAINDN": self.names.domaindn, "CONFIGDN": self.names.configdn, "SCHEMADN": self.names.schemadn, "MEMBEROF_CONFIG": memberof_config, "MIRRORMODE": mmr_on_config, "REPLICATOR_ACL": mmr_replicator_acl, "MMR_SERVERIDS_CONFIG": mmr_serverids_config, "MMR_SYNCREPL_SCHEMA_CONFIG": mmr_syncrepl_schema_config, "MMR_SYNCREPL_CONFIG_CONFIG": mmr_syncrepl_config_config, "MMR_SYNCREPL_DOMAINDNS_CONFIG": mmr_syncrepl_domaindns_config, "MMR_SYNCREPL_FORESTDNS_CONFIG": mmr_syncrepl_forestdns_config, "MMR_SYNCREPL_USER_CONFIG": mmr_syncrepl_user_config, "OLC_SYNCREPL_CONFIG": olc_syncrepl_config, "OLC_MMR_CONFIG": olc_mmr_config, "REFINT_CONFIG": refint_config, "INDEX_CONFIG": index_config, "ADMIN_UID": str(os.getuid()), "NOSYNC": nosync_config, }) self.setup_db_dir(os.path.join(self.ldapdir, "db", "forestdns")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "domaindns")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "user")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "config")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "schema")) self.setup_db_dir(os.path.join(self.ldapdir, "db", "samba")) if self.ol_mmr_urls is not None: mmr = "" else: mmr = "#" cn_samba = read_and_sub_file( setup_path("cn=samba.ldif"), { "LDAPADMINPASS": self.ldapadminpass, "MMR_PASSWORD": mmr_pass, "MMR": mmr }) mapping = "schema-map-openldap-2.3" backend_schema = "backend-schema.schema" f = open(setup_path(mapping), 'r') try: backend_schema_data = self.schema.convert_to_openldap( "openldap", f.read()) finally: f.close() assert backend_schema_data is not None f = open(os.path.join(self.ldapdir, backend_schema), 'w') try: f.write(backend_schema_data) finally: f.close() # now we generate the needed strings to start slapd automatically, if self.ldap_backend_extra_port is not None: # When we use MMR, we can't use 0.0.0.0 as it uses the name # specified there as part of it's clue as to it's own name, # and not to replicate to itself if self.ol_mmr_urls is None: server_port_string = "ldap://0.0.0.0:%d" % self.ldap_backend_extra_port else: server_port_string = "ldap://%s.%s:%d" ( self.names.hostname, self.names.dnsdomain, self.ldap_backend_extra_port) else: server_port_string = "" # Prepare the 'result' information - the commands to return in # particular self.slapd_provision_command = [ self.slapd_path, "-F" + self.olcdir, "-h" ] # copy this command so we have two version, one with -d0 and only # ldapi (or the forced ldap_uri), and one with all the listen commands self.slapd_command = list(self.slapd_provision_command) self.slapd_provision_command.extend([self.ldap_uri, "-d0"]) uris = self.ldap_uri if server_port_string is not "": uris = uris + " " + server_port_string self.slapd_command.append(uris) # Wipe the old sam.ldb databases away shutil.rmtree(self.olcdir, True) os.makedirs(self.olcdir, 0o770) # 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 if self.ldap_dryrun_mode: sys.exit(0) slapd_cmd = [ self.slapd_path, "-Ttest", "-n", "0", "-f", self.slapdconf, "-F", self.olcdir ] retcode = subprocess.call(slapd_cmd, close_fds=True, shell=False) if retcode != 0: self.logger.error( "conversion from slapd.conf to cn=config failed slapd started with: %s" % "\'" + "\' \'".join(slapd_cmd) + "\'") raise ProvisioningError( "conversion from slapd.conf to cn=config failed") if not os.path.exists(os.path.join(self.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(self.slapdconf) cn_samba_cmd = [ self.slapd_path, "-Tadd", "-b", "cn=samba", "-F", self.olcdir ] p = subprocess.Popen(cn_samba_cmd, stdin=subprocess.PIPE, shell=False) p.stdin.write(cn_samba) p.communicate()
def provision(self): from samba.provision import ProvisioningError, setup_path if self.ldap_backend_extra_port is not None: serverport = "ServerPort=%d" % self.ldap_backend_extra_port else: serverport = "" setup_file(setup_path("fedorads.inf"), self.fedoradsinf, {"ROOT": self.root, "HOSTNAME": self.hostname, "DNSDOMAIN": self.names.dnsdomain, "LDAPDIR": self.ldapdir, "DOMAINDN": self.names.domaindn, "LDAP_INSTANCE": self.ldap_instance, "LDAPMANAGERDN": self.names.ldapmanagerdn, "LDAPMANAGERPASS": self.ldapadminpass, "SERVERPORT": serverport}) setup_file(setup_path("fedorads-partitions.ldif"), self.partitions_ldif, {"CONFIGDN": self.names.configdn, "SCHEMADN": self.names.schemadn, "SAMBADN": self.sambadn, }) setup_file(setup_path("fedorads-sasl.ldif"), self.sasl_ldif, {"SAMBADN": self.sambadn, }) setup_file(setup_path("fedorads-dna.ldif"), self.dna_ldif, {"DOMAINDN": self.names.domaindn, "SAMBADN": self.sambadn, "DOMAINSID": str(self.domainsid), }) setup_file(setup_path("fedorads-pam.ldif"), self.pam_ldif) lnkattr = self.schema.linked_attributes() f = open(setup_path("fedorads-refint-delete.ldif"), 'r') try: refint_config = f.read() finally: f.close() memberof_config = "" index_config = "" argnum = 3 for attr in lnkattr.keys(): if lnkattr[attr] is not None: refint_config += read_and_sub_file( setup_path("fedorads-refint-add.ldif"), { "ARG_NUMBER" : str(argnum), "LINK_ATTR" : attr }) memberof_config += read_and_sub_file( setup_path("fedorads-linked-attributes.ldif"), { "MEMBER_ATTR" : attr, "MEMBEROF_ATTR" : lnkattr[attr] }) index_config += read_and_sub_file( setup_path("fedorads-index.ldif"), { "ATTR" : attr }) argnum += 1 f = open(self.refint_ldif, 'w') try: f.write(refint_config) finally: f.close() f = open(self.linked_attrs_ldif, 'w') try: f.write(memberof_config) finally: f.close() attrs = ["lDAPDisplayName"] res = self.schema.ldb.search( expression="(&(objectclass=attributeSchema)" "(searchFlags:1.2.840.113556.1.4.803:=1))", base=self.names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs) for i in range(0, len(res)): attr = res[i]["lDAPDisplayName"][0] if attr == "objectGUID": attr = "nsUniqueId" index_config += read_and_sub_file( setup_path("fedorads-index.ldif"), { "ATTR" : attr }) f = open(self.index_ldif, 'w') try: f.write(index_config) finally: f.close() setup_file(setup_path("fedorads-samba.ldif"), self.samba_ldif, { "SAMBADN": self.sambadn, "LDAPADMINPASS": self.ldapadminpass }) mapping = "schema-map-fedora-ds-1.0" backend_schema = "99_ad.ldif" # Build a schema file in Fedora DS format f = open(setup_path(mapping), 'r') try: backend_schema_data = self.schema.convert_to_openldap("fedora-ds", f.read()) finally: f.close() assert backend_schema_data is not None f = open(os.path.join(self.ldapdir, backend_schema), 'w') try: f.write(backend_schema_data) finally: f.close() 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) self.slapd_provision_command = [self.slapd_path, "-D", fedora_ds_dir, "-i", self.slapd_pid] # In the 'provision' command line, stay in the foreground so we can # easily kill it self.slapd_provision_command.append("-d0") #the command for the final run is the normal script self.slapd_command = [os.path.join(self.ldapdir, "slapd-" + self.ldap_instance, "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 if self.ldap_dryrun_mode: sys.exit(0) # Try to print helpful messages when the user has not specified the # path to the setup-ds tool if self.setup_ds_path is None: raise ProvisioningError("Fedora DS LDAP-Backend must be setup with path to setup-ds, e.g. --setup-ds-path=\"/usr/sbin/setup-ds.pl\"!") if not os.path.exists(self.setup_ds_path): self.logger.warning("Path (%s) to slapd does not exist!", self.setup_ds_path) # Run the Fedora DS setup utility retcode = subprocess.call([self.setup_ds_path, "--silent", "--file", self.fedoradsinf], close_fds=True, shell=False) if retcode != 0: raise ProvisioningError("setup-ds failed") # Load samba-admin retcode = subprocess.call([ os.path.join(self.ldapdir, "slapd-" + self.ldap_instance, "ldif2db"), "-s", self.sambadn, "-i", self.samba_ldif], close_fds=True, shell=False) if retcode != 0: raise ProvisioningError("ldif2db failed")
def provision(self): # Wipe the directories so we can start shutil.rmtree(os.path.join(self.paths.ldapdir, "db"), True) #Allow the test scripts to turn off fsync() for OpenLDAP as for TDB and LDB nosync_config = "" if self.nosync: nosync_config = "dbnosync" lnkattr = self.schema.linked_attributes() refint_attributes = "" memberof_config = "# Generated from Samba4 schema\n" for att in lnkattr.keys(): if lnkattr[att] is not None: refint_attributes = refint_attributes + " " + att memberof_config += read_and_sub_file(self.setup_path("memberof.conf"), { "MEMBER_ATTR" : att , "MEMBEROF_ATTR" : lnkattr[att] }) refint_config = read_and_sub_file(self.setup_path("refint.conf"), { "LINK_ATTRS" : refint_attributes}) attrs = ["linkID", "lDAPDisplayName"] res = self.schema.ldb.search(expression="(&(objectclass=attributeSchema)(searchFlags:1.2.840.113556.1.4.803:=1))", base=self.names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs) index_config = "" for i in range (0, len(res)): index_attr = res[i]["lDAPDisplayName"][0] if index_attr == "objectGUID": index_attr = "entryUUID" index_config += "index " + index_attr + " eq\n" # generate serverids, ldap-urls and syncrepl-blocks for mmr hosts mmr_on_config = "" mmr_replicator_acl = "" mmr_serverids_config = "" mmr_syncrepl_schema_config = "" mmr_syncrepl_config_config = "" mmr_syncrepl_user_config = "" if self.ol_mmr_urls is not None: # For now, make these equal mmr_pass = self.ldapadminpass url_list=filter(None,self.ol_mmr_urls.split(' ')) if (len(url_list) == 1): url_list=filter(None,self.ol_mmr_urls.split(',')) mmr_on_config = "MirrorMode On" mmr_replicator_acl = " by dn=cn=replicator,cn=samba read" serverid=0 for url in url_list: serverid=serverid+1 mmr_serverids_config += read_and_sub_file(self.setup_path("mmr_serverids.conf"), { "SERVERID" : str(serverid), "LDAPSERVER" : url }) rid=serverid*10 rid=rid+1 mmr_syncrepl_schema_config += read_and_sub_file(self.setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), "MMRDN": self.names.schemadn, "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) rid=rid+1 mmr_syncrepl_config_config += read_and_sub_file(self.setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), "MMRDN": self.names.configdn, "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) rid=rid+1 mmr_syncrepl_user_config += read_and_sub_file(self.setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), "MMRDN": self.names.domaindn, "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass }) # OpenLDAP cn=config initialisation olc_syncrepl_config = "" olc_mmr_config = "" # if mmr = yes, generate cn=config-replication directives # and olc_seed.lif for the other mmr-servers if self.ol_mmr_urls is not None: serverid=0 olc_serverids_config = "" olc_syncrepl_seed_config = "" olc_mmr_config += read_and_sub_file(self.setup_path("olc_mmr.conf"),{}) rid=1000 for url in url_list: serverid=serverid+1 olc_serverids_config += read_and_sub_file(self.setup_path("olc_serverid.conf"), { "SERVERID" : str(serverid), "LDAPSERVER" : url }) rid=rid+1 olc_syncrepl_config += read_and_sub_file(self.setup_path("olc_syncrepl.conf"), { "RID" : str(rid), "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) olc_syncrepl_seed_config += read_and_sub_file(self.setup_path("olc_syncrepl_seed.conf"), { "RID" : str(rid), "LDAPSERVER" : url}) setup_file(self.setup_path("olc_seed.ldif"), self.paths.olcseedldif, {"OLC_SERVER_ID_CONF": olc_serverids_config, "OLC_PW": self.ldapadminpass, "OLC_SYNCREPL_CONF": olc_syncrepl_seed_config}) # end olc setup_file(self.setup_path("slapd.conf"), self.paths.slapdconf, {"DNSDOMAIN": self.names.dnsdomain, "LDAPDIR": self.paths.ldapdir, "DOMAINDN": self.names.domaindn, "CONFIGDN": self.names.configdn, "SCHEMADN": self.names.schemadn, "MEMBEROF_CONFIG": memberof_config, "MIRRORMODE": mmr_on_config, "REPLICATOR_ACL": mmr_replicator_acl, "MMR_SERVERIDS_CONFIG": mmr_serverids_config, "MMR_SYNCREPL_SCHEMA_CONFIG": mmr_syncrepl_schema_config, "MMR_SYNCREPL_CONFIG_CONFIG": mmr_syncrepl_config_config, "MMR_SYNCREPL_USER_CONFIG": mmr_syncrepl_user_config, "OLC_SYNCREPL_CONFIG": olc_syncrepl_config, "OLC_MMR_CONFIG": olc_mmr_config, "REFINT_CONFIG": refint_config, "INDEX_CONFIG": index_config, "NOSYNC": nosync_config}) setup_db_config(self.setup_path, os.path.join(self.paths.ldapdir, "db", "user")) setup_db_config(self.setup_path, os.path.join(self.paths.ldapdir, "db", "config")) setup_db_config(self.setup_path, os.path.join(self.paths.ldapdir, "db", "schema")) if not os.path.exists(os.path.join(self.paths.ldapdir, "db", "samba", "cn=samba")): os.makedirs(os.path.join(self.paths.ldapdir, "db", "samba", "cn=samba"), 0700) setup_file(self.setup_path("cn=samba.ldif"), os.path.join(self.paths.ldapdir, "db", "samba", "cn=samba.ldif"), { "UUID": str(uuid.uuid4()), "LDAPTIME": timestring(int(time.time()))} ) setup_file(self.setup_path("cn=samba-admin.ldif"), os.path.join(self.paths.ldapdir, "db", "samba", "cn=samba", "cn=samba-admin.ldif"), {"LDAPADMINPASS_B64": b64encode(self.ldapadminpass), "UUID": str(uuid.uuid4()), "LDAPTIME": timestring(int(time.time()))} ) if self.ol_mmr_urls is not None: setup_file(self.setup_path("cn=replicator.ldif"), os.path.join(self.paths.ldapdir, "db", "samba", "cn=samba", "cn=replicator.ldif"), {"MMR_PASSWORD_B64": b64encode(mmr_pass), "UUID": str(uuid.uuid4()), "LDAPTIME": timestring(int(time.time()))} ) mapping = "schema-map-openldap-2.3" backend_schema = "backend-schema.schema" backend_schema_data = self.schema.ldb.convert_schema_to_openldap("openldap", open(self.setup_path(mapping), 'r').read()) assert backend_schema_data is not None open(os.path.join(self.paths.ldapdir, backend_schema), 'w').write(backend_schema_data) # now we generate the needed strings to start slapd automatically, # first ldapi_uri... if self.ldap_backend_extra_port is not None: # When we use MMR, we can't use 0.0.0.0 as it uses the name # specified there as part of it's clue as to it's own name, # and not to replicate to itself if self.ol_mmr_urls is None: server_port_string = "ldap://0.0.0.0:%d" % self.ldap_backend_extra_port else: server_port_string = "ldap://" + self.names.hostname + "." + self.names.dnsdomain +":%d" % self.ldap_backend_extra_port else: server_port_string = "" # Prepare the 'result' information - the commands to return in particular self.slapd_provision_command = [self.slapd_path] self.slapd_provision_command.append("-F" + self.paths.olcdir) self.slapd_provision_command.append("-h") # copy this command so we have two version, one with -d0 and only ldapi, and one with all the listen commands self.slapd_command = list(self.slapd_provision_command) self.slapd_provision_command.append(self.ldapi_uri) self.slapd_provision_command.append("-d0") uris = self.ldapi_uri if server_port_string is not "": uris = uris + " " + server_port_string 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 if self.ldap_dryrun_mode: sys.exit(0) # Finally, convert the configuration into cn=config style! if not os.path.isdir(self.paths.olcdir): os.makedirs(self.paths.olcdir, 0770) retcode = subprocess.call([self.slapd_path, "-Ttest", "-f", self.paths.slapdconf, "-F", self.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... # # if retcode != 0: # raise ProvisioningError("conversion from slapd.conf to cn=config failed") if not os.path.exists(os.path.join(self.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(self.paths.slapdconf)