Probably some stuff still missing, definately b0rken.

This commit is contained in:
Chris Snijder 2016-08-01 17:16:53 +02:00
parent e55b4e9da7
commit b85b14cf20
23 changed files with 1503 additions and 129 deletions

1
.gitignore vendored
View File

@ -39,3 +39,4 @@ Scripts
# LE HAProxy dev stuff
working
.vagrant

3
MANIFEST.in Normal file
View File

@ -0,0 +1,3 @@
include LICENSE.txt
include README.rst
recursive-include docs *

View File

@ -1,15 +1,12 @@
HAProxy plugin for Certbot
==========================
Getting started (development)
-----------------------------
Contributing
------------
You need to create a virtual environment and start it, then install this plugin
as a editable package using Python setuptools. I abstracted this in the
`dev_vars` script, which you should source:
```
source dev_vars
```
In order to run tests against the Let's Encrypt API we will run a Boulder
server, which is the exact same server Let's Encrypt is running. The server is
started in Virtual Box using Vagrant. To prevent the installation of any
components and dependencies from cluttering up your computer there is also a
client Virtual Box instance. Both of these machines can be setup and started by
running the `dev_start.sh` script.

62
Vagrantfile vendored Normal file
View File

@ -0,0 +1,62 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION=2
PROJECT_NAME = "lehaproxy"
CLIENT_MEMORY=1024
CLIENT_CPU_COUNT = 2
CLIENT_IOAPIC = "on"
CLIENT_NAT_DNS_HOSTRESOLVER="on"
SERVER_MEMORY=2048
SERVER_CPU_COUNT = 2
SERVER_IOAPIC = "on"
SERVER_NAT_DNS_HOSTRESOLVER="on"
ENVS = {
'PROJECT_NAME' => PROJECT_NAME,
'PROJECT_TZ' => "Europe/Amsterdam",
'PROJECT_CLIENT_HOSTNAME' => PROJECT_NAME + ".local",
'PROJECT_SERVER_HOSTNAME' => "boulder.local",
'PROJECT_SERVER_IP' => "192.168.33.111",
'PROJECT_CLIENT_IP' => "192.168.33.222"
}
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.hostmanager.enabled = true
config.hostmanager.manage_host = true
config.vbguest.auto_update = true
config.vbguest.no_remote = false
config.vm.synced_folder ".", "/vagrant/", disabled: true
config.vm.synced_folder ".", "/" + PROJECT_NAME + "/", type: "virtualbox"
config.vm.define "boulder", autostart: true do |server|
server.vm.box = "debian/jessie64"
server.vm.hostname = "boulder.local"
server.vm.network :private_network, ip: ENVS['PROJECT_SERVER_IP']
server.vm.provision "shell" do |s|
s.path = './provisioning_server.sh'
s.env = ENVS
end
server.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--memory", SERVER_MEMORY]
vb.customize ["modifyvm", :id, "--cpus", SERVER_CPU_COUNT]
vb.customize ["modifyvm", :id, "--ioapic", SERVER_IOAPIC]
vb.customize ["modifyvm", :id, "--natdnshostresolver1", SERVER_NAT_DNS_HOSTRESOLVER]
end
end
config.vm.define "lehaproxy", autostart: true do |client|
client.vm.box = "debian/jessie64"
client.vm.hostname = PROJECT_NAME + ".local"
client.vm.network :private_network, ip: ENVS['PROJECT_CLIENT_IP']
client.vm.provision "shell" do |s|
s.path = './provisioning_client.sh'
s.env = ENVS
end
client.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--memory", CLIENT_MEMORY]
vb.customize ["modifyvm", :id, "--cpus", CLIENT_CPU_COUNT]
vb.customize ["modifyvm", :id, "--ioapic", CLIENT_IOAPIC]
vb.customize ["modifyvm", :id, "--natdnshostresolver1", CLIENT_NAT_DNS_HOSTRESOLVER]
end
end
end

View File

@ -0,0 +1 @@
"""Certbot HAProxy plugin."""

View File

