#!/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()