def __init__(self, backend_type, paths=None, lp=None, credentials=None, names=None, logger=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_dryrun_mode=False, ol_mmr_urls=None, nosync=False, ldap_backend_forced_uri=None): from samba.provision import setup_path super(OpenLDAPBackend, self).__init__(backend_type=backend_type, paths=paths, lp=lp, names=names, logger=logger, domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.ol_mmr_urls = ol_mmr_urls self.nosync = nosync self.slapdconf = os.path.join(self.ldapdir, "slapd.conf") self.modulesconf = os.path.join(self.ldapdir, "modules.conf") self.memberofconf = os.path.join(self.ldapdir, "memberof.conf") self.olmmrserveridsconf = os.path.join(self.ldapdir, "mmr_serverids.conf") self.olmmrsyncreplconf = os.path.join(self.ldapdir, "mmr_syncrepl.conf") self.olcdir = os.path.join(self.ldapdir, "slapd.d") self.olcseedldif = os.path.join(self.ldapdir, "olc_seed.ldif") self.schema = Schema(self.domainsid, schemadn=self.names.schemadn, files=[ setup_path("schema_samba4.ldif")])
def __init__(self, backend_type, paths=None, lp=None, names=None, logger=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_backend_forced_uri=None, ldap_dryrun_mode=False, root=None, setup_ds_path=None): from samba.provision import setup_path super(FDSBackend, self).__init__(backend_type=backend_type, paths=paths, lp=lp, names=names, logger=logger, domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.root = root self.setup_ds_path = setup_ds_path self.ldap_instance = self.names.netbiosname.lower() self.sambadn = "CN=Samba" self.fedoradsinf = os.path.join(self.ldapdir, "fedorads.inf") self.partitions_ldif = os.path.join(self.ldapdir, "fedorads-partitions.ldif") self.sasl_ldif = os.path.join(self.ldapdir, "fedorads-sasl.ldif") self.dna_ldif = os.path.join(self.ldapdir, "fedorads-dna.ldif") self.pam_ldif = os.path.join(self.ldapdir, "fedorads-pam.ldif") self.refint_ldif = os.path.join(self.ldapdir, "fedorads-refint.ldif") self.linked_attrs_ldif = os.path.join(self.ldapdir, "fedorads-linked-attributes.ldif") self.index_ldif = os.path.join(self.ldapdir, "fedorads-index.ldif") self.samba_ldif = os.path.join(self.ldapdir, "fedorads-samba.ldif") self.samba3_schema = setup_path( "../../examples/LDAP/samba.schema") self.samba3_ldif = os.path.join(self.ldapdir, "samba3.ldif") self.retcode = subprocess.call(["bin/oLschema2ldif", "-I", self.samba3_schema, "-O", self.samba3_ldif, "-b", self.names.domaindn], close_fds=True, shell=False) if self.retcode != 0: raise Exception("Unable to convert Samba 3 schema.") self.schema = Schema( self.domainsid, schemadn=self.names.schemadn, files=[setup_path("schema_samba4.ldif"), self.samba3_ldif], additional_prefixmap=["1000:1.3.6.1.4.1.7165.2.1", "1001:1.3.6.1.4.1.7165.2.2"])
def __init__(self, backend_type, paths=None, lp=None, credentials=None, names=None, logger=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_dryrun_mode=False, ol_mmr_urls=None, nosync=False, ldap_backend_forced_uri=None): from samba.provision import setup_path super(OpenLDAPBackend, self).__init__( backend_type=backend_type, paths=paths, lp=lp, names=names, logger=logger, domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.ol_mmr_urls = ol_mmr_urls self.nosync = nosync self.slapdconf = os.path.join(self.ldapdir, "slapd.conf") self.modulesconf = os.path.join(self.ldapdir, "modules.conf") self.memberofconf = os.path.join(self.ldapdir, "memberof.conf") self.olmmrserveridsconf = os.path.join(self.ldapdir, "mmr_serverids.conf") self.olmmrsyncreplconf = os.path.join(self.ldapdir, "mmr_syncrepl.conf") self.olcdir = os.path.join(self.ldapdir, "slapd.d") self.olcseedldif = os.path.join(self.ldapdir, "olc_seed.ldif") self.schema = Schema(self.domainsid, schemadn=self.names.schemadn, files=[ setup_path("schema_samba4.ldif")])
def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None, names=None, message=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_dryrun_mode=False, root=None, setup_ds_path=None): super(FDSBackend, self).__init__( backend_type=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, ldap_dryrun_mode=ldap_dryrun_mode) self.root = root self.setup_ds_path = setup_ds_path self.sambadn = "CN=Samba" self.fedoradsinf = os.path.join(paths.ldapdir, "fedorads.inf") self.partitions_ldif = os.path.join(paths.ldapdir, "fedorads-partitions.ldif") self.sasl_ldif = os.path.join(paths.ldapdir, "fedorads-sasl.ldif") self.dna_ldif = os.path.join(paths.ldapdir, "fedorads-dna.ldif") self.pam_ldif = os.path.join(paths.ldapdir, "fedorads-pam.ldif") self.refint_ldif = os.path.join(paths.ldapdir, "fedorads-refint.ldif") self.linked_attrs_ldif = os.path.join(paths.ldapdir, "fedorads-linked-attributes.ldif") self.index_ldif = os.path.join(paths.ldapdir, "fedorads-index.ldif") self.samba_ldif = os.path.join(paths.ldapdir, "fedorads-samba.ldif") self.samba3_schema = self.setup_path("../../examples/LDAP/samba.schema") self.samba3_ldif = os.path.join(self.paths.ldapdir, "samba3.ldif") self.retcode = subprocess.call(["bin/oLschema2ldif", "-H", "NONE", "-I", self.samba3_schema, "-O", self.samba3_ldif, "-b", self.names.domaindn], close_fds=True, shell=False) if self.retcode != 0: raise Exception("Unable to convert Samba 3 schema.") self.schema = Schema( self.setup_path, self.domainsid, schemadn=self.names.schemadn, serverdn=self.names.serverdn, 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 __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None, names=None, message=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_dryrun_mode=False, ol_mmr_urls=None, nosync=False): super(OpenLDAPBackend, self).__init__( backend_type=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, ldap_dryrun_mode=ldap_dryrun_mode) self.ol_mmr_urls = ol_mmr_urls self.nosync = nosync self.schema = Schema( self.setup_path, self.domainsid, schemadn=self.names.schemadn, serverdn=self.names.serverdn, files=[setup_path("schema_samba4.ldif")]);
def create_tmp_samdb(ctx): '''create a temporary samdb object for schema queries''' ctx.tmp_schema = Schema(security.dom_sid(ctx.domsid), schemadn=ctx.schema_dn) ctx.tmp_samdb = SamDB(session_info=system_session(), url=None, auto_connect=False, credentials=ctx.creds, lp=ctx.lp, global_schema=False, am_rodc=False) ctx.tmp_samdb.set_schema(ctx.tmp_schema)
def setUp(self): super(SamDBTestCase, self).setUp() invocationid = str(uuid.uuid4()) domaindn = "DC=COM,DC=EXAMPLE" self.domaindn = domaindn configdn = "CN=Configuration," + domaindn schemadn = "CN=Schema," + configdn domainguid = str(uuid.uuid4()) policyguid = DEFAULT_POLICY_GUID domainsid = security.random_sid() path = os.path.join(self.tempdir, "samdb.ldb") session_info = system_session() hostname = "foo" domain = "EXAMPLE" dnsdomain = "example.com" serverrole = "domain controller" policyguid_dc = DEFAULT_DC_POLICY_GUID smbconf = os.path.join(self.tempdir, "smb.conf") make_smbconf(smbconf, hostname, domain, dnsdomain, serverrole, self.tempdir) self.lp = param.LoadParm() self.lp.load(smbconf) names = guess_names(lp=self.lp, hostname=hostname, domain=domain, dnsdomain=dnsdomain, serverrole=serverrole, domaindn=self.domaindn, configdn=configdn, schemadn=schemadn) paths = provision_paths_from_lp(self.lp, names.dnsdomain) logger = logging.getLogger("provision") provision_backend = ProvisionBackend("ldb", paths=paths, lp=self.lp, credentials=None, names=names, logger=logger) schema = Schema(domainsid, invocationid=invocationid, schemadn=names.schemadn, serverdn=names.serverdn, am_rodc=False) self.samdb = setup_samdb(path, session_info, provision_backend, self.lp, names, logger, domainsid, domainguid, policyguid, policyguid_dc, False, "secret", "secret", "secret", invocationid, "secret", None, "domain controller", schema=schema)
class FDSBackend(LDAPBackend): def __init__(self, backend_type, paths=None, lp=None, names=None, logger=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_backend_forced_uri=None, ldap_dryrun_mode=False, root=None, setup_ds_path=None): from samba.provision import setup_path super(FDSBackend, self).__init__(backend_type=backend_type, paths=paths, lp=lp, names=names, logger=logger, domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.root = root self.setup_ds_path = setup_ds_path self.ldap_instance = self.names.netbiosname.lower() self.sambadn = "CN=Samba" self.fedoradsinf = os.path.join(self.ldapdir, "fedorads.inf") self.partitions_ldif = os.path.join(self.ldapdir, "fedorads-partitions.ldif") self.sasl_ldif = os.path.join(self.ldapdir, "fedorads-sasl.ldif") self.dna_ldif = os.path.join(self.ldapdir, "fedorads-dna.ldif") self.pam_ldif = os.path.join(self.ldapdir, "fedorads-pam.ldif") self.refint_ldif = os.path.join(self.ldapdir, "fedorads-refint.ldif") self.linked_attrs_ldif = os.path.join( self.ldapdir, "fedorads-linked-attributes.ldif") self.index_ldif = os.path.join(self.ldapdir, "fedorads-index.ldif") self.samba_ldif = os.path.join(self.ldapdir, "fedorads-samba.ldif") self.samba3_schema = setup_path("../../examples/LDAP/samba.schema") self.samba3_ldif = os.path.join(self.ldapdir, "samba3.ldif") self.retcode = subprocess.call([ "bin/oLschema2ldif", "-I", self.samba3_schema, "-O", self.samba3_ldif, "-b", self.names.domaindn ], close_fds=True, shell=False) if self.retcode != 0: raise Exception("Unable to convert Samba 3 schema.") self.schema = Schema( self.domainsid, schemadn=self.names.schemadn, files=[setup_path("schema_samba4.ldif"), self.samba3_ldif], additional_prefixmap=[ "1000:1.3.6.1.4.1.7165.2.1", "1001:1.3.6.1.4.1.7165.2.2" ]) 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 post_setup(self): ldapi_db = Ldb(self.ldap_uri, credentials=self.credentials) # configure in-directory access control on Fedora DS via the aci # attribute (over a direct ldapi:// socket) aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % self.sambadn m = ldb.Message() m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci") for dnstring in (self.names.domaindn, self.names.configdn, self.names.schemadn): m.dn = ldb.Dn(ldapi_db, dnstring) ldapi_db.modify(m) return LDAPBackendResult(self.credentials, self.slapd_command_escaped, self.ldapdir)
class OpenLDAPBackend(LDAPBackend): def __init__(self, backend_type, paths=None, lp=None, credentials=None, names=None, logger=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_dryrun_mode=False, ol_mmr_urls=None, nosync=False, ldap_backend_forced_uri=None): from samba.provision import setup_path super(OpenLDAPBackend, self).__init__(backend_type=backend_type, paths=paths, lp=lp, names=names, logger=logger, domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.ol_mmr_urls = ol_mmr_urls self.nosync = nosync self.slapdconf = os.path.join(self.ldapdir, "slapd.conf") self.modulesconf = os.path.join(self.ldapdir, "modules.conf") self.memberofconf = os.path.join(self.ldapdir, "memberof.conf") self.olmmrserveridsconf = os.path.join(self.ldapdir, "mmr_serverids.conf") self.olmmrsyncreplconf = os.path.join(self.ldapdir, "mmr_syncrepl.conf") self.olcdir = os.path.join(self.ldapdir, "slapd.d") self.olcseedldif = os.path.join(self.ldapdir, "olc_seed.ldif") self.schema = Schema(self.domainsid, schemadn=self.names.schemadn, files=[setup_path("schema_samba4.ldif")]) def setup_db_dir(self, dbdir): """Create a database directory. :param dbdir: Database directory. """ if not os.path.exists(dbdir): os.makedirs(dbdir, 0o700) 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()
class FDSBackend(LDAPBackend): def __init__(self, backend_type, paths=None, lp=None, names=None, logger=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_backend_forced_uri=None, ldap_dryrun_mode=False, root=None, setup_ds_path=None): from samba.provision import setup_path super(FDSBackend, self).__init__(backend_type=backend_type, paths=paths, lp=lp, names=names, logger=logger, domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.root = root self.setup_ds_path = setup_ds_path self.ldap_instance = self.names.netbiosname.lower() self.sambadn = "CN=Samba" self.fedoradsinf = os.path.join(self.ldapdir, "fedorads.inf") self.partitions_ldif = os.path.join(self.ldapdir, "fedorads-partitions.ldif") self.sasl_ldif = os.path.join(self.ldapdir, "fedorads-sasl.ldif") self.dna_ldif = os.path.join(self.ldapdir, "fedorads-dna.ldif") self.pam_ldif = os.path.join(self.ldapdir, "fedorads-pam.ldif") self.refint_ldif = os.path.join(self.ldapdir, "fedorads-refint.ldif") self.linked_attrs_ldif = os.path.join(self.ldapdir, "fedorads-linked-attributes.ldif") self.index_ldif = os.path.join(self.ldapdir, "fedorads-index.ldif") self.samba_ldif = os.path.join(self.ldapdir, "fedorads-samba.ldif") self.samba3_schema = setup_path( "../../examples/LDAP/samba.schema") self.samba3_ldif = os.path.join(self.ldapdir, "samba3.ldif") self.retcode = subprocess.call(["bin/oLschema2ldif", "-I", self.samba3_schema, "-O", self.samba3_ldif, "-b", self.names.domaindn], close_fds=True, shell=False) if self.retcode != 0: raise Exception("Unable to convert Samba 3 schema.") self.schema = Schema( self.domainsid, schemadn=self.names.schemadn, files=[setup_path("schema_samba4.ldif"), self.samba3_ldif], additional_prefixmap=["1000:1.3.6.1.4.1.7165.2.1", "1001:1.3.6.1.4.1.7165.2.2"]) 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 post_setup(self): ldapi_db = Ldb(self.ldap_uri, credentials=self.credentials) # configure in-directory access control on Fedora DS via the aci # attribute (over a direct ldapi:// socket) aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % self.sambadn m = ldb.Message() m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci") for dnstring in (self.names.domaindn, self.names.configdn, self.names.schemadn): m.dn = ldb.Dn(ldapi_db, dnstring) ldapi_db.modify(m) return LDAPBackendResult(self.credentials, self.slapd_command_escaped, self.ldapdir)
class OpenLDAPBackend(LDAPBackend): def __init__(self, backend_type, paths=None, lp=None, credentials=None, names=None, logger=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_dryrun_mode=False, ol_mmr_urls=None, nosync=False, ldap_backend_forced_uri=None): from samba.provision import setup_path super(OpenLDAPBackend, self).__init__( backend_type=backend_type, paths=paths, lp=lp, names=names, logger=logger, domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.ol_mmr_urls = ol_mmr_urls self.nosync = nosync self.slapdconf = os.path.join(self.ldapdir, "slapd.conf") self.modulesconf = os.path.join(self.ldapdir, "modules.conf") self.memberofconf = os.path.join(self.ldapdir, "memberof.conf") self.olmmrserveridsconf = os.path.join(self.ldapdir, "mmr_serverids.conf") self.olmmrsyncreplconf = os.path.join(self.ldapdir, "mmr_syncrepl.conf") self.olcdir = os.path.join(self.ldapdir, "slapd.d") self.olcseedldif = os.path.join(self.ldapdir, "olc_seed.ldif") self.schema = Schema(self.domainsid, schemadn=self.names.schemadn, files=[ setup_path("schema_samba4.ldif")]) def setup_db_dir(self, dbdir): """Create a database directory. :param dbdir: Database directory. """ if not os.path.exists(dbdir): os.makedirs(dbdir, 0o700) 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()
class OpenLDAPBackend(LDAPBackend): def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None, names=None, message=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_dryrun_mode=False, ol_mmr_urls=None, nosync=False): super(OpenLDAPBackend, self).__init__( backend_type=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, ldap_dryrun_mode=ldap_dryrun_mode) self.ol_mmr_urls = ol_mmr_urls self.nosync = nosync self.schema = Schema( self.setup_path, self.domainsid, schemadn=self.names.schemadn, serverdn=self.names.serverdn, files=[setup_path("schema_samba4.ldif")]); 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)