dns-sync script near to completion

This commit is contained in:
Sebastian Lohff 2017-04-07 15:06:05 +02:00
parent a9863ed5c2
commit f10c9433c0
1 changed files with 63 additions and 80 deletions

View File

@ -9,7 +9,8 @@ import requests
import django import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dnmgmt.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dnmgmt.settings")
sys.path.append("..") BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
django.setup() django.setup()
from django.db.models import Count from django.db.models import Count
@ -32,11 +33,11 @@ def _parser():
return parser return parser
def mergeDomains(domains, zoneData): def mergeDomains(zoneData, pdnsData):
rrAdd = [] rrAdd = []
rrData = zoneData['rrsets'] rrData = pdnsData['rrsets']
for domain, rrType, records in domains: for domain, rrType, records in zoneData:
found = False found = False
pdnsDom = list(filter(lambda _x: _x['name'] == domain and _x['type'] == rrType, rrData)) pdnsDom = list(filter(lambda _x: _x['name'] == domain and _x['type'] == rrType, rrData))
if len(pdnsDom) > 0: if len(pdnsDom) > 0:
@ -57,13 +58,13 @@ def mergeDomains(domains, zoneData):
return rrAdd return rrAdd
def removeOldDomains(domains, zoneData): def removeOldDomains(zoneData, pdnsData):
rrDel = [] rrDel = []
for entry in zoneData['rrsets']: for entry in pdnsData['rrsets']:
# search for name/type in domain dict. if non-existtant mark for deletion # search for name/type in domain dict. if non-existtant mark for deletion
# this could be much more efficient with a dict! name: [rrset...] # this could be much more efficient with a dict! name: [rrset...]
if not any(entry['name'] == _x[0] and entry['type'] == _x[1] for _x in domains): if not any(entry['name'] == _x[0] and entry['type'] == _x[1] for _x in zoneData):
rrDel.append({ rrDel.append({
"changetype": "DELETE", "changetype": "DELETE",
"name": entry["name"], "name": entry["name"],
@ -83,10 +84,44 @@ def handleNameserver(ns, servers, usedNameservers, domains):
domains.append((ns.name, "AAAA", [ns.glueIPv6])) domains.append((ns.name, "AAAA", [ns.glueIPv6]))
def getDomainsFromQueryset(qs, zone, glueRecords, usedNameservers):
for domain in qs:
servers = []
for ns in domain.nameservers.all():
servers.append(ns.name)
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
usedNameservers.append(ns.name)
if ns.glueIPv4:
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
zone.append((domain.getZone(), "NS", servers))
def mergeDomainsWithPdns(s, args, zone, zoneData, protectedRecords=[]):
url = "http://potatos.portal.dn:8081/api/v1/servers/localhost/zones/%s" % (zone,)
pdnsData = s.get(url).json()
# add dn. (NS + glue Nameservers)
newDomains = mergeDomains(zoneData, pdnsData)
print("Add/replace", newDomains)
if len(newDomains) > 0:
r = s.patch(url, data=json.dumps({'rrsets': newDomains}))
if r.status_code != 204:
raise RuntimeError("Could not update records in powerdns")
delDomains = removeOldDomains(zoneData, zoneData + protectedRecords)
print("Del", delDomains)
r = s.patch(url, data=json.dumps({'rrsets': delDomains}))
if r.status_code != 204:
raise RuntimeError("Could not update records in powerdns")
def main(): def main():
parser = _parser() parser = _parser()
args = parser.parse_args() args = parser.parse_args()
print(args)
s = requests.Session() s = requests.Session()
s.headers = { s.headers = {
@ -94,88 +129,36 @@ def main():
'Accept': 'application/json' 'Accept': 'application/json'
} }
print(" --> TLD dn.")
zoneData = s.get("http://potatos.portal.dn:8081/api/v1/servers/localhost/zones/dn.").json()
domains = [] domains = []
rzone4 = []
rzone6 = []
usedNameservers = [] usedNameservers = []
# assenble domain data
# dn.
qs = Domain.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("name") qs = Domain.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("name")
getDomainsFromQueryset(qs, domains, domains, usedNameservers)
# cycle through all domains # reverse zones
for domain in qs: qs = ReverseZone.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("parentNet__address")
print(" %s" % (domain.name)) qs4 = filter(lambda _revz: _revz.getNetwork().version == 4, qs)
servers = [] qs6 = filter(lambda _revz: _revz.getNetwork().version == 6, qs)
for ns in domain.nameservers.all(): getDomainsFromQueryset(qs4, rzone4, domains, usedNameservers)
servers.append(ns.name) getDomainsFromQueryset(qs6, rzone6, domains, usedNameservers)
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6): print("dn.", domains)
# FIXME: find dns glue record duplicates in whois webif print("v4", rzone4)
usedNameservers.append(ns.name) print("v6", rzone6)
if ns.glueIPv4:
domains.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
domains.append((ns.name, "AAAA", [ns.glueIPv6]))
domains.append((domain.name, "NS", servers)) protectedRecords = [
# cycle through all reverse records
qs = Domain.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("name")
for rzone in qs:
print(" %s" % (rzone.getZone(),))
servers = []
for ns in domain.nameservers.all():
servers.append(ns.name)
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
# FIXME: find dns glue record duplicates in whois webif
usedNameservers.append(ns.name)
if ns.glueIPv4:
domains.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
domains.append((ns.name, "AAAA", [ns.glueIPv6]))
rzones.append((rzone.getZone, "PTR", servers))
newDomains = mergeDomains(domains, zoneData)
print("Add/replace", newDomains)
r = s.patch("http://potatos.portal.dn:8081/api/v1/servers/localhost/zones/dn.", data=json.dumps({'rrsets': newDomains}))
if r.status_code != 204:
raise RuntimeError("Could not update records in powerdns")
# delete old domains (except for NS/SOA of head)
domains.extend([
("dn.", "NS", []), ("dn.", "NS", []),
("dn.", "SOA", []), ("dn.", "SOA", []),
]) ]
delDomains = removeOldDomains(domains, zoneData) mergeDomainsWithPdns(s, args, "dn.", domains, protectedRecords)
print("Del", delDomains) mergeDomainsWithPdns(s, args, "10.in-addr.arpa.", rzone4)
r = s.patch("http://potatos.portal.dn:8081/api/v1/servers/localhost/zones/dn.", data=json.dumps({'rrsets': delDomains})) mergeDomainsWithPdns(s, args, "3.2.7.c.3.a.d.f.ip6.arpa.")
if r.status_code != 204:
raise RuntimeError("Could not update records in powerdns")
# and now for the reverse zones...
zoneData = s.get("http://potatos.portal.dn:8081/api/v1/servers/localhost/zones/dn.").json()
qs = ReverseZone.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("name")
# cycle through all domains
for domain in qs:
print(" %s" % (domain.name))
servers = []
for ns in domain.nameservers.all():
servers.append(ns.name)
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
# FIXME: find dns glue record duplicates in whois webif
usedNameservers.append(ns.name)
if ns.glueIPv4:
domains.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
domains.append((ns.name, "AAAA", [ns.glueIPv6]))
domains.append((domain.name, "NS", servers))
if __name__ == '__main__': if __name__ == '__main__':