@ -0,0 +1,301 @@
"""HAProxy Configuration."""
import logging
import zope.component
import zope.interface
from acme import challenges
from certbot import errors
from certbot import interfaces
from certbot import util
from certbot import reverter
from certbot.plugins import common
# from certbot.plugins.util import path_surgery
from certbot_haproxy import constants
logger = logging.getLogger(__name__) # pylint:disable=invalid-name
@zope.interface.implementer(interfaces.IAuthenticator, interfaces.IInstaller)
@zope.interface.provider(interfaces.IPluginFactory)
class HAProxyConfigurator(common.Plugin):
"""
HAProxy configurator.
"""
description = "HaProxy - Alpha"
@classmethod
def add_parser_arguments(cls, add):
# TODO: This is how we add arguments, do we need any?
#add("enmod", default=constants.os_constant("enmod"),
# help="Path to the Apache 'a2enmod' binary.")
pass
def __init__(self, *args, **kwargs):
"""Initialize an Apache Configurator.
:param tup version: version of Apache as a tuple (2, 4, 7)
(used mostly for unittesting)
"""
version = kwargs.pop("version", None)
super(HAProxyConfigurator, self).__init__(*args, **kwargs)
# Add name_server association dict
self.assoc = dict()
# Outstanding challenges
self._chall_out = set()
# No additional capabilities
self._enhance_func = {}
def prepare(self):
"""Prepare the authenticator/installer.
"""
# Verify Apache is installed
restart_cmd = constants.os_constant("restart_cmd")[0]
if not util.exe_exists(restart_cmd):
if not path_surgery(restart_cmd):
raise errors.NoInstallationError(
'Cannot find HAProxy control command {0}'.format(
restart_cmd
)
)
def deploy_cert(self, domain, cert_path, key_path,
chain_path=None, fullchain_path=None):
"""
Deploys certificate to HAProxy certificate store.
:raises errors.PluginError: When unable to deploy certificate due to
a lack of directives
"""
vhost = self.choose_vhost(domain)
self._clean_vhost(vhost)
# This is done first so that ssl module is enabled and cert_path,
# cert_key... can all be parsed appropriately
self.prepare_server_https("443")
path = {"cert_path": self.parser.find_dir("SSLCertificateFile",
None, vhost.path),
"cert_key": self.parser.find_dir("SSLCertificateKeyFile",
None, vhost.path)}
# Only include if a certificate chain is specified
if chain_path is not None:
path["chain_path"] = self.parser.find_dir(
"SSLCertificateChainFile", None, vhost.path)
if not path["cert_path"] or not path["cert_key"]:
# Throw some can't find all of the directives error"
logger.warn(
"Cannot find a cert or key directive in %s. "
"VirtualHost was not modified", vhost.path)
# Presumably break here so that the virtualhost is not modified
raise errors.PluginError(
"Unable to find cert and/or key directives")
logger.info("Deploying Certificate to VirtualHost %s", vhost.filep)
logger.debug("Apache version is %s",
".".join(str(i) for i in self.version))
if self.version < (2, 4, 8) or (chain_path and not fullchain_path):
# install SSLCertificateFile, SSLCertificateKeyFile,
# and SSLCertificateChainFile directives
set_cert_path = cert_path
self.aug.set(path["cert_path"][-1], cert_path)
self.aug.set(path["cert_key"][-1], key_path)
if chain_path is not None:
self.parser.add_dir(vhost.path,
"SSLCertificateChainFile", chain_path)
else:
raise errors.PluginError("--chain-path is required for your "
"version of Apache")
else:
if not fullchain_path:
raise errors.PluginError("Please provide the --fullchain-path "
"option pointing to your full chain f"
"ile")
set_cert_path = fullchain_path
self.aug.set(path["cert_path"][-1], fullchain_path)
self.aug.set(path["cert_key"][-1], key_path)
# Save notes about the transaction that took place
self.save_notes += ("Changed vhost at %s with addresses of %s\n"
"\tSSLCertificateFile %s\n"
"\tSSLCertificateKeyFile %s\n" %
(vhost.filep,
", ".join(str(addr) for addr in vhost.addrs),
set_cert_path, key_path))
if chain_path is not None:
self.save_notes += "\tSSLCertificateChainFile %s\n" % chain_path
# Make sure vhost is enabled if distro with enabled / available
if self.conf("handle-sites"):
if not vhost.enabled:
self.enable_site(vhost)
######################################################################
# Enhancements
######################################################################
def supported_enhancements(self): # pylint: disable=no-self-use
"""Returns currently supported enhancements."""
return []
def enhance(self, domain, enhancement, options=None):
"""Enhance configuration.
:param str domain: domain to enhance
:param str enhancement: enhancement type defined in
:const:`~certbot.constants.ENHANCEMENTS`
:param options: options for the enhancement
See :const:`~certbot.constants.ENHANCEMENTS`
documentation for appropriate parameter.
:raises .errors.PluginError: If Enhancement is not supported, or if
there is any other problem with the enhancement.
"""
try:
func = self._enhance_func[enhancement]
except KeyError:
raise errors.PluginError(
"Unsupported enhancement: {0}".format(enhancement))
try:
func(self.choose_vhost(domain), options)
except errors.PluginError:
logger.warn("Failed %s for %s", enhancement, domain)
raise
def restart(self):
"""Runs a config test and reloads the Apache server.
:raises .errors.MisconfigurationError: If either the config test
or reload fails.
"""
self.config_test()
try:
util.run_script(constants.os_constant("restart_cmd"))
except errors.SubprocessError as err:
raise errors.MisconfigurationError(str(err))
def config_test(self): # pylint: disable=no-self-use
"""Check the configuration of HaProxy for errors.
:raises .errors.MisconfigurationError: If config_test fails
"""
try:
util.run_script(constants.os_constant("conftest_cmd"))
except errors.SubprocessError as err:
raise errors.MisconfigurationError(str(err))
def get_version(self):
"""Return version of Apache Server.
Version is returned as tuple. (ie. 2.4.7 = (2, 4, 7))
:returns: version
:rtype: tuple
:raises .PluginError: if unable to find Apache version
"""
try:
stdout, _ = util.run_script(constants.os_constant("version_cmd"))
except errors.SubprocessError:
raise errors.PluginError(
"Unable to run %s -v" %
constants.os_constant("version_cmd"))
regex = re.compile(r"Apache/([0-9\.]*)", re.IGNORECASE)
matches = regex.findall(stdout)
if len(matches) != 1:
raise errors.PluginError("Unable to find Apache version")
return tuple([int(i) for i in matches[0].split(".")])
def more_info(self):
"""Human-readable string to help understand the module"""
return (
"Configures Apache to authenticate and install HTTPS.{0}"
"Server root: {root}{0}"
"Version: {version}".format(
os.linesep, root=self.parser.loc["root"],
version=".".join(str(i) for i in self.version))
)
###########################################################################
# Challenges Section
###########################################################################
def get_chall_pref(self, unused_domain): # pylint: disable=no-self-use
"""Return list of challenge preferences."""
return [challenges.TLSSNI01]
def perform(self, achalls):
"""Perform the configuration related challenge.
This function currently assumes all challenges will be fulfilled.
If this turns out not to be the case in the future. Cleanup and
outstanding challenges will have to be designed better.
"""
self._chall_out.update(achalls)
responses = [None] * len(achalls)
chall_doer = tls_sni_01.ApacheTlsSni01(self)
for i, achall in enumerate(achalls):
# Currently also have chall_doer hold associated index of the
# challenge. This helps to put all of the responses back together
# when they are all complete.
chall_doer.add_chall(achall, i)
sni_response = chall_doer.perform()
if sni_response:
# Must reload in order to activate the challenges.
# Handled here because we may be able to load up other challenge
# types
self.restart()
# TODO: Remove this dirty hack. We need to determine a reliable way
# of identifying when the new configuration is being used.
time.sleep(3)
# Go through all of the challenges and assign them to the proper
# place in the responses return value. All responses must be in the
# same order as the original challenges.
for i, resp in enumerate(sni_response):
responses[chall_doer.indices[i]] = resp
return responses
def cleanup(self, achalls):
"""Revert all challenges."""
self._chall_out.difference_update(achalls)
# If all of the challenges have been finished, clean up everything
if not self._chall_out:
self.revert_challenge_config()
self.restart()
self.parser.init_modules()
def revert_challenge_config(self):
"""Used to cleanup challenge configurations.
:raises .errors.PluginError: If unable to revert the challenge config.
"""
try:
self.reverter.revert_temporary_config()
except errors.ReverterError as err:
raise errors.PluginError(str(err))
self.parser.load()

