1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00

s4-provision Add initial support for joining as a new subdomain

To do this we need to reorganise a lot of the provision code, so that
we can create the framework for the inbound replicaton of the config
and schema partitions and then add in the new subdomain locally.

Andrew Bartlett
This commit is contained in:
Andrew Bartlett 2011-08-24 15:39:51 +10:00
parent 6d9b0ee26e
commit 6635bb70d3
7 changed files with 457 additions and 326 deletions

View File

@ -27,9 +27,10 @@ import ldb, samba, sys, os, uuid
from samba.ndr import ndr_pack
from samba.dcerpc import security, drsuapi, misc, nbt
from samba.credentials import Credentials, DONT_USE_KERBEROS
from samba.provision import secretsdb_self_join, provision, FILL_DRS
from samba.provision import secretsdb_self_join, provision, provision_fill, FILL_DRS, FILL_SUBDOMAIN
from samba.schema import Schema
from samba.net import Net
from samba.dcerpc import security
import logging
import talloc
@ -82,9 +83,6 @@ class dc_join(object):
ctx.domsid = ctx.samdb.get_domain_sid()
ctx.domain_name = ctx.get_domain_name()
lp.set("workgroup", ctx.domain_name)
print("workgroup is %s" % ctx.domain_name)
ctx.dc_ntds_dn = ctx.get_dsServiceName()
ctx.dc_dnsHostName = ctx.get_dnsHostName()
ctx.behavior_version = ctx.get_behavior_version()
@ -105,9 +103,6 @@ class dc_join(object):
ctx.dnshostname = "%s.%s" % (ctx.myname, ctx.dnsdomain)
ctx.realm = ctx.dnsdomain
lp.set("realm", ctx.realm)
print("realm is %s" % ctx.realm)
ctx.acct_dn = "CN=%s,OU=Domain Controllers,%s" % (ctx.myname, ctx.base_dn)
@ -314,23 +309,24 @@ class dc_join(object):
def join_add_objects(ctx):
'''add the various objects needed for the join'''
print "Adding %s" % ctx.acct_dn
rec = {
"dn" : ctx.acct_dn,
"objectClass": "computer",
"displayname": ctx.samname,
"samaccountname" : ctx.samname,
"userAccountControl" : str(ctx.userAccountControl | samba.dsdb.UF_ACCOUNTDISABLE),
"dnshostname" : ctx.dnshostname}
if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2008:
rec['msDS-SupportedEncryptionTypes'] = str(samba.dsdb.ENC_ALL_TYPES)
if ctx.managedby:
rec["managedby"] = ctx.managedby
if ctx.never_reveal_sid:
rec["msDS-NeverRevealGroup"] = ctx.never_reveal_sid
if ctx.reveal_sid:
rec["msDS-RevealOnDemandGroup"] = ctx.reveal_sid
ctx.samdb.add(rec)
if ctx.acct_dn:
print "Adding %s" % ctx.acct_dn
rec = {
"dn" : ctx.acct_dn,
"objectClass": "computer",
"displayname": ctx.samname,
"samaccountname" : ctx.samname,
"userAccountControl" : str(ctx.userAccountControl | samba.dsdb.UF_ACCOUNTDISABLE),
"dnshostname" : ctx.dnshostname}
if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2008:
rec['msDS-SupportedEncryptionTypes'] = str(samba.dsdb.ENC_ALL_TYPES)
if ctx.managedby:
rec["managedby"] = ctx.managedby
if ctx.never_reveal_sid:
rec["msDS-NeverRevealGroup"] = ctx.never_reveal_sid
if ctx.reveal_sid:
rec["msDS-RevealOnDemandGroup"] = ctx.reveal_sid
ctx.samdb.add(rec)
if ctx.krbtgt_dn:
ctx.add_krbtgt_account()
@ -342,8 +338,11 @@ class dc_join(object):
"systemFlags" : str(samba.dsdb.SYSTEM_FLAG_CONFIG_ALLOW_RENAME |
samba.dsdb.SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE |
samba.dsdb.SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE),
"serverReference" : ctx.acct_dn,
"dnsHostName" : ctx.dnshostname}
if ctx.acct_dn:
rec["serverReference"] = ctx.acct_dn
ctx.samdb.add(rec)
# FIXME: the partition (NC) assignment has to be made dynamic
@ -388,7 +387,7 @@ class dc_join(object):
"fromServer" : ctx.dc_ntds_dn}
ctx.samdb.add(rec)
if ctx.topology_dn:
if ctx.topology_dn and ctx.acct_dn:
print "Adding %s" % ctx.topology_dn
rec = {
"dn" : ctx.topology_dn,
@ -397,31 +396,32 @@ class dc_join(object):
"serverReference" : ctx.ntds_dn}
ctx.samdb.add(rec)
print "Adding SPNs to %s" % ctx.acct_dn
m = ldb.Message()
m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn)
for i in range(len(ctx.SPNs)):
ctx.SPNs[i] = ctx.SPNs[i].replace("$NTDSGUID", str(ctx.ntds_guid))
m["servicePrincipalName"] = ldb.MessageElement(ctx.SPNs,
ldb.FLAG_MOD_ADD,
"servicePrincipalName")
ctx.samdb.modify(m)
if ctx.acct_dn:
print "Adding SPNs to %s" % ctx.acct_dn
m = ldb.Message()
m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn)
for i in range(len(ctx.SPNs)):
ctx.SPNs[i] = ctx.SPNs[i].replace("$NTDSGUID", str(ctx.ntds_guid))
m["servicePrincipalName"] = ldb.MessageElement(ctx.SPNs,
ldb.FLAG_MOD_ADD,
"servicePrincipalName")
ctx.samdb.modify(m)
print "Setting account password for %s" % ctx.samname
ctx.samdb.setpassword("(&(objectClass=user)(sAMAccountName=%s))" % ldb.binary_encode(ctx.samname),
ctx.acct_pass,
force_change_at_next_login=False,
username=ctx.samname)
res = ctx.samdb.search(base=ctx.acct_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-keyVersionNumber"])
ctx.key_version_number = int(res[0]["msDS-keyVersionNumber"][0])
print "Setting account password for %s" % ctx.samname
ctx.samdb.setpassword("(&(objectClass=user)(sAMAccountName=%s))" % ldb.binary_encode(ctx.samname),
ctx.acct_pass,
force_change_at_next_login=False,
username=ctx.samname)
res = ctx.samdb.search(base=ctx.acct_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-keyVersionNumber"])
ctx.key_version_number = int(res[0]["msDS-keyVersionNumber"][0])
print("Enabling account")
m = ldb.Message()
m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn)
m["userAccountControl"] = ldb.MessageElement(str(ctx.userAccountControl),
ldb.FLAG_MOD_REPLACE,
"userAccountControl")
ctx.samdb.modify(m)
print("Enabling account")
m = ldb.Message()
m.dn = ldb.Dn(ctx.samdb, ctx.acct_dn)
m["userAccountControl"] = ldb.MessageElement(str(ctx.userAccountControl),
ldb.FLAG_MOD_REPLACE,
"userAccountControl")
ctx.samdb.modify(m)
def join_provision(ctx):
'''provision the local SAM'''
@ -445,6 +445,24 @@ class dc_join(object):
ctx.local_samdb = presult.samdb
ctx.lp = presult.lp
ctx.paths = presult.paths
ctx.names = presult.names
def join_provision_own_domain(ctx):
'''provision the local SAM'''
print "Calling bare provision"
logger = logging.getLogger("provision")
logger.addHandler(logging.StreamHandler(sys.stdout))
secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp)
presult = provision_fill(ctx.local_samdb, secrets_ldb,
logger, ctx.names, ctx.paths, domainsid=security.dom_sid(ctx.domsid),
targetdir=ctx.targetdir, samdb_fill=FILL_SUBDOMAIN,
machinepass=ctx.acct_pass, serverrole="domain controller",
lp=ctx.lp)
print "Provision OK for domain %s" % ctx.names.dnsdomain
def join_replicate(ctx):
@ -478,9 +496,10 @@ class dc_join(object):
repl.replicate(ctx.config_dn, source_dsa_invocation_id,
destination_dsa_guid, rodc=ctx.RODC,
replica_flags=ctx.replica_flags)
repl.replicate(ctx.base_dn, source_dsa_invocation_id,
destination_dsa_guid, rodc=ctx.RODC,
replica_flags=ctx.domain_replica_flags)
if not ctx.subdomain:
repl.replicate(ctx.base_dn, source_dsa_invocation_id,
destination_dsa_guid, rodc=ctx.RODC,
replica_flags=ctx.domain_replica_flags)
if ctx.RODC:
repl.replicate(ctx.acct_dn, source_dsa_invocation_id,
destination_dsa_guid,
@ -526,7 +545,10 @@ class dc_join(object):
ctx.join_add_objects()
ctx.join_provision()
ctx.join_replicate()
ctx.join_finalise()
if ctx.subdomain:
ctx.join_provision_own_domain()
else:
ctx.join_finalise()
except Exception:
print "Join failed - cleaning up"
ctx.cleanup_old_join()
@ -539,6 +561,12 @@ def join_RODC(server=None, creds=None, lp=None, site=None, netbios_name=None,
ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, domain)
lp.set("workgroup", ctx.domain_name)
print("workgroup is %s" % ctx.domain_name)
lp.set("realm", ctx.realm)
print("realm is %s" % ctx.realm)
ctx.krbtgt_dn = "CN=krbtgt_%s,CN=Users,%s" % (ctx.myname, ctx.base_dn)
# setup some defaults for accounts that should be replicated to this RODC
@ -584,6 +612,12 @@ def join_DC(server=None, creds=None, lp=None, site=None, netbios_name=None,
"""join as a DC"""
ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, domain)
lp.set("workgroup", ctx.domain_name)
print("workgroup is %s" % ctx.domain_name)
lp.set("realm", ctx.realm)
print("realm is %s" % ctx.realm)
ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION
ctx.SPNs.append('E3514235-4B06-11D1-AB04-00C04FC2DCD2/$NTDSGUID/%s' % ctx.dnsdomain)
@ -600,3 +634,31 @@ def join_DC(server=None, creds=None, lp=None, site=None, netbios_name=None,
ctx.do_join()
print "Joined domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid)
def join_subdomain(server=None, creds=None, lp=None, site=None, netbios_name=None,
targetdir=None, parent_domain=None, dnsdomain=None, netbios_domain=None):
"""join as a DC"""
ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, parent_domain)
ctx.subdomain = True
ctx.domain_name = netbios_domain
ctx.realm = dnsdomain
ctx.dnsdomain = dnsdomain
ctx.base_dn = samba.dn_from_dns_name(dnsdomain)
ctx.domsid = str(security.random_sid())
ctx.acct_dn = None
ctx.dnshostname = "%s.%s" % (ctx.myname, ctx.dnsdomain)
ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION
ctx.SPNs.append('E3514235-4B06-11D1-AB04-00C04FC2DCD2/$NTDSGUID/%s' % ctx.dnsdomain)
ctx.secure_channel_type = misc.SEC_CHAN_BDC
ctx.replica_flags = (drsuapi.DRSUAPI_DRS_WRIT_REP |
drsuapi.DRSUAPI_DRS_INIT_SYNC |
drsuapi.DRSUAPI_DRS_PER_SYNC |
drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS |
drsuapi.DRSUAPI_DRS_NEVER_SYNCED)
ctx.domain_replica_flags = ctx.replica_flags
ctx.do_join()
print "Created domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid)

View File

@ -31,7 +31,7 @@ import logging
from samba import Ldb
from samba.net import Net, LIBNET_JOIN_AUTOMATIC
from samba.dcerpc.misc import SEC_CHAN_WKSTA
from samba.join import join_RODC, join_DC
from samba.join import join_RODC, join_DC, join_subdomain
from samba.auth import system_session
from samba.samdb import SamDB
from samba.dcerpc.samr import DOMAIN_PASSWORD_COMPLEX, DOMAIN_PASSWORD_STORE_CLEARTEXT
@ -76,12 +76,13 @@ class cmd_domain_export_keytab(Command):
class cmd_domain_join(Command):
"""Joins domain as either member or backup domain controller *"""
synopsis = "%prog domain join <dnsdomain> [DC|RODC|MEMBER] [options]"
synopsis = "%prog domain join <dnsdomain> [DC|RODC|MEMBER|SUBDOMAIN] [options]"
takes_options = [
Option("--server", help="DC to join", type=str),
Option("--site", help="site to join", type=str),
Option("--targetdir", help="where to store provision", type=str),
Option("--parent-domain", help="parent domain to create subdomain under", type=str),
Option("--domain-critical-only",
help="only replicate critical domain objects",
action="store_true"),
@ -91,7 +92,7 @@ class cmd_domain_join(Command):
def run(self, domain, role=None, sambaopts=None, credopts=None,
versionopts=None, server=None, site=None, targetdir=None,
domain_critical_only=False):
domain_critical_only=False, parent_domain=None):
lp = sambaopts.get_loadparm()
creds = credopts.get_credentials(lp)
net = Net(creds, lp, server=credopts.ipaddress)
@ -121,6 +122,13 @@ class cmd_domain_join(Command):
site=site, netbios_name=netbios_name, targetdir=targetdir,
domain_critical_only=domain_critical_only)
return
elif role == "SUBDOMAIN":
netbios_domain = lp.get("workgroup")
if parent_domain is None:
parent_domain = ".".join(domain.split(".")[1:])
join_subdomain(server=server, creds=creds, lp=lp, dnsdomain=domain, parent_domain=parent_domain,
site=site, netbios_name=netbios_name, netbios_domain=netbios_domain, targetdir=targetdir)
return
else:
raise CommandError("Invalid role %s (possible values: MEMBER, DC, RODC)" % role)

