Config for dns sync script
This commit is contained in:
parent
a7aec57852
commit
e35f89bc57
75
bin/dns-sync
75
bin/dns-sync
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import argparse
|
import argparse
|
||||||
|
import configparser
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
@ -26,9 +27,10 @@ def _parser():
|
||||||
#description='do some awesome foo',
|
#description='do some awesome foo',
|
||||||
)
|
)
|
||||||
|
|
||||||
#parser.add_argument("-p", "--port", default=2323, type=int, help="Your port")
|
parser.add_argument("--pdns-host", default="127.0.0.1", help="PDNS host")
|
||||||
#parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Be more verbose")
|
parser.add_argument("--pdns-port", default=8081, help="PDNS port")
|
||||||
|
parser.add_argument("-c", "--config", default=None, type=argparse.FileType("r"), help="Path to config file (default path: ./dns-sync.conf, /etc/dns-sync.conf)")
|
||||||
|
parser.add_argument("--api-key", default=None, help="PDNS API key")
|
||||||
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
|
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
@ -61,6 +63,8 @@ def mergeDomains(zoneData, pdnsData):
|
||||||
def removeOldDomains(zoneData, pdnsData):
|
def removeOldDomains(zoneData, pdnsData):
|
||||||
rrDel = []
|
rrDel = []
|
||||||
|
|
||||||
|
#print("zone data", zoneData)
|
||||||
|
#print("pdnsData", pdnsData)
|
||||||
for entry in pdnsData['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...]
|
||||||
|
@ -84,7 +88,7 @@ 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):
|
def getDomainsFromQueryset(qs, zone, glueRecords, usedNameservers, v4reverse=False):
|
||||||
for domain in qs:
|
for domain in qs:
|
||||||
servers = []
|
servers = []
|
||||||
for ns in domain.nameservers.all():
|
for ns in domain.nameservers.all():
|
||||||
|
@ -99,10 +103,30 @@ def getDomainsFromQueryset(qs, zone, glueRecords, usedNameservers):
|
||||||
|
|
||||||
zone.append((domain.getZone(), "NS", servers))
|
zone.append((domain.getZone(), "NS", servers))
|
||||||
|
|
||||||
|
if v4reverse:
|
||||||
|
# for ipv4 reverse we have to do some extra work in case of classless delegations
|
||||||
|
# see RFC2317
|
||||||
|
net = domain.parentNet.getNetwork()
|
||||||
|
if net.prefixlen % 8 != 0:
|
||||||
|
revZone = domain.getZone()
|
||||||
|
parts = str(net.network_address).split(".")
|
||||||
|
baseZone = ".".join(reversed(parts[:net.prefixlen // 8])) + ".in-addr.arpa."
|
||||||
|
startNo = int(parts[net.prefixlen // 8])
|
||||||
|
lenExp = 8 - (net.prefixlen % 8)
|
||||||
|
|
||||||
|
for i in range(2 ** lenExp):
|
||||||
|
no = startNo + i
|
||||||
|
zone.append(("%d.%s" % (no, baseZone), "CNAME", ["%d.%s" % (no, revZone)]))
|
||||||
|
|
||||||
def mergeDomainsWithPdns(s, args, zone, zoneData, protectedRecords=[]):
|
def mergeDomainsWithPdns(s, args, zone, zoneData, protectedRecords=[]):
|
||||||
url = "http://potatos.portal.dn:8081/api/v1/servers/localhost/zones/%s" % (zone,)
|
url = "http://%s:%s/api/v1/servers/localhost/zones/%s" % (args.pdns_host, args.pdns_port, zone,)
|
||||||
pdnsData = s.get(url).json()
|
pdnsData = s.get(url).json()
|
||||||
|
|
||||||
|
baseProtectedRecords = [
|
||||||
|
(zone, "NS", []),
|
||||||
|
(zone, "SOA", []),
|
||||||
|
]
|
||||||
|
|
||||||
# add dn. (NS + glue Nameservers)
|
# add dn. (NS + glue Nameservers)
|
||||||
newDomains = mergeDomains(zoneData, pdnsData)
|
newDomains = mergeDomains(zoneData, pdnsData)
|
||||||
print("Add/replace", newDomains)
|
print("Add/replace", newDomains)
|
||||||
|
@ -110,22 +134,38 @@ def mergeDomainsWithPdns(s, args, zone, zoneData, protectedRecords=[]):
|
||||||
if len(newDomains) > 0:
|
if len(newDomains) > 0:
|
||||||
r = s.patch(url, data=json.dumps({'rrsets': newDomains}))
|
r = s.patch(url, data=json.dumps({'rrsets': newDomains}))
|
||||||
if r.status_code != 204:
|
if r.status_code != 204:
|
||||||
raise RuntimeError("Could not update records in powerdns")
|
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
|
||||||
|
|
||||||
delDomains = removeOldDomains(zoneData, zoneData + protectedRecords)
|
delDomains = removeOldDomains(zoneData + protectedRecords + baseProtectedRecords, pdnsData)
|
||||||
print("Del", delDomains)
|
print("Del", delDomains)
|
||||||
r = s.patch(url, data=json.dumps({'rrsets': delDomains}))
|
r = s.patch(url, data=json.dumps({'rrsets': delDomains}))
|
||||||
if r.status_code != 204:
|
if r.status_code != 204:
|
||||||
raise RuntimeError("Could not update records in powerdns")
|
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = _parser()
|
parser = _parser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
if args.config:
|
||||||
|
config.read_file(args.config)
|
||||||
|
else:
|
||||||
|
config.read([os.path.join(os.path.abspath(__file__), "dns-sync.conf"), "/etc/dns-sync.conf"])
|
||||||
|
#print(config)
|
||||||
|
#print(config.get("DEFAULT", "api-key"))
|
||||||
|
#print(config.has_section("DEFAULT"), config.has_option("DEFAULT", "api-key"))
|
||||||
|
|
||||||
|
if args.api_key:
|
||||||
|
config["DEFAULT"]["api-key"] = args.api_key
|
||||||
|
|
||||||
|
if not config.has_option("DEFAULT", "api-key"):
|
||||||
|
print("Error: Could not find api-key (not present in config under [DEFAULT]; not given via command line)", file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
s = requests.Session()
|
s = requests.Session()
|
||||||
s.headers = {
|
s.headers = {
|
||||||
'X-API-Key': 'bei2aequ2OBi',
|
'X-API-Key': config.get("DEFAULT", "api-key"),
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,21 +183,16 @@ def main():
|
||||||
qs = ReverseZone.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("parentNet__address")
|
qs = ReverseZone.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("parentNet__address")
|
||||||
qs4 = filter(lambda _revz: _revz.getNetwork().version == 4, qs)
|
qs4 = filter(lambda _revz: _revz.getNetwork().version == 4, qs)
|
||||||
qs6 = filter(lambda _revz: _revz.getNetwork().version == 6, qs)
|
qs6 = filter(lambda _revz: _revz.getNetwork().version == 6, qs)
|
||||||
getDomainsFromQueryset(qs4, rzone4, domains, usedNameservers)
|
getDomainsFromQueryset(qs4, rzone4, domains, usedNameservers, v4reverse=True)
|
||||||
getDomainsFromQueryset(qs6, rzone6, domains, usedNameservers)
|
getDomainsFromQueryset(qs6, rzone6, domains, usedNameservers)
|
||||||
|
|
||||||
print("dn.", domains)
|
#print("dn.", domains)
|
||||||
print("v4", rzone4)
|
#print("v4", rzone4)
|
||||||
print("v6", rzone6)
|
#print("v6", rzone6)
|
||||||
|
|
||||||
protectedRecords = [
|
mergeDomainsWithPdns(s, args, "dn.", domains)
|
||||||
("dn.", "NS", []),
|
|
||||||
("dn.", "SOA", []),
|
|
||||||
]
|
|
||||||
|
|
||||||
mergeDomainsWithPdns(s, args, "dn.", domains, protectedRecords)
|
|
||||||
mergeDomainsWithPdns(s, args, "10.in-addr.arpa.", rzone4)
|
mergeDomainsWithPdns(s, args, "10.in-addr.arpa.", rzone4)
|
||||||
mergeDomainsWithPdns(s, args, "3.2.7.c.3.a.d.f.ip6.arpa.")
|
mergeDomainsWithPdns(s, args, "3.2.7.c.3.a.d.f.ip6.arpa.", rzone6)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue