1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

s4-provision: Reworked DNS provisioning to support AD DNS schema

This changes configure DNS partitions used by AD DNS and populate
with relevant entries. This has an advantage that Windows can
replicate these partitions and set up dns server using them.

In addition, these partitions are used by bind9_dlz module to query
zone information directly and do not need to create text database
for dynamic zones.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Amitay Isaacs 2011-09-05 16:19:02 +10:00 committed by Andrew Bartlett
parent b36e9de863
commit 4b5ebfc5ff

View File

@ -2,6 +2,7 @@
# backend code for provisioning DNS for a Samba4 server
#
# Copyright (C) Kai Blin <kai@samba.org> 2011
# Copyright (C) Amitay Isaacs <amitay@gmail.com> 2011
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -20,11 +21,48 @@
"""DNS-related provisioning"""
import os
import uuid
import ldb
import samba
from samba.ndr import ndr_pack
from samba.ndr import ndr_pack, ndr_unpack
from samba import read_and_sub_file
from samba.dcerpc import dnsp
from samba.dcerpc import dnsp, misc
from samba.dsdb import (
DS_DOMAIN_FUNCTION_2000,
DS_DOMAIN_FUNCTION_2003,
DS_DOMAIN_FUNCTION_2008,
DS_DOMAIN_FUNCTION_2008_R2
)
def add_ldif(ldb, ldif_file, subst_vars, controls=["relax:0"]):
ldif_file_path = os.path.join(samba.param.setup_dir(), ldif_file)
data = read_and_sub_file(ldif_file_path, subst_vars)
ldb.add_ldif(data, controls)
def modify_ldif(ldb, ldif_file, subst_vars, controls=["relax:0"]):
ldif_file_path = os.path.join(samba.param.setup_dir(), ldif_file)
data = read_and_sub_file(ldif_file_path, subst_vars)
ldb.modify_ldif(data, controls)
def get_domainguid(samdb, domaindn):
res = samdb.search(base=domaindn, scope=ldb.SCOPE_BASE, attrs=["objectGUID"])
domainguid = str(ndr_unpack(misc.GUID, res[0]["objectGUID"][0]))
return domainguid
def get_ntdsguid(samdb, domaindn):
configdn = "CN=Configuration,%s" % domaindn
res1 = samdb.search(base="OU=Domain Controllers,%s" % domaindn, scope=ldb.SCOPE_ONELEVEL,
attrs=["dNSHostName"])
res2 = samdb.search(expression="serverReference=%s" % res1[0].dn, base=configdn)
res3 = samdb.search(base="CN=NTDS Settings,%s" % res2[0].dn, scope=ldb.SCOPE_BASE,
attrs=["objectGUID"])
ntdsguid = str(ndr_unpack(misc.GUID, res3[0]["objectGUID"][0]))
return ntdsguid
class ARecord(dnsp.DnssrvRpcRecord):
def __init__(self, ip_addr, serial=1, ttl=3600):
@ -42,6 +80,14 @@ class AAAARecord(dnsp.DnssrvRpcRecord):
self.dwTtlSeconds = ttl
self.data = ip6_addr
class CNameRecord(dnsp.DnssrvRpcRecord):
def __init__(self, cname, serial=1, ttl=900):
super(CNameRecord, self).__init__()
self.wType = dnsp.DNS_TYPE_CNAME
self.dwSerial = serial
self.dwTtlSeconds = ttl
self.data = cname
class NSRecord(dnsp.DnssrvRpcRecord):
def __init__(self, dns_server, serial=1, ttl=3600):
super(NSRecord, self).__init__()
@ -50,6 +96,15 @@ class NSRecord(dnsp.DnssrvRpcRecord):
self.dwTtlSeconds = ttl
self.data = dns_server
class RootNSRecord(dnsp.DnssrvRpcRecord):
def __init__(self, dns_server, serial=1, ttl=3600):
super(RootNSRecord, self).__init__()
self.wType = dnsp.DNS_TYPE_NS
self.dwSerial = serial
self.dwTtlSeconds = ttl
self.data = dns_server
self.rank = dnsp.DNS_RANK_ROOT_HINT
class SOARecord(dnsp.DnssrvRpcRecord):
def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
expire=86400, minimum=3600, ttl=3600):
@ -79,153 +134,419 @@ class SRVRecord(dnsp.DnssrvRpcRecord):
srv.wWeight = weight
self.data = srv
def setup_ad_dns(samdb, names, hostip=None, hostip6=None):
domaindn = names.domaindn
dnsdomain = names.dnsdomain.lower()
hostname = names.netbiosname.lower()
dnsname = "%s.%s" % (hostname, dnsdomain)
site = names.sitename
dns_ldif = os.path.join(samba.param.setup_dir(), "provision_dns_add.ldif")
def setup_dns_partitions(samdb, domaindn, forestdn, configdn, serverdn):
dns_data = read_and_sub_file(dns_ldif, {
"DOMAINDN": domaindn,
"DNSDOMAIN" : dnsdomain
})
samdb.add_ldif(dns_data, ["relax:0"])
# FIXME: Default security descriptor for Domain-DNS objectCategory is different in
# our documentation from windows
soa_subrecords = []
dns_records = []
domainzone_dn = "DC=DomainDnsZones,%s" % domaindn
forestzone_dn = "DC=ForestDnsZones,%s" % forestdn
# @ entry for the domain
at_soa_record = SOARecord(dnsname, "hostmaster.%s" % dnsdomain)
soa_subrecords.append(ndr_pack(at_soa_record))
add_ldif(samdb, "provision_dnszones_partitions.ldif", {
"DOMAINZONE_DN": domainzone_dn,
"FORESTZONE_DN": forestzone_dn,
})
at_ns_record = NSRecord(dnsname)
soa_subrecords.append(ndr_pack(at_ns_record))
domainzone_guid = get_domainguid(samdb, domainzone_dn)
forestzone_guid = get_domainguid(samdb, forestzone_dn)
domainzone_guid = str(uuid.uuid4())
forestzone_guid = str(uuid.uuid4())
domainzone_dns = ldb.Dn(samdb, domainzone_dn).canonical_ex_str().strip()
forestzone_dns = ldb.Dn(samdb, forestzone_dn).canonical_ex_str().strip()
add_ldif(samdb, "provision_dnszones_add.ldif", {
"DOMAINZONE_DN": domainzone_dn,
"FORESTZONE_DN": forestzone_dn,
"DOMAINZONE_GUID": domainzone_guid,
"FORESTZONE_GUID": forestzone_guid,
"DOMAINZONE_DNS": domainzone_dns,
"FORESTZONE_DNS": forestzone_dns,
"CONFIGDN": configdn,
})
modify_ldif(samdb, "provision_dnszones_modify.ldif", {
"CONFIGDN": configdn,
"SERVERDN": serverdn,
"DOMAINZONE_DN": domainzone_dn,
"FORESTZONE_DN": forestzone_dn,
})
def add_dns_accounts(samdb, domaindn):
add_ldif(samdb, "provision_dns_accounts_add.ldif", {
"DOMAINDN": domaindn,
})
def add_dns_container(samdb, domaindn, prefix):
# CN=MicrosoftDNS,<PREFIX>,<DOMAINDN>
msg = ldb.Message(ldb.Dn(samdb, "CN=MicrosoftDNS,%s,%s" % (prefix, domaindn)))
msg["objectClass"] = ["top", "container"]
msg["displayName"] = ldb.MessageElement("DNS Servers", ldb.FLAG_MOD_ADD, "displayName")
samdb.add(msg)
def add_rootservers(samdb, domaindn, prefix):
rootservers = {}
rootservers["a.root-servers.net"] = "198.41.0.4"
rootservers["b.root-servers.net"] = "192.228.79.201"
rootservers["c.root-servers.net"] = "192.33.4.12"
rootservers["d.root-servers.net"] = "128.8.10.90"
rootservers["e.root-servers.net"] = "192.203.230.10"
rootservers["f.root-servers.net"] = "192.5.5.241"
rootservers["g.root-servers.net"] = "192.112.36.4"
rootservers["h.root-servers.net"] = "128.63.2.53"
rootservers["i.root-servers.net"] = "192.36.148.17"
rootservers["j.root-servers.net"] = "192.58.128.30"
rootservers["k.root-servers.net"] = "193.0.14.129"
rootservers["l.root-servers.net"] = "199.7.83.42"
rootservers["m.root-servers.net"] = "202.12.27.33"
rootservers_v6 = {}
rootservers_v6["a.root-servers.net"] = "2001:503:ba3e::2:30"
rootservers_v6["f.root-servers.net"] = "2001:500:2f::f"
rootservers_v6["h.root-servers.net"] = "2001:500:1::803f:235"
rootservers_v6["j.root-servers.net"] = "2001:503:c27::2:30"
rootservers_v6["k.root-servers.net"] = "2001:7fd::1"
rootservers_v6["m.root-servers.net"] = "2001:dc3::35"
container_dn = "DC=RootDNSServers,CN=MicrosoftDNS,%s,%s" % (prefix, domaindn)
# Add DC=RootDNSServers,CN=MicrosoftDNS,<PREFIX>,<DOMAINDN>
msg = ldb.Message(ldb.Dn(samdb, container_dn))
msg["objectClass"] = ["top", "dnsZone"]
samdb.add(msg)
# Add DC=@,DC=RootDNSServers,CN=MicrosoftDNS,<PREFIX>,<DOMAINDN>
record = []
for rserver in rootservers:
record.append(ndr_pack(RootNSRecord(rserver, serial=0, ttl=0)))
msg = ldb.Message(ldb.Dn(samdb, "DC=@,%s" % container_dn))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = ldb.MessageElement(record, ldb.FLAG_MOD_ADD, "dnsRecord")
samdb.add(msg)
# Add DC=<rootserver>,DC=RootDNSServers,CN=MicrosoftDNS,<PREFIX>,<DOMAINDN>
for rserver in rootservers:
record = [ndr_pack(ARecord(rootservers[rserver], serial=0, ttl=0))]
# Add AAAA record as well (How does W2K* add IPv6 records?)
#if rserver in rootservers_v6:
# record.append(ndr_pack(AAAARecord(rootservers_v6[rserver], serial=0, ttl=0)))
msg = ldb.Message(ldb.Dn(samdb, "DC=%s,%s" % (rserver, container_dn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = ldb.MessageElement(record, ldb.FLAG_MOD_ADD, "dnsRecord")
samdb.add(msg)
def add_at_record(samdb, container_dn, prefix, hostname, dnsdomain, hostip, hostip6):
fqdn_hostname = "%s.%s" % (hostname, dnsdomain)
at_records = []
# SOA record
at_soa_record = SOARecord(fqdn_hostname, "hostmaster.%s" % dnsdomain)
at_records.append(ndr_pack(at_soa_record))
# NS record
at_ns_record = NSRecord(fqdn_hostname)
at_records.append(ndr_pack(at_ns_record))
if hostip is not None:
# A record
at_a_record = ARecord(hostip)
dns_records.append(ndr_pack(at_a_record))
at_records.append(ndr_pack(at_a_record))
if hostip6 is not None:
# AAAA record
at_aaaa_record = AAAARecord(hostip6)
dns_records.append(ndr_pack(at_aaaa_record))
at_records.append(ndr_pack(at_aaaa_record))
msg = ldb.Message(ldb.Dn(samdb, "DC=@,DC=%s,CN=MicrosoftDNS,CN=System,%s" %\
(dnsdomain, domaindn )))
msg = ldb.Message(ldb.Dn(samdb, "DC=@,%s" % container_dn))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = ldb.MessageElement(soa_subrecords + dns_records,
ldb.FLAG_MOD_ADD, "dnsRecord")
msg["dnsRecord"] = ldb.MessageElement(at_records, ldb.FLAG_MOD_ADD, "dnsRecord")
samdb.add(msg)
# _gc._tcp record
gc_tcp_record = SRVRecord(dnsname, 3268)
msg = ldb.Message(ldb.Dn(samdb,
"DC=_gc._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(dnsdomain, domaindn)))
def add_srv_record(samdb, container_dn, prefix, host, port):
srv_record = SRVRecord(host, port)
msg = ldb.Message(ldb.Dn(samdb, "%s,%s" % (prefix, container_dn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(gc_tcp_record)]
msg["dnsRecord"] = ldb.MessageElement(ndr_pack(srv_record), ldb.FLAG_MOD_ADD, "dnsRecord")
samdb.add(msg)
# _gc._tcp.sitename._site record
msg = ldb.Message(ldb.Dn(samdb,
"DC=_gc._tcp.%s._sites,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(names.sitename, dnsdomain, domaindn)))
def add_ns_record(samdb, container_dn, prefix, host):
ns_record = NSRecord(host)
msg = ldb.Message(ldb.Dn(samdb, "%s,%s" % (prefix, container_dn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(gc_tcp_record)]
msg["dnsRecord"] = ldb.MessageElement(ndr_pack(ns_record), ldb.FLAG_MOD_ADD, "dnsRecord")
samdb.add(msg)
# _kerberos._tcp record
kerberos_record = SRVRecord(dnsname, 88)
msg = ldb.Message(ldb.Dn(samdb,
"DC=_kerberos._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(dnsdomain, domaindn)))
def add_cname_record(samdb, container_dn, prefix, host):
cname_record = CNameRecord(host)
msg = ldb.Message(ldb.Dn(samdb, "%s,%s" % (prefix, container_dn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(kerberos_record)]
msg["dnsRecord"] = ldb.MessageElement(ndr_pack(cname_record), ldb.FLAG_MOD_ADD, "dnsRecord")
samdb.add(msg)
# _kerberos._tcp.sitename._site record
msg = ldb.Message(ldb.Dn(samdb,
"DC=_kerberos._tcp.%s._sites,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(site, dnsdomain, domaindn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(kerberos_record)]
samdb.add(msg)
# _kerberos._udp record
msg = ldb.Message(ldb.Dn(samdb,
"DC=_kerberos._udp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(dnsdomain, domaindn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(kerberos_record)]
samdb.add(msg)
# _kpasswd._tcp record
kpasswd_record = SRVRecord(dnsname, 464)
msg = ldb.Message(ldb.Dn(samdb,
"DC=_kpasswd._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(dnsdomain, domaindn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(kpasswd_record)]
samdb.add(msg)
# _kpasswd._udp record
msg = ldb.Message(ldb.Dn(samdb,
"DC=_kpasswd._udp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(dnsdomain, domaindn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(kpasswd_record)]
samdb.add(msg)
# _ldap._tcp record
ldap_record = SRVRecord(dnsname, 389)
msg = ldb.Message(ldb.Dn(samdb,
"DC=_ldap._tcp,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(dnsdomain, domaindn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(ldap_record)]
samdb.add(msg)
# _ldap._tcp.sitename._site record
msg = ldb.Message(ldb.Dn(samdb,
"DC=_ldap._tcp.%s._site,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(site, dnsdomain, domaindn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(ldap_record)]
samdb.add(msg)
# _msdcs record
msdcs_record = NSRecord(dnsname)
msg = ldb.Message(ldb.Dn(samdb,
"DC=_msdcs,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(dnsdomain, domaindn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = [ndr_pack(msdcs_record)]
samdb.add(msg)
# the host's own record
# Only do this if there's IP addresses to set up.
# This is a bit weird, but the samba4.blackbox.provision.py test apparently
# doesn't set up any IPs
if len(dns_records) > 0:
msg = ldb.Message(ldb.Dn(samdb,
"DC=%s,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(hostname, dnsdomain, domaindn)))
def add_host_record(samdb, container_dn, prefix, hostip, hostip6):
host_records = []
if hostip:
a_record = ARecord(hostip)
host_records.append(ndr_pack(a_record))
if hostip6:
aaaa_record = AAAARecord(hostip6)
host_records.append(ndr_pack(aaaa_record))
if host_records:
msg = ldb.Message(ldb.Dn(samdb, "%s,%s" % (prefix, container_dn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = ldb.MessageElement(dns_records,
ldb.FLAG_MOD_ADD, "dnsRecord")
msg["dnsRecord"] = ldb.MessageElement(host_records, ldb.FLAG_MOD_ADD, "dnsRecord")
samdb.add(msg)
# DomainDnsZones record
msg = ldb.Message(ldb.Dn(samdb,
"DC=DomainDnsZones,DC=%s,CN=MicrosoftDNS,CN=System,%s" % \
(dnsdomain, domaindn)))
msg["objectClass"] = ["top", "dnsNode"]
msg["dnsRecord"] = ldb.MessageElement(dns_records,
ldb.FLAG_MOD_ADD, "dnsRecord")
def add_domain_record(samdb, domaindn, prefix, dnsdomain):
# DC=<DNSDOMAIN>,CN=MicrosoftDNS,<PREFIX>,<DOMAINDN>
msg = ldb.Message(ldb.Dn(samdb, "DC=%s,CN=MicrosoftDNS,%s,%s" % (dnsdomain, prefix, domaindn)))
msg["objectClass"] = ["top", "dnsZone"]
samdb.add(msg)
samdb.add(msg)
def add_msdcs_record(samdb, forestdn, prefix, dnsforest):
# DC=_msdcs.<DNSFOREST>,CN=MicrosoftDNS,<PREFIX>,<FORESTDN>
msg = ldb.Message(ldb.Dn(samdb, "DC=_msdcs.%s,CN=MicrosoftDNS,%s,%s" %
(dnsforest, prefix, forestdn)))
msg["objectClass"] = ["top", "dnsZone"]
samdb.add(msg)
def add_dc_domain_records(samdb, domaindn, prefix, site, dnsdomain, hostname, hostip, hostip6):
fqdn_hostname = "%s.%s" % (hostname, dnsdomain)
# Set up domain container - DC=<DNSDOMAIN>,CN=MicrosoftDNS,<PREFIX>,<DOMAINDN>
domain_container_dn = ldb.Dn(samdb, "DC=%s,CN=MicrosoftDNS,%s,%s" %
(dnsdomain, prefix, domaindn))
# DC=@ record
add_at_record(samdb, domain_container_dn, "DC=@", hostname, dnsdomain, hostip, hostip6)
# DC=<HOSTNAME> record
add_host_record(samdb, domain_container_dn, "DC=%s" % hostname, hostip, hostip6)
# DC=_kerberos._tcp record
add_srv_record(samdb, domain_container_dn, "DC=_kerberos._tcp", fqdn_hostname, 88)
# DC=_kerberos._tcp.<SITENAME>._sites record
add_srv_record(samdb, domain_container_dn, "DC=_kerberos._tcp.%s._sites" % site,
fqdn_hostname, 88)
# DC=_kerberos._udp record
add_srv_record(samdb, domain_container_dn, "DC=_kerberos._udp", fqdn_hostname, 88)
# DC=_kpasswd._tcp record
add_srv_record(samdb, domain_container_dn, "DC=_kpasswd._tcp", fqdn_hostname, 464)
# DC=_kpasswd._udp record
add_srv_record(samdb, domain_container_dn, "DC=_kpasswd._udp", fqdn_hostname, 464)
# DC=_ldap._tcp record
add_srv_record(samdb, domain_container_dn, "DC=_ldap._tcp", fqdn_hostname, 389)
# DC=_ldap._tcp.<SITENAME>._sites record
add_srv_record(samdb, domain_container_dn, "DC=_ldap._tcp.%s._sites" % site,
fqdn_hostname, 389)
# FIXME: The number of SRV records depend on the various roles this DC has.
# _gc and _msdcs records are added if the we are the forest dc and not subdomain dc
#
# Assumption: current DC is GC and add all the entries
# DC=_gc._tcp record
add_srv_record(samdb, domain_container_dn, "DC=_gc._tcp", fqdn_hostname, 3268)
# DC=_gc._tcp.<SITENAME>,_sites record
add_srv_record(samdb, domain_container_dn, "DC=_gc._tcp.%s._sites" % site, fqdn_hostname, 3268)
# DC=_msdcs record
add_ns_record(samdb, domain_container_dn, "DC=_msdcs", fqdn_hostname)
# FIXME: Following entries are added only if DomainDnsZones and ForestDnsZones partitions
# are created
#
# Assumption: Additional entries won't hurt on os_level = 2000
# DC=_ldap._tcp.<SITENAME>._sites.DomainDnsZones
add_srv_record(samdb, domain_container_dn, "DC=_ldap._tcp.%s._sites.DomainDnsZones" % site,
fqdn_hostname, 389)
# DC=_ldap._tcp.<SITENAME>._sites.ForestDnsZones
add_srv_record(samdb, domain_container_dn, "DC=_ldap._tcp.%s._sites.ForestDnsZones" % site,
fqdn_hostname, 389)
# DC=_ldap._tcp.DomainDnsZones
add_srv_record(samdb, domain_container_dn, "DC=_ldap._tcp.DomainDnsZones",
fqdn_hostname, 389)
# DC=_ldap._tcp.ForestDnsZones
add_srv_record(samdb, domain_container_dn, "DC=_ldap._tcp.ForestDnsZones",
fqdn_hostname, 389)
# DC=DomainDnsZones
add_host_record(samdb, domain_container_dn, "DC=DomainDnsZones", hostip, hostip6)
# DC=ForestDnsZones
add_host_record(samdb, domain_container_dn, "DC=ForestDnsZones", hostip, hostip6)
def add_dc_msdcs_records(samdb, forestdn, prefix, site, dnsforest, hostname,
hostip, hostip6, domainguid, ntdsguid):
fqdn_hostname = "%s.%s" % (hostname, dnsforest)
# Set up forest container - DC=<DNSDOMAIN>,CN=MicrosoftDNS,<PREFIX>,<DOMAINDN>
forest_container_dn = ldb.Dn(samdb, "DC=_msdcs.%s,CN=MicrosoftDNS,%s,%s" %
(dnsforest, prefix, forestdn))
# DC=@ record
add_at_record(samdb, forest_container_dn, "DC=@", hostname, dnsforest, None, None)
# DC=_kerberos._tcp.dc record
add_srv_record(samdb, forest_container_dn, "DC=_kerberos._tcp.dc", fqdn_hostname, 88)
# DC=_kerberos._tcp.<SITENAME>._sites.dc record
add_srv_record(samdb, forest_container_dn, "DC=_kerberos._tcp.%s._sites.dc" % site,
fqdn_hostname, 88)
# DC=_ldap._tcp.dc record
add_srv_record(samdb, forest_container_dn, "DC=_ldap._tcp.dc", fqdn_hostname, 389)
# DC=_ldap._tcp.<SITENAME>._sites.dc record
add_srv_record(samdb, forest_container_dn, "DC=_ldap._tcp.%s._sites.dc" % site,
fqdn_hostname, 389)
# DC=_ldap._tcp.<SITENAME>._sites.gc record
add_srv_record(samdb, forest_container_dn, "DC=_ldap._tcp.%s._sites.gc" % site,
fqdn_hostname, 3268)
# DC=_ldap._tcp.gc record
add_srv_record(samdb, forest_container_dn, "DC=_ldap._tcp.gc", fqdn_hostname, 3268)
# DC=_ldap._tcp.pdc record
add_srv_record(samdb, forest_container_dn, "DC=_ldap._tcp.pdc", fqdn_hostname, 389)
# DC=gc record
add_host_record(samdb, forest_container_dn, "DC=gc", hostip, hostip6)
# DC=_ldap._tcp.<DOMAINGUID>.domains record
add_srv_record(samdb, forest_container_dn, "DC=_ldap._tcp.%s.domains" % domainguid,
fqdn_hostname, 389)
# DC=<NTDSGUID>
add_cname_record(samdb, forest_container_dn, "DC=%s" % ntdsguid, fqdn_hostname)
def setup_ad_dns(samdb, names, logger, hostip=None, hostip6=None, dns_backend=None,
os_level=None):
"""Provision DNS information (assuming GC role)
:param samdb: LDB object connected to sam.ldb file
:param names: Names shortcut
:param logger: Logger object
:param hostip: IPv4 address
:param hostip6: IPv6 address
:param dns_backend: Type of DNS backend
:param os_level: Functional level (treated as os level)
"""
if dns_backend is None:
dns_backend = "BIND9"
logger.info("Assuming bind9 DNS server backend")
# If dns_backend is BIND9
# Populate only CN=MicrosoftDNS,CN=System,<DOMAINDN>
#
# If dns_backend is SAMBA or BIND9_DLZ
# Populate DNS partitions
if os_level is None:
os_level = DS_DOMAIN_FUNCTION_2003
# If os_level < 2003 (DS_DOMAIN_FUNCTION_2000)
# All dns records are in CN=MicrosoftDNS,CN=System,<DOMAINDN>
#
# If os_level >= 2003 (DS_DOMAIN_FUNCTION_2003, DS_DOMAIN_FUNCTION_2008,
# DS_DOMAIN_FUNCTION_2008_R2)
# Root server records are in CN=MicrosoftDNS,CN=System,<DOMAINDN>
# Domain records are in CN=MicrosoftDNS,CN=System,<DOMAINDN>
# Domain records are in CN=MicrosoftDNS,DC=DomainDnsZones,<DOMAINDN>
# Forest records are in CN=MicrosoftDNS,DC=ForestDnsZones,<DOMAINDN>
domaindn = names.domaindn
forestdn = samdb.get_root_basedn().get_linearized()
dnsdomain = names.dnsdomain.lower()
dnsforest = dnsdomain
hostname = names.netbiosname.lower()
site = names.sitename
domainguid = get_domainguid(samdb, domaindn)
ntdsguid = get_ntdsguid(samdb, domaindn)
# Add dns accounts (DnsAdmins, DnsUpdateProxy) in domain
logger.info("Adding DNS accounts")
add_dns_accounts(samdb, domaindn)
logger.info("Populating CN=System,%s" % domaindn)
# Set up MicrosoftDNS container
add_dns_container(samdb, domaindn, "CN=System")
# Add root servers
add_rootservers(samdb, domaindn, "CN=System")
if os_level == DS_DOMAIN_FUNCTION_2000:
# Add domain record
add_domain_record(samdb, domaindn, "CN=System", dnsdomain)
# Add DNS records for a DC in domain
add_dc_domain_records(samdb, domaindn, "CN=System", site, dnsdomain,
hostname, hostip, hostip6)
elif (dns_backend == "SAMBA" or dns_backend == "BIND9_DLZ") and (
os_level == DS_DOMAIN_FUNCTION_2003 or
os_level == DS_DOMAIN_FUNCTION_2008 or
os_level == DS_DOMAIN_FUNCTION_2008_R2):
# Set up additional partitions (DomainDnsZones, ForstDnsZones)
logger.info("Creating DomainDnsZones and ForestDnsZones partitions")
setup_dns_partitions(samdb, domaindn, forestdn, names.configdn, names.serverdn)
##### Set up DC=DomainDnsZones,<DOMAINDN>
logger.info("Populating DomainDnsZones partition")
# Set up MicrosoftDNS container
add_dns_container(samdb, domaindn, "DC=DomainDnsZones")
# Add rootserver records
add_rootservers(samdb, domaindn, "DC=DomainDnsZones")
# Add domain record
add_domain_record(samdb, domaindn, "DC=DomainDnsZones", dnsdomain)
# Add DNS records for a DC in domain
add_dc_domain_records(samdb, domaindn, "DC=DomainDnsZones", site, dnsdomain,
hostname, hostip, hostip6)
##### Set up DC=ForestDnsZones,<DOMAINDN>
logger.info("Populating ForestDnsZones partition")
# Set up MicrosoftDNS container
add_dns_container(samdb, forestdn, "DC=ForestDnsZones")
# Add _msdcs record
add_msdcs_record(samdb, forestdn, "DC=ForestDnsZones", dnsforest)
# Add DNS records for a DC in forest
add_dc_msdcs_records(samdb, forestdn, "DC=ForestDnsZones", site, dnsforest,
hostname, hostip, hostip6, domainguid, ntdsguid)