--- /dev/null
+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 <domain>
+
+
+The Hitch installer plugin is licensed under the same terms as the Let's
+Encrypt client itself.
+
+ - Steinar H. Gunderson <steinar+letsencrypt@gunderson.no>
+
--- /dev/null
+"""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"])