dns-sync script near to completion
This commit is contained in:
parent
a9863ed5c2
commit
f10c9433c0
143
bin/dns-sync
143
bin/dns-sync
|
@ -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__':
|
||||||
|
|
Loading…
Reference in New Issue