View File

@ -0,0 +1,36 @@
"""HAProxy plugin constants."""
from certbot import util
CLI_DEFAULTS_DEBIAN_JESSIE = dict(
server_root="/etc/haproxy",
version_cmd=['haproxy', '-v'],
restart_cmd=['systemctl', 'restart', 'haproxy'],
conftest_cmd=['haproxy' '-c' '-f'], # Need the config file as an argument.
)
CLI_DEFAULTS_DEBIAN_WHEEZY = dict(
server_root="/etc/haproxy",
version_cmd=['haproxy', '-v'],
restart_cmd=['service', 'haproxy', 'restart'],
conftest_cmd=['haproxy' '-c' '-f'], # Need the config file as an argument.
)
CLI_DEFAULTS = {
"debian": CLI_DEFAULTS_DEBIAN_JESSIE,
"debian:jessie": CLI_DEFAULTS_DEBIAN_JESSIE,
"debian:wheezy": CLI_DEFAULTS_DEBIAN_WHEEZY,
"ubuntu": CLI_DEFAULTS_DEBIAN_WHEEZY
}
def os_constant(key):
"""Get a constant value for operating system
:param key: name of cli constant
:return: value of constant for active os
"""
os_info = util.get_os_info()
try:
constants = CLI_DEFAULTS[os_info[0].lower()]
except KeyError:
constants = CLI_DEFAULTS["debian"]
return constants[key]

