dns-sync draft
This commit is contained in:
parent
c09ba916e0
commit
9f8695dddc
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
|
||||
import django
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dnmgmt.settings")
|
||||
sys.path.append("..")
|
||||
django.setup()
|
||||
|
||||
from django.db.models import Count
|
||||
from domains.models import Domain, ReverseZone
|
||||
|
||||
|
||||
__VERSION__ = '0.1'
|
||||
|
||||
|
||||
def _parser():
|
||||
parser = argparse.ArgumentParser(
|
||||
#prog='foo',
|
||||
#description='do some awesome foo',
|
||||
)
|
||||
|
||||
#parser.add_argument("-p", "--port", default=2323, type=int, help="Your port")
|
||||
#parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Be more verbose")
|
||||
|
||||
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
|
||||
|
||||
return parser
|
||||
|
||||
def mergeDomains(domains, zoneData):
|
||||
rrAdd = []
|
||||
rrData = zoneData['rrsets']
|
||||
|
||||
for domain, rrType, records in domains:
|
||||
found = False
|
||||
pdnsDom = list(filter(lambda _x: _x['name'] == domain and _x['type'] == rrType, rrData))
|
||||
if len(pdnsDom) > 0:
|
||||
rrSet = set(_x['content'] for _x in pdnsDom[0]['records'])
|
||||
if rrSet == set(records):
|
||||
found = True
|
||||
|
||||
if not found:
|
||||
# new domain!
|
||||
rrAdd.append({
|
||||
"name": domain,
|
||||
"type": rrType,
|
||||
"ttl": 60*60,
|
||||
"changetype": "REPLACE",
|
||||
"records": [{"content": record, "disabled": False} for record in records],
|
||||
})
|
||||
|
||||
return rrAdd
|
||||
|
||||
|
||||
def removeOldDomains(domains, zoneData):
|
||||
rrDel = []
|
||||
|
||||
for entry in zoneData['rrsets']:
|
||||
# search for name/type in domain dict. if non-existtant mark for deletion
|
||||
# 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):
|
||||
rrDel.append({
|
||||
"changetype": "DELETE",
|
||||
"name": entry["name"],
|
||||
"type": entry["type"],
|
||||
})
|
||||
|
||||
return rrDel
|
||||
|
||||
def handleNameserver(ns, servers, usedNameservers, domains):
|
||||
servers.append(ns.name)
|
||||
|
||||
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
|
||||
usedNameservers.append(ns.name)
|
||||
if ns.glueIPv4:
|
||||
domains.append((ns.name, "A", [ns.glueIPv4]))
|
||||
if ns.glueIPv6:
|
||||
domains.append((ns.name, "AAAA", [ns.glueIPv6]))
|
||||
|
||||
|
||||
def main():
|
||||
parser = _parser()
|
||||
args = parser.parse_args()
|
||||
print(args)
|
||||
|
||||
s = requests.Session()
|
||||
s.headers = {
|
||||
'X-API-Key': 'bei2aequ2OBi',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
|
||||
print(" --> TLD dn.")
|
||||
zoneData = s.get("http://potatos.portal.dn:8081/api/v1/servers/localhost/zones/dn.").json()
|
||||
|
||||
domains = []
|
||||
usedNameservers = []
|
||||
qs = Domain.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))
|
||||
|
||||
# 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.", "SOA", []),
|
||||
])
|
||||
|
||||
delDomains = removeOldDomains(domains, zoneData)
|
||||
print("Del", delDomains)
|
||||
r = s.patch("http://potatos.portal.dn:8081/api/v1/servers/localhost/zones/dn.", data=json.dumps({'rrsets': delDomains}))
|
||||
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__':
|
||||
main()
|
Loading…
Reference in New Issue