#!/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', datefmt='%Y-%m-%d,%H:%M:%S') ch.setFormatter(formatter) # add handler to logger logger.addHandler(ch) logger.propagate = False return logger def set_log_level(config): try: loglevel = str(config.get('LOG', 'LEVEL')).upper() except (configparser.NoSectionError, configparser.NoOptionError) as e: logger.error("Config error: %s" % (e)) sys.exit(1) if loglevel == 'INFO': level = logging.INFO elif loglevel == 'ERROR': level = logging.ERROR elif loglevel == 'DEBUG': level = logging.DEBUG else: level = logging.INFO logger = logging.getLogger('certbot_dns_corenetworks') logger.setLevel(level) for handler in logger.handlers: handler.setLevel(level) 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) 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", "delete")) headers = {"Authorization": "Bearer %s" % (token)} data = {} data["name"] = config.get('DNS', 'RECORD') data["data"] = config.get('DNS', 'DATA') 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 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 def main(): """Main logic entrypoint""" logger = setup_logger() config = load_config(logger) set_log_level(config) # 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) records = z_record.json() if not records: logger.error("No records found") sys.exit(1) elif len(records) > 1: logger.error("Too many records found") sys.exit(1) else: if records[0].get("name") and records[0].get("data"): config.set('DNS', 'RECORD', records[0]["name"]) config.set('DNS', 'DATA', records[0]["data"]) else: logger.error("Not enough data available") sys.exit(1) # delete record logger.info("Try to delete TXT record") z_delete = delete_record(config, logger) # commit changes z_commit = dns_commit(config, logger) os.remove('/tmp/CERTBOT_%s.json' % (os.environ['CERTBOT_DOMAIN'])) logger.info("Delete TXT record successful") if __name__ == "__main__": main()