View File

@ -0,0 +1 @@
"""Certbot HAProxy Tests"""

96
dev_start.sh Executable file
View File

@ -0,0 +1,96 @@
#!/bin/bash
CMDS="vagrant"
DEPS="vagrant"
VERBOSE=0
for arg in "$@"; do
if [ "${arg}" = "-v" -o "${arg}" = "--verbose" ]; then
VERBOSE=1
echo "Verbose mode enabled"
fi
done
commands_exist () {
DEPS_MISSING=0
for cmd in $1; do
if ! type "${cmd}" &> /dev/null; then
DEPS_MISSING=1
echo "Dependency '${cmd}' is not installed."
fi
done
return $DEPS_MISSING
}
function_defined() {
type "$1" &> /dev/null;
}
please_install () {
if [ -f /etc/redhat-release ] ; then
PKMGR=$(which yum)
elif [ -f /etc/debian_version ] ; then
PKMGR=$(which apt-get)
fi
echo
echo "Before running this script, please run:"
echo "${PKMGR} install $1"
}
log () {
if [ $VERBOSE -eq 1 ]; then
echo "$1"
fi
}
SUDO=0
do_sudo () {
if [ $SUDO -eq 0 ]; then
echo "Your hosts file does not contain the required entries, will need"
echo "root privileges to set them.."
sudo ls &> /dev/null
SUDO=1
fi
}
if ! commands_exist "${CMDS}"; then
log "Missing one or more dependencies."
please_install "${DEPS}"
exit 1
fi
#log "Checking for vagrant plugins.."
#vagrant plugin install vagrant-hostmanager
#vagrant plugin install vagrant-vbguest
log "Checking hosts file for required entries.."
for hostname in "le.wtf le1.wtf le2.wtf le3.wtf nginx.wtf"; do
if ! grep "${hostname}" /etc/hosts &> /dev/null; then
do_sudo
sudo cat <<EOF >> /etc/hosts
127.0.0.1 ${hostname}
EOF
fi
done
if ! grep "lehaproxy.local" /etc/hosts &> /dev/null; then
do_sudo
sudo cat <<EOF >> /etc/hosts
127.0.0.1 lehaproxy.lan
EOF
fi
if ! grep "boulder.local" /etc/hosts &> /dev/null; then
do_sudo
sudo cat <<EOF >> /etc/hosts
127.0.0.1 boulder.lan
EOF
fi
log "Starting LE HAProxy client and server instance.."
vagrant up
echo "You can now connect to the Vagrant instance:"
echo "vagrant ssh lehaproxy"
echo "After connecting please run:"
echo "sudo -s; cd /lehaproxy/; source /lehaproxy_venv/"

View File

