From 0c9ae1b30a012ac10ac9c80c007d87c430c35c1e Mon Sep 17 00:00:00 2001 From: Yohann Dedy Date: Mon, 5 Apr 2021 22:53:17 +0200 Subject: [PATCH] Working script --- gldns-zones-updater.py | 99 ++++++++++++++++++++++++++++++++++++++++++ zones-example.yml | 14 ++++++ 2 files changed, 113 insertions(+) create mode 100644 gldns-zones-updater.py create mode 100644 zones-example.yml diff --git a/gldns-zones-updater.py b/gldns-zones-updater.py new file mode 100644 index 0000000..db22841 --- /dev/null +++ b/gldns-zones-updater.py @@ -0,0 +1,99 @@ +#!/usr/bin/python3 +import os +import datetime +import requests +import json +import yaml +import argparse + +def create_snapshot(domain, apikey, message='Snapshot from GLD-updater'): + url = 'https://api.gandi.net/v5/livedns/domains/%s/snapshots' % domain + headers = {} + headers['authorization'] = "Apikey %s" % apikey + headers['Content-Type'] = "application/json" + data = {} + data['name'] = message + + r = requests.post(url, headers=headers, data=json.dumps(data)) + if r.status_code != 201: + raise Exception("Snapshot creation failed (error %d)" % r.status_code) + + else: + print(r.json()['message']) + +def backup_records(domain, apikey, dest_path): + url = 'https://api.gandi.net/v5/livedns/domains/%s/records' % domain + headers = {} + headers['authorization'] = "Apikey %s" % apikey + r = requests.get(url, headers=headers) + + if r.status_code != 200: + raise Exception("Can't get current DNS records (error %d)" % r.status_code) + + full_dir = os.path.join(dest_path,domain) + os.makedirs(full_dir, exist_ok=True) + os.chdir(full_dir) + + filename = datetime.datetime.now().strftime('%Y%m%d-%H%M') + ".json" + backup_file = open(filename,"w") + backup_file.write(r.text) + backup_file.close() + print('Current config saved in %s/%s' % (full_dir, filename)) + +def update_dns_zone(domain, apikey, config_data): + # must provide json data as required by the PUT records endpoint + url = 'https://api.gandi.net/v5/livedns/domains/%s/records' % domain + headers = {} + headers['authorization'] = "Apikey %s" % apikey + headers['Content-Type'] = "application/json" + data = config_data + + r = requests.put(url, headers=headers, data=data) + if r.status_code != 201: + raise Exception("Zone replacement failed (error %d)" % r.status_code) + else: + print(r.json()['message']) + +def parse_config_file(config_file): + yaml_file = open(config_file, 'r') + yaml_content = yaml.load(yaml_file) + + for key in yaml_content: + domain = key + zone_json = json.dumps(yaml_content[key]) + yield domain, zone_json + +def parse_backup(backup_file): + pass + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-c", "--config-file", help="Zones records in YAML format") + parser.add_argument("-k", "--api-key", help="Gandi API key") + parser.add_argument("-d", "--backup-dir", help="Directory where the backups will be located (the same folder as the script per default)", default="BACKUPS") + parser.add_argument("--no-snapshot", help="Don't create a snapshot of the current zones", action="store_true") + parser.add_argument("--no-backup", help="Don't create a local backup of the current zones", action="store_true") + args = parser.parse_args() + + if args.config_file is None: + print("No config file provided, check --help.") + exit(1) + + if args.api_key is None: + print("No API key provided, check --help.") + exit(1) + + apikey = args.api_key + backup_dir = os.path.join(os.getcwd(),args.backup_dir) + + for domain, zone in parse_config_file(args.config_file): + if not args.no_snapshot: + create_snapshot(domain,apikey) + if not args.no_backup: + backup_records(domain,apikey,backup_dir) + update_dns_zone(domain,apikey,zone) + +if __name__ == '__main__': + main() + print('ALL DONE') + diff --git a/zones-example.yml b/zones-example.yml new file mode 100644 index 0000000..99a29ab --- /dev/null +++ b/zones-example.yml @@ -0,0 +1,14 @@ +example.net: + items: + - { rrset_name: '@', rrset_type: MX, rrset_values: ['10 spool.mail.gandi.net.', '50 fb.mail.gandi.net.'] } + - { rrset_name: '@', rrset_type: TXT, rrset_values: ['"v=spf1 include:_mailcust.gandi.net ?all"'] } + - { rrset_name: 'webmail', rrset_type: CNAME, rrset_values: ['webmail.gandi.net.'] } + - { rrset_name: 'wiki', rrset_type: A, rrset_values: ['91.198.174.192'] } + - { rrset_name: '@', rrset_type: A, rrset_values: ['93.184.216.34'] } + - { rrset_name: 'search', rrset_type: AAAA, rrset_values: ['2a00:1450:4007:818::200e'] } + +example.org: + items: + - { rrset_name: '@', rrset_type: AAAA, rrset_values: ['2606:2800:220:1:248:1893:25c8:1946'] } + - { rrset_name: 'dns', rrset_type: A, rrset_values: ['1.1.1.1'] } +