Skip to content

Commit

Permalink
Merge remote-tracking branch 'github/letsencrypt/master' into acme-py…
Browse files Browse the repository at this point in the history
…lint
  • Loading branch information
kuba committed Jan 10, 2016
2 parents a367c98 + e58fc0a commit 1182dcf
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 30 deletions.
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ env:
matrix:
- TOXENV=py26 BOULDER_INTEGRATION=1
- TOXENV=py27 BOULDER_INTEGRATION=1
- TOXENV=py33
- TOXENV=py34
- TOXENV=lint
- TOXENV=cover
# Disabled for now due to requiring sudo -> causing more boulder integration
# DNS timeouts :(
# - TOXENV=apacheconftest
matrix:
include:
- env: TOXENV=py35
python: 3.5


# Only build pushes to the master branch, PRs, and branches beginning with
Expand Down
1 change: 1 addition & 0 deletions acme/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Security',
],
Expand Down
48 changes: 31 additions & 17 deletions bootstrap/_deb_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,42 @@ if apt-cache show python-virtualenv > /dev/null 2>&1; then
virtualenv="$virtualenv python-virtualenv"
fi

augeas_pkg=libaugeas0
augeas_pkg="libaugeas0 augeas-lenses"
AUGVERSION=`apt-cache show --no-all-versions libaugeas0 | grep ^Version: | cut -d" " -f2`