View File

@ -438,6 +438,7 @@ class ProvisionResult(object):
self.lp = None
self.samdb = None
self.idmap = None
self.names = None
def check_install(lp, session_info, credentials):
@ -761,7 +762,7 @@ def make_smbconf(smbconf, hostname, domain, realm, serverrole,
def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid,
def setup_name_mappings(idmap, sid, root_uid, nobody_uid,
users_gid, wheel_gid):
"""setup reasonable name mappings for sam names to unix names.
@ -1064,7 +1065,7 @@ def setup_samdb_rootdse(samdb, names):
})
def setup_self_join(samdb, names, machinepass, dnspass,
def setup_self_join(samdb, names, fill, machinepass, dnspass,
domainsid, next_rid, invocationid,
policyguid, policyguid_dc, domainControllerFunctionality,
ntdsguid, dc_rid=None):
@ -1100,18 +1101,35 @@ def setup_self_join(samdb, names, machinepass, dnspass,
"DNSDOMAIN": names.dnsdomain,
"DOMAINDN": names.domaindn})
# add the NTDSGUID based SPNs
ntds_dn = "CN=NTDS Settings,%s" % names.serverdn
names.ntdsguid = samdb.searchone(basedn=ntds_dn, attribute="objectGUID",
expression="", scope=ldb.SCOPE_BASE)
assert isinstance(names.ntdsguid, str)
# If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
if fill == FILL_FULL:
setup_add_ldif(samdb, setup_path("provision_self_join_config.ldif"), {
"CONFIGDN": names.configdn,
"SCHEMADN": names.schemadn,
"DOMAINDN": names.domaindn,
"SERVERDN": names.serverdn,
"INVOCATIONID": invocationid,
"NETBIOSNAME": names.netbiosname,
"DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
"MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')),
"DOMAINSID": str(domainsid),
"DCRID": str(dc_rid),
"SAMBA_VERSION_STRING": version,
"NTDSGUID": ntdsguid_line,
"DOMAIN_CONTROLLER_FUNCTIONALITY": str(
domainControllerFunctionality)})
# Setup fSMORoleOwner entries to point at the newly created DC entry
setup_modify_ldif(samdb, setup_path("provision_self_join_modify_config.ldif"), {
"CONFIGDN": names.configdn,
"SCHEMADN": names.schemadn,
"DEFAULTSITE": names.sitename,
"SERVERDN": names.serverdn,
})
# Setup fSMORoleOwner entries to point at the newly created DC entry
setup_modify_ldif(samdb, setup_path("provision_self_join_modify.ldif"), {
"DOMAINDN": names.domaindn,
"CONFIGDN": names.configdn,
"SCHEMADN": names.schemadn,
"DEFAULTSITE": names.sitename,
"SERVERDN": names.serverdn,
"NETBIOSNAME": names.netbiosname,
"RIDALLOCATIONSTART": str(next_rid + 100),
@ -1174,40 +1192,13 @@ def create_default_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
def setup_samdb(path, session_info, provision_backend, lp, names,
logger, domainsid, domainguid, policyguid, policyguid_dc, fill,
adminpass, krbtgtpass, machinepass, invocationid, dnspass, ntdsguid,
serverrole, am_rodc=False, dom_for_fun_level=None, schema=None,
next_rid=None, dc_rid=None):
logger, fill, serverrole,
am_rodc=False, schema=None):
"""Setup a complete SAM Database.
:note: This will wipe the main SAM database file!
"""
if next_rid is None:
next_rid = 1000
# Provision does not make much sense values larger than 1000000000
# as the upper range of the rIDAvailablePool is 1073741823 and
# we don't want to create a domain that cannot allocate rids.
if next_rid < 1000 or next_rid > 1000000000:
error = "You want to run SAMBA 4 with a next_rid of %u, " % (next_rid)
error += "the valid range is %u-%u. The default is %u." % (
1000, 1000000000, 1000)
raise ProvisioningError(error)
# ATTENTION: Do NOT change these default values without discussion with the
# team and/or release manager. They have a big impact on the whole program!
domainControllerFunctionality = DS_DOMAIN_FUNCTION_2008_R2
if dom_for_fun_level is None:
dom_for_fun_level = DS_DOMAIN_FUNCTION_2003
if dom_for_fun_level > domainControllerFunctionality:
raise ProvisioningError("You want to run SAMBA 4 on a domain and forest function level which itself is higher than its actual DC function level (2008_R2). This won't work!")
domainFunctionality = dom_for_fun_level
forestFunctionality = dom_for_fun_level
# Also wipes the database
setup_samdb_partitions(path, logger=logger, lp=lp,
provision_backend=provision_backend, session_info=session_info,
@ -1235,8 +1226,42 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
# DB
samdb.connect(path)
if fill == FILL_DRS:
return samdb
return samdb
def fill_samdb(samdb, lp, names,
logger, domainsid, domainguid, policyguid, policyguid_dc, fill,
adminpass, krbtgtpass, machinepass, invocationid, dnspass, ntdsguid,
serverrole, am_rodc=False, dom_for_fun_level=None, schema=None,
next_rid=None, dc_rid=None):
if next_rid is None:
next_rid = 1000
# Provision does not make much sense values larger than 1000000000
# as the upper range of the rIDAvailablePool is 1073741823 and
# we don't want to create a domain that cannot allocate rids.
if next_rid < 1000 or next_rid > 1000000000:
error = "You want to run SAMBA 4 with a next_rid of %u, " % (next_rid)
error += "the valid range is %u-%u. The default is %u." % (
1000, 1000000000, 1000)
raise ProvisioningError(error)
# ATTENTION: Do NOT change these default values without discussion with the
# team and/or release manager. They have a big impact on the whole program!
domainControllerFunctionality = DS_DOMAIN_FUNCTION_2008_R2
if dom_for_fun_level is None:
dom_for_fun_level = DS_DOMAIN_FUNCTION_2003
if dom_for_fun_level > domainControllerFunctionality:
raise ProvisioningError("You want to run SAMBA 4 on a domain and forest function level which itself is higher than its actual DC function level (2008_R2). This won't work!")
domainFunctionality = dom_for_fun_level
forestFunctionality = dom_for_fun_level
# Set the NTDS settings DN manually - in order to have it already around
# before the provisioned tree exists and we connect
samdb.set_ntds_settings_dn("CN=NTDS Settings,%s" % names.serverdn)
samdb.transaction_start()
try:
@ -1283,28 +1308,29 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
"SAMBA_VERSION_STRING": version
})
logger.info("Adding configuration container")
descr = b64encode(get_config_descriptor(domainsid))
setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
"CONFIGDN": names.configdn,
"DESCRIPTOR": descr,
})
# If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
if fill == FILL_FULL:
logger.info("Adding configuration container")
descr = b64encode(get_config_descriptor(domainsid))
setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
"CONFIGDN": names.configdn,
"DESCRIPTOR": descr,
})
# The LDIF here was created when the Schema object was constructed
logger.info("Setting up sam.ldb schema")
samdb.add_ldif(schema.schema_dn_add, controls=["relax:0"])
samdb.modify_ldif(schema.schema_dn_modify)
samdb.write_prefixes_from_schema()
samdb.add_ldif(schema.schema_data, controls=["relax:0"])
setup_add_ldif(samdb, setup_path("aggregate_schema.ldif"),
{"SCHEMADN": names.schemadn})
# Now register this container in the root of the forest
msg = ldb.Message(ldb.Dn(samdb, names.domaindn))
msg["subRefs"] = ldb.MessageElement(names.configdn , ldb.FLAG_MOD_ADD,
"subRefs")
# The LDIF here was created when the Schema object was constructed
logger.info("Setting up sam.ldb schema")
samdb.add_ldif(schema.schema_dn_add, controls=["relax:0"])
samdb.modify_ldif(schema.schema_dn_modify)
samdb.write_prefixes_from_schema()
samdb.add_ldif(schema.schema_data, controls=["relax:0"])
setup_add_ldif(samdb, setup_path("aggregate_schema.ldif"),
{"SCHEMADN": names.schemadn})
logger.info("Reopening sam.ldb with new schema")
except Exception:
samdb.transaction_cancel()
raise
@ -1324,27 +1350,29 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
try:
samdb.invocation_id = invocationid
logger.info("Setting up sam.ldb configuration data")
setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
"CONFIGDN": names.configdn,
"NETBIOSNAME": names.netbiosname,
"DEFAULTSITE": names.sitename,
"DNSDOMAIN": names.dnsdomain,
"DOMAIN": names.domain,
"SCHEMADN": names.schemadn,
"DOMAINDN": names.domaindn,
"SERVERDN": names.serverdn,
"FOREST_FUNCTIONALITY": str(forestFunctionality),
"DOMAIN_FUNCTIONALITY": str(domainFunctionality),
})
# If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
if fill == FILL_FULL:
logger.info("Setting up sam.ldb configuration data")
setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
"CONFIGDN": names.configdn,
"NETBIOSNAME": names.netbiosname,
"DEFAULTSITE": names.sitename,
"DNSDOMAIN": names.dnsdomain,
"DOMAIN": names.domain,
"SCHEMADN": names.schemadn,
"DOMAINDN": names.domaindn,
"SERVERDN": names.serverdn,
"FOREST_FUNCTIONALITY": str(forestFunctionality),
"DOMAIN_FUNCTIONALITY": str(domainFunctionality),
})
logger.info("Setting up display specifiers")
display_specifiers_ldif = read_ms_ldif(
setup_path('display-specifiers/DisplaySpecifiers-Win2k8R2.txt'))
display_specifiers_ldif = substitute_var(display_specifiers_ldif,
{"CONFIGDN": names.configdn})
check_all_substituted(display_specifiers_ldif)
samdb.add_ldif(display_specifiers_ldif)
logger.info("Setting up display specifiers")
display_specifiers_ldif = read_ms_ldif(
setup_path('display-specifiers/DisplaySpecifiers-Win2k8R2.txt'))
display_specifiers_ldif = substitute_var(display_specifiers_ldif,
{"CONFIGDN": names.configdn})
check_all_substituted(display_specifiers_ldif)
samdb.add_ldif(display_specifiers_ldif)
logger.info("Adding users container")
setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
@ -1371,15 +1399,17 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
"POLICYGUID_DC": policyguid_dc
})
setup_modify_ldif(samdb,
setup_path("provision_basedn_references.ldif"), {
"DOMAINDN": names.domaindn})
# If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
if fill == FILL_FULL:
setup_modify_ldif(samdb,
setup_path("provision_basedn_references.ldif"),
{"DOMAINDN": names.domaindn})
setup_modify_ldif(samdb,
setup_path("provision_configuration_references.ldif"), {
"CONFIGDN": names.configdn,
"SCHEMADN": names.schemadn})
if fill == FILL_FULL:
if fill == FILL_FULL or fill == FILL_SUBDOMAIN:
logger.info("Setting up sam.ldb users and groups")
setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
"DOMAINDN": names.domaindn,
@ -1390,7 +1420,7 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
})
logger.info("Setting up self join")
setup_self_join(samdb, names=names, invocationid=invocationid,
setup_self_join(samdb, names=names, fill=fill, invocationid=invocationid,
dnspass=dnspass,
machinepass=machinepass,
domainsid=domainsid,
@ -1414,6 +1444,7 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
FILL_FULL = "FULL"
FILL_SUBDOMAIN = "SUBDOMAIN"
FILL_NT4SYNC = "NT4SYNC"
FILL_DRS = "DRS"
SYSVOL_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)"
@ -1512,30 +1543,16 @@ def interface_ips_v6(lp, linklocal=False):
return ret
def provision(logger, session_info, credentials, smbconf=None,
targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
domaindn=None, schemadn=None, configdn=None, serverdn=None,
domain=None, hostname=None, hostip=None, hostip6=None, domainsid=None,
next_rid=1000, dc_rid=None, adminpass=None, ldapadminpass=None, krbtgtpass=None,
domainguid=None, policyguid=None, policyguid_dc=None,
invocationid=None, machinepass=None, ntdsguid=None,
dns_backend=None, dnspass=None,
root=None, nobody=None, users=None, wheel=None, backup=None, aci=None,
serverrole=None, dom_for_fun_level=None, ldap_backend_extra_port=None,
ldap_backend_forced_uri=None, backend_type=None, sitename=None,
ol_mmr_urls=None, ol_olc=None, setup_ds_path=None, slapd_path=None,
nosync=False, ldap_dryrun_mode=False, useeadb=False, am_rodc=False,
lp=None):
"""Provision samba4
:note: caution, this wipes all existing data!
"""
if domainsid is None:
domainsid = security.random_sid()
else:
domainsid = security.dom_sid(domainsid)
def provision_fill(samdb, secrets_ldb, logger, names, paths,
domainsid, schema=None,
targetdir=None, samdb_fill=FILL_FULL,
hostip=None, hostip6=None,
next_rid=1000, dc_rid=None, adminpass=None, krbtgtpass=None,
domainguid=None, policyguid=None, policyguid_dc=None,
invocationid=None, machinepass=None, ntdsguid=None,
dns_backend=None, dnspass=None,
serverrole=None, dom_for_fun_level=None,
am_rodc=False, lp=None):
# create/adapt the group policy GUIDs
# Default GUID for default policy are described at
# "How Core Group Policy Works"
@ -1547,6 +1564,9 @@ def provision(logger, session_info, credentials, smbconf=None,
policyguid_dc = DEFAULT_DC_POLICY_GUID
policyguid_dc = policyguid_dc.upper()
if invocationid is None:
invocationid = str(uuid.uuid4())
if adminpass is None:
adminpass = samba.generate_random_password(12, 32)
if krbtgtpass is None:
@ -1555,6 +1575,135 @@ def provision(logger, session_info, credentials, smbconf=None,
machinepass = samba.generate_random_password(128, 255)
if dnspass is None:
dnspass = samba.generate_random_password(128, 255)
samdb = fill_samdb(samdb, lp, names, logger=logger,
domainsid=domainsid, schema=schema, domainguid=domainguid,
policyguid=policyguid, policyguid_dc=policyguid_dc,
fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass,
invocationid=invocationid, machinepass=machinepass,
dnspass=dnspass, ntdsguid=ntdsguid, serverrole=serverrole,
dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
next_rid=next_rid, dc_rid=dc_rid)
if serverrole == "domain controller":
# Set up group policies (domain policy and domain controller
# policy)
create_default_gpo(paths.sysvol, names.dnsdomain, policyguid,
policyguid_dc)
setsysvolacl(samdb, paths.netlogon, paths.sysvol, paths.wheel_gid,
domainsid, names.dnsdomain, names.domaindn, lp)
logger.info("Setting up sam.ldb rootDSE marking as synchronized")
setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"),
{ 'NTDSGUID' : names.ntdsguid })
secretsdb_self_join(secrets_ldb, domain=names.domain,
realm=names.realm, dnsdomain=names.dnsdomain,
netbiosname=names.netbiosname, domainsid=domainsid,
machinepass=machinepass, secure_channel_type=SEC_CHAN_BDC)
# Now set up the right msDS-SupportedEncryptionTypes into the DB
# In future, this might be determined from some configuration
kerberos_enctypes = str(ENC_ALL_TYPES)
try:
msg = ldb.Message(ldb.Dn(samdb,
samdb.searchone("distinguishedName",
expression="samAccountName=%s$" % names.netbiosname,
scope=ldb.SCOPE_SUBTREE)))
msg["msDS-SupportedEncryptionTypes"] = ldb.MessageElement(
elements=kerberos_enctypes, flags=ldb.FLAG_MOD_REPLACE,
name="msDS-SupportedEncryptionTypes")
samdb.modify(msg)
except ldb.LdbError, (enum, estr):
if enum != ldb.ERR_NO_SUCH_ATTRIBUTE:
# It might be that this attribute does not exist in this schema
raise
if serverrole == "domain controller":
secretsdb_setup_dns(secrets_ldb, names,
paths.private_dir, realm=names.realm,
dnsdomain=names.dnsdomain,
dns_keytab_path=paths.dns_keytab, dnspass=dnspass)
# Default DNS backend is BIND9 using txt files for zone information
if not dns_backend:
dns_backend = "BIND9"
setup_ad_dns(samdb, names, logger, hostip=hostip, hostip6=hostip6,
dns_backend=dns_backend, os_level=dom_for_fun_level)
domainguid = samdb.searchone(basedn=samdb.get_default_basedn(),
attribute="objectGUID")
assert isinstance(domainguid, str)
create_dns_dir(logger, paths)
# Only make a zone file on the first DC, it should be
# replicated with DNS replication
if dns_backend == "BIND9":
create_zone_file(lp, logger, paths, targetdir,
dnsdomain=names.dnsdomain, hostip=hostip, hostip6=hostip6,
hostname=names.hostname, realm=names.realm,
domainguid=domainguid, ntdsguid=names.ntdsguid)
create_named_conf(paths, realm=names.realm,
dnsdomain=names.dnsdomain, dns_backend=dns_backend)
create_named_txt(paths.namedtxt,
realm=names.realm, dnsdomain=names.dnsdomain,
dnsname = "%s.%s" % (names.hostname, names.dnsdomain),
private_dir=paths.private_dir,
keytab_name=paths.dns_keytab)
logger.info("See %s for an example configuration include file for BIND", paths.namedconf)
logger.info("and %s for further documentation required for secure DNS "
"updates", paths.namedtxt)
lastProvisionUSNs = get_last_provision_usn(samdb)
maxUSN = get_max_usn(samdb, str(names.rootdn))
if lastProvisionUSNs is not None:
update_provision_usn(samdb, 0, maxUSN, invocationid, 1)
else:
set_provision_usn(samdb, 0, maxUSN, invocationid)
# fix any dangling GUIDs from the provision
logger.info("Fixing provision GUIDs")
chk = dbcheck(samdb, samdb_schema=samdb, verbose=False, fix=True, yes=True, quiet=True)
samdb.transaction_start()
# a small number of GUIDs are missing because of ordering issues in the
# provision code
for schema_obj in ['CN=Domain', 'CN=Organizational-Person', 'CN=Contact', 'CN=inetOrgPerson']:
chk.check_database(DN="%s,%s" % (schema_obj, names.schemadn),
scope=ldb.SCOPE_BASE, attrs=['defaultObjectCategory'])
chk.check_database(DN="CN=IP Security,CN=System,%s" % names.domaindn,
scope=ldb.SCOPE_ONELEVEL,
attrs=['ipsecOwnersReference',
'ipsecFilterReference',
'ipsecISAKMPReference',
'ipsecNegotiationPolicyReference',
'ipsecNFAReference'])
samdb.transaction_commit()
def provision(logger, session_info, credentials, smbconf=None,
targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
domaindn=None, schemadn=None, configdn=None, serverdn=None,
domain=None, hostname=None, hostip=None, hostip6=None, domainsid=None,
next_rid=1000, dc_rid=None, adminpass=None, ldapadminpass=None, krbtgtpass=None,
domainguid=None, policyguid=None, policyguid_dc=None,
dns_backend=None, dnspass=None,
invocationid=None, machinepass=None, ntdsguid=None,
root=None, nobody=None, users=None, wheel=None, backup=None, aci=None,
serverrole=None, dom_for_fun_level=None, ldap_backend_extra_port=None,
ldap_backend_forced_uri=None, backend_type=None, sitename=None,
ol_mmr_urls=None, ol_olc=None, setup_ds_path=None, slapd_path=None,
nosync=False, ldap_dryrun_mode=False, useeadb=False, am_rodc=False,
lp=None):
"""Provision samba4
:note: caution, this wipes all existing data!
"""
if ldapadminpass is None:
# Make a new, random password between Samba and it's LDAP server
ldapadminpass=samba.generate_random_password(128, 255)
@ -1562,6 +1711,11 @@ def provision(logger, session_info, credentials, smbconf=None,
if backend_type is None:
backend_type = "ldb"
if domainsid is None:
domainsid = security.random_sid()
else:
domainsid = security.dom_sid(domainsid)
sid_generator = "internal"
if backend_type == "fedora-ds":
sid_generator = "backend"
@ -1610,6 +1764,7 @@ def provision(logger, session_info, credentials, smbconf=None,
paths = provision_paths_from_lp(lp, names.dnsdomain)
paths.bind_gid = bind_gid
paths.wheel_gid = wheel_gid
if hostip is None:
logger.info("Looking up IPv4 addresses")
@ -1638,8 +1793,6 @@ def provision(logger, session_info, credentials, smbconf=None,
serverrole = lp.get("server role")
assert serverrole in ("domain controller", "member server", "standalone")
if invocationid is None:
invocationid = str(uuid.uuid4())
if not os.path.exists(paths.private_dir):
os.mkdir(paths.private_dir)
@ -1710,16 +1863,15 @@ def provision(logger, session_info, credentials, smbconf=None,
idmap = setup_idmapdb(paths.idmapdb,
session_info=session_info, lp=lp)
setup_name_mappings(idmap, sid=str(domainsid),
root_uid=root_uid, nobody_uid=nobody_uid,
users_gid=users_gid, wheel_gid=wheel_gid)
logger.info("Setting up SAM db")
samdb = setup_samdb(paths.samdb, session_info,
provision_backend, lp, names, logger=logger,
domainsid=domainsid, schema=schema, domainguid=domainguid,
policyguid=policyguid, policyguid_dc=policyguid_dc,
fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass,
invocationid=invocationid, machinepass=machinepass,
dnspass=dnspass, ntdsguid=ntdsguid, serverrole=serverrole,
dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
next_rid=next_rid, dc_rid=dc_rid)
provision_backend, lp, names, logger=logger,
serverrole=serverrole,
schema=schema, fill=samdb_fill, am_rodc=am_rodc)
if serverrole == "domain controller":
if paths.netlogon is None:
@ -1739,90 +1891,16 @@ def provision(logger, session_info, credentials, smbconf=None,
os.makedirs(paths.netlogon, 0755)
if samdb_fill == FILL_FULL:
setup_name_mappings(samdb, idmap, str(domainsid), names.domaindn,
root_uid=root_uid, nobody_uid=nobody_uid,
users_gid=users_gid, wheel_gid=wheel_gid)
if serverrole == "domain controller":
# Set up group policies (domain policy and domain controller
# policy)
create_default_gpo(paths.sysvol, names.dnsdomain, policyguid,
policyguid_dc)
setsysvolacl(samdb, paths.netlogon, paths.sysvol, wheel_gid,
domainsid, names.dnsdomain, names.domaindn, lp)
logger.info("Setting up sam.ldb rootDSE marking as synchronized")
setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"),
{ 'NTDSGUID' : names.ntdsguid })
secretsdb_self_join(secrets_ldb, domain=names.domain,
realm=names.realm, dnsdomain=names.dnsdomain,
netbiosname=names.netbiosname, domainsid=domainsid,
machinepass=machinepass, secure_channel_type=SEC_CHAN_BDC)
# Now set up the right msDS-SupportedEncryptionTypes into the DB
# In future, this might be determined from some configuration
kerberos_enctypes = str(ENC_ALL_TYPES)
try:
msg = ldb.Message(ldb.Dn(samdb,
samdb.searchone("distinguishedName",
expression="samAccountName=%s$" % names.netbiosname,
scope=ldb.SCOPE_SUBTREE)))
msg["msDS-SupportedEncryptionTypes"] = ldb.MessageElement(
elements=kerberos_enctypes, flags=ldb.FLAG_MOD_REPLACE,
name="msDS-SupportedEncryptionTypes")
samdb.modify(msg)
except ldb.LdbError, (enum, estr):
if enum != ldb.ERR_NO_SUCH_ATTRIBUTE:
# It might be that this attribute does not exist in this schema
raise
if serverrole == "domain controller":
secretsdb_setup_dns(secrets_ldb, names,
paths.private_dir, realm=names.realm,
dnsdomain=names.dnsdomain,
dns_keytab_path=paths.dns_keytab, dnspass=dnspass)
# Default DNS backend is BIND9 using txt files for zone information
if not dns_backend:
dns_backend = "BIND9"
setup_ad_dns(samdb, names, logger, hostip=hostip, hostip6=hostip6,
dns_backend=dns_backend, os_level=dom_for_fun_level)
domainguid = samdb.searchone(basedn=domaindn,
attribute="objectGUID")
assert isinstance(domainguid, str)
create_dns_dir(logger, paths)
# Only make a zone file on the first DC, it should be
# replicated with DNS replication
if dns_backend == "BIND9":
create_zone_file(lp, logger, paths, targetdir,
dnsdomain=names.dnsdomain, hostip=hostip, hostip6=hostip6,
hostname=names.hostname, realm=names.realm,
domainguid=domainguid, ntdsguid=names.ntdsguid)
create_named_conf(paths, realm=names.realm,
dnsdomain=names.dnsdomain, dns_backend=dns_backend)
create_named_txt(paths.namedtxt,
realm=names.realm, dnsdomain=names.dnsdomain,
dnsname = "%s.%s" % (names.hostname, names.dnsdomain),
private_dir=paths.private_dir,
keytab_name=paths.dns_keytab)
logger.info("See %s for an example configuration include file for BIND", paths.namedconf)
logger.info("and %s for further documentation required for secure DNS "
"updates", paths.namedtxt)
lastProvisionUSNs = get_last_provision_usn(samdb)
maxUSN = get_max_usn(samdb, str(names.rootdn))
if lastProvisionUSNs is not None:
update_provision_usn(samdb, 0, maxUSN, invocationid, 1)
else:
set_provision_usn(samdb, 0, maxUSN, invocationid)
provision_fill(samdb, secrets_ldb, logger,
names, paths, schema=schema, targetdir=targetdir,
samdb_fill=samdb_fill, hostip=hostip, hostip6=hostip6, domainsid=domainsid,
next_rid=next_rid, dc_rid=dc_rid, adminpass=adminpass,
krbtgtpass=krbtgtpass, domainguid=domainguid,
policyguid=policyguid, policyguid_dc=policyguid_dc,
invocationid=invocationid, machinepass=machinepass,
ntdsguid=ntdsguid, dns_backend=dns_backend, dnspass=dnspass,
serverrole=serverrole, dom_for_fun_level=dom_for_fun_level,
am_rodc=am_rodc, lp=lp)
create_krb5_conf(paths.krb5conf,
dnsdomain=names.dnsdomain, hostname=names.hostname,
@ -1856,26 +1934,6 @@ def provision(logger, session_info, credentials, smbconf=None,
logger.info("Failed to chown %s to bind gid %u",
dns_keytab_path, paths.bind_gid)
if samdb_fill != FILL_DRS:
# fix any dangling GUIDs from the provision
logger.info("Fixing provision GUIDs")
chk = dbcheck(samdb, samdb_schema=samdb, verbose=False, fix=True, yes=True, quiet=True)
samdb.transaction_start()
# a small number of GUIDs are missing because of ordering issues in the
# provision code
for schema_obj in ['CN=Domain', 'CN=Organizational-Person', 'CN=Contact', 'CN=inetOrgPerson']:
chk.check_database(DN="%s,%s" % (schema_obj, names.schemadn),
scope=ldb.SCOPE_BASE, attrs=['defaultObjectCategory'])
chk.check_database(DN="CN=IP Security,CN=System,%s" % names.domaindn,
scope=ldb.SCOPE_ONELEVEL,
attrs=['ipsecOwnersReference',
'ipsecFilterReference',
'ipsecISAKMPReference',
'ipsecNegotiationPolicyReference',
'ipsecNFAReference'])
samdb.transaction_commit()
logger.info("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php",
paths.phpldapadminconfig)
@ -1909,6 +1967,7 @@ def provision(logger, session_info, credentials, smbconf=None,
result = ProvisionResult()
result.domaindn = domaindn
result.paths = paths
result.names = names
result.lp = lp
result.samdb = samdb
result.idmap = idmap

View File

@ -20,38 +20,3 @@ sAMAccountName: ${NETBIOSNAME}$
userAccountControl: 532480
clearTextPassword:: ${MACHINEPASS_B64}
objectSid: ${DOMAINSID}-${DCRID}
# Here are missing the objects for the NTFRS subscription since we don't
# support this technique yet.
# Objects under "Configuration/Sites/<Default sitename>/Servers"
dn: ${SERVERDN}
objectClass: top
objectClass: server
systemFlags: 1375731712
dNSHostName: ${DNSNAME}
serverReference: CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
dn: CN=NTDS Settings,${SERVERDN}
objectClass: top
objectClass: applicationSettings
objectClass: nTDSDSA
dMDLocation: ${SCHEMADN}
hasMasterNCs: ${CONFIGDN}
hasMasterNCs: ${SCHEMADN}
hasMasterNCs: ${DOMAINDN}
invocationId: ${INVOCATIONID}
msDS-Behavior-Version: ${DOMAIN_CONTROLLER_FUNCTIONALITY}
msDS-HasDomainNCs: ${DOMAINDN}
# "msDS-HasInstantiatedNCs"s for DNS is added from provision_dnszones_modify.ldif
msDS-HasInstantiatedNCs: B:8:0000000D:${CONFIGDN}
msDS-HasInstantiatedNCs: B:8:0000000D:${SCHEMADN}
msDS-HasInstantiatedNCs: B:8:00000005:${DOMAINDN}
# "msDS-hasMasterNCs"s for DNS is added from provision_dnszones_modify.ldif
msDS-hasMasterNCs: ${CONFIGDN}
msDS-hasMasterNCs: ${SCHEMADN}
msDS-hasMasterNCs: ${DOMAINDN}
options: 1
systemFlags: 33554432
${NTDSGUID}

View File

@ -0,0 +1,33 @@
# Here are missing the objects for the NTFRS subscription since we don't
# support this technique yet.
# Objects under "Configuration/Sites/<Default sitename>/Servers"
dn: ${SERVERDN}
objectClass: top
objectClass: server
systemFlags: 1375731712
dNSHostName: ${DNSNAME}
dn: CN=NTDS Settings,${SERVERDN}
objectClass: top
objectClass: applicationSettings
objectClass: nTDSDSA
dMDLocation: ${SCHEMADN}
hasMasterNCs: ${CONFIGDN}
hasMasterNCs: ${SCHEMADN}
hasMasterNCs: ${DOMAINDN}
invocationId: ${INVOCATIONID}
msDS-Behavior-Version: ${DOMAIN_CONTROLLER_FUNCTIONALITY}
msDS-HasDomainNCs: ${DOMAINDN}
# "msDS-HasInstantiatedNCs"s for DNS is added from provision_dnszones_modify.ldif
msDS-HasInstantiatedNCs: B:8:0000000D:${CONFIGDN}
msDS-HasInstantiatedNCs: B:8:0000000D:${SCHEMADN}
msDS-HasInstantiatedNCs: B:8:00000005:${DOMAINDN}
# "msDS-hasMasterNCs"s for DNS is added from provision_dnszones_modify.ldif
msDS-hasMasterNCs: ${CONFIGDN}
msDS-hasMasterNCs: ${SCHEMADN}
msDS-hasMasterNCs: ${DOMAINDN}
options: 1
systemFlags: 33554432
${NTDSGUID}

View File

@ -5,11 +5,6 @@ fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
replace: rIDManagerReference
rIDManagerReference: CN=RID Manager$,CN=System,${DOMAINDN}
dn: ${SCHEMADN}
changetype: modify
replace: fSMORoleOwner
fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
dn: CN=Infrastructure,${DOMAINDN}
changetype: modify
replace: fSMORoleOwner
@ -20,16 +15,6 @@ changetype: modify
replace: fSMORoleOwner
fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
dn: CN=Partitions,${CONFIGDN}
changetype: modify
replace: fSMORoleOwner
fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
dn: CN=NTDS Site Settings,CN=${DEFAULTSITE},CN=Sites,${CONFIGDN}
changetype: modify
replace: interSiteTopologyGenerator
interSiteTopologyGenerator: CN=NTDS Settings,${SERVERDN}
dn: CN=RID Set,CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
changetype: add
objectClass: rIDSet
@ -42,3 +27,8 @@ dn: CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
changetype: modify
add: rIDSetReferences
rIDSetReferences: CN=RID Set,CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}
dn: ${SERVERDN}
changetype: modify
add: serverReference
serverReference: CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN}

View File

@ -0,0 +1,14 @@
dn: ${SCHEMADN}
changetype: modify
replace: fSMORoleOwner
fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
dn: CN=Partitions,${CONFIGDN}
changetype: modify
replace: fSMORoleOwner
fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
dn: CN=NTDS Site Settings,CN=${DEFAULTSITE},CN=Sites,${CONFIGDN}
changetype: modify
replace: interSiteTopologyGenerator
interSiteTopologyGenerator: CN=NTDS Settings,${SERVERDN}