dns-ansible/main.py
Jeltz 220f268fef
Convert some 'str' arguments to 'dns.name.Name'
It seems to be required by dnspython.
2021-12-22 09:30:51 +01:00

211 lines
7.9 KiB
Python
Executable file

#!/usr/bin/env python3
import dns
from dns import rdata, rdataclass, rdatatype
from dns.zone import Zone
from dns.rdtypes.ANY import CNAME, MX, NS, SOA, TXT
from dns.rdtypes.IN import A, AAAA
SOA_SERIAL_TIME = 31695
SOA_REFRESH_TIME = 8640
SOA_RETRY_TIME = 7200
SOA_EXPIRE_TIME = 3600000
SOA_TIME_TO_LIVE = 10800
def format_rname(mail: str) -> dns.name.Name:
"""
Given an email address in the standard string format `mail@example.tld`
return an email address in the format required by RFC 1035
`mail.example.tld.`
Be careful when using this function. It is a very simple email parsing
function and does support the wide range of possible emails format. It also
does not check is email is valid and does not escape caracters.
Return a `dns.name.Name` object.
"""
local, domain = mail.split("@")
rname = dns.name.Name((local, *dns.name.from_text(domain)))
return rname
class Record:
def __init__(self, name: str, dns_rdata: rdata.Rdata):
self.name = name
self.dns_rdata = dns_rdata
self.dataclass = dns_rdata.rdclass
self.datatype = dns_rdata.rdtype
class IPv4Record(Record):
def __init__(self, name: str, address: str):
super().__init__(name, A.A(rdataclass.IN, rdatatype.A, address))
class IPv6Record(Record):
def __init__(self, name: str, address: str):
super().__init__(name, AAAA.AAAA(rdataclass.IN, rdatatype.AAAA, address))
class CanonicalNameRecord(Record):
def __init__(self, name: str, address: str):
super().__init__(
name,
CNAME.CNAME(rdataclass.IN, rdatatype.CNAME, dns.name.from_text(address)),
)
class MailExchangeRecord(Record):
def __init__(self, name: str, priority: int, exchange: str):
super().__init__(
name,
MX.MX(rdataclass.IN, rdatatype.MX, priority, dns.name.from_text(exchange)),
)
class NameServerRecord(Record):
def __init__(self, name: str, address: str):
super().__init__(
name, NS.NS(rdataclass.IN, rdatatype.NS, dns.name.from_text(address))
)
class TextRecord(Record):
def __init__(self, name: str, data: str):
super().__init__(name, TXT.TXT(rdataclass.IN, rdatatype.TXT, data))
class StartOfAuthorityRecord(Record):
def __init__(
self,
name: str,
address: str,
rname: str,
serial=SOA_SERIAL_TIME,
refresh=SOA_REFRESH_TIME,
retry=SOA_RETRY_TIME,
expire=SOA_EXPIRE_TIME,
ttl=SOA_TIME_TO_LIVE,
):
super().__init__(
name,
SOA.SOA(
rdataclass.IN,
rdatatype.SOA,
dns.name.from_text(address),
format_rname(rname),
serial,
refresh,
retry,
expire,
ttl,
),
)
def main() -> int:
# Sample from "dns.auro.re.zone" file
origin = "auro.re."
records = [
CanonicalNameRecord("auth", "proxy-ovh.auro.re."),
CanonicalNameRecord("belenios", "proxy-ovh.auro.re."),
CanonicalNameRecord("cas", "proxy-ovh.auro.re."),
CanonicalNameRecord("chat", "proxy-ovh.auro.re."),
CanonicalNameRecord("codimd", "proxy-ovh.auro.re."),
CanonicalNameRecord("dns-main", "serge.auro.re."),
CanonicalNameRecord("dns-secondary", "lama.auro.re."),
CanonicalNameRecord("drone", "proxy.auro.re."),
CanonicalNameRecord("element", "proxy-ovh.auro.re."),
CanonicalNameRecord("etherpad", "proxy-ovh.auro.re."),
CanonicalNameRecord("gitea", "proxy.auro.re."),
CanonicalNameRecord("grafana", "proxy.auro.re."),
CanonicalNameRecord("hedgedoc", "proxy-ovh.auro.re."),
CanonicalNameRecord("imap", "mail.auro.re."),
CanonicalNameRecord("intranet", "proxy.auro.re."),
CanonicalNameRecord("jitsi", "jitsi-aurore.auro.re."),
CanonicalNameRecord("kanboard", "proxy-ovh.auro.re."),
CanonicalNameRecord("litl", "proxy.auro.re."),
CanonicalNameRecord("netbox", "proxy.auro.re."),
CanonicalNameRecord("nextcloud", "proxy.auro.re."),
CanonicalNameRecord("pad", "proxy-ovh.auro.re."),
CanonicalNameRecord("passbolt", "proxy-ovh.auro.re."),
CanonicalNameRecord("paste", "proxy-ovh.auro.re."),
CanonicalNameRecord("phabricator", "proxy-ovh.auro.re."),
CanonicalNameRecord("portail-edc", "portail.accueil.edc.auro.re."),
CanonicalNameRecord("portail-fleming", "portail.accueil.fleming.auro.re."),
CanonicalNameRecord("portail-gs", "portail.accueil.sand.auro.re."),
CanonicalNameRecord("portail-pacaterie", "portail.accueil.pacaterie.auro.re."),
CanonicalNameRecord("portail-rives", "portail.accueil.rives.auro.re."),
CanonicalNameRecord("privatebin", "proxy-ovh.auro.re."),
CanonicalNameRecord("radius", "radius-aurore.auro.re."),
CanonicalNameRecord("re2o", "proxy.auro.re."),
CanonicalNameRecord("re2o-server", "proxy.auro.re."),
CanonicalNameRecord("re2o-test", "proxy.auro.re."),
CanonicalNameRecord("riot", "proxy-ovh.auro.re."),
CanonicalNameRecord("rss", "proxy-ovh.auro.re."),
CanonicalNameRecord("sharelatex", "proxy-ovh.auro.re."),
CanonicalNameRecord("smtp", "mail.auro.re."),
CanonicalNameRecord("status", "proxy-ovh.auro.re."),
CanonicalNameRecord("virtu", "horus.auro.re."),
CanonicalNameRecord("vote", "proxy.auro.re."),
CanonicalNameRecord("wiki", "proxy.auro.re."),
CanonicalNameRecord("wikijs", "proxy.auro.re."),
CanonicalNameRecord("www", "proxy-ovh.auro.re."),
CanonicalNameRecord("zero", "proxy-ovh.auro.re."),
IPv4Record("@", "92.222.211.195"),
IPv4Record("camelot", "45.66.111.59"),
IPv4Record("dns-aurore", "45.66.111.253"),
IPv4Record("galene", "45.66.111.65"),
IPv4Record("horus", "94.23.218.136"),
IPv4Record("jitsi-aurore", "45.66.111.55"),
IPv4Record("lama", "185.230.78.238"),
IPv4Record("mail", "45.66.111.62"),
IPv4Record("passerelle", "45.66.111.254"),
IPv4Record("proxy", "45.66.111.61"),
IPv4Record("proxy-ovh", "92.222.211.195"),
IPv4Record("radius-aurore", "45.66.111.251"),
IPv4Record("router-infra", "45.66.111.10"),
IPv4Record("routeur-aurore", "45.66.111.240"),
IPv4Record("routeur-aurore-backup", "45.66.111.140"),
IPv4Record("routeur-ovh", "92.222.211.198"),
IPv4Record("serge", "92.222.211.196"),
IPv4Record("vpn-ovh", "92.222.211.197"),
IPv6Record("camelot", "2a09:6840:111::59"),
IPv6Record("dns-aurore", "2a09:6840:111::253"),
IPv6Record("galene", "2a09:6840:111:0:1ccb:e1ff:feab:5d88"),
IPv6Record("jitsi-aurore", "2a09:6840:111::55"),
IPv6Record("lama", "2a0c:700:12:0:42:55ff:fe46:5ac5"),
IPv6Record("mail", "2a09:6840:111::62"),
IPv6Record("passerelle", "2a09:6840:111::254"),
IPv6Record("proxy", "2a09:6840:111::61"),
IPv6Record("radius-aurore", "2a09:6840:111::251"),
IPv6Record("router-infra", "2a09:6841:111:0:10::"),
IPv6Record("routeur-aurore", "2a09:6840:111::240"),
IPv6Record("routeur-aurore-backup", "2a09:6840:111::140"),
MailExchangeRecord("@", 5, "mail.auro.re."),
MailExchangeRecord("@", 10, "proxy-ovh.auro.re."),
NameServerRecord("@", "lama.auro.re."),
NameServerRecord("@", "serge.auro.re."),
StartOfAuthorityRecord("auro.re.", "serge.auro.re", "mail@fede-aurore.net"),
TextRecord("@", "v=spf1 mx ~all"),
]
zone = Zone(origin)
for record in records:
node = zone.get_node(record.name, create=True)
dataset = node.get_rdataset(record.dataclass, record.datatype, create=True)
dataset.add(record.dns_rdata)
print(zone.to_text(relativize=False))
return 0
if __name__ == "__main__":
exit(main())