From 4bba26579d124af6c0767bb98bee67357001e1e7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 17 Mar 2023 16:48:26 +0100 Subject: [PATCH] python:provision: run adprep as part of provision With the default of base_schema=2019 we'll adprep to 2016. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- python/samba/netcmd/domain.py | 32 +++++++++ python/samba/provision/__init__.py | 71 +++++++++++++++++++- python/samba/upgradehelpers.py | 5 +- source4/scripting/bin/samba_upgradeprovision | 2 +- testprogs/blackbox/functionalprep.sh | 6 +- testprogs/blackbox/schemaupgrade.sh | 2 +- 6 files changed, 109 insertions(+), 9 deletions(-) diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py index c3bdc7f448e..72905f1975d 100644 --- a/python/samba/netcmd/domain.py +++ b/python/samba/netcmd/domain.py @@ -320,6 +320,10 @@ class cmd_domain_provision(Command): choices=["2008_R2", "2008_R2_old", "2012", "2012_R2", "2016", "2019"], help="The base schema files to use. Default is (Windows) 2019.", default="2019"), + Option("--adprep-level", type="choice", metavar="FUNCTION_LEVEL", + choices=["SKIP", "2008_R2", "2012", "2012_R2", "2016"], + help="The highest functional level to prepare for. Default is based on --base-schema", + default=None), Option("--next-rid", type="int", metavar="NEXTRID", default=1000, help="The initial nextRid value (only needed for upgrades). Default is 1000."), Option("--partitions-only", @@ -369,6 +373,7 @@ class cmd_domain_provision(Command): blank=None, server_role=None, function_level=None, + adprep_level=None, next_rid=None, partitions_only=None, targetdir=None, @@ -471,6 +476,32 @@ class cmd_domain_provision(Command): elif function_level == "2008_R2": dom_for_fun_level = DS_DOMAIN_FUNCTION_2008_R2 + if adprep_level is None: + # Select the adprep_level default based + # on what the base schema premits + if base_schema in ["2008_R2", "2008_R2_old"]: + # without explicit --adprep-level=2008_R2 + # we will skip the adprep step on + # provision + adprep_level = "SKIP" + elif base_schema in ["2012"]: + adprep_level = "2012" + elif base_schema in ["2012_R2"]: + adprep_level = "2012_R2" + else: + adprep_level = "2016" + + if adprep_level == "SKIP": + provision_adprep_level = None + elif adprep_level == "2008R2": + provision_adprep_level = DS_DOMAIN_FUNCTION_2008_R2 + elif adprep_level == "2012": + provision_adprep_level = DS_DOMAIN_FUNCTION_2012 + elif adprep_level == "2012_R2": + provision_adprep_level = DS_DOMAIN_FUNCTION_2012_R2 + elif adprep_level == "2016": + provision_adprep_level = DS_DOMAIN_FUNCTION_2016 + if dns_backend == "SAMBA_INTERNAL" and dns_forwarder is None: dns_forwarder = suggested_forwarder @@ -537,6 +568,7 @@ class cmd_domain_provision(Command): useeadb=eadb, next_rid=next_rid, lp=lp, use_ntvfs=use_ntvfs, use_rfc2307=use_rfc2307, skip_sysvolacl=False, base_schema=base_schema, + adprep_level=provision_adprep_level, plaintext_secrets=plaintext_secrets, backend_store=backend_store, backend_store_size=backend_store_size) diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py index c779963c21f..6946eb42f38 100644 --- a/python/samba/provision/__init__.py +++ b/python/samba/provision/__init__.py @@ -48,7 +48,6 @@ import samba from samba import auth from samba.samba3 import smbd, passdb from samba.samba3 import param as s3param -from samba.dsdb import DS_DOMAIN_FUNCTION_2000 from samba import ( Ldb, MAX_NETBIOS_NAME_LEN, @@ -66,8 +65,13 @@ from samba.dcerpc.misc import ( SEC_CHAN_WKSTA, ) from samba.dsdb import ( + DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2003, + DS_DOMAIN_FUNCTION_2008, DS_DOMAIN_FUNCTION_2008_R2, + DS_DOMAIN_FUNCTION_2012, + DS_DOMAIN_FUNCTION_2012_R2, + DS_DOMAIN_FUNCTION_2016, ENC_ALL_TYPES, ) from samba.idmap import IDmapDB @@ -2146,7 +2150,7 @@ def provision(logger, session_info, smbconf=None, sitename=None, serverrole=None, dom_for_fun_level=None, useeadb=False, am_rodc=False, lp=None, use_ntvfs=False, use_rfc2307=False, maxuid=None, maxgid=None, skip_sysvolacl=True, - base_schema="2019", + base_schema="2019", adprep_level=DS_DOMAIN_FUNCTION_2016, plaintext_secrets=False, backend_store=None, backend_store_size=None, batch_mode=False): """Provision samba4 @@ -2159,6 +2163,30 @@ def provision(logger, session_info, smbconf=None, except ValueError: raise ProvisioningError('server role (%s) should be one of "active directory domain controller", "member server", "standalone server"' % serverrole) + if dom_for_fun_level is None: + dom_for_fun_level = DS_DOMAIN_FUNCTION_2008_R2 + + if base_schema in ["2008_R2", "2008_R2_old"]: + max_adprep_level = DS_DOMAIN_FUNCTION_2008_R2 + elif base_schema in ["2012"]: + max_adprep_level = DS_DOMAIN_FUNCTION_2012 + elif base_schema in ["2012_R2"]: + max_adprep_level = DS_DOMAIN_FUNCTION_2012_R2 + else: + max_adprep_level = DS_DOMAIN_FUNCTION_2016 + + if max_adprep_level < dom_for_fun_level: + raise ProvisioningError('dom_for_fun_level[%u] incompatible with base_schema[%s]' % + (dom_for_fun_level, base_schema)) + + if adprep_level is not None and max_adprep_level < adprep_level: + raise ProvisioningError('base_schema[%s] incompatible with adprep_level[%u]' % + (base_schema, adprep_level)) + + if adprep_level is not None and adprep_level < dom_for_fun_level: + raise ProvisioningError('dom_for_fun_level[%u] incompatible with adprep_level[%u]' % + (dom_for_fun_level, adprep_level)) + if ldapadminpass is None: # Make a new, random password between Samba and it's LDAP server ldapadminpass = samba.generate_random_password(128, 255) @@ -2337,6 +2365,45 @@ def provision(logger, session_info, smbconf=None, backend_store=backend_store, backend_store_size=backend_store_size) + if adprep_level is not None: + updates_allowed_overridden = False + if lp.get("dsdb:schema update allowed") is None: + lp.set("dsdb:schema update allowed", "yes") + print("Temporarily overriding 'dsdb:schema update allowed' setting") + updates_allowed_overridden = True + + samdb.transaction_start() + try: + from samba.forest_update import ForestUpdate + forest = ForestUpdate(samdb, fix=True) + + forest.check_updates_iterator([11, 54, 79, 80, 81, 82, 83]) + forest.check_updates_functional_level(adprep_level, + DS_DOMAIN_FUNCTION_2008_R2, + update_revision=True) + + samdb.transaction_commit() + except Exception as e: + samdb.transaction_cancel() + raise e + + samdb.transaction_start() + try: + from samba.domain_update import DomainUpdate + + domain = DomainUpdate(samdb, fix=True) + domain.check_updates_functional_level(adprep_level, + DS_DOMAIN_FUNCTION_2008, + update_revision=True) + + samdb.transaction_commit() + except Exception as e: + samdb.transaction_cancel() + raise e + + if updates_allowed_overridden: + lp.set("dsdb:schema update allowed", "no") + if not is_heimdal_built(): create_kdc_conf(paths.kdcconf, realm, domain, os.path.dirname(lp.get("log file"))) logger.info("The Kerberos KDC configuration for Samba AD is " diff --git a/python/samba/upgradehelpers.py b/python/samba/upgradehelpers.py index d6e81c07635..5a314762858 100644 --- a/python/samba/upgradehelpers.py +++ b/python/samba/upgradehelpers.py @@ -233,7 +233,7 @@ def update_policyids(names, samdb): names.policyid_dc = None -def newprovision(names, session, smbconf, provdir, logger, base_schema=None): +def newprovision(names, session, smbconf, provdir, logger, base_schema=None, adprep_level=None): """Create a new provision. This provision will be the reference for knowing what has changed in the @@ -261,7 +261,8 @@ def newprovision(names, session, smbconf, provdir, logger, base_schema=None): nobody=None, users=None, serverrole="domain controller", dom_for_fun_level=names.domainlevel, dns_backend=names.dns_backend, - useeadb=True, use_ntvfs=True, base_schema=base_schema) + useeadb=True, use_ntvfs=True, base_schema=base_schema, + adprep_level=adprep_level) def dn_sort(x, y): diff --git a/source4/scripting/bin/samba_upgradeprovision b/source4/scripting/bin/samba_upgradeprovision index 3d072bc64fe..c5c508a9c28 100755 --- a/source4/scripting/bin/samba_upgradeprovision +++ b/source4/scripting/bin/samba_upgradeprovision @@ -1649,7 +1649,7 @@ if __name__ == '__main__': provisiondir = tempfile.mkdtemp(dir=paths.private_dir, prefix="referenceprovision") result = newprovision(names, session, smbconf, provisiondir, - provision_logger, base_schema="2008_R2") + provision_logger, base_schema="2008_R2", adprep_level=None) result.report_logger(provision_logger) # TODO diff --git a/testprogs/blackbox/functionalprep.sh b/testprogs/blackbox/functionalprep.sh index 3ddd31456f0..477c9c0b972 100755 --- a/testprogs/blackbox/functionalprep.sh +++ b/testprogs/blackbox/functionalprep.sh @@ -64,9 +64,9 @@ undump_old() PROVISION_OPTS="--use-ntvfs --host-ip6=::1 --host-ip=127.0.0.1" -provision_2019() +provision_schema_2019_prep_skip() { - $PYTHON $BINDIR/samba-tool domain provision $PROVISION_OPTS --domain=REALM --realm=REALM.COM --targetdir=$PREFIX_ABS/2019_schema --base-schema=2019 --host-name=FLPREP + $PYTHON $BINDIR/samba-tool domain provision $PROVISION_OPTS --domain=REALM --realm=REALM.COM --targetdir=$PREFIX_ABS/2019_schema --base-schema=2019 --adprep-level=SKIP --host-name=FLPREP } provision_2012r2() @@ -140,7 +140,7 @@ testit "functional_prep_old" functional_prep_old || failed=$(expr $failed + 1) cleanup_output_directories # Provision a DC based on 2019 schema -testit "provision_2019_schema" provision_2019 || failed=$(expr $failed + 1) +testit "provision_schema_2019_prep_skip" provision_schema_2019_prep_skip || failed=$(expr $failed + 1) # Perform functional prep up to 2016 level testit "functional_prep_2016" functional_prep_2016 || failed=$(expr $failed + 1) diff --git a/testprogs/blackbox/schemaupgrade.sh b/testprogs/blackbox/schemaupgrade.sh index b5b638d02ff..236a0bb754f 100755 --- a/testprogs/blackbox/schemaupgrade.sh +++ b/testprogs/blackbox/schemaupgrade.sh @@ -27,7 +27,7 @@ PROVISION_OPTS="--use-ntvfs --host-ip6=::1 --host-ip=127.0.0.1" provision_2012r2() { - $PYTHON $BINDIR/samba-tool domain provision $PROVISION_OPTS --domain=SAMBA --realm=w2012r2.samba.corp --targetdir=$PREFIX_ABS/2012R2_schema --base-schema=2012_R2 + $PYTHON $BINDIR/samba-tool domain provision $PROVISION_OPTS --domain=SAMBA --realm=w2012r2.samba.corp --targetdir=$PREFIX_ABS/2012R2_schema --base-schema=2012_R2 --adprep-level=SKIP } provision_2008r2() -- 2.34.1