@ -1,71 +0,0 @@
#!/bin/bash
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
echo "ERROR: You need to source this script, not run it."
echo "Please run like this: \`source $0\`"
exit 255
fi
VERBOSE=0
for arg in "$@"; do
if [ "${arg}" = "-v" -o "${arg}" = "--verbose" ]; then
VERBOSE=1
echo "Verbose mode enabled"
fi
done
commands_exist () {
DEPS_MISSING=0
for cmd in $1; do
if ! type "${cmd}" &> /dev/null; then
DEPS_MISSING=1
echo "Dependency '${cmd}' is not installed."
fi
done
return $DEPS_MISSING
}
function_defined() {
type "$1" &> /dev/null;
}
please_install () {
if [ -f /etc/redhat-release ] ; then
PKMGR=$(which yum)
elif [ -f /etc/debian_version ] ; then
PKMGR=$(which apt-get)
fi
echo
echo "Before running this script, please run:"
echo "${PKMGR} install $1"
}
log () {
if [ $VERBOSE -eq 1 ]; then
echo "$1"
fi
}
CMDS="virtualenv python2.7 pip"
DEPS="virtualenv python2.7 python-setuptools"
if [ ! -d "${PWD}/venv/" ]; then
log "Virtual environment is not present."
log "Checking for dependencies."
if ! commands_exist "${CMDS}"; then
log "Missing one or more dependencies."
please_install "${DEPS}"
exit 1
fi
log "Creating virtual environment."
virtualenv "${PWD}/venv"
fi
if function_defined deactivate; then
log "Deactivating activated virtual environment."
deactivate
fi
log "Checking for dependencies."
source "$PWD/venv/bin/activate"
pip install -e .

1
docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/_build/

192
docs/Makefile Normal file
View File

@ -0,0 +1,192 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/certbot-haproxy.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/certbot-haproxy.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/certbot-haproxy"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/certbot-haproxy"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

0
docs/_static/.gitignore vendored Normal file
View File

0
docs/_templates/.gitignore vendored Normal file
View File

8
docs/api.rst Normal file
View File

