add mail alias checks and other cleanup
This commit is contained in:
parent
deab8974ec
commit
343886d818
|
@ -8,10 +8,14 @@ import dns.reversename, dns.resolver
|
||||||
|
|
||||||
from dns_update import get_dns_zones
|
from dns_update import get_dns_zones
|
||||||
from web_update import get_web_domains, get_domain_ssl_files
|
from web_update import get_web_domains, get_domain_ssl_files
|
||||||
|
from mailconfig import get_mail_domains, get_mail_aliases
|
||||||
|
|
||||||
from utils import shell, sort_domains
|
from utils import shell, sort_domains
|
||||||
|
|
||||||
def run_checks(env):
|
def run_checks(env):
|
||||||
|
# Get the list of domains we handle mail for.
|
||||||
|
mail_domains = get_mail_domains(env)
|
||||||
|
|
||||||
# Get the list of domains we serve DNS zones for (i.e. does not include subdomains).
|
# Get the list of domains we serve DNS zones for (i.e. does not include subdomains).
|
||||||
dns_zonefiles = dict(get_dns_zones(env))
|
dns_zonefiles = dict(get_dns_zones(env))
|
||||||
dns_domains = set(dns_zonefiles)
|
dns_domains = set(dns_zonefiles)
|
||||||
|
@ -20,13 +24,25 @@ def run_checks(env):
|
||||||
web_domains = set(get_web_domains(env))
|
web_domains = set(get_web_domains(env))
|
||||||
|
|
||||||
# Check the domains.
|
# Check the domains.
|
||||||
for domain in sort_domains(dns_domains | web_domains, env):
|
for domain in sort_domains(mail_domains | dns_domains | web_domains, env):
|
||||||
print(domain)
|
print(domain)
|
||||||
print("=" * len(domain))
|
print("=" * len(domain))
|
||||||
if domain == env["PUBLIC_HOSTNAME"]: check_primary_hostname_dns(domain, env)
|
|
||||||
if domain in dns_domains: check_dns_zone(domain, env, dns_zonefiles)
|
if domain == env["PUBLIC_HOSTNAME"]:
|
||||||
check_mx(domain, env)
|
check_primary_hostname_dns(domain, env)
|
||||||
check_ssl_cert(domain, env)
|
|
||||||
|
if domain in dns_domains:
|
||||||
|
check_dns_zone(domain, env, dns_zonefiles)
|
||||||
|
|
||||||
|
if domain in mail_domains:
|
||||||
|
check_mail_domain(domain, env)
|
||||||
|
|
||||||
|
if domain == env["PUBLIC_HOSTNAME"] or domain in web_domains:
|
||||||
|
# We need a SSL certificate for PUBLIC_HOSTNAME because that's where the
|
||||||
|
# user will log in with IMAP or webmail. Any other domain we serve a
|
||||||
|
# website for also needs a signed certificate.
|
||||||
|
check_ssl_cert(domain, env)
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
def check_primary_hostname_dns(domain, env):
|
def check_primary_hostname_dns(domain, env):
|
||||||
|
@ -61,6 +77,16 @@ def check_primary_hostname_dns(domain, env):
|
||||||
print_error("""Your box's reverse DNS is currently %s, but it should be %s. Your ISP or cloud provider will have instructions
|
print_error("""Your box's reverse DNS is currently %s, but it should be %s. Your ISP or cloud provider will have instructions
|
||||||
on setting up reverse DNS for your box at %s.""" % (existing_rdns, domain, env['PUBLIC_IP']) )
|
on setting up reverse DNS for your box at %s.""" % (existing_rdns, domain, env['PUBLIC_IP']) )
|
||||||
|
|
||||||
|
# Check that the hostmaster@ email address exists.
|
||||||
|
check_alias_exists("hostmaster@" + domain, env)
|
||||||
|
|
||||||
|
def check_alias_exists(alias, env):
|
||||||
|
mail_alises = dict(get_mail_aliases(env))
|
||||||
|
if alias in mail_alises:
|
||||||
|
print_ok("%s exists as a mail alias [=> %s]" % (alias, mail_alises[alias]))
|
||||||
|
else:
|
||||||
|
print_error("""You must add a mail alias for %s and direct email to you or another administrator.""" % alias)
|
||||||
|
|
||||||
def check_dns_zone(domain, env, dns_zonefiles):
|
def check_dns_zone(domain, env, dns_zonefiles):
|
||||||
# We provide a DNS zone for the domain. It should have NS records set up
|
# We provide a DNS zone for the domain. It should have NS records set up
|
||||||
# at the domain name's registrar pointing to this box.
|
# at the domain name's registrar pointing to this box.
|
||||||
|
@ -106,7 +132,7 @@ def check_dns_zone(domain, env, dns_zonefiles):
|
||||||
print(" " + ds_correct)
|
print(" " + ds_correct)
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
def check_mx(domain, env):
|
def check_mail_domain(domain, env):
|
||||||
# Check the MX record.
|
# Check the MX record.
|
||||||
mx = query_dns(domain, "MX")
|
mx = query_dns(domain, "MX")
|
||||||
expected_mx = "10 " + env['PUBLIC_HOSTNAME']
|
expected_mx = "10 " + env['PUBLIC_HOSTNAME']
|
||||||
|
@ -117,14 +143,14 @@ def check_mx(domain, env):
|
||||||
be delivered to this box. It may take several hours for public DNS to update after a change. This problem may result from
|
be delivered to this box. It may take several hours for public DNS to update after a change. This problem may result from
|
||||||
other issues listed here.""" % (mx, expected_mx))
|
other issues listed here.""" % (mx, expected_mx))
|
||||||
|
|
||||||
|
# Check that the postmaster@ email address exists.
|
||||||
|
check_alias_exists("postmaster@" + domain, env)
|
||||||
|
|
||||||
def query_dns(qname, rtype, nxdomain='[Not Set]'):
|
def query_dns(qname, rtype, nxdomain='[Not Set]'):
|
||||||
resolver = dns.resolver.get_default_resolver()
|
resolver = dns.resolver.get_default_resolver()
|
||||||
try:
|
try:
|
||||||
response = dns.resolver.query(qname, rtype)
|
response = dns.resolver.query(qname, rtype)
|
||||||
except dns.resolver.NoNameservers:
|
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
||||||
# Could not reach nameserver.
|
|
||||||
raise
|
|
||||||
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
|
||||||
# Host did not have an answer for this query; not sure what the
|
# Host did not have an answer for this query; not sure what the
|
||||||
# difference is between the two exceptions.
|
# difference is between the two exceptions.
|
||||||
return nxdomain
|
return nxdomain
|
||||||
|
@ -137,6 +163,10 @@ def query_dns(qname, rtype, nxdomain='[Not Set]'):
|
||||||
def check_ssl_cert(domain, env):
|
def check_ssl_cert(domain, env):
|
||||||
# Check that SSL certificate is signed.
|
# Check that SSL certificate is signed.
|
||||||
|
|
||||||
|
# Skip the check if the A record is not pointed here.
|
||||||
|
if query_dns(domain, "A") != env['PUBLIC_IP']: return
|
||||||
|
|
||||||
|
# Where is the SSL stored?
|
||||||
ssl_key, ssl_certificate, ssl_csr_path = get_domain_ssl_files(domain, env)
|
ssl_key, ssl_certificate, ssl_csr_path = get_domain_ssl_files(domain, env)
|
||||||
|
|
||||||
if not os.path.exists(ssl_certificate):
|
if not os.path.exists(ssl_certificate):
|
||||||
|
|
|
@ -16,9 +16,10 @@ def get_dns_domains(env):
|
||||||
domains.add(env['PUBLIC_HOSTNAME'])
|
domains.add(env['PUBLIC_HOSTNAME'])
|
||||||
return domains
|
return domains
|
||||||
|
|
||||||
def get_dns_zones(domains, env):
|
def get_dns_zones(env):
|
||||||
# What domains should we create DNS zones for? Never create a zone for
|
# What domains should we create DNS zones for? Never create a zone for
|
||||||
# a domain & a subdomain of that domain.
|
# a domain & a subdomain of that domain.
|
||||||
|
domains = get_dns_domains(env)
|
||||||
|
|
||||||
# Exclude domains that are subdomains of other domains we know. Proceed
|
# Exclude domains that are subdomains of other domains we know. Proceed
|
||||||
# by looking at shorter domains first.
|
# by looking at shorter domains first.
|
||||||
|
@ -49,7 +50,7 @@ def get_dns_zones(domains, 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?
|
||||||
domains = get_dns_domains(env)
|
domains = get_dns_domains(env)
|
||||||
zonefiles = get_dns_zones(domains, env)
|
zonefiles = get_dns_zones(env)
|
||||||
|
|
||||||
# Write zone files.
|
# Write zone files.
|
||||||
os.makedirs('/etc/nsd/zones', exist_ok=True)
|
os.makedirs('/etc/nsd/zones', exist_ok=True)
|
||||||
|
|
Loading…
Reference in New Issue