149 lines
5.2 KiB
Python
Executable File
149 lines
5.2 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
try:
|
|
import requests
|
|
import json
|
|
import tempfile
|
|
import tldextract
|
|
import os
|
|
except ModuleNotFoundError:
|
|
print("Missing module, see requirements.txt")
|
|
exit(1)
|
|
|
|
def getZone(email, apiKey, host):
|
|
listZones = requests.get(f"https://api.cloudflare.com/client/v4/zones/",
|
|
headers={"X-Auth-Email": f"{email}","X-Auth-Key": f"{apiKey}","Content-Type": "application/json"}).json()
|
|
|
|
if listZones["success"] != True:
|
|
print("Could not get Zone ID from Cloudflare. Errors were: " + str(listZones["errors"]))
|
|
exit(1)
|
|
|
|
# Extract the root domain from the full host.
|
|
extractedHost = tldextract.extract(host)
|
|
domain = (extractedHost.domain + "." + extractedHost.suffix)
|
|
|
|
for zone in listZones["result"]:
|
|
if zone["name"] == domain:
|
|
return zone["id"]
|
|
|
|
print("Could not find a Zone ID for the specified domain.")
|
|
exit(1)
|
|
|
|
def storeIP(ip, scriptDir):
|
|
# Store the given IP in the lastip file.
|
|
file = open(scriptDir + 'updateCloudflare.lastip', 'w+')
|
|
file.write(ip)
|
|
|
|
def checkCloudflare(zone, email, apiKey, host):
|
|
# Get all the records in the zone.
|
|
allRecords = requests.get(f"https://api.cloudflare.com/client/v4/zones/{zone}/dns_records",
|
|
headers={"X-Auth-Email": f"{email}","X-Auth-Key": f"{apiKey}","Content-Type": "application/json"}).json()
|
|
|
|
# Search for the defined zone in the list and get it's IP.
|
|
for currentRecord in allRecords["result"]:
|
|
if currentRecord["name"] == host:
|
|
recordIP = currentRecord["content"]
|
|
print(f"IP of {host} is " + recordIP)
|
|
return(recordIP)
|
|
|
|
def updateCloudflare(zone, email, apiKey, host, ip):
|
|
# Get all records for the given zone.
|
|
allRecords = requests.get(f"https://api.cloudflare.com/client/v4/zones/{zone}/dns_records",
|
|
headers={"X-Auth-Email": f"{email}","X-Auth-Key": f"{apiKey}","Content-Type": "application/json"}).json()
|
|
|
|
# Find the record for the domain we want to work on.
|
|
for currentRecord in allRecords["result"]:
|
|
if currentRecord["name"] == host:
|
|
recordID = currentRecord["id"]
|
|
print(f"ID for {host} is " + recordID)
|
|
|
|
# Update our record with the new IP.
|
|
result = requests.patch(f"https://api.cloudflare.com/client/v4/zones/{zone}/dns_records/" + recordID,
|
|
headers={"X-Auth-Email": f"{email}","X-Auth-Key": f"{apiKey}","Content-Type": "application/json"},
|
|
data='{"content":"%s"}' % ip).json()
|
|
|
|
# Check if Cloudflare returned any errors.
|
|
if result["success"] == True:
|
|
print("Cloudflare was successfully updated")
|
|
else:
|
|
print("Updating failed, errors were: " + str(result["errors"]))
|
|
|
|
def main():
|
|
print(
|
|
'''
|
|
------------------------------
|
|
Cloudflare updater
|
|
www.jakecharman.co.uk
|
|
------------------------------
|
|
'''
|
|
)
|
|
|
|
# Get the directory of the script.
|
|
scriptDir = os.path.dirname(os.path.realpath(__file__)) + "/"
|
|
|
|
# Read in parameters from the config file.
|
|
try:
|
|
configFile = open(scriptDir + "updateCloudflare.conf", "r")
|
|
except FileNotFoundError:
|
|
print("Configuration file does not exist.")
|
|
exit(1)
|
|
|
|
configLines = configFile.readlines()
|
|
for line in configLines:
|
|
if line[0] == "#":
|
|
continue
|
|
# Remove any spaces from the line then split it to an array on the = sign.
|
|
splitLn = line.replace(" ", "").strip().split('#')[0].split("=")
|
|
|
|
# Pull in the known config lines.
|
|
if (splitLn[0] == "email"):
|
|
authEmail = splitLn[1]
|
|
elif (splitLn[0] == "apiKey"):
|
|
apiKey = splitLn[1]
|
|
elif (splitLn[0] == "host"):
|
|
hostToUpdate = splitLn[1]
|
|
else:
|
|
# Error out on an unknown config line.
|
|
print("Unknown config: " + splitLn[0])
|
|
exit(1)
|
|
|
|
# Get the Zone ID for the given hostname.
|
|
zoneID = getZone(authEmail, apiKey, hostToUpdate)
|
|
|
|
# Open the temp file.
|
|
try:
|
|
file = open(scriptDir + 'updateCloudflare.lastip', 'r')
|
|
lastip = file.read()
|
|
except FileNotFoundError:
|
|
lastip = ""
|
|
|
|
if lastip == "":
|
|
storedIP = False
|
|
print("No stored IP... checking Cloudflare API")
|
|
cloudflareIP = checkCloudflare(zoneID, authEmail, apiKey, hostToUpdate)
|
|
else:
|
|
storedIP = lastip
|
|
print("Stored IP is " + lastip)
|
|
|
|
# Get our external IP
|
|
ip = requests.get('https://api.ipify.org').text
|
|
print("Our current IP is " + ip)
|
|
if storedIP:
|
|
if ip == storedIP:
|
|
print("IP has not changed since last run... Exiting")
|
|
exit(0)
|
|
else:
|
|
print("IP has changed since last run... Updating Cloudflare")
|
|
storeIP(ip, scriptDir)
|
|
updateCloudflare(zoneID, authEmail, apiKey, hostToUpdate, ip)
|
|
else:
|
|
storeIP(ip, scriptDir)
|
|
if ip == cloudflareIP:
|
|
print("Cloudflare matches our current IP... Exiting")
|
|
exit(0)
|
|
else:
|
|
print("Cloudflare IP does not match our current IP... Updating Cloudflare.")
|
|
updateCloudflare(zoneID, authEmail, apiKey, hostToUpdate, ip)
|
|
|
|
if __name__ == "__main__":
|
|
main() |