@ -0,0 +1,8 @@
=================
API Documentation
=================
.. toctree::
:glob:
api/**

View File

@ -0,0 +1,5 @@
:mod:`certbot_haproxy.configurator`
--------------------------------------
.. automodule:: certbot_haproxy.configurator
:members:

313
docs/conf.py Normal file
View File

@ -0,0 +1,313 @@
# -*- coding: utf-8 -*-
#
# certbot-haproxy documentation build configuration file, created by
# sphinx-quickstart on Sun Oct 18 13:39:26 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
import shlex
import mock
here = os.path.abspath(os.path.dirname(__file__))
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath(os.path.join(here, '..')))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
]
autodoc_member_order = 'bysource'
autodoc_default_flags = ['show-inheritance', 'private-members']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'certbot-haproxy'
copyright = u'2014-2015, Let\'s Encrypt Project'
author = u'Certbot Project'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0'
# The full version, including alpha/beta/rc tags.
release = '0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'en'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
default_role = 'py:obj'
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs
# on_rtd is whether we are on readthedocs.org
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# otherwise, readthedocs.org uses their theme by default, so no need to specify it
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'certbot-haproxydoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'certbot-haproxy.tex', u'certbot-haproxy Documentation',
u'Certbot Project', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'certbot-haproxy', u'certbot-haproxy Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'certbot-haproxy', u'certbot-haproxy Documentation',
author, 'certbot-haproxy', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
intersphinx_mapping = {
'python': ('https://docs.python.org/', None),
'acme': ('https://acme-python.readthedocs.org/en/latest/', None),
'certbot': ('https://certbot.eff.org/docs/', None),
}

31
docs/index.rst Normal file
View File

@ -0,0 +1,31 @@
.. certbot-haproxy documentation master file, created by
sphinx-quickstart on Sun Oct 18 13:39:26 2015.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to certbot-haproxy's documentation!
==============================================
Contents:
.. toctree::
:maxdepth: 2
.. toctree::
:maxdepth: 1
api
.. automodule:: certbot_haproxy
:members:
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

263
docs/make.bat Normal file
View File

@ -0,0 +1,263 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
echo. coverage to run coverage check of the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
REM Check if sphinx-build is available and fallback to Python version if any
%SPHINXBUILD% 2> nul
if errorlevel 9009 goto sphinx_python
goto sphinx_ok
:sphinx_python
set SPHINXBUILD=python -m sphinx.__init__
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
:sphinx_ok
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\certbot-haproxy.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\certbot-haproxy.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "coverage" (
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
if errorlevel 1 exit /b 1
echo.
echo.Testing of coverage in the sources finished, look at the ^
results in %BUILDDIR%/coverage/python.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end

70
provisioning_client.sh Normal file
View File

@ -0,0 +1,70 @@
#!/bin/bash -x
echo "$PROJECT_TZ" > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata
export DEBIAN_FRONTEND="noninteractive"
echo "deb http://ftp.debian.org/debian jessie-backports main" >> /etc/apt/sources.list
apt-get update
apt-get upgrade -y
apt-get install -y \
sudo htop net-tools tcpdump ufw git haproxy \
openssl ca-certificates \
python python-setuptools python-dev libssl-dev
apt-get install -y -t jessie-backports certbot
easy_install pip
pip install virtualenv
ufw allow ssh
ufw allow http
ufw allow https
ufw default deny incoming
ufw --force enable
virtualenv "/${PROJECT_NAME}_venv" -p /usr/bin/python
source "/${PROJECT_NAME}_venv/bin/activate"
cd "/${PROJECT_NAME}"
pip install --editable .
echo "${PROJECT_CLIENT_HOSTNAME}" > /etc/hostname
hostname -F /etc/hostname
cat <<EOF >> /etc/letsencrypt/cli.ini
server http://le.wtf
EOF
cat <<EOF >> /etc/hosts
${PROJECT_SERVER_IP} le.wtf
${PROJECT_SERVER_IP} le1.wtf
${PROJECT_SERVER_IP} le2.wtf
${PROJECT_SERVER_IP} le3.wtf
${PROJECT_SERVER_IP} nginx.wtf
EOF
cat <<EOF > /etc/systemd/system/letsencrypt.timer
[Unit]
Description=Run Let's Encrypt every 12 hours
[Timer]
# Time to wait after booting before we run first time
OnBootSec=2min
# Time between running each consecutive time
OnUnitActiveSec=12h
Unit=letsencrypt.service
[Install]
WantedBy=timers.target
EOF
cat <<EOF > /etc/systemd/system/letsencrypt.service
[Unit]
Description=Renew Let's Encrypt Certificates
[Service]
Type=simple
ExecStart=/usr/bin/certbot renew -q
EOF
systemctl enable letsencrypt.timer
systemctl start letsencrypt.timer
echo "Provisioning completed."

View File

@ -1,44 +0,0 @@
#!/bin/bash -x
echo "deb http://ftp.debian.org/debian jessie-backports main" >> /etc/apt/sources.list
apt-get update
apt-get upgrade -y
apt-get install -y \
sudo htop net-tools tcpdump ufw git haproxy\
openssl ca-certificates \
python python-setuptools virtualenv
apt-get install -y -t jessie-backports certbot
ufw allow ssh
ufw allow http
ufw allow https
ufw default deny incoming
# echo HOSTNAME > /etc/hostname
# hostname -F /etc/hostname
cat <<EOF > /etc/systemd/system/letsencrypt.timer
[Unit]
Description=Run Let's Encrypt every 12 hours
[Timer]
# Time to wait after booting before we run first time
OnBootSec=2min
# Time between running each consecutive time
OnUnitActiveSec=12h
Unit=letsencrypt.service
[Install]
WantedBy=timers.target
EOF
cat <<EOF > /etc/systemd/system/letsencrypt.service
[Unit]
Description=Renew Let's Encrypt Certificate
[Service]
Type=simple
ExecStart=certbot renew q
EOF
systemctl start letsencrypt.timer
systemctl enable letsencrypt.timer

108
provisioning_server.sh Normal file
View File

@ -0,0 +1,108 @@
#!/bin/bash -x
echo "$PROJECT_TZ" > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata
export DEBIAN_FRONTEND="noninteractive"
echo "deb http://ftp.debian.org/debian jessie-backports main" >> /etc/apt/sources.list
apt-get update
apt-get upgrade -y
apt-get install -y \
sudo htop net-tools tcpdump ufw git curl \
openssl ca-certificates golang \
python2.7 python-setuptools python-virtualenv \
rabbitmq-server make libltdl-dev mariadb-server nginx-light
apt-get install -y -t jessie-backports \
protobuf-compiler golang-goprotobuf-dev libprotobuf-dev \
python-protobuf protobuf-c-compiler golang-protobuf-extensions-dev
echo boulder.local > /etc/hostname
hostname -F /etc/hostname
ufw allow ssh
ufw allow 4000
ufw allow 8000
ufw allow 8001
ufw allow 8002
ufw allow 8003
ufw allow 8004
ufw allow 8005
ufw default deny incoming
ufw --force enable
if ! grep -Fxq "export GOROOT=/usr/local/go" ~/.bashrc; then
echo "export GOROOT=/usr/local/go" >> ~/.bashrc
fi
if ! grep -Fxq "export GOPATH=/boulder" /root/.bashrc; then
echo "export GOPATH=/boulder" >> /root/.bashrc
fi
if ! grep -Fxq "export PATH=\$GOROOT/bin:\$PATH" ~/.bashrc; then
echo "export PATH=\$GOROOT/bin:\$PATH" >> ~/.bashrc
fi
if ! grep -Fxq "export PATH=\$PATH:\$GOPATH" /root/.bashrc; then
echo "export PATH=\$PATH:\$GOPATH" >> /root/.bashrc
fi
if ! grep -Fxq "127.0.0.1 boulder boulder-rabbitmq boulder-mysql" /etc/hosts; then
echo '127.0.0.1 boulder boulder-rabbitmq boulder-mysql' >> /etc/hosts
fi
source ~/.bashrc
# wget -q https://storage.googleapis.com/golang/go1.5.3.linux-amd64.tar.gz -P /tmp/
# sudo tar -C /usr/local -xzf /tmp/go1.5.3.linux-amd64.tar.gz
# if ! grep -Fxq "export GOROOT=/usr/local/go" ~/.profile ; then echo "export GOROOT=/usr/local/go" >> ~/.profile; fi
# if ! grep -Fxq "export PATH=\\$GOROOT/bin:\\$PATH" ~/.profile ; then echo "export PATH=\\$GOROOT/bin:\\$PATH" >> ~/.profile; fi
cd /vagrant
./letsencrypt-auto-source/letsencrypt-auto --os-packages-only
./tools/venv.sh
./tests/boulder-start.sh
virtualenv /boulder_venv -p /usr/bin/python2
source /boulder_venv/bin/activate
git clone https://github.com/letsencrypt/boulder.git /boulder
cd /boulder
mkdir /boulder/bin
mkdir /boulder/src
curl https://glide.sh/get | sh
glide create --non-interactive
glide install
#go get \
# bitbucket.org/liamstask/goose/cmd/goose \
# github.com/golang/lint/golint \
# github.com/golang/mock/mockgen \
# github.com/golang/protobuf/proto \
# github.com/golang/protobuf/protoc-gen-go \
# github.com/jsha/listenbuddy \
# github.com/kisielk/errcheck \
# github.com/mattn/goveralls \
# github.com/modocache/gover \
# github.com/tools/godep \
# golang.org/x/tools/cover \
# github.com/letsencrypt/boulder/cmd \
# github.com/streadway/amqp
./test/create_db.sh
go run cmd/rabbitmq-setup/main.go -server amqp://boulder-rabbitmq
cat > "/lib/systemd/system/boulder.service" <<EOF
[Unit]
Description=Boulder Server
After=network.target
Wants=mariadb.service,rabbitmq.service
[Service]
Type=simple
KillMode=process
RemainAfterExit=no
Restart=always
ExecStart=/boulder_venv/bin/python /boulder/start.py"
[Install]
WantedBy=multi-user.target
EOF
systemctl enable boulder.service
systemctl start boulder.service
echo "Provisioning completed."

View File

@ -4,12 +4,12 @@ from setuptools import setup
from setuptools import find_packages
certbot_version = '0.9.0.dev0'
certbot_version = '0.8.1'
# Please update tox.ini when modifying dependency version requirements
install_requires = [
'acme~={0}'.format(certbot_version),
'certbot~={0}'.format(certbot_version),
'acme>={0}'.format(certbot_version),
'certbot>={0}'.format(certbot_version),
# For pkg_resources. >=1.0 so pip resolves it to a version cryptography
# will tolerate; see #2599:
'setuptools>=1.0',