diff --git a/authenticator.py b/authenticator.py index 47ad059..f6ac682 100755 --- a/authenticator.py +++ b/authenticator.py @@ -46,15 +46,10 @@ def load_config(logger): return config -def write_backup(name, value, logger): +def write_backup(filename, name, value, logger): data = {} data["name"] = name data["data"] = value - filename = '/tmp/CERTBOT_%s.json' % (name) - - if os.path.isfile(filename): - logger.error("File '%s' exists. There seems to be an existing DNS record." % (filename)) - sys.exit(1) with codecs.open(filename, 'w', encoding='utf8') as f: f.write(json.dumps(data, sort_keys=True, indent=4, ensure_ascii=False)) @@ -108,6 +103,11 @@ def get_zone(config, logger): def set_record(config, logger): + filename = '/tmp/CERTBOT_%s.json' % (os.environ['CERTBOT_DOMAIN']) + if os.path.isfile(filename): + logger.error("File '%s' exists. There seems to be an existing DNS record." % (filename)) + sys.exit(1) + try: host = config.get('API', 'HOST') zone = config.get('DNS', 'ZONE') @@ -123,6 +123,7 @@ def set_record(config, logger): custom_cache_extract = tldextract.TLDExtract( cache_file=os.path.join(os.path.expanduser("~"), "tld_set")) subdomain = custom_cache_extract(os.environ['CERTBOT_DOMAIN']).subdomain + record_name = "_acme-challenge.%s" % (os.environ['CERTBOT_DOMAIN']) if subdomain: certbot_domain = "_acme-challenge.%s" % (subdomain) else: @@ -132,8 +133,6 @@ def set_record(config, logger): logger.error("Environment Variable %s not set" % (e)) sys.exit(1) - write_backup(os.environ['CERTBOT_DOMAIN'], certbot_validation, logger) - data = {} data["name"] = certbot_domain data["ttl"] = 120 @@ -148,6 +147,30 @@ def set_record(config, logger): logger.error(e) sys.exit(1) + write_backup(filename, certbot_domain, certbot_validation, logger) + + return r + + +def dns_commit(config, logger): + try: + host = config.get('API', 'HOST') + zone = config.get('DNS', 'ZONE') + token = config.get('API', 'TOKEN') + except (configparser.NoSectionError, configparser.NoOptionError) as e: + logger.error("Config error: %s" % (e)) + sys.exit(1) + + url = urlparse.urljoin(host, os.path.join("dnszones", zone, "records", "commit")) + headers = {"Authorization": "Bearer %s" % (token)} + + try: + r = requests.post(url, headers=headers) + r.raise_for_status() + except requests.exceptions.HTTPError, e: + logger.error(e) + sys.exit(1) + return r @@ -185,6 +208,11 @@ def main(): z_record = set_record(config, logger) logger.info("Set TXT record successful") + # commit changes + logger.info("Try to commit dns changes to nameservers") + z_commit = dns_commit(config, logger) + logger.info("Commit successful") + if __name__ == "__main__": main() diff --git a/cleanup.py b/cleanup.py index faa18be..0a9b4da 100755 --- a/cleanup.py +++ b/cleanup.py @@ -1,2 +1,172 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- + +"""API client to core-networks""" + +import requests +import os +import json +import urlparse +import configparser +import sys +import logging +import tldextract +import codecs + + +def setup_logger(): + # seup logging + logger = logging.getLogger("certbot_dns_corenetworks") + logging.basicConfig(level=logging.INFO) + # silence logging from requests module + logging.getLogger('requests').setLevel(logging.CRITICAL) + + # create console handler + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + + formatter = logging.Formatter('%(asctime)s - %(name)s- %(levelname)s - %(message)s') + ch.setFormatter(formatter) + # add handler to logger + logger.addHandler(ch) + logger.propagate = False + return logger + + +def load_config(logger): + config_path = os.path.join(os.path.expanduser("~"), ".certbot_dns_corenetworks", "config.ini") + + if os.path.isfile(config_path): + config = configparser.ConfigParser() + config.read(config_path) + else: + logger.error("Configfile " + config_path + " not present.") + sys.exit(1) + + return config + + +def get_auth_token(config, logger): + data = {} + + try: + data["login"] = config.get('API', 'USER') + data["password"] = config.get('API', 'PASSWORD') + json_data = json.dumps(data) + + host = config.get('API', 'HOST') + except (configparser.NoSectionError, configparser.NoOptionError) as e: + logger.error("Config error: %s" % (e)) + sys.exit(1) + + url = urlparse.urljoin(host, os.path.join("auth", "token")) + + try: + r = requests.post(url, data=json_data) + r.raise_for_status() + except requests.exceptions.HTTPError as e: + logger.error(e) + sys.exit(1) + + return r + + +def get_record(config, logger): + filename = '/tmp/CERTBOT_%s.json' % (os.environ['CERTBOT_DOMAIN']) + if not os.path.isfile(filename): + logger.error("File '%s' does not exists." % (filename)) + sys.exit(1) + + with open(filename) as f: + data = json.load(f) + + try: + host = config.get('API', 'HOST') + zone = config.get('DNS', 'ZONE') + token = config.get('API', 'TOKEN') + except (configparser.NoSectionError, configparser.NoOptionError) as e: + logger.error("Config error: %s" % (e)) + sys.exit(1) + + url = urlparse.urljoin( + host, os.path.join("dnszones", zone, "records", "?type=TXT&name=%s&data=%s") % + (data['name'], data['data']) + ) + headers = {"Authorization": "Bearer %s" % (token)} + + try: + r = requests.get(url, headers=headers) + r.raise_for_status() + except requests.exceptions.HTTPError, e: + logger.error(e) + sys.exit(1) + print url + print r.json() + sys.exit(1) + + return r + + +def delete_record(config, logger): + try: + host = config.get('API', 'HOST') + zone = config.get('DNS', 'ZONE') + token = config.get('API', 'TOKEN') + except (configparser.NoSectionError, configparser.NoOptionError) as e: + logger.error("Config error: %s" % (e)) + sys.exit(1) + + url = urlparse.urljoin(host, os.path.join("dnszones", zone, "records/")) + headers = {"Authorization": "Bearer %s" % (token)} + + try: + custom_cache_extract = tldextract.TLDExtract( + cache_file=os.path.join(os.path.expanduser("~"), "tld_set")) + subdomain = custom_cache_extract(os.environ['CERTBOT_DOMAIN']).subdomain + if subdomain: + certbot_domain = "_acme-challenge.%s" % (subdomain) + else: + certbot_domain = "_acme-challenge" + certbot_validation = os.environ['CERTBOT_VALIDATION'] + except KeyError, e: + logger.error("Environment Variable %s not set" % (e)) + sys.exit(1) + + write_backup(os.environ['CERTBOT_DOMAIN'], certbot_validation, logger) + + data = {} + data["name"] = certbot_domain + data["ttl"] = 120 + data["type"] = "TXT" + data["data"] = certbot_validation + json_data = json.dumps(data) + + try: + r = requests.post(url, headers=headers, data=json_data) + r.raise_for_status() + except requests.exceptions.HTTPError, e: + logger.error(e) + sys.exit(1) + + return r + + +def main(): + """Main logic entrypoint""" + + logger = setup_logger() + config = load_config(logger) + + # get auth token + logger.info("Try to get auth token") + r_token = get_auth_token(config, logger) + config.set('API', 'TOKEN', r_token.json()["token"]) + logger.info("Authentication successful") + + # get txt record + logger.info("Verify TXT record") + z_record = get_record(config, logger) + + +if __name__ == "__main__": + main()