mirror of
https://github.com/certbot/certbot.git
synced 2026-06-03 13:59:02 -04:00
Merge remote-tracking branch 'github/letsencrypt/master' into acme-pylint
This commit is contained in:
commit
1182dcf0c2
9 changed files with 153 additions and 31 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ setup(
|
|||
'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',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
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")'
|
||||
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
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
/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
|
||||
fi
|
||||
apt-get install -y --no-install-recommends -t wheezy-backports libaugeas0
|
||||
augeas_pkg=
|
||||
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..."
|
||||
|
|
|
|||
|
|
@ -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
|
||||
------
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class ApacheParser(object):
|
|||
# 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()
|
||||
|
|
@ -471,16 +472,63 @@ class ApacheParser(object):
|
|||
: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.
|
||||
|
|
@ -502,6 +550,13 @@ class ApacheParser(object):
|
|||
# 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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class BasicParserTest(util.ParserTest):
|
|||
|
||||
"""
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ class NginxConfigurator(common.Plugin):
|
|||
|
||||
# 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.
|
||||
|
||||
|
|
@ -136,7 +136,15 @@ class NginxConfigurator(common.Plugin):
|
|||
|
||||
.. 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]]
|
||||
|
|
@ -150,6 +158,12 @@ class NginxConfigurator(common.Plugin):
|
|||
['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)
|
||||
|
|
@ -168,7 +182,7 @@ class NginxConfigurator(common.Plugin):
|
|||
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
|
||||
|
||||
#######################
|
||||
|
|
|
|||
|
|
@ -159,6 +159,24 @@ class NginxConfiguratorTest(util.NginxTest):
|
|||
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')
|
||||
|
|
|
|||
Loading…
Reference in a new issue