Refactored to include a CloudflareAPI class

This commit is contained in:
Anon 2022-10-21 14:16:02 -07:00
parent f1fb4624b4
commit 2ecff9e0d5

View File

@ -24,20 +24,40 @@ import argparse
import configparser
import contextlib
import logging
from collections import OrderedDict
class CloudflairAPI:
domain_name = None
cf_api_key = None
cf_zone_id = None
cf_record_id = None
def __init__(self, domain_name, cf_api_key, cf_zone_id, cf_record_id):
self.domain_name = domain_name
self.cf_api_key = cf_api_key
self.cf_zone_id = cf_zone_id
self.cf_record_id = cf_record_id
def get_cf_dns_domain(cf_zone_id):
def get_missing_config_var(self):
keys = ("domain_name", "cf_api_key", "cf_zone_id", "cf_record_id")
missing_parameter = next(
(key for key in keys if getattr(self, key) is None),
None
)
return missing_parameter
def get_cf_dns_domain(self):
return "https://api.cloudflare.com/client/v4/zones/{}/dns_records".format(
cf_zone_id
self.cf_zone_id
)
def get_cf_dns_domain_record_id(cf_zone_id, cf_record_id):
return "/".join([
get_cf_dns_domain(cf_zone_id),
cf_record_id
])
def get_cf_dns_domain_record_id(self):
return "{}/{}".format(
self.get_cf_dns_domain(),
self.cf_record_id
)
# !! Do not use this !! The global Cloudflair API is dangerous. Keeping this here for posterity and info
@ -48,16 +68,16 @@ def get_cf_dns_domain_record_id(cf_zone_id, cf_record_id):
# }
def get_headers(cf_api_key):
def get_headers(self):
return {
"Authorization": "Bearer {}".format(cf_api_key)
"Authorization": "Bearer {}".format(self.cf_api_key)
}
def get_record_id(cf_zone_id, cf_api_key):
def get_record_id(self):
resp = requests.get(
url=get_cf_dns_domain(cf_zone_id),
headers=get_headers(cf_api_key)
url=self.get_cf_dns_domain(),
headers=self.get_headers()
)
failed = resp.status_code != 200
if not failed:
@ -65,48 +85,42 @@ def get_record_id(cf_zone_id, cf_api_key):
return failed
# A hack to prevent pycharm from bitching
def dictionary_split(s, delim='='):
k, v = s.split(delim, 1)
return k, v
# Get the current ip address of the user
def get_new_ip():
with contextlib.suppress(Exception):
a = requests.get("https://1.1.1.1/cdn-cgi/trace").text.split("\n")
ip = dict(dictionary_split(item) for item in a if item != "")["ip"]
return ip
return None
def get_old_ip(cf_zone_id, cf_record_id, cf_api_key):
def get_old_ip(self):
resp = requests.get(
url=get_cf_dns_domain_record_id(cf_zone_id, cf_record_id),
headers=get_headers(cf_api_key)
url=self.get_cf_dns_domain_record_id(),
headers=self.get_headers()
)
if resp.status_code == 200:
return resp.json()["result"]["content"]
return None
def put_new_ip(domain_name, ip, cf_zone_id, cf_record_id, cf_api_key):
def put_new_ip(self, ip):
json_payload = {
"type": 'A',
"name": domain_name,
"name": self.domain_name,
"content": ip,
"proxied": True
}
resp = requests.put(
url=get_cf_dns_domain_record_id(cf_zone_id, cf_record_id),
url=self.get_cf_dns_domain_record_id(),
json=json_payload,
headers=get_headers(cf_api_key)
headers=self.get_headers()
)
success = resp.status_code == 200
return success
# Get the current ip address of the user
def get_new_ip():
with contextlib.suppress(Exception):
a = requests.get("https://1.1.1.1/cdn-cgi/trace").text.split("\n")
ip = dict(item.split('=', 1) for item in filter(None, a))["ip"]
return ip
return None
def config_parser_has_option(config, profile, option):
# 'DEFAULT' is a special value in ConfigParser
config_name = "" if profile == "DEFAULT" else profile
@ -162,36 +176,28 @@ def main():
config = configparser.ConfigParser()
config.read(arguments.config)
options = OrderedDict([
("domain_name", config_parser_has_option(config, arguments.profile, "domain_name")),
("cf_api_key", config_parser_has_option(config, arguments.profile, "cf_api_key")),
("cf_zone_id", config_parser_has_option(config, arguments.profile, "cf_zone_id")),
("cf_record_id", config_parser_has_option(config, arguments.profile, "cf_record_id"))
])
cloudflair_api = CloudflairAPI(
domain_name = config_parser_has_option(config, arguments.profile, "domain_name"),
cf_api_key = config_parser_has_option(config, arguments.profile, "cf_api_key"),
cf_zone_id = config_parser_has_option(config, arguments.profile, "cf_zone_id"),
cf_record_id = config_parser_has_option(config, arguments.profile, "cf_record_id")
)
# Validate configuration file
missing_parameter = next((i for i in options if options[i] is None and i != "cf_record_id"), None)
if missing_parameter is not None:
logging.error("Configuration: {} | Profile: {} | Option: {}".format(
missing_parameter = cloudflair_api.get_missing_config_var()
# If cf_zone_id is None, print out all record ids. The user will have to update this setting in their config file
# This will have to be done once
if missing_parameter == "cf_record_id" or arguments.get_record_ids:
return int(cloudflair_api.get_record_id())
elif missing_parameter is not None:
logging.error("Missing Configuration - Configuration: {} | Profile: {} | Option: {}".format(
arguments.config, arguments.profile, missing_parameter
))
return 1
# If cf_zone_id is None, print out all record ids. The user will have to update this setting in their config file
# This will have to be done at least once
if arguments.get_record_ids or options["cf_record_id"] is None:
return int(get_record_id(options["cf_zone_id"], options["cf_api_key"]))
# Get the current dns record from cloudflair (old)
old_ip = get_old_ip(options["cf_zone_id"], options["cf_record_id"], options["cf_api_key"])
# Get the current ip address of the server (new)
new_ip = None
if arguments.set:
new_ip = arguments.set
else:
new_ip = get_new_ip()
old_ip = cloudflair_api.get_old_ip()
new_ip = arguments.set or get_new_ip()
if new_ip is None:
logging.error("Could not determine new IP")
@ -207,10 +213,10 @@ def main():
elif old_ip == new_ip:
logging.info("New IP matches old IP: {}".format(new_ip))
else:
if put_new_ip(options["domain_name"], new_ip, options["cf_zone_id"], options["cf_record_id"], options["cf_api_key"]):
logging.info("IP updated to: {} from: {}".format(old_ip, new_ip))
if cloudflair_api.put_new_ip(new_ip):
logging.info("IP updated to: {} from: {}".format(new_ip, old_ip))
else:
logging.error("Failed to update to: {} from: {}".format(old_ip, new_ip))
logging.error("Failed to update to: {} from: {}".format(new_ip, old_ip))
return 1
return 0