diff options
-rw-r--r-- | source4/scripting/python/samba/provision/__init__.py | 189 | ||||
-rw-r--r-- | source4/scripting/python/samba/provision/sambadns.py | 192 |
2 files changed, 194 insertions, 187 deletions
diff --git a/source4/scripting/python/samba/provision/__init__.py b/source4/scripting/python/samba/provision/__init__.py index 3ee6e767f9..a8a5a572a6 100644 --- a/source4/scripting/python/samba/provision/__init__.py +++ b/source4/scripting/python/samba/provision/__init__.py @@ -74,7 +74,7 @@ from samba.provision.backend import ( LDBBackend, OpenLDAPBackend, ) -from samba.provision.sambadns import setup_ad_dns +from samba.provision.sambadns import setup_ad_dns, create_dns_update_list import samba.param import samba.registry @@ -1593,36 +1593,15 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths, # It might be that this attribute does not exist in this schema raise - setup_ad_dns(samdb, secrets_ldb, names, paths, logger, hostip=hostip, - hostip6=hostip6, dns_backend=dns_backend, - dnspass=dnspass, os_level=dom_for_fun_level) + 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, site=DEFAULTSITE) 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_FLATFILE": - 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: @@ -1977,164 +1956,6 @@ def create_phpldapadmin_config(path, ldapi_uri): {"S4_LDAPI_URI": ldapi_uri}) -def create_dns_dir(logger, paths): - """Write out a DNS zone file, from the info in the current database. - - :param logger: Logger object - :param paths: paths object - """ - dns_dir = os.path.dirname(paths.dns) - - try: - shutil.rmtree(dns_dir, True) - except OSError: - pass - - os.mkdir(dns_dir, 0770) - - if paths.bind_gid is not None: - try: - os.chown(dns_dir, -1, paths.bind_gid) - # chmod needed to cope with umask - os.chmod(dns_dir, 0770) - except OSError: - if not os.environ.has_key('SAMBA_SELFTEST'): - logger.error("Failed to chown %s to bind gid %u" % ( - dns_dir, paths.bind_gid)) - - -def create_zone_file(lp, logger, paths, targetdir, dnsdomain, - hostip, hostip6, hostname, realm, domainguid, - ntdsguid): - """Write out a DNS zone file, from the info in the current database. - - :param paths: paths object - :param dnsdomain: DNS Domain name - :param domaindn: DN of the Domain - :param hostip: Local IPv4 IP - :param hostip6: Local IPv6 IP - :param hostname: Local hostname - :param realm: Realm name - :param domainguid: GUID of the domain. - :param ntdsguid: GUID of the hosts nTDSDSA record. - """ - assert isinstance(domainguid, str) - - if hostip6 is not None: - hostip6_base_line = " IN AAAA " + hostip6 - hostip6_host_line = hostname + " IN AAAA " + hostip6 - gc_msdcs_ip6_line = "gc._msdcs IN AAAA " + hostip6 - else: - hostip6_base_line = "" - hostip6_host_line = "" - gc_msdcs_ip6_line = "" - - if hostip is not None: - hostip_base_line = " IN A " + hostip - hostip_host_line = hostname + " IN A " + hostip - gc_msdcs_ip_line = "gc._msdcs IN A " + hostip - else: - hostip_base_line = "" - hostip_host_line = "" - gc_msdcs_ip_line = "" - - # we need to freeze the zone while we update the contents - if targetdir is None: - rndc = ' '.join(lp.get("rndc command")) - os.system(rndc + " freeze " + lp.get("realm")) - - setup_file(setup_path("provision.zone"), paths.dns, { - "HOSTNAME": hostname, - "DNSDOMAIN": dnsdomain, - "REALM": realm, - "HOSTIP_BASE_LINE": hostip_base_line, - "HOSTIP_HOST_LINE": hostip_host_line, - "DOMAINGUID": domainguid, - "DATESTRING": time.strftime("%Y%m%d%H"), - "DEFAULTSITE": DEFAULTSITE, - "NTDSGUID": ntdsguid, - "HOSTIP6_BASE_LINE": hostip6_base_line, - "HOSTIP6_HOST_LINE": hostip6_host_line, - "GC_MSDCS_IP_LINE": gc_msdcs_ip_line, - "GC_MSDCS_IP6_LINE": gc_msdcs_ip6_line, - }) - - if paths.bind_gid is not None: - try: - os.chown(paths.dns, -1, paths.bind_gid) - # chmod needed to cope with umask - os.chmod(paths.dns, 0664) - except OSError: - if not os.environ.has_key('SAMBA_SELFTEST'): - logger.error("Failed to chown %s to bind gid %u" % ( - paths.dns, paths.bind_gid)) - - if targetdir is None: - os.system(rndc + " unfreeze " + lp.get("realm")) - - -def create_dns_update_list(lp, logger, paths): - """Write out a dns_update_list file""" - # note that we use no variable substitution on this file - # the substitution is done at runtime by samba_dnsupdate, samba_spnupdate - setup_file(setup_path("dns_update_list"), paths.dns_update_list, None) - setup_file(setup_path("spn_update_list"), paths.spn_update_list, None) - - -def create_named_conf(paths, realm, dnsdomain, dns_backend): - """Write out a file containing zone statements suitable for inclusion in a - named.conf file (including GSS-TSIG configuration). - - :param paths: all paths - :param realm: Realm name - :param dnsdomain: DNS Domain name - :param dns_backend: DNS backend type - :param keytab_name: File name of DNS keytab file - """ - - if dns_backend == "BIND9_FLATFILE": - setup_file(setup_path("named.conf"), paths.namedconf, { - "DNSDOMAIN": dnsdomain, - "REALM": realm, - "ZONE_FILE": paths.dns, - "REALM_WC": "*." + ".".join(realm.split(".")[1:]), - "NAMED_CONF": paths.namedconf, - "NAMED_CONF_UPDATE": paths.namedconf_update - }) - - setup_file(setup_path("named.conf.update"), paths.namedconf_update) - - elif dns_backend == "BIND9_DLZ": - dlz_module_path = os.path.join(samba.param.modules_dir(), - "bind9/dlz_bind9.so") - setup_file(setup_path("named.conf.dlz"), paths.namedconf, { - "NAMED_CONF": paths.namedconf, - "BIND9_DLZ_MODULE": dlz_module_path, - }) - - - -def create_named_txt(path, realm, dnsdomain, dnsname, private_dir, - keytab_name): - """Write out a file containing zone statements suitable for inclusion in a - named.conf file (including GSS-TSIG configuration). - - :param path: Path of the new named.conf file. - :param realm: Realm name - :param dnsdomain: DNS Domain name - :param private_dir: Path to private directory - :param keytab_name: File name of DNS keytab file - """ - setup_file(setup_path("named.txt"), path, { - "DNSDOMAIN": dnsdomain, - "DNSNAME" : dnsname, - "REALM": realm, - "DNS_KEYTAB": keytab_name, - "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name), - "PRIVATE_DIR": private_dir - }) - - def create_krb5_conf(path, dnsdomain, hostname, realm): """Write out a file containing zone statements suitable for inclusion in a named.conf file (including GSS-TSIG configuration). diff --git a/source4/scripting/python/samba/provision/sambadns.py b/source4/scripting/python/samba/provision/sambadns.py index ad8387f9dc..c45e04f777 100644 --- a/source4/scripting/python/samba/provision/sambadns.py +++ b/source4/scripting/python/samba/provision/sambadns.py @@ -22,10 +22,12 @@ import os import uuid +import shutil +import time import ldb import samba from samba.ndr import ndr_pack, ndr_unpack -from samba import read_and_sub_file +from samba import read_and_sub_file, setup_file from samba.dcerpc import dnsp, misc from samba.dsdb import ( DS_DOMAIN_FUNCTION_2000, @@ -499,6 +501,164 @@ def secretsdb_setup_dns(secretsdb, names, private_dir, realm, }) +def create_dns_dir(logger, paths): + """Write out a DNS zone file, from the info in the current database. + + :param logger: Logger object + :param paths: paths object + """ + dns_dir = os.path.dirname(paths.dns) + + try: + shutil.rmtree(dns_dir, True) + except OSError: + pass + + os.mkdir(dns_dir, 0770) + + if paths.bind_gid is not None: + try: + os.chown(dns_dir, -1, paths.bind_gid) + # chmod needed to cope with umask + os.chmod(dns_dir, 0770) + except OSError: + if not os.environ.has_key('SAMBA_SELFTEST'): + logger.error("Failed to chown %s to bind gid %u" % ( + dns_dir, paths.bind_gid)) + + +def create_zone_file(lp, logger, paths, targetdir, dnsdomain, + hostip, hostip6, hostname, realm, domainguid, + ntdsguid, site): + """Write out a DNS zone file, from the info in the current database. + + :param paths: paths object + :param dnsdomain: DNS Domain name + :param domaindn: DN of the Domain + :param hostip: Local IPv4 IP + :param hostip6: Local IPv6 IP + :param hostname: Local hostname + :param realm: Realm name + :param domainguid: GUID of the domain. + :param ntdsguid: GUID of the hosts nTDSDSA record. + """ + assert isinstance(domainguid, str) + + if hostip6 is not None: + hostip6_base_line = " IN AAAA " + hostip6 + hostip6_host_line = hostname + " IN AAAA " + hostip6 + gc_msdcs_ip6_line = "gc._msdcs IN AAAA " + hostip6 + else: + hostip6_base_line = "" + hostip6_host_line = "" + gc_msdcs_ip6_line = "" + + if hostip is not None: + hostip_base_line = " IN A " + hostip + hostip_host_line = hostname + " IN A " + hostip + gc_msdcs_ip_line = "gc._msdcs IN A " + hostip + else: + hostip_base_line = "" + hostip_host_line = "" + gc_msdcs_ip_line = "" + + # we need to freeze the zone while we update the contents + if targetdir is None: + rndc = ' '.join(lp.get("rndc command")) + os.system(rndc + " freeze " + lp.get("realm")) + + setup_file(setup_path("provision.zone"), paths.dns, { + "HOSTNAME": hostname, + "DNSDOMAIN": dnsdomain, + "REALM": realm, + "HOSTIP_BASE_LINE": hostip_base_line, + "HOSTIP_HOST_LINE": hostip_host_line, + "DOMAINGUID": domainguid, + "DATESTRING": time.strftime("%Y%m%d%H"), + "DEFAULTSITE": site, + "NTDSGUID": ntdsguid, + "HOSTIP6_BASE_LINE": hostip6_base_line, + "HOSTIP6_HOST_LINE": hostip6_host_line, + "GC_MSDCS_IP_LINE": gc_msdcs_ip_line, + "GC_MSDCS_IP6_LINE": gc_msdcs_ip6_line, + }) + + if paths.bind_gid is not None: + try: + os.chown(paths.dns, -1, paths.bind_gid) + # chmod needed to cope with umask + os.chmod(paths.dns, 0664) + except OSError: + if not os.environ.has_key('SAMBA_SELFTEST'): + logger.error("Failed to chown %s to bind gid %u" % ( + paths.dns, paths.bind_gid)) + + if targetdir is None: + os.system(rndc + " unfreeze " + lp.get("realm")) + + +def create_dns_update_list(lp, logger, paths): + """Write out a dns_update_list file""" + # note that we use no variable substitution on this file + # the substitution is done at runtime by samba_dnsupdate, samba_spnupdate + setup_file(setup_path("dns_update_list"), paths.dns_update_list, None) + setup_file(setup_path("spn_update_list"), paths.spn_update_list, None) + + +def create_named_conf(paths, realm, dnsdomain, dns_backend): + """Write out a file containing zone statements suitable for inclusion in a + named.conf file (including GSS-TSIG configuration). + + :param paths: all paths + :param realm: Realm name + :param dnsdomain: DNS Domain name + :param dns_backend: DNS backend type + :param keytab_name: File name of DNS keytab file + """ + + if dns_backend == "BIND9_FLATFILE": + setup_file(setup_path("named.conf"), paths.namedconf, { + "DNSDOMAIN": dnsdomain, + "REALM": realm, + "ZONE_FILE": paths.dns, + "REALM_WC": "*." + ".".join(realm.split(".")[1:]), + "NAMED_CONF": paths.namedconf, + "NAMED_CONF_UPDATE": paths.namedconf_update + }) + + setup_file(setup_path("named.conf.update"), paths.namedconf_update) + + elif dns_backend == "BIND9_DLZ": + dlz_module_path = os.path.join(samba.param.modules_dir(), + "bind9/dlz_bind9.so") + setup_file(setup_path("named.conf.dlz"), paths.namedconf, { + "NAMED_CONF": paths.namedconf, + "BIND9_DLZ_MODULE": dlz_module_path, + }) + + + +def create_named_txt(path, realm, dnsdomain, dnsname, private_dir, + keytab_name): + """Write out a file containing zone statements suitable for inclusion in a + named.conf file (including GSS-TSIG configuration). + + :param path: Path of the new named.conf file. + :param realm: Realm name + :param dnsdomain: DNS Domain name + :param private_dir: Path to private directory + :param keytab_name: File name of DNS keytab file + """ + setup_file(setup_path("named.txt"), path, { + "DNSDOMAIN": dnsdomain, + "DNSNAME" : dnsname, + "REALM": realm, + "DNS_KEYTAB": keytab_name, + "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name), + "PRIVATE_DIR": private_dir + }) + + def is_valid_dns_backend(dns_backend): return dns_backend in ("BIND9_FLATFILE", "BIND9_DLZ", "SAMBA_INTERNAL", "NONE") @@ -507,20 +667,24 @@ def is_valid_os_level(os_level): return DS_DOMAIN_FUNCTION_2000 <= os_level <= DS_DOMAIN_FUNCTION_2008_R2 -def setup_ad_dns(samdb, secretsdb, names, paths, logger, dns_backend, os_level, - dnspass=None, hostip=None, hostip6=None): +def setup_ad_dns(samdb, secretsdb, names, paths, lp, logger, dns_backend, + os_level, site, dnspass=None, hostip=None, hostip6=None, + targetdir=None): """Provision DNS information (assuming GC role) :param samdb: LDB object connected to sam.ldb file :param secretsdb: LDB object connected to secrets.ldb file :param names: Names shortcut :param paths: Paths shortcut + :param lp: Loadparm object :param logger: Logger object :param dns_backend: Type of DNS backend :param os_level: Functional level (treated as os level) + :param site: Site to create hostnames in :param dnspass: Password for bind's DNS account :param hostip: IPv4 address :param hostip6: IPv6 address + :param targetdir: Target directory for creating DNS-related files for BIND9 """ if not is_valid_dns_backend(dns_backend): @@ -623,3 +787,25 @@ def setup_ad_dns(samdb, secretsdb, names, paths, logger, dns_backend, os_level, paths.private_dir, realm=names.realm, dnsdomain=names.dnsdomain, dns_keytab_path=paths.dns_keytab, dnspass=dnspass) + + 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_FLATFILE": + create_zone_file(lp, logger, paths, targetdir, site=site, + 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) |