From f4bf889c9b4007567e637bb6f3331e9311d2a15f Mon Sep 17 00:00:00 2001 From: arjuan <arjuan@raspberrypi> Date: Mon, 3 Apr 2017 22:55:01 +0000 Subject: [PATCH] initial commit --- README.md | 7 +++ config-template.txt | 16 +++++++ gandi.py | 107 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 config-template.txt create mode 100644 gandi.py diff --git a/README.md b/README.md index e69de29..1564078 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,7 @@ +Simple Python script to update DNS A record of your domain dynamically using gandi.net LiveDNS API: + +http://doc.livedns.gandi.net/ + +The config-example.txt file should be renamed to config.txt, and modified with your gandi.net API key, domain name, and A-record (@, dev, home, pi, etc). + +Every time the script runs, it will query an external service to retrieve the external IP of the machine, compare it to the current record (if any) in the zone at gandi.net, and then add a new record (if none currently exists), or delete then add a new record (if a record already exists). diff --git a/config-template.txt b/config-template.txt new file mode 100644 index 0000000..2187bb5 --- /dev/null +++ b/config-template.txt @@ -0,0 +1,16 @@ +[local] +# gandi.net API (Production) key +apikey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +# domain +domain = example.com + +# A-record name (@, dev, home, etc) that will be updated +# example is for raspbian.example.com +a_name = raspbian + +# TTL (seconds) +ttl = 900 + +# Production API +api = https://dns.beta.gandi.net/api/v5/ diff --git a/gandi.py b/gandi.py new file mode 100644 index 0000000..000fd0a --- /dev/null +++ b/gandi.py @@ -0,0 +1,107 @@ +import ConfigParser as configparser +import sys +import os +import requests +import json + +config_file = "config.txt" + +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) + +def get_ip(): + #Get external IP + try: + # Could be any service that just gives us a simple raw ASCII IP address (not HTML etc) + r = requests.get("http://ipv4.myexternalip.com/raw", timeout=3) + except Exception: + print('Unable to retrieve external IP address.') + sys.exit(2) + if r.status_code != 200: + print('Failed to retrieve external IP. Server responded with status_code: %d' % result.status_code) + sys.exit(2) + + return r.text + +def read_config(config_path): + #Read configuration file + cfg = configparser.ConfigParser() + cfg.read(config_path) + + return cfg + +def get_record(url, headers): + #Get existing record + r = requests.get(url, headers=headers) + + return r + +def add_record(url, headers, payload): + #Add record + r = requests.post(url, headers=headers, json=payload) + if r.status_code != 201: + print('Record update failed with status code: %d' % r.status_code) + print(r.text) + sys.exit(2) + print r.text + + return r + + +def del_record(url, headers): + #Delete record + r = requests.delete(url, headers=headers) + if r.status_code != 204: + print('Record delete failed with status code: %d' % r.status_code) + print(r.text) + sys.exit(2) + print('Record delete succeeded') + + return r + + +def main(): + global api, zone_uuid + path = config_file + if not path.startswith('/'): + path = os.path.join(SCRIPT_DIR, path) + config = read_config(path) + if not config: + sys.exit("please fill in the 'config.txt' file") + + for section in config.sections(): + print(config.get(section, "api")) + print(config.get(section, "domain")) + print(config.get(section, "a_name")) + print(config.get(section, "ttl")) + + #Retrieve API key + apikey = config.get(section, "apikey") + + #Set headers + headers = { 'Content-Type': 'application/json', 'X-Api-Key': '%s' % config.get(section, "apikey")} + + #Set URL + url = 'https://dns.beta.gandi.net/api/v5/domains/%s/records/%s/A' % (config.get(section, "domain"), config.get(section, "a_name")) + + #Discover External IP + external_ip = get_ip()[0:-1] + print("external IP is: %s" % external_ip) + + #Prepare record + payload = {'rrset_ttl': 900, 'rrset_values': [external_ip]} + + #Check if record already exists + record = get_record(url, headers) + + if record.status_code == 404: + add_record(url, headers, payload) + elif record.status_code == 200: + print("current record is: %s" % json.loads(record.text)['rrset_values'][0]) + if(json.loads(record.text)['rrset_values'][0] == external_ip): + print("no change in IP address") + sys.exit(2) + del_record(url, headers) + add_record(url, headers, payload) + +if __name__ == "__main__": + main() -- GitLab