ascension

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

commit c7b20648a731b7a9ba07e3b42fa4e6fc410b333c
parent 1990ea7518d7ef0de3a8743ede70f7d3a3efdb0a
Author: rexxnor <rexxnor+git@brief.li>
Date:   Sun, 26 Apr 2020 12:15:57 +0200

refactored argument parsing and updated man page accordingly

- switched from docopt to argparse
- improved docstring by removing docopt format
- updated man page with more verbose instructions

Diffstat:
MREADME | 43+++++++++++++++++++------------------------
Dascension-0.5.0.tar.gz | 0
Dascension-0.6.1.tar.gz | 0
Mascension.1 | 74+++++++++++++++++++++++++++++++++++++++++---------------------------------
Mascension/ascension.py | 146++++++++++++++++++++++++++++++++++++++++++-------------------------------------
5 files changed, 138 insertions(+), 125 deletions(-)

diff --git a/README b/README @@ -1,4 +1,4 @@ -# Ascension +#Ascension Tool to easily migrate existing DNS Zones into the GNU Name System using incremental zone transfers (AXFR/IXFR). @@ -35,30 +35,25 @@ You can also just run the file ascension.py itself directly. Taken from the docstring of the ascension.py file: ``` -Ascension +usage: ascension.py [-h] [-n NAMESERVER] [-P PORT] [-t] [-s] [-p] [-g] [-v] [-V] domain + +Easy tool to migrate DNS zones into GNS -Usage: - ascension <domain> [-d] [-p] [-s] [--minimum-ttl=<ttl>] [--dry-run] - ascension <domain> <port> [-d] [-p] [-s] [--minimum-ttl=<ttl>] [--dry-run] - ascension <domain> -n <transferns> [-d] [-p] [-s] [--minimum-ttl=<ttl>] [--dry-run] - ascension <domain> -n <transferns> <port> [-d] [-p] [-s] [--minimum-ttl=<ttl>] [--dry-run] - ascension -p | --public - ascension -s | --debug - ascension -s | --standalone - ascension -h | --help - ascension -v | --version +positional arguments: + domain Domain to be migrated -Options: - <domain> Domain to migrate - <port> Port for zone transfer - <transferns> DNS Server that does the zone transfer - --minimum-ttl=<ttl> Minimum TTL for records to migrate [default: 3600] - --dry-run Only try if a zone transfer is allowed - -p --public Make records public on the DHT - -s --standalone Run ascension once - -d --debug Enable debugging - -h --help Show this screen. - -v --version Show version. +optional arguments: + -h, --help show this help message and exit + -n NAMESERVER, --nameserver NAMESERVER + Nameserver to use for migrating + -P PORT, --port PORT Port to use for zone transfer with nameserver + -t, --ttl Sets TTL of records lower than TTL to specified TTL + -s, --standalone Run ascension once and not as daemon + -p, --public Push records to the public DHT + -g, --dryrun Tests if zone is transferrable without changing anything + -v, --verbose Enable verbose debugging + -V, --version show program's version number and exit +Ascension ``` Example use: @@ -66,5 +61,5 @@ Example use: # Transfers the sy TLD from ns1.tld.sy. ascension sy -n ns1.tld.sy. # Transfers the nu TLD from zonedata.iis.se with debug options enabled -ascension nu -n zonedata.iis.se. -d +ascension nu -n zonedata.iis.se. -v ``` diff --git a/ascension-0.5.0.tar.gz b/ascension-0.5.0.tar.gz Binary files differ. diff --git a/ascension-0.6.1.tar.gz b/ascension-0.6.1.tar.gz Binary files differ. diff --git a/ascension.1 b/ascension.1 @@ -21,56 +21,64 @@ .\" .\" SPDX-License-Identifier: GPL3.0-or-later OR FDL1.3-or-later .\" -.Dd May 9, 2019 +.Dd April 26, 2020 .Dt ASCENSION 1 .Os .Sh NAME -.Nm ascension +.Nm Ascension .Nd migrate existing DNS zones into the GNU Name System .Sh SYNOPSIS -.Nm -.Op Ar domain Fl d Fl p Fl s -minimum-ttl=<ttl> -dry-run -.Nm -.Op Ar domain port Fl d Fl p Fl s -minimum-ttl=<ttl> -dry-run -.Nm -.Op Ar domain Fl n Ar transferns Fl d Fl p Fl s Fl -minimum-ttl=<ttl> -dry-run -.Nm -.Op Ar domain Fl n Ar transferns Ar port Fl d Fl p Fl s -minimum-ttl=<ttl> -dry-run +.Op -n NAMESERVER +.Op -P PORT +.Op -t TTL +.Op -s +.Op -p +.Op -v +.Op -g +.Op -V +domain .Sh DESCRIPTION .Nm is a tool to migrate existing DNS Zones into the GNU Name System (GNS) using incremental zone transfers (AXFR/IXFR). -To achieve this it uses +To achieve this it calls .Xr gnunet-identity 1 , .Xr gnunet-namestore 1 , .Xr gnunet-gns 1 . -As .Nm -relies on these 3 GNUnet services, +relies on GNUnet and these 3 GNUnet services, .Xr gnunet-arm 1 must be installed and running. .Bl -tag -width Ds -.It Ar domain Fl d Fl p Fl s -minimum-ttl=<ttl> -dry-run -Migrate the DOMAIN passed as domain. -The debug, public and standalone options are optional. -.It Ar domain port Fl d Fl p Fl s -minimum-ttl=<ttl> -dry-run -Migrate the DOMAIN domain, using port for zone transfer. -The debug, public and standalone options are optional. -.It Ar domain Fl n Ar transferns Fl d Fl p Fl s -minimum-ttl=<ttl> -dry-run -Migrate the DOMAIN domain from the DNS server transferns. -The debug, public and standalone options are optional. -.It Ar domain Fl n Ar transferns Ar port Fl d Fl p Fl s -minimum-ttl=<ttl> -dry-run -Migrate the DOMAIN domain from the DNS server transferns using port for the zone transfer. -The debug, public and standalone options are optional. +.It Ar domain +The domain that should be migrated to the GNU Name System (GNS) +.It Fl n | \-nameserver Ar NAMESERVER +Nameserver to contact for zone transfer. Defaults to name server listed in the SOA record +.It Fl p | \-port Ar PORT +Use the specified port when contacting the nameserver to transfer the zone +.It Fl t | \-ttl Ar TTL +When adding records to GNS a small ttl in DNS can cause issues as records need +to be resigned often (every ttl seconds as recordsets in GNS are signed with an +absolut expiration time) to remain valid. Therefore this ttl specifies the +lowest ttl a record will have in GNS. .It Fl s | \-standalone -Run Ascension once -.It Fl d | \-debug -Enable debugging -.It Fl h | \-help -Print short help on options +Run Ascension to migrate a zone once. If not specified it will run as a daemon +that updates the zone after the expiry specified in the zones SOA record has +elapsed. +.It Fl v | \-verbose +Increase logging verbosity. Shows more log levels than default including INFO, +DEBUG and WARNING. .It Fl p | \-public -Make records public on the DHT +Set the public flag for records and publish them on the DHT. When in possession +of the public key of the zone in BASE32 format anyone can resolve a record +within the zone provided they also know the label under which the recorset is +stored. +.It Fl g | \-dryrun +Checks whether or not the domains nameserver supports zone transfer for the +given domain. When a nameserver is specified it will be checked instead. +.It Fl h | \-help +Show the usage and argument syntax of Ascension. .It Fl v | \-version -Print ascension version number +Show the current version number .El .\" .Sh FILES .Sh EXAMPLES @@ -78,7 +86,7 @@ To transfer the sy TLD from ns1.tld.sy: .Pp .Dl $ ascension sy -n ns1.tld.sy. .Pp -To transfer the nu TLD from zonedata.iis.se with debug options enabled: +To test if the given domains nameserver supports zone transfers for that zone: .Pp .Dl $ ascension nu -n zonedata.iis.se. -d .Sh SEE ALSO diff --git a/ascension/ascension.py b/ascension/ascension.py @@ -1,49 +1,28 @@ #!/usr/bin/env python3 -# This file is part of Ascension. -# Copyright (C) 2019 GNUnet e.V. -# -# Ascension is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, -# or (at your option) any later version. -# -# Ascension is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# SPDX-License-Identifier: AGPL3.0-or-later -# -# Author rexxnor """ -Usage: - ascension <domain> [-d] [-p] [-s] [--minimum-ttl=<ttl>] [--dry-run] - ascension <domain> <port> [-d] [-p] [-s] [--minimum-ttl=<ttl>] [--dry-run] - ascension <domain> -n <transferns> [-d] [-p] [-s] [--minimum-ttl=<ttl>] [--dry-run] - ascension <domain> -n <transferns> <port> [-d] [-p] [-s] [--minimum-ttl=<ttl>] [--dry-run] - ascension -p | --public - ascension -d | --debug - ascension -s | --standalone - ascension -h | --help - ascension -v | --version - -Options: - <domain> Domain to migrate - <port> Port for zone transfer - <transferns> DNS Server that does the zone transfer - --minimum-ttl=<ttl> Minimum TTL for records to migrate [default: 3600] - --dry-run Only try if a zone transfer is allowed - -p --public Make records public on the DHT - -s --standalone Run ascension once - -d --debug Enable debugging - -h --help Show this screen. - -v --version Show version. +This file is part of Ascension. +Copyright (C) 2019-2020 GNUnet e.V. + +Ascension is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published +by the Free Software Foundation, either version 3 of the License, +or (at your option) any later version. + +Ascension is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +SPDX-License-Identifier: AGPL3.0-or-later + +Author rexxnor """ # imports +import argparse import logging import os import queue @@ -56,13 +35,13 @@ import threading import dns.query import dns.resolver import dns.zone -import docopt # GLOBALS for different environments GNUNET_ZONE_CREATION_COMMAND = 'gnunet-identity' GNUNET_NAMESTORE_COMMAND = 'gnunet-namestore' GNUNET_GNS_COMMAND = 'gnunet-gns' GNUNET_ARM_COMMAND = 'gnunet-arm' + # This is the list of record types Ascension (and GNS) currently # explicitly supports. Record types we encounter that are not # in this list and not in the OBSOLETE_RECORD_TYPES list will @@ -70,6 +49,7 @@ GNUNET_ARM_COMMAND = 'gnunet-arm' SUPPORTED_RECORD_TYPES = [ "A", "AAAA", "NS", "MX", "SRV", "TXT", "CNAME" ] + # Record types that exist in DNS but that won't ever exist in GNS # as they are not needed anymore (so we should not create a warning # if we drop one of these). @@ -122,7 +102,7 @@ class Ascender(): keystring = ret.stdout.decode().strip() pkey, _, privkey = keystring.split(" ") self.subzonedict[self.domain] = (pkey, self.minimum, privkey) - logging.info("executed command: %s", " ".join(ret.args)) + logging.info("Executed command: %s", " ".join(ret.args)) except sp.CalledProcessError: ret = sp.run([GNUNET_ZONE_CREATION_COMMAND, '-dqpe', self.domain], @@ -194,7 +174,7 @@ class Ascender(): def add_records_to_gns(self) -> None: """ - Extracts records from zone and adds them to GNS + Extracts records from transferred zone and adds them to GNS :raises AttributeError: When getting incomplete data """ logging.info("Starting to add records into GNS...") @@ -332,7 +312,7 @@ class Ascender(): taskqueue.put(None) thread.join(timeout=10) if thread.is_alive(): - logging.critical("thread join timed out, still running") + logging.critical("Thread joining timed out, still running") # Add soa record to GNS once completed (updates the previous one) self.add_soa_record_to_gns(self.soa) @@ -739,37 +719,33 @@ class Ascender(): logging.info("adding zone %s with %s pkey into %s", zone, pkey, domain) self.add_pkey_record_to_zone(pkey, domain, label, ttl) -def main(): +def main(args): """ Initializes object and handles arguments """ - # argument parsing from docstring definition - args = docopt.docopt(__doc__, version='Ascension 0.11.5') - - # argument parsing - debug = args['--debug'] - domain = args.get('<domain>', None) - transferns = args['<transferns>'] if args['<transferns>'] else None - port = args['<port>'] if args['<port>'] else "53" - flags = "p" if args.get('--public') else "n" - standalone = bool(args.get('--standalone')) - dryrun = bool(args.get('--dry-run')) - minimum = args['--minimum-ttl'] + flags = "p" if args.public else "n" # Change logging severity to debug - if debug: + if args.verbose: logging.basicConfig(level=logging.DEBUG) # Initialize class instance - ascender = Ascender(domain, transferns, port, flags, minimum) + ascender = Ascender(args.domain, + args.nameserver, + args.port, + flags, + args.ttl) # Do dry run before GNUnet check - if dryrun: + if args.dryrun: dns_zone_serial = ascender.get_dns_zone_serial(ascender.domain, ascender.transferns) if dns_zone_serial is None: + logging.critical('The specified domain is not transferrable \ + using the given option!') return 1 else: + logging.critical('SUCCESS! The specified domain is transferrable!') return 0 # Checks if GNUnet services are running @@ -779,7 +755,7 @@ def main(): logging.critical('GNUnet services are not running!') sys.exit(1) - # Set to defaults to use before we get a SOA for the first time + # Set defaults to use before we get a SOA for the first time retry = 300 refresh = 300 @@ -804,7 +780,7 @@ def main(): if not dns_zone_serial: logging.error("Could not get DNS zone serial") - if standalone: + if args.standalone: return 1 time.sleep(retry) continue @@ -815,21 +791,21 @@ def main(): elif gns_zone_serial == dns_zone_serial: logging.info("GNS zone is up to date.") print("GNS zone is up to date.") - if standalone: + if args.standalone: return 0 time.sleep(refresh) continue elif gns_zone_serial > dns_zone_serial: logging.critical("SOA serial in GNS is bigger than SOA serial in DNS?") logging.critical("GNS zone: %s, DNS zone: %s", gns_zone_serial, dns_zone_serial) - if standalone: + if args.standalone: return 1 time.sleep(retry) continue else: logging.info("GNS zone is out of date, performing incremental transfer.") needsupdate = True - if standalone: + if args.standalone: return 1 print("GNS zone is out of date, performing incremental transfer.") @@ -846,7 +822,7 @@ def main(): retry = int(str(ascender.soa[2]).split(" ")[4]) except dns.zone.BadZone: logging.critical("Malformed DNS Zone '%s'", ascender.domain) - if standalone: + if args.standalone: return 2 time.sleep(retry) continue @@ -857,4 +833,38 @@ def main(): logging.info("Finished migration of the zone %s", ascender.domain) if __name__ == '__main__': - main() + parser = argparse.ArgumentParser( + description='Easy tool to migrate DNS zones into GNS', + ) + parser.add_argument('domain', metavar='domain', + type=str, + help='Domain to be migrated into GNS') + parser.add_argument('-n', '--nameserver', + help='Nameserver to use for migrating', + required=False) + parser.add_argument('-P', '--port', + help='Port to use for zone transfer with nameserver', + required=False, + default=53) + parser.add_argument('-t', '--ttl', + help='Sets the minimum ttl of records added to GNS', + required=False, default=3600) + parser.add_argument('-s', '--standalone', + help='Run ascension once and not as daemon', + action='store_true', + required=False, default=False) + parser.add_argument('-p', '--public', + help='Push records to the public DHT', + action='store_true', + required=False, default=False) + parser.add_argument('-g', '--dryrun', + help='Tests if zone is transferrable without changing anything', + action='store_true', + required=False, default=False) + parser.add_argument('-v', '--verbose', + help='Enable verbose debugging', + action='store_true', + required=False, default=False) + parser.add_argument('-V', '--version', action='version', version='%(prog)s 0.11.5') + args = parser.parse_args() + main(args)