mirror of
https://github.com/samba-team/samba.git
synced 2025-02-01 05:47:28 +03:00
provision: allow provisioning of a different database backend
This sets the backendStore field in @PARTITION, depending on which argument you set in the provision. Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
301cd5e58a
commit
34b12fbd88
@ -43,7 +43,7 @@ from samba.net import Net, LIBNET_JOIN_AUTOMATIC
|
||||
import samba.ntacls
|
||||
from samba.join import join_RODC, join_DC, join_subdomain
|
||||
from samba.auth import system_session
|
||||
from samba.samdb import SamDB
|
||||
from samba.samdb import SamDB, get_default_backend_store
|
||||
from samba.ndr import ndr_unpack, ndr_pack, ndr_print
|
||||
from samba.dcerpc import drsuapi
|
||||
from samba.dcerpc import drsblobs
|
||||
@ -258,6 +258,10 @@ class cmd_domain_provision(Command):
|
||||
Option("--plaintext-secrets", action="store_true",
|
||||
help="Store secret/sensitive values as plain text on disk" +
|
||||
"(default is to encrypt secret/ensitive values)"),
|
||||
Option("--backend-store", type="choice", metavar="BACKENDSTORE",
|
||||
choices=["tdb", "mdb"],
|
||||
help="Specify the database backend to be used "
|
||||
"(default is %s)" % get_default_backend_store()),
|
||||
]
|
||||
|
||||
openldap_options = [
|
||||
@ -328,7 +332,8 @@ class cmd_domain_provision(Command):
|
||||
ldap_backend_forced_uri=None,
|
||||
ldap_dryrun_mode=None,
|
||||
base_schema=None,
|
||||
plaintext_secrets=False):
|
||||
plaintext_secrets=False,
|
||||
backend_store=None):
|
||||
|
||||
self.logger = self.get_logger("provision")
|
||||
if quiet:
|
||||
@ -476,6 +481,8 @@ class cmd_domain_provision(Command):
|
||||
domain_sid = security.dom_sid(domain_sid)
|
||||
|
||||
session = system_session()
|
||||
if backend_store is None:
|
||||
backend_store = get_default_backend_store()
|
||||
try:
|
||||
result = provision(self.logger,
|
||||
session, smbconf=smbconf, targetdir=targetdir,
|
||||
@ -498,7 +505,8 @@ class cmd_domain_provision(Command):
|
||||
ldap_backend_forced_uri=ldap_backend_forced_uri,
|
||||
nosync=ldap_backend_nosync, ldap_dryrun_mode=ldap_dryrun_mode,
|
||||
base_schema=base_schema,
|
||||
plaintext_secrets=plaintext_secrets)
|
||||
plaintext_secrets=plaintext_secrets,
|
||||
backend_store=backend_store)
|
||||
|
||||
except ProvisioningError as e:
|
||||
raise CommandError("Provision failed", e)
|
||||
|
@ -123,6 +123,7 @@ from samba.schema import Schema
|
||||
from samba.samdb import SamDB
|
||||
from samba.dbchecker import dbcheck
|
||||
from samba.provision.kerberos import create_kdc_conf
|
||||
from samba.samdb import get_default_backend_store
|
||||
|
||||
DEFAULT_POLICY_GUID = "31B2F340-016D-11D2-945F-00C04FB984F9"
|
||||
DEFAULT_DC_POLICY_GUID = "6AC1786C-016F-11D2-945F-00C04FB984F9"
|
||||
@ -814,7 +815,8 @@ def setup_name_mappings(idmap, sid, root_uid, nobody_uid,
|
||||
|
||||
def setup_samdb_partitions(samdb_path, logger, lp, session_info,
|
||||
provision_backend, names, serverrole,
|
||||
erase=False, plaintext_secrets=False):
|
||||
erase=False, plaintext_secrets=False,
|
||||
backend_store=None):
|
||||
"""Setup the partitions for the SAM database.
|
||||
|
||||
Alternatively, provision() may call this, and then populate the database.
|
||||
@ -847,11 +849,16 @@ def setup_samdb_partitions(samdb_path, logger, lp, session_info,
|
||||
if not plaintext_secrets:
|
||||
required_features = "requiredFeatures: encryptedSecrets"
|
||||
|
||||
if backend_store is None:
|
||||
backend_store = get_default_backend_store()
|
||||
backend_store_line = "backendStore: %s" % backend_store
|
||||
|
||||
samdb.transaction_start()
|
||||
try:
|
||||
logger.info("Setting up sam.ldb partitions and settings")
|
||||
setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
|
||||
"LDAP_BACKEND_LINE": ldap_backend_line
|
||||
"LDAP_BACKEND_LINE": ldap_backend_line,
|
||||
"BACKEND_STORE": backend_store_line
|
||||
})
|
||||
|
||||
|
||||
@ -1245,7 +1252,7 @@ def create_default_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
|
||||
|
||||
def setup_samdb(path, session_info, provision_backend, lp, names,
|
||||
logger, fill, serverrole, schema, am_rodc=False,
|
||||
plaintext_secrets=False):
|
||||
plaintext_secrets=False, backend_store=None):
|
||||
"""Setup a complete SAM Database.
|
||||
|
||||
:note: This will wipe the main SAM database file!
|
||||
@ -1254,7 +1261,8 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
|
||||
# Also wipes the database
|
||||
setup_samdb_partitions(path, logger=logger, lp=lp,
|
||||
provision_backend=provision_backend, session_info=session_info,
|
||||
names=names, serverrole=serverrole, plaintext_secrets=plaintext_secrets)
|
||||
names=names, serverrole=serverrole, plaintext_secrets=plaintext_secrets,
|
||||
backend_store=backend_store)
|
||||
|
||||
# Load the database, but don's load the global schema and don't connect
|
||||
# quite yet
|
||||
@ -1293,7 +1301,8 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
|
||||
def fill_samdb(samdb, lp, names, logger, policyguid,
|
||||
policyguid_dc, fill, adminpass, krbtgtpass, machinepass, dns_backend,
|
||||
dnspass, invocationid, ntdsguid, serverrole, am_rodc=False,
|
||||
dom_for_fun_level=None, schema=None, next_rid=None, dc_rid=None):
|
||||
dom_for_fun_level=None, schema=None, next_rid=None, dc_rid=None,
|
||||
backend_store=None):
|
||||
|
||||
if next_rid is None:
|
||||
next_rid = 1000
|
||||
@ -1831,7 +1840,8 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
|
||||
invocationid=None, machinepass=None, ntdsguid=None,
|
||||
dns_backend=None, dnspass=None,
|
||||
serverrole=None, dom_for_fun_level=None,
|
||||
am_rodc=False, lp=None, use_ntvfs=False, skip_sysvolacl=False):
|
||||
am_rodc=False, lp=None, use_ntvfs=False,
|
||||
skip_sysvolacl=False, backend_store=None):
|
||||
# create/adapt the group policy GUIDs
|
||||
# Default GUID for default policy are described at
|
||||
# "How Core Group Policy Works"
|
||||
@ -1863,7 +1873,8 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
|
||||
dns_backend=dns_backend, 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)
|
||||
next_rid=next_rid, dc_rid=dc_rid,
|
||||
backend_store=backend_store)
|
||||
|
||||
# Set up group policies (domain policy and domain controller
|
||||
# policy)
|
||||
@ -1913,7 +1924,8 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
|
||||
setup_ad_dns(samdb, secrets_ldb, names, paths, lp, logger,
|
||||
hostip=hostip, hostip6=hostip6, dns_backend=dns_backend,
|
||||
dnspass=dnspass, os_level=dom_for_fun_level,
|
||||
targetdir=targetdir, fill_level=samdb_fill)
|
||||
targetdir=targetdir, fill_level=samdb_fill,
|
||||
backend_store=backend_store)
|
||||
|
||||
domainguid = samdb.searchone(basedn=samdb.get_default_basedn(),
|
||||
attribute="objectGUID")
|
||||
@ -2033,7 +2045,7 @@ def provision(logger, session_info, smbconf=None,
|
||||
use_rfc2307=False, maxuid=None, maxgid=None, skip_sysvolacl=True,
|
||||
ldap_backend_forced_uri=None, nosync=False, ldap_dryrun_mode=False,
|
||||
ldap_backend_extra_port=None, base_schema=None,
|
||||
plaintext_secrets=False):
|
||||
plaintext_secrets=False, backend_store=None):
|
||||
"""Provision samba4
|
||||
|
||||
:note: caution, this wipes all existing data!
|
||||
@ -2050,6 +2062,8 @@ def provision(logger, session_info, smbconf=None,
|
||||
|
||||
if backend_type is None:
|
||||
backend_type = "ldb"
|
||||
if backend_store is None:
|
||||
backend_store = get_default_backend_store()
|
||||
|
||||
if domainsid is None:
|
||||
domainsid = security.random_sid()
|
||||
@ -2233,7 +2247,8 @@ def provision(logger, session_info, smbconf=None,
|
||||
provision_backend, lp, names, logger=logger,
|
||||
serverrole=serverrole,
|
||||
schema=schema, fill=samdb_fill, am_rodc=am_rodc,
|
||||
plaintext_secrets=plaintext_secrets)
|
||||
plaintext_secrets=plaintext_secrets,
|
||||
backend_store=backend_store)
|
||||
|
||||
if serverrole == "active directory domain controller":
|
||||
if paths.netlogon is None:
|
||||
@ -2264,7 +2279,8 @@ def provision(logger, session_info, smbconf=None,
|
||||
dnspass=dnspass, serverrole=serverrole,
|
||||
dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
|
||||
lp=lp, use_ntvfs=use_ntvfs,
|
||||
skip_sysvolacl=skip_sysvolacl)
|
||||
skip_sysvolacl=skip_sysvolacl,
|
||||
backend_store=backend_store)
|
||||
|
||||
if not is_heimdal_built():
|
||||
create_kdc_conf(paths.kdcconf, realm, domain, os.path.dirname(lp.get("log file")))
|
||||
|
@ -29,6 +29,7 @@ from base64 import b64encode
|
||||
import subprocess
|
||||
import samba
|
||||
from samba.tdb_util import tdb_copy
|
||||
from samba.mdb_util import mdb_copy
|
||||
from samba.ndr import ndr_pack, ndr_unpack
|
||||
from samba import setup_file
|
||||
from samba.dcerpc import dnsp, misc, security
|
||||
@ -58,6 +59,7 @@ from samba.provision.common import (
|
||||
FILL_DRS,
|
||||
)
|
||||
|
||||
from samba.samdb import get_default_backend_store
|
||||
|
||||
def get_domainguid(samdb, domaindn):
|
||||
res = samdb.search(base=domaindn, scope=ldb.SCOPE_BASE, attrs=["objectGUID"])
|
||||
@ -787,12 +789,19 @@ def create_samdb_copy(samdb, logger, paths, names, domainsid, domainguid):
|
||||
|
||||
# Find the partitions and corresponding filenames
|
||||
partfile = {}
|
||||
res = samdb.search(base="@PARTITION", scope=ldb.SCOPE_BASE, attrs=["partition"])
|
||||
res = samdb.search(base="@PARTITION",
|
||||
scope=ldb.SCOPE_BASE,
|
||||
attrs=["partition", "backendStore"])
|
||||
for tmp in res[0]["partition"]:
|
||||
(nc, fname) = tmp.split(':')
|
||||
partfile[nc.upper()] = fname
|
||||
|
||||
backend_store = get_default_backend_store()
|
||||
if "backendStore" in res[0]:
|
||||
backend_store = res[0]["backendStore"][0]
|
||||
|
||||
# Create empty domain partition
|
||||
|
||||
domaindn = names.domaindn.upper()
|
||||
domainpart_file = os.path.join(dns_dir, partfile[domaindn])
|
||||
try:
|
||||
@ -800,7 +809,8 @@ def create_samdb_copy(samdb, logger, paths, names, domainsid, domainguid):
|
||||
file(domainpart_file, 'w').close()
|
||||
|
||||
# Fill the basedn and @OPTION records in domain partition
|
||||
dom_ldb = samba.Ldb(domainpart_file)
|
||||
dom_url = "%s://%s" % (backend_store, domainpart_file)
|
||||
dom_ldb = samba.Ldb(dom_url)
|
||||
domainguid_line = "objectGUID: %s\n-" % domainguid
|
||||
descr = b64encode(get_domain_descriptor(domainsid))
|
||||
setup_add_ldif(dom_ldb, setup_path("provision_basedn.ldif"), {
|
||||
@ -859,8 +869,12 @@ def create_samdb_copy(samdb, logger, paths, names, domainsid, domainguid):
|
||||
os.path.join(dns_dir, "sam.ldb"))
|
||||
for nc in partfile:
|
||||
pfile = partfile[nc]
|
||||
tdb_copy(os.path.join(private_dir, pfile),
|
||||
os.path.join(dns_dir, pfile))
|
||||
if backend_store == "mdb":
|
||||
mdb_copy(os.path.join(private_dir, pfile),
|
||||
os.path.join(dns_dir, pfile))
|
||||
else:
|
||||
tdb_copy(os.path.join(private_dir, pfile),
|
||||
os.path.join(dns_dir, pfile))
|
||||
except:
|
||||
logger.error(
|
||||
"Failed to setup database for BIND, AD based DNS cannot be used")
|
||||
@ -875,7 +889,7 @@ def create_samdb_copy(samdb, logger, paths, names, domainsid, domainguid):
|
||||
os.chown(dpath, -1, paths.bind_gid)
|
||||
os.chmod(dpath, 0o770)
|
||||
for f in files:
|
||||
if f.endswith('.ldb') or f.endswith('.tdb'):
|
||||
if f.endswith(('.ldb', '.tdb', 'ldb-lock')):
|
||||
fpath = os.path.join(dirname, f)
|
||||
os.chown(fpath, -1, paths.bind_gid)
|
||||
os.chmod(fpath, 0o660)
|
||||
@ -1069,7 +1083,7 @@ def fill_dns_data_partitions(samdb, domainsid, site, domaindn, forestdn,
|
||||
|
||||
def setup_ad_dns(samdb, secretsdb, names, paths, lp, logger,
|
||||
dns_backend, os_level, dnspass=None, hostip=None, hostip6=None,
|
||||
targetdir=None, fill_level=FILL_FULL):
|
||||
targetdir=None, fill_level=FILL_FULL, backend_store=None):
|
||||
"""Provision DNS information (assuming GC role)
|
||||
|
||||
:param samdb: LDB object connected to sam.ldb file
|
||||
@ -1164,12 +1178,14 @@ def setup_ad_dns(samdb, secretsdb, names, paths, lp, logger,
|
||||
if dns_backend.startswith("BIND9_"):
|
||||
setup_bind9_dns(samdb, secretsdb, names, paths, lp, logger,
|
||||
dns_backend, os_level, site=site, dnspass=dnspass, hostip=hostip,
|
||||
hostip6=hostip6, targetdir=targetdir)
|
||||
hostip6=hostip6, targetdir=targetdir,
|
||||
backend_store=backend_store)
|
||||
|
||||
|
||||
def setup_bind9_dns(samdb, secretsdb, names, paths, lp, logger,
|
||||
dns_backend, os_level, site=None, dnspass=None, hostip=None,
|
||||
hostip6=None, targetdir=None, key_version_number=None):
|
||||
hostip6=None, targetdir=None, key_version_number=None,
|
||||
backend_store=None):
|
||||
"""Provision DNS information (assuming BIND9 backend in DC role)
|
||||
|
||||
:param samdb: LDB object connected to sam.ldb file
|
||||
@ -1216,7 +1232,8 @@ def setup_bind9_dns(samdb, secretsdb, names, paths, lp, logger,
|
||||
ntdsguid=names.ntdsguid)
|
||||
|
||||
if dns_backend == "BIND9_DLZ" and os_level >= DS_DOMAIN_FUNCTION_2003:
|
||||
create_samdb_copy(samdb, logger, paths, names, names.domainsid, domainguid)
|
||||
create_samdb_copy(samdb, logger, paths,
|
||||
names, names.domainsid, domainguid)
|
||||
|
||||
create_named_conf(paths, realm=names.realm,
|
||||
dnsdomain=names.dnsdomain, dns_backend=dns_backend,
|
||||
|
@ -37,6 +37,9 @@ from samba.dcerpc import security
|
||||
__docformat__ = "restructuredText"
|
||||
|
||||
|
||||
def get_default_backend_store():
|
||||
return "tdb"
|
||||
|
||||
class SamDB(samba.Ldb):
|
||||
"""The SAM database."""
|
||||
|
||||
|
@ -2,5 +2,6 @@ dn: @PARTITION
|
||||
replicateEntries: @ATTRIBUTES
|
||||
replicateEntries: @INDEXLIST
|
||||
replicateEntries: @OPTIONS
|
||||
${BACKEND_STORE}
|
||||
${LDAP_BACKEND_LINE}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user