From 1d7ddad995f9283220f50e22273ccbe55e62a604 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 21 Nov 2015 00:09:50 +0100 Subject: [PATCH] Initial checkin. --- README | 27 ++++++++++++++ hitch.py | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 16 ++++++++ 3 files changed, 155 insertions(+) create mode 100644 README create mode 100644 hitch.py create mode 100644 setup.py diff --git a/README b/README new file mode 100644 index 0000000..35d9a67 --- /dev/null +++ b/README @@ -0,0 +1,27 @@ +This is a Let's Encrypt installer module for hitch. It is currently +(very) alpha quality. See also my Varnish plugin for authentication, at + + https://git.sesse.net/?p=letsencrypt-varnish-plugin;a=summary + +To use, assuming you've installed the Varnish authentication plugin: + + 1. Install letsencrypt as usual, with letsencrypt-auto. + + 2. Activate the venv: + + . ~/.local/share/letsencrypt/bin/activate + + 3. Install the module: + + pip install -e path/to/this/letsencrypt-hitch + + 4. Ask for and install a certificate: + + sudo ~/.local/share/letsencrypt/bin/letsencrypt --agree-dev-preview --server https://acme-v01.api.letsencrypt.org/directory -a letsencrypt-varnish-plugin:varnish -i letsencrypt-hitch-plugin:hitch -d + + +The Hitch installer plugin is licensed under the same terms as the Let's +Encrypt client itself. + + - Steinar H. Gunderson + diff --git a/hitch.py b/hitch.py new file mode 100644 index 0000000..89d682e --- /dev/null +++ b/hitch.py @@ -0,0 +1,112 @@ +"""Hitch plugin.""" +import logging +import os +import re +import subprocess + +import zope.component +import zope.interface + +from letsencrypt import errors +from letsencrypt import interfaces +from letsencrypt.plugins import common + + +logger = logging.getLogger(__name__) + + +class Installer(common.Plugin): + """Hitch installer.""" + zope.interface.implements(interfaces.IInstaller) + zope.interface.classProvides(interfaces.IPluginFactory) + + description = "Hitch Installer" + hidden = True + + def prepare(self): + with open("/etc/hitch/hitch.conf") as config_file: + self.config = config_file.readlines() + + def more_info(self): + return "Installer for Hitch TLS wrapper." + + def get_all_names(self): + raise errors.PluginError("not implemented") + + def deploy_cert(self, domain, cert_path, key_path, + chain_path=None, fullchain_path=None): + # Concatenate private key and certificate together into one file. + with open(key_path) as key_file: + pem = key_file.read() + + # Add the full chain if we have it; else just the certificate. + if fullchain_path is not None: + with open(fullchain_path) as cert_file: + pem += cert_file.read() + else: + with open(cert_path) as cert_file: + pem += cert_file.read() + + # Add DH params if we have them (needed for PFS). + try: + with open("/etc/hitch/dh-param.pem") as dh_param_file: + pem += dh_param_file.read() + except: + pass + + # Actually write the full file. + filename = os.path.join(os.path.dirname(cert_path), "all.pem") + fd = os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0600) + with os.fdopen(fd, 'w') as pem_file: + pem_file.write(pem) + + # Now go check the config file to see if this file is already there. + found = False + last_pem_line = None + for line_num in xrange(len(self.config)): + m = re.match("^\s*pem-file\s*=\s*\"([^\"]+)\"", self.config[line_num]) + if m: + last_pem_line = line_num + if m.groups()[0] == filename: + found = True + + # If it's not already there, add it after the last line. + if not found: + if last_pem_line is None: + last_pem_line = len(self.config) - 1 + config_line = "pem-file = \"%s\" # Added by Let's Encrypt installer.\n" % filename + self.config.insert(last_pem_line + 1, config_line) + + pass # pragma: no cover + + def enhance(self, domain, enhancement, options=None): + raise errors.PluginError("not implemented") + + def supported_enhancements(self): + return [] + + def get_all_certs_keys(self): + raise errors.PluginError("not implemented") + return [] + + def save(self, title=None, temporary=False): + if temporary: + raise errors.PluginError("temporary is not implemented") + + with open("/etc/hitch/hitch.conf", "w") as config_file: + config_file.writelines(self.config) + + def rollback_checkpoints(self, rollback=1): + raise errors.PluginError("not implemented") + + def recovery_routine(self): + raise errors.PluginError("not implemented") + + def view_config_changes(self): + raise errors.PluginError("not implemented") + + def config_test(self): + raise errors.PluginError("not implemented") + + def restart(self): + subprocess.call(["systemctl", "reload", "hitch.service"]) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..bbe3859 --- /dev/null +++ b/setup.py @@ -0,0 +1,16 @@ +from setuptools import setup + + +setup( + name='letsencrypt-hitch-plugin', + package='hitch.py', + install_requires=[ + 'letsencrypt', + 'zope.interface', + ], + entry_points={ + 'letsencrypt.plugins': [ + 'hitch = hitch:Installer', + ], + }, +) -- 2.39.2