Last active
March 3, 2025 13:03
-
-
Save robweber/3e83c29b38a60bf896e20d2924e424f7 to your computer and use it in GitHub Desktop.
Use the GoDaddy API to update a DNS record when external IP changes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""update_godaddy_dns.py | |
Updates a GoDaddy DNS record with a new external IP address using the GoDaddy API | |
Run in debug mode (-D) to check the IP but not update DNS records | |
https://developer.godaddy.com/doc/endpoint/domains | |
Requires: | |
configargparse | |
requests | |
""" | |
import configargparse | |
import json | |
import requests | |
import sys | |
class GoDaddyRecord: | |
""" | |
Represents a single GoDaddy DNS record | |
Includes functions to both retrieve and update the record's data | |
""" | |
GODADDY_API = "https://api.godaddy.com/v1/domains" | |
key = None | |
secret = None | |
url = None | |
def __init__(self, key, secret, domain, type, name): | |
self.key = key | |
self.secret = secret | |
self.url = f"{self.GODADDY_API}/{domain}/records/{type}/{name}" | |
def __generate_headers(self): | |
return {"Authorization": f"sso-key {self.key}:{self.secret}", | |
"Content-type": "application/json"} | |
def get_record(self): | |
""" | |
Get the DNS record listed from GoDaddy | |
https://developer.godaddy.com/doc/endpoint/domains#/v1/recordGet | |
:returns: The current data value of this record as a string | |
""" | |
response = requests.get(self.url, headers=self.__generate_headers()) | |
if(response.status_code == 200): | |
result = response.json() | |
if('data' not in result[0]): | |
# the request was not successful | |
raise Exception(f"{result['message']}") | |
else: | |
raise Exception("Error contacting api.godaddy.com") | |
return result[0]['data'] | |
def update_record(self, updated_data, ttl=3600): | |
""" | |
Update the DNS record listed with GoDaddy | |
https://developer.godaddy.com/doc/endpoint/domains#/v1/recordReplaceTypeName | |
:param updated_data: new data record | |
:param ttl: the time to live, default is 3600 | |
""" | |
response = requests.put(self.url, data=json.dumps([{"data": updated_data, "ttl": ttl}]), | |
headers=self.__generate_headers()) | |
if(response.status_code != 200): | |
raise Exception(f"Error updating record {response.json()}") | |
def get_external_ip(): | |
""" | |
try and get the external IP from ipify.org | |
raise an error if no response found | |
:returns: the external IP as a string | |
""" | |
result = None | |
response = requests.get('https://api.ipify.org?format=json') | |
if(response.status_code == 200): | |
result = response.json() | |
else: | |
raise Exception("Ipify not available") | |
return result['ip'] | |
def main(): | |
# create the godaddy api object | |
record = GoDaddyRecord(args.key, args.secret, args.domain, args.type, args.name) | |
# get the current external ip and the godaddy record ip | |
current_ip = get_external_ip() | |
godaddy_ip = record.get_record() | |
print(f"Current IP: {current_ip}") | |
print(f"GoDaddy IP: {godaddy_ip}") | |
if(current_ip != godaddy_ip): | |
if(not args.debug): | |
print("Data does not match, updating DNS") | |
record.update_record(current_ip) | |
else: | |
# exit with a warning state | |
sys.exit(2) | |
parser = configargparse.ArgumentParser(description='GoDaddy DNS Update') | |
parser.add_argument('-c', '--config', is_config_file=True, | |
help="Path to the config file, notifications will be sent if given") | |
parser.add_argument('-k', '--key', required=True, type=str, | |
help="GoDaddy API Key") | |
parser.add_argument('-s', '--secret', required=True, type=str, | |
help="GoDaddy API Secret") | |
parser.add_argument('-d', '--domain', required=True, type=str, | |
help="The domain to update") | |
parser.add_argument('-t', '--type', default='A', type=str, | |
help="The DNS record type to update, %(default)s is the default type") | |
parser.add_argument('-N', '--name', default="@", type=str, | |
help="The name of the DNS record, %(default)s is the default") | |
parser.add_argument('-D', '--debug', action='store_true', | |
help="Run the script in debug mode, prevents updating of record") | |
args = parser.parse_args() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment