· 5 years ago · Jul 08, 2020, 02:14 PM
1 import configparser
2 import sys
3 import os
4 import requests
5 import json
6 import ipaddress, logging
7
8 # config file must have the following format:
9 #[tv]
10 #apikey = #####
11 #domain = domain.com
12 #a_name = subdomaine
13 #ttl = 300
14 #api = https://dns.api.gandi.net/api/v5/
15 config_file = "share/config.txt"
16
17 SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
18 log_path = SCRIPT_DIR + '/share/maj_ip.log'
19
20 logging.basicConfig(level=logging.INFO, filename=log_path, format='%(asctime)s %(levelname)s - %(message)s')
21
22 def get_ip():
23 #Get external IP
24 try:
25 # Could be any service that just gives us a simple raw ASCII IP address (not HTML etc)
26 r = requests.get('https://api.ipify.org', timeout=3)
27 except Exception:
28 logging.error('Failed to retrieve external IP.')
29 sys.exit(2)
30 if r.status_code != 200:
31 logging.error(('Failed to retrieve external IP. Server responded with status_code: %d' % r.status_code))
32 sys.exit(2)
33
34 ip = r.text.rstrip() # strip \n and any trailing whitespace
35
36 if not(ipaddress.IPv4Address(ip)): # check if valid IPv4 address
37 sys.exit(2)
38
39 return ip
40
41 def read_config(config_path):
42 #Read configuration file
43 cfg = configparser.ConfigParser()
44 cfg.read(config_path)
45
46 return cfg
47
48 def get_record(url, headers):
49 #Get existing record
50 r = requests.get(url, headers=headers)
51
52 return r
53
54 def update_record(url, headers, payload):
55 #Add record
56 r = requests.put(url, headers=headers, json=payload)
57 if r.status_code != 201:
58 logging.info(('Record update failed with status code: %d' % r.status_code))
59 logging.info((r.text))
60 sys.exit(2)
61 logging.info('Zone record updated.')
62
63 return r
64
65
66 def main():
67 path = config_file
68 if not path.startswith('/'):
69 path = os.path.join(SCRIPT_DIR, path)
70 config = read_config(path)
71 if not config:
72 sys.exit("Please fill in the 'config.txt' file.")
73
74 for section in config.sections():
75
76 #Retrieve API key
77 apikey = config.get(section, 'apikey')
78
79 #Set headers
80 headers = { 'Content-Type': 'application/json', 'X-Api-Key': '%s' % config.get(section, 'apikey')}
81
82 #Set URL
83 url = '%sdomains/%s/records/%s/A' % (config.get(section, 'api'), config.get(section, 'domain'), config.get(section, 'a_name'))
84 logging.info(url)
85 #Discover External IP
86 external_ip = get_ip()
87 logging.info(('External IP is: %s' % external_ip))
88
89 #Prepare record
90 payload = {'rrset_ttl': config.get(section, 'ttl'), 'rrset_values': [external_ip]}
91
92 #Check current record
93 record = get_record(url, headers)
94
95 if record.status_code == 200:
96 logging.info(('Current record value is: %s' % json.loads(record.text)['rrset_values'][0]))
97 if(json.loads(record.text)['rrset_values'][0] == external_ip):
98 logging.info('No change in IP address. Goodbye.')
99 else:
100 logging.info('No existing record. Adding...')
101
102 update_record(url, headers, payload)
103
104 if __name__ == "__main__":
105 main()