From 6762480a1548bcec5d9a46de39d4d96b24eb2b91 Mon Sep 17 00:00:00 2001 From: cave beat Date: Mon, 14 Aug 2017 23:18:04 +0200 Subject: [PATCH] initial working state --- .project | 17 ++++++++ .pydevproject | 8 ++++ src/.gitignore | 2 + src/config.pyc | Bin 0 -> 525 bytes src/example.config.py | 43 ++++++++++++++++++++ src/gandi_live_dns.py | 92 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 162 insertions(+) create mode 100644 .project create mode 100644 .pydevproject create mode 100644 src/.gitignore create mode 100644 src/config.pyc create mode 100644 src/example.config.py create mode 100644 src/gandi_live_dns.py diff --git a/.project b/.project new file mode 100644 index 0000000..79a2389 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + gandi_live_dns + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000..0ebadbb --- /dev/null +++ b/.pydevproject @@ -0,0 +1,8 @@ + + + +/${PROJECT_DIR_NAME}/src + +python 2.7 +Default + diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..3abc68b --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,2 @@ +/config.py +/test.py diff --git a/src/config.pyc b/src/config.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a2d324e2d599e954906c2e711a26387c65b8aad GIT binary patch literal 525 zcmYjNO;5ux4D}dvP~gCg1BY_ksoD4t2qA>vfH;f`5*oc!X&kzUt*H`ksDFdM${)bV zK#(Yo{o=f5yZ^PH4i7$G75uD(?^`}T7z8NT_MqqiZa}dC*oUGIxCyugm;ep{w*hyc zPM}~gg@W;2DEMg)o`?H^X~-tMcUqFh%r@D{X*Q8vb}|}Yr0K0((#*Q6Ov#l_Q#$12 zsng?j`ts|~|Kb?+7{)mxZ{c3LO z{J)Ga?b9$wMZK~_tICp62Dq-$YvuHsiNmOgb|Fm@GyJkzM?Pv1&0{I%P1)wn)M0|~ zXZ)B$F|!LTLIL8#y7x*qY9`_=%DGwTlIJ75Q)11Kw_RksURYet^-X9$4k}5KUf73x Fz5&j&e|!J{ literal 0 HcmV?d00001 diff --git a/src/example.config.py b/src/example.config.py new file mode 100644 index 0000000..f1b30cf --- /dev/null +++ b/src/example.config.py @@ -0,0 +1,43 @@ +''' +Created on 13 Aug 2017 +@author: cave +Copy this file to config.py and update the settings +''' +#!/usr/bin/env python +# encoding: utf-8 + +''' +Get your API key +Start by retrieving your API Key from the "Security" section in new Account admin panel to be able to make authenticated requests to the API. +https://account.gandi.net/ +''' +api_secret = '---my_secret_API_KEY----' + +''' +Gandiv5 LiveDNS API Location +http://doc.livedns.gandi.net/#api-endpoint +https://dns.beta.gandi.net/api/v5/ +''' +api = 'https://dns.beta.gandi.net/api/v5' + +#your domain with the subdomains in the zone file/UUID +domain = 'mydomain.tld' + +#enter all subdomains to be updated, subdomains must already exist to be updated +subdomains = ["subdomain1", "subdomain2", "subdomain3"] + +#300 seconds = 5 minutes +ttl = '300' + +'''external ip provider +run your own external IP provider: ++ https://github.com/mpolden/ipd ++ + +e.g. ++ http://ifconfig.me/ip ++ https://ifconfig.co ++ http://whatismyip.akamai.com/ ++ http://ipinfo.io/ip +''' +ifconfig = 'choose_from_above_or_run_your_own' \ No newline at end of file diff --git a/src/gandi_live_dns.py b/src/gandi_live_dns.py new file mode 100644 index 0000000..9fa6491 --- /dev/null +++ b/src/gandi_live_dns.py @@ -0,0 +1,92 @@ +''' +Gandi v5 LiveDNS - DynDNS Update via REST API and CURL/requests + +@author: cave +Licsense GPLv3 +https://www.gnu.org/licenses/gpl-3.0.html + +Created on 13 Aug 2017 +http://doc.livedns.gandi.net/ +http://doc.livedns.gandi.net/#api-endpoint -> https://dns.beta.gandi.net/api/v5/ +''' + +import requests, json +import config + + +def get_dynip(ifconfig_provider): + ''' find out own IPv4 at home <-- this is the dynamic IP which changes more or less frequently + similar to curl ifconfig.me/ip, see example.config.py for details to ifconfig providers + ''' + r = requests.get(ifconfig_provider) + print 'Checking dynamic IP: ' , r._content.strip('\n') + return r.content.strip('\n') + +def get_uuid(): + ''' + find out ZONE UUID from domain + Info on domain "DOMAIN" + GET /domains/: + + ''' + url = config.api + '/domains/' + config.domain + u = requests.get(url, headers={"X-Api-Key":config.api_secret}) + json_object = json.loads(u._content) + return json_object['zone_uuid'] + +def get_dnsip(uuid): + ''' find out IP from first Subdomain DNS-Record + List all records with name "NAME" and type "TYPE" in the zone UUID + GET /zones//records//: + ''' + + url = config.api + '/zones/' + uuid + '/records/' + config.subdomains[0] + '/A' + headers = {"X-Api-Key":config.api_secret} + u = requests.get(url, headers=headers) + json_object = json.loads(u._content) + print 'Checking IP from DNS Record' , config.subdomains[0], ' : ', json_object['rrset_values'][0].encode('ascii','ignore').strip('\n') + return json_object['rrset_values'][0].encode('ascii','ignore').strip('\n') + +def update_records(uuid, dynIP, subdomain): + ''' update DNS Records for Subdomains + Change the "NAME"/"TYPE" record from the zone UUID + PUT /zones//records//: + curl -X PUT -H "Content-Type: application/json" \ + -H 'X-Api-Key: XXX' \ + -d '{"rrset_ttl": 10800, + "rrset_values": [""]}' \ + https://dns.beta.gandi.net/api/v5/zones//records// + ''' + url = config.api + '/zones/' + uuid + '/records/' + subdomain + '/A' + payload = {"rrset_ttl": config.ttl, "rrset_values": [dynIP]} + headers = {"Content-Type": "application/json", "X-Api-Key":config.api_secret} + record_update = requests.put(url, data=json.dumps(payload), headers=headers) + json_object = json.loads(record_update._content) + print 'Status Code: ', record_update.status_code, ', ', json_object['message'], ', IP updated for', subdomain + return True + + +def main(): + + #get zone ID from Account + uuid = get_uuid() + + #compare dynIP and DNS IP + dynIP = get_dynip(config.ifconfig) + dnsIP = get_dnsip(uuid) + + if dynIP == dnsIP: + print "IP Address match - no further action" + else: + print "IP Address mismatch - going to update the DNS Records for the subdomains" + for sub in config.subdomains: + update_records(uuid, dynIP, sub) + +if __name__ == "__main__": + main() + + + + + + \ No newline at end of file