def __init__(self, domain_sid, invocationid=None, schemadn=None, files=None, override_prefixmap=None, additional_prefixmap=None): from samba.provision import setup_path """Load schema for the SamDB from the AD schema files and samba4_schema.ldif :param samdb: Load a schema into a SamDB. :param schemadn: DN of the schema Returns the schema data loaded, to avoid double-parsing when then needing to add it to the db """ self.schemadn = schemadn # We need to have the am_rodc=False just to keep some warnings quiet - # this isn't a real SAM, so it's meaningless. self.ldb = SamDB(global_schema=False, am_rodc=False) if invocationid is not None: self.ldb.set_invocation_id(invocationid) self.schema_data = read_ms_schema( # setup_path('ad-schema/MS-AD_Schema_2K8_R2_Attributes.txt'), # setup_path('ad-schema/MS-AD_Schema_2K8_R2_Classes.txt'), # setup_path('ad-schema/Attributes_for_AD_DS__Windows_Server_2012.ldf'), # setup_path('ad-schema/Classes_for_AD_DS__Windows_Server_2012.ldf')) setup_path('ad-schema/AD_DS_Attributes__Windows_Server_2012_R2.ldf'), setup_path('ad-schema/AD_DS_Classes__Windows_Server_2012_R2.ldf')) if files is not None: for file in files: self.schema_data += open(file, 'r').read() self.schema_data = substitute_var(self.schema_data, {"SCHEMADN": schemadn}) check_all_substituted(self.schema_data) self.schema_dn_modify = read_and_sub_file( setup_path("provision_schema_basedn_modify.ldif"), {"SCHEMADN": schemadn}) descr = b64encode(get_schema_descriptor(domain_sid)) self.schema_dn_add = read_and_sub_file( setup_path("provision_schema_basedn.ldif"), {"SCHEMADN": schemadn, "DESCRIPTOR": descr}) if override_prefixmap is not None: self.prefixmap_data = override_prefixmap else: self.prefixmap_data = open(setup_path("prefixMap.txt"), 'r').read() if additional_prefixmap is not None: for map in additional_prefixmap: self.prefixmap_data += "%s\n" % map self.prefixmap_data = b64encode(self.prefixmap_data) # We don't actually add this ldif, just parse it prefixmap_ldif = "dn: %s\nprefixMap:: %s\n\n" % (self.schemadn, self.prefixmap_data) self.set_from_ldif(prefixmap_ldif, self.schema_data, self.schemadn)
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, 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 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 __init__(self, domain_sid, invocationid=None, schemadn=None, files=None, override_prefixmap=None, additional_prefixmap=None, base_schema=None): from samba.provision import setup_path """Load schema for the SamDB from the AD schema files and samba4_schema.ldif :param samdb: Load a schema into a SamDB. :param schemadn: DN of the schema Returns the schema data loaded, to avoid double-parsing when then needing to add it to the db """ if base_schema is None: base_schema = Schema.default_base_schema() self.base_schema = base_schema self.schemadn = schemadn # We need to have the am_rodc=False just to keep some warnings quiet - # this isn't a real SAM, so it's meaningless. self.ldb = SamDB(global_schema=False, am_rodc=False) if invocationid is not None: self.ldb.set_invocation_id(invocationid) self.schema_data = read_ms_schema( setup_path('ad-schema/%s' % Schema.base_schemas[base_schema][0]), setup_path('ad-schema/%s' % Schema.base_schemas[base_schema][1])) if files is not None: for file in files: self.schema_data += open(file, 'rb').read() self.schema_data = substitute_var(self.schema_data, {"SCHEMADN": schemadn}) check_all_substituted(self.schema_data) schema_version = str(Schema.get_version(base_schema)) self.schema_dn_modify = read_and_sub_file( setup_path("provision_schema_basedn_modify.ldif"), { "SCHEMADN": schemadn, "OBJVERSION": schema_version }) descr = b64encode(get_schema_descriptor(domain_sid)).decode('utf8') self.schema_dn_add = read_and_sub_file( setup_path("provision_schema_basedn.ldif"), { "SCHEMADN": schemadn, "DESCRIPTOR": descr }) if override_prefixmap is not None: self.prefixmap_data = override_prefixmap else: self.prefixmap_data = open(setup_path("prefixMap.txt"), 'rb').read() if additional_prefixmap is not None: for map in additional_prefixmap: self.prefixmap_data += "%s\n" % map self.prefixmap_data = b64encode(self.prefixmap_data).decode('utf8') # We don't actually add this ldif, just parse it prefixmap_ldif = "dn: %s\nprefixMap:: %s\n\n" % (self.schemadn, self.prefixmap_data) self.set_from_ldif(prefixmap_ldif, self.schema_data, self.schemadn)
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 __init__(self, domain_sid, invocationid=None, schemadn=None, files=None, override_prefixmap=None, additional_prefixmap=None, base_schema=None): from samba.provision import setup_path """Load schema for the SamDB from the AD schema files and samba4_schema.ldif :param samdb: Load a schema into a SamDB. :param schemadn: DN of the schema Returns the schema data loaded, to avoid double-parsing when then needing to add it to the db """ if base_schema is None: base_schema = Schema.default_base_schema() self.base_schema = base_schema self.schemadn = schemadn # We need to have the am_rodc=False just to keep some warnings quiet - # this isn't a real SAM, so it's meaningless. self.ldb = SamDB(global_schema=False, am_rodc=False) if invocationid is not None: self.ldb.set_invocation_id(invocationid) self.schema_data = read_ms_schema( setup_path('ad-schema/%s' % Schema.base_schemas[base_schema][0]), setup_path('ad-schema/%s' % Schema.base_schemas[base_schema][1])) if files is not None: for file in files: self.schema_data += open(file, 'r').read() self.schema_data = substitute_var(self.schema_data, {"SCHEMADN": schemadn}) check_all_substituted(self.schema_data) schema_version = str(Schema.get_version(base_schema)) self.schema_dn_modify = read_and_sub_file( setup_path("provision_schema_basedn_modify.ldif"), {"SCHEMADN": schemadn, "OBJVERSION" : schema_version}) descr = b64encode(get_schema_descriptor(domain_sid)).decode('utf8') self.schema_dn_add = read_and_sub_file( setup_path("provision_schema_basedn.ldif"), {"SCHEMADN": schemadn, "DESCRIPTOR": descr}) if override_prefixmap is not None: self.prefixmap_data = override_prefixmap else: self.prefixmap_data = open(setup_path("prefixMap.txt"), 'r').read() if additional_prefixmap is not None: for map in additional_prefixmap: self.prefixmap_data += "%s\n" % map self.prefixmap_data = b64encode(self.prefixmap_data).decode('utf8') # We don't actually add this ldif, just parse it prefixmap_ldif = "dn: %s\nprefixMap:: %s\n\n" % (self.schemadn, self.prefixmap_data) self.set_from_ldif(prefixmap_ldif, self.schema_data, self.schemadn)