if dpkg --compare-versions 1.0 gt "$AUGVERSION" ; then
if lsb_release -a | grep -q wheezy ; then
if ! grep -v -e ' *#' /etc/apt/sources.list | grep -q wheezy-backports ; then
# This can theoretically error if sources.list.d is empty, but in that case we don't care.
if ! grep -v -e ' *#' /etc/apt/sources.list.d/* 2>/dev/null | grep -q wheezy-backports ; then
/bin/echo -n "Installing augeas from wheezy-backports in 3 seconds..."
sleep 1s
/bin/echo -ne "\e[0K\rInstalling augeas from wheezy-backports in 2 seconds..."
sleep 1s
/bin/echo -e "\e[0K\rInstalling augeas from wheezy-backports in 1 second ..."
sleep 1s
AddBackportRepo() {
# ARGS:
BACKPORT_NAME="$1"
BACKPORT_SOURCELINE="$2"
if ! grep -v -e ' *#' /etc/apt/sources.list | grep -q "$BACKPORT_NAME" ; then
# This can theoretically error if sources.list.d is empty, but in that case we don't care.
if ! grep -v -e ' *#' /etc/apt/sources.list.d/* 2>/dev/null | grep -q "$BACKPORT_NAME"; then
/bin/echo -n "Installing augeas from $BACKPORT_NAME in 3 seconds..."
sleep 1s
/bin/echo -ne "\e[0K\rInstalling augeas from $BACKPORT_NAME in 2 seconds..."
sleep 1s
/bin/echo -e "\e[0K\rInstalling augeas from $BACKPORT_NAME in 1 second ..."
sleep 1s
if echo $BACKPORT_NAME | grep -q wheezy ; then
/bin/echo '(Backports are only installed if explicitly requested via "apt-get install -t wheezy-backports")'

echo deb http://http.debian.net/debian wheezy-backports main >> /etc/apt/sources.list.d/wheezy-backports.list
apt-get update
fi

echo $BACKPORT_SOURCELINE >> /etc/apt/sources.list.d/"$BACKPORT_NAME".list
apt-get update
apt-get install -y --no-install-recommends -t "$BACKPORT_NAME" $augeas_pkg
augeas_pkg=
fi
apt-get install -y --no-install-recommends -t wheezy-backports libaugeas0
augeas_pkg=
fi

}


if dpkg --compare-versions 1.0 gt "$AUGVERSION" ; then
if lsb_release -a | grep -q wheezy ; then
AddBackportRepo wheezy-backports "deb http://http.debian.net/debian wheezy-backports main"
elif lsb_release -a | grep -q precise ; then
# XXX add ARM case
AddBackportRepo precise-backports "deb http://archive.ubuntu.com/ubuntu precise-backports main restricted universe multiverse"
else
echo "No libaugeas0 version is available that's new enough to run the"
echo "Let's Encrypt apache plugin..."
Expand Down
15 changes: 14 additions & 1 deletion docs/using.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,20 @@ Would obtain a single certificate for all of those names, using the
``/var/www/example`` webroot directory for the first two, and
``/var/www/eg`` for the second two.

The webroot plugin works by creating a temporary file for each of your requested
domains in ``${webroot-path}/.well-known/acme-challenge``. Then the Let's
Encrypt validation server makes HTTP requests to validate that the DNS for each
requested domain resolves to the server running letsencrypt. An example request
made to your web server would look like:

::

66.133.109.36 - - [05/Jan/2016:20:11:24 -0500] "GET /.well-known/acme-challenge/HGr8U1IeTW4kY_Z6UIyaakzOkyQgPr_7ArlLgtZE8SX HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"

Note that to use the webroot plugin, your server must be configured to serve
files from hidden directories.


Manual
------

Expand Down Expand Up @@ -237,7 +248,9 @@ The following files are available:
server certificate, i.e. root and intermediate certificates only.

This is what Apache < 2.4.8 needs for `SSLCertificateChainFile
<https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcertificatechainfile>`_.
<https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcertificatechainfile>`_,
and what nginx >= 1.3.7 needs for `ssl_trusted_certificate
<http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_trusted_certificate>`_.

``fullchain.pem``
All certificates, **including** server certificate. This is
Expand Down
71 changes: 63 additions & 8 deletions letsencrypt-apache/letsencrypt_apache/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, aug, root, vhostroot, version=(2, 4)):
# https://httpd.apache.org/docs/2.4/mod/core.html#define
# https://httpd.apache.org/docs/2.4/mod/core.html#ifdefine
# This only handles invocation parameters and Define directives!
self.parser_paths = {}
self.variables = {}
if version >= (2, 4):
self.update_runtime_variables()
Expand Down Expand Up @@ -471,16 +472,63 @@ def _parse_file(self, filepath):
:param str filepath: Apache config file path
"""
use_new, remove_old = self._check_path_actions(filepath)
# Test if augeas included file for Httpd.lens
# Note: This works for augeas globs, ie. *.conf
inc_test = self.aug.match(
"/augeas/load/Httpd/incl [. ='%s']" % filepath)
if not inc_test:
# Load up files
# This doesn't seem to work on TravisCI
# self.aug.add_transform("Httpd.lns", [filepath])
self._add_httpd_transform(filepath)
self.aug.load()
if use_new:
inc_test = self.aug.match(
"/augeas/load/Httpd/incl [. ='%s']" % filepath)
if not inc_test:
# Load up files
# This doesn't seem to work on TravisCI
# self.aug.add_transform("Httpd.lns", [filepath])
if remove_old:
self._remove_httpd_transform(filepath)
self._add_httpd_transform(filepath)
self.aug.load()

def _check_path_actions(self, filepath):
"""Determine actions to take with a new augeas path
This helper function will return a tuple that defines
if we should try to append the new filepath to augeas
parser paths, and / or remove the old one with more
narrow matching.
:param str filepath: filepath to check the actions for
"""

try:
new_file_match = os.path.basename(filepath)
existing_matches = self.parser_paths[os.path.dirname(filepath)]
if "*" in existing_matches:
use_new = False
else:
use_new = True
if new_file_match == "*":
remove_old = True
else:
remove_old = False
except KeyError:
use_new = True
remove_old = False
return use_new, remove_old

def _remove_httpd_transform(self, filepath):
"""Remove path from Augeas transform
:param str filepath: filepath to remove
"""

remove_basenames = self.parser_paths[os.path.dirname(filepath)]
remove_dirname = os.path.dirname(filepath)
for name in remove_basenames:
remove_path = remove_dirname + "/" + name
remove_inc = self.aug.match(
"/augeas/load/Httpd/incl [. ='%s']" % remove_path)
self.aug.remove(remove_inc[0])
self.parser_paths.pop(remove_dirname)

def _add_httpd_transform(self, incl):
"""Add a transform to Augeas.
Expand All @@ -502,6 +550,13 @@ def _add_httpd_transform(self, incl):
# Augeas uses base 1 indexing... insert at beginning...
self.aug.set("/augeas/load/Httpd/lens", "Httpd.lns")
self.aug.set("/augeas/load/Httpd/incl", incl)
# Add included path to paths dictionary
try:
self.parser_paths[os.path.dirname(incl)].append(
os.path.basename(incl))
except KeyError:
self.parser_paths[os.path.dirname(incl)] = [
os.path.basename(incl)]

def standardize_excl(self):
"""Standardize the excl arguments for the Httpd lens in Augeas.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ if [ "$1" = --debian-modules ] ; then
sudo apt-get install -y libapache2-mod-wsgi
sudo apt-get install -y libapache2-mod-macro

for mod in ssl rewrite macro wsgi deflate userdir version mime ; do
for mod in ssl rewrite macro wsgi deflate userdir version mime setenvif ; do
echo -n enabling $mod
sudo a2enmod $mod
done
fi
Expand Down
2 changes: 1 addition & 1 deletion letsencrypt-apache/letsencrypt_apache/tests/parser_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_parse_file(self):
"""
file_path = os.path.join(
self.config_path, "sites-available", "letsencrypt.conf")
self.config_path, "not-parsed-by-default", "letsencrypt.conf")

self.parser._parse_file(file_path) # pylint: disable=protected-access

Expand Down
18 changes: 16 additions & 2 deletions letsencrypt-nginx/letsencrypt_nginx/configurator.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def prepare(self):

# Entry point in main.py for installing cert
def deploy_cert(self, domain, cert_path, key_path,
chain_path, fullchain_path):
chain_path=None, fullchain_path=None):
# pylint: disable=unused-argument
"""Deploys certificate to specified virtual host.
Expand All @@ -136,7 +136,15 @@ def deploy_cert(self, domain, cert_path, key_path,
.. note:: This doesn't save the config files!
:raises errors.PluginError: When unable to deploy certificate due to
a lack of directives or configuration
"""
if not fullchain_path:
raise errors.PluginError(
"The nginx plugin currently requires --fullchain-path to "
"install a cert.")

vhost = self.choose_vhost(domain)
cert_directives = [['ssl_certificate', fullchain_path],
['ssl_certificate_key', key_path]]
Expand All @@ -150,6 +158,12 @@ def deploy_cert(self, domain, cert_path, key_path,
['ssl_stapling', 'on'],
['ssl_stapling_verify', 'on']]

if len(stapling_directives) != 0 and not chain_path:
raise errors.PluginError(
"--chain-path is required to enable "
"Online Certificate Status Protocol (OCSP) stapling "
"on nginx >= 1.3.7.")

try:
self.parser.add_server_directives(vhost.filep, vhost.names,
cert_directives, replace=True)
Expand All @@ -168,7 +182,7 @@ def deploy_cert(self, domain, cert_path, key_path,
self.save_notes += ("Changed vhost at %s with addresses of %s\n" %
(vhost.filep,
", ".join(str(addr) for addr in vhost.addrs)))
self.save_notes += "\tssl_certificate %s\n" % cert_path
self.save_notes += "\tssl_certificate %s\n" % fullchain_path
self.save_notes += "\tssl_certificate_key %s\n" % key_path

#######################
Expand Down
18 changes: 18 additions & 0 deletions letsencrypt-nginx/letsencrypt_nginx/tests/configurator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,24 @@ def test_deploy_cert_stapling(self):
self.assertTrue(util.contains_at_depth(generated_conf,
['ssl_trusted_certificate', 'example/chain.pem'], 2))

def test_deploy_cert_stapling_requires_chain_path(self):
self.config.version = (1, 3, 7)
self.assertRaises(errors.PluginError, self.config.deploy_cert,
"www.example.com",
"example/cert.pem",
"example/key.pem",
None,
"example/fullchain.pem")

def test_deploy_cert_requires_fullchain_path(self):
self.config.version = (1, 3, 1)
self.assertRaises(errors.PluginError, self.config.deploy_cert,
"www.example.com",
"example/cert.pem",
"example/key.pem",
"example/chain.pem",
None)

def test_deploy_cert(self):
server_conf = self.config.parser.abs_path('server.conf')
nginx_conf = self.config.parser.abs_path('nginx.conf')
Expand Down

0 comments on commit 1182dcf

Please sign in to comment.