if we handle mail for both a domain and any subdomain, only create a zone for the domain and put the subdomain's DNS records in the main domain's zone file
This commit is contained in:
parent
4668367420
commit
deab8974ec
|
@ -8,28 +8,33 @@ import rtyaml
|
||||||
from mailconfig import get_mail_domains
|
from mailconfig import get_mail_domains
|
||||||
from utils import shell, load_env_vars_from_file, safe_domain_name, sort_domains
|
from utils import shell, load_env_vars_from_file, safe_domain_name, sort_domains
|
||||||
|
|
||||||
def get_dns_zones(env):
|
def get_dns_domains(env):
|
||||||
# What domains should we serve DNS for?
|
# Add all domain names in use by email users and mail aliases and ensure
|
||||||
|
# PUBLIC_HOSTNAME is in the list.
|
||||||
domains = set()
|
domains = set()
|
||||||
|
|
||||||
# Add all domain names in use by email users and mail aliases.
|
|
||||||
domains |= get_mail_domains(env)
|
domains |= get_mail_domains(env)
|
||||||
|
domains.add(env['PUBLIC_HOSTNAME'])
|
||||||
|
return domains
|
||||||
|
|
||||||
# Ensure the PUBLIC_HOSTNAME is in that list if it is not a subdomain of
|
def get_dns_zones(domains, env):
|
||||||
# any other domain we manage. If it's a subdomain, having it be a separate
|
# What domains should we create DNS zones for? Never create a zone for
|
||||||
# zone will confuse DNSSEC because it will be signed without having a DS
|
# a domain & a subdomain of that domain.
|
||||||
# record at the parent.
|
|
||||||
for d in domains:
|
# Exclude domains that are subdomains of other domains we know. Proceed
|
||||||
if env['PUBLIC_HOSTNAME'].endswith("." + d):
|
# by looking at shorter domains first.
|
||||||
break
|
zone_domains = set()
|
||||||
else:
|
for domain in sorted(domains, key=lambda d : len(d)):
|
||||||
# No 'break' was executed, so it is not a subdomain of a domain
|
for d in zone_domains:
|
||||||
# we know about. Thus add it.
|
if domain.endswith("." + d):
|
||||||
domains.add(env['PUBLIC_HOSTNAME'])
|
# We found a parent domain already in the list.
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# 'break' did not occur: there is no parent domain.
|
||||||
|
zone_domains.add(domain)
|
||||||
|
|
||||||
# Make a nice and safe filename for each domain.
|
# Make a nice and safe filename for each domain.
|
||||||
zonefiles = []
|
zonefiles = []
|
||||||
for domain in domains:
|
for domain in zone_domains:
|
||||||
zonefiles.append([domain, safe_domain_name(domain) + ".txt"])
|
zonefiles.append([domain, safe_domain_name(domain) + ".txt"])
|
||||||
|
|
||||||
# Sort the list so that the order is nice and so that nsd.conf has a
|
# Sort the list so that the order is nice and so that nsd.conf has a
|
||||||
|
@ -43,14 +48,16 @@ def get_dns_zones(env):
|
||||||
|
|
||||||
def do_dns_update(env):
|
def do_dns_update(env):
|
||||||
# What domains (and their zone filenames) should we build?
|
# What domains (and their zone filenames) should we build?
|
||||||
zonefiles = get_dns_zones(env)
|
domains = get_dns_domains(env)
|
||||||
|
zonefiles = get_dns_zones(domains, env)
|
||||||
|
|
||||||
# Write zone files.
|
# Write zone files.
|
||||||
os.makedirs('/etc/nsd/zones', exist_ok=True)
|
os.makedirs('/etc/nsd/zones', exist_ok=True)
|
||||||
updated_domains = []
|
updated_domains = []
|
||||||
for i, (domain, zonefile) in enumerate(zonefiles):
|
for i, (domain, zonefile) in enumerate(zonefiles):
|
||||||
# Build the records to put in the zone.
|
# Build the records to put in the zone.
|
||||||
records = build_zone(domain, zonefile, env)
|
subdomains = [d for d in domains if d.endswith("." + domain)]
|
||||||
|
records = build_zone(domain, zonefile, subdomains, env)
|
||||||
|
|
||||||
# See if the zone has changed, and if so update the serial number
|
# See if the zone has changed, and if so update the serial number
|
||||||
# and write the zone file.
|
# and write the zone file.
|
||||||
|
@ -111,7 +118,7 @@ def do_dns_update(env):
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
def build_zone(domain, zonefile, env, with_ns=True):
|
def build_zone(domain, zonefile, subdomains, env, with_ns=True):
|
||||||
records = []
|
records = []
|
||||||
|
|
||||||
# For top-level zones, define ourselves as the authoritative name server.
|
# For top-level zones, define ourselves as the authoritative name server.
|
||||||
|
@ -122,14 +129,15 @@ def build_zone(domain, zonefile, env, with_ns=True):
|
||||||
records.append((None, "MX", "10 %s." % env["PUBLIC_HOSTNAME"]))
|
records.append((None, "MX", "10 %s." % env["PUBLIC_HOSTNAME"]))
|
||||||
records.append((None, "TXT", '"v=spf1 mx -all"'))
|
records.append((None, "TXT", '"v=spf1 mx -all"'))
|
||||||
|
|
||||||
# If PUBLIC_HOSTNAME is a subdomain of this domain, define it here.
|
# If we need to define DNS for any subdomains of this domain, include it
|
||||||
if env['PUBLIC_HOSTNAME'].endswith("." + domain):
|
# in the zone.
|
||||||
ph = env['PUBLIC_HOSTNAME'][0:-len("." + domain)]
|
for subdomain in subdomains:
|
||||||
for child_qname, child_rtype, child_value in build_zone(env['PUBLIC_HOSTNAME'], None, env, with_ns=False):
|
subdomain_qname = subdomain[0:-len("." + domain)]
|
||||||
|
for child_qname, child_rtype, child_value in build_zone(subdomain, None, [], env, with_ns=False):
|
||||||
if child_qname == None:
|
if child_qname == None:
|
||||||
child_qname = ph
|
child_qname = subdomain_qname
|
||||||
else:
|
else:
|
||||||
child_qname += "." + ph
|
child_qname += "." + subdomain_qname
|
||||||
records.append((child_qname, child_rtype, child_value))
|
records.append((child_qname, child_rtype, child_value))
|
||||||
|
|
||||||
# In PUBLIC_HOSTNAME...
|
# In PUBLIC_HOSTNAME...
|
||||||
|
|
Loading…
Reference in New Issue