ascension

Migrate DNS zones to the GNU Name System
Log | Files | Refs | README | LICENSE

commit d1ff79f3355b55498b55b08b2d6bec5dbd69e82e
parent 81683c98e459b37667fb94231ff8daa250047530
Author: rexxnor <rexxnor+gnunet@brief.li>
Date:   Thu, 27 Sep 2018 22:05:29 +0200

added incremental zone transfer logic

Diffstat:
Mgnsmigrator/gnsmigrator.py | 68++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 50 insertions(+), 18 deletions(-)

diff --git a/gnsmigrator/gnsmigrator.py b/gnsmigrator/gnsmigrator.py @@ -16,6 +16,8 @@ Options: """ # imports +import sys +import time import subprocess import csv import dns.query @@ -53,12 +55,13 @@ class GNSMigrator(): master_answer = dns.resolver.query(soa_answer[0].mname, 'A') try: - zone = dns.zone.from_xfr(dns.query.xfr(master_answer[0].address, domain)) + zone = dns.zone.from_xfr(dns.query.xfr( + master_answer[0].address, domain)) except dns.resolver.NoAnswer: - print("the domain '%s' did not answer our xfr request" % domain) + print("nameserver for '%s' did not answer" % domain) continue except dns.exception.FormError: - print("the domain '%s' does not allow xfr requests from your ip" % domain) + print("domain '%s' does not allow xfr requests" % domain) continue cls.zones[domain] = (zone, (master_answer[0].address, domain)) @@ -72,13 +75,16 @@ class GNSMigrator(): # building list with arguments reverse_parsing = domain.split('.')[::-1] for domainpart in reverse_parsing: - pkey_lookup = subprocess.Popen([GNUNET_ZONE_CREATION_COMMAND, '-d'], + pkey_lookup = subprocess.Popen([GNUNET_ZONE_CREATION_COMMAND, + '-d'], stdout=subprocess.PIPE) pkey_line = subprocess.Popen(['grep', domainpart], stdin=pkey_lookup.stdout, stdout=subprocess.PIPE) - pkey_zone = subprocess.check_output(['cut', '-d', ' ', '-f3'], - stdin=pkey_line.stdout).decode().strip() + pkey_zone = subprocess.check_output(['cut', '-d', + ' ', '-f3'], + stdin=pkey_line.stdout) + pkey_zone = pkey_zone.decode().strip() pkey_lookup.stdout.close() pkey_line.stdout.close() # Create identity in GNUnet @@ -86,22 +92,26 @@ class GNSMigrator(): subprocess.run([GNUNET_ZONE_CREATION_COMMAND, '-C', domainpart]) - pkey_lookup = subprocess.Popen([GNUNET_ZONE_CREATION_COMMAND, '-d'], + pkey_lookup = subprocess.Popen([GNUNET_ZONE_CREATION_COMMAND, + '-d'], stdout=subprocess.PIPE) pkey_line = subprocess.Popen(['grep', domainpart], stdin=pkey_lookup.stdout, stdout=subprocess.PIPE) - pkey_zone = subprocess.check_output(['cut', '-d', ' ', '-f3'], - stdin=pkey_line.stdout).decode().strip() + pkey_zone = subprocess.check_output(['cut', '-d', + ' ', '-f3'], + stdin=pkey_line.stdout) + pkey_zone = pkey_zone.decode().strip() pkey_lookup.stdout.close() pkey_line.stdout.close() - # If it is TLD, don't add PKEY to higher zone as they do not exist + # If it is TLD, don't add PKEY to higher zone if counter > 0: result = subprocess.check_output([GNUNET_GNS_COMMAND, '-t', 'PKEY', '-u', '%s.%s' % - (domainpart, reverse_parsing[counter - 1])]) + (domainpart, + reverse_parsing[counter - 1])]) if "No results." in result.decode(): subprocess.run([GNUNET_NAMESTORE_COMMAND, @@ -115,7 +125,7 @@ class GNSMigrator(): @staticmethod def add_records_to_gns(zonename, zone, domain, dnsresolver): """ - Checks if records are present + Checks if records are present and adds them if not :param zonename: zonename of zone to add records to :param zone: the transfered zone :param domain: full domain of zone @@ -186,6 +196,31 @@ class GNSMigrator(): """ return domain.split('.')[0] + @classmethod + def refresh_zone(cls, domain, zonetuple, dnsresolver): + """ + Refresh the zone using IXFR and the previous serial as reference + + Returns 0 on unchanged and 1 on changed + + :param domain: The domain to transfer and migrate + :param zonetuple: The necessary data tuple for the transfer + :param dnsresolver: Optional user specified resolver for subdomains + """ + zone, xfrinfo = zonetuple + zonename = cls.get_lowest_domain_part(domain) + cls.add_records_to_gns(zonename, zone, domain, dnsresolver) + + # Ugly way to get serial + serial = int(str(zone.get_rdataset('@', dns.rdatatype.SOA)).split(' ')[5]) + newzone = dns.zone.from_xfr(dns.query.xfr(xfrinfo[0], + xfrinfo[1], + rdtype=dns.rdatatype.IXFR, + serial=serial)) + if newzone == zone: + return 1 + return 0 + def main(): """ @@ -202,7 +237,7 @@ def main(): print('Exiting...') return 1 - dnsresolver = args['<resolver>'] + dnsresolver = args.get('<resolver>', None) domainlist = [] @@ -225,11 +260,8 @@ def main(): gnsmigrator.initial_zone_transfer() for domain, zonetuple in gnsmigrator.zones.items(): - zone, xfrinfo = zonetuple - zonename = gnsmigrator.get_lowest_domain_part(domain) - gnsmigrator.add_records_to_gns(zonename, zone, domain, dnsresolver) - # retain the information needed for a second zone transfer - #print(xfrinfo) + # Returns a value 0 if not changed and 1 if changed + gnsmigrator.refresh_zone(domain, zonetuple, dnsresolver) if __name__ == '__main__': main()