From d06c6f27bdfbde31e18d5a5f3fc40c0a85b723e7 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 16 Dec 2015 14:33:41 -0800 Subject: [PATCH 01/35] Removed duplicate cancel --- letsencrypt/cli.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/letsencrypt/cli.py b/letsencrypt/cli.py index 29519d430..6634b422d 100644 --- a/letsencrypt/cli.py +++ b/letsencrypt/cli.py @@ -276,12 +276,11 @@ def _handle_identical_cert_request(config, cert): elif config.verb == "certonly": keep_opt = "Keep the existing certificate for now" choices = [keep_opt, - "Renew & replace the cert (limit ~5 per 7 days)", - "Cancel this operation and do nothing"] + "Renew & replace the cert (limit ~5 per 7 days)"] display = zope.component.getUtility(interfaces.IDisplay) response = display.menu(question, choices, "OK", "Cancel") - if response[0] == "cancel" or response[1] == 2: + if response[0] == display_util.CANCEL: # TODO: Add notification related to command-line options for # skipping the menu for this case. raise errors.Error( From 177e42e9d67601e860db45df1c0121f4905b536d Mon Sep 17 00:00:00 2001 From: Eugene Kazakov Date: Sun, 20 Dec 2015 12:43:57 +0600 Subject: [PATCH 02/35] Remove warning "Root (sudo) is required" --- letsencrypt/cli.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/letsencrypt/cli.py b/letsencrypt/cli.py index 29519d430..f614e13f8 100644 --- a/letsencrypt/cli.py +++ b/letsencrypt/cli.py @@ -1384,17 +1384,6 @@ def main(cli_args=sys.argv[1:]): zope.component.provideUtility(report) atexit.register(report.atexit_print_messages) - if not os.geteuid() == 0: - logger.warning( - "Root (sudo) is required to run most of letsencrypt functionality.") - # check must be done after arg parsing as --help should work - # w/o root; on the other hand, e.g. "letsencrypt run - # --authenticator dns" or "letsencrypt plugins" does not - # require root as well - #return ( - # "{0}Root is required to run letsencrypt. Please use sudo.{0}" - # .format(os.linesep)) - return args.func(args, config, plugins) if __name__ == "__main__": From a04b92eb8e91e6f51b3a851313e16821057c9edf Mon Sep 17 00:00:00 2001 From: asaph Date: Tue, 22 Dec 2015 13:37:36 -0800 Subject: [PATCH 03/35] OSX: check if augeas, dialog are already installed This check avoids the following 2 noisy warnings: Warning: augeas-1.4.0 already installed Warning: dialog-1.2-20150528 already installed --- bootstrap/mac.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bootstrap/mac.sh b/bootstrap/mac.sh index 4d1fb8208..4b6612336 100755 --- a/bootstrap/mac.sh +++ b/bootstrap/mac.sh @@ -4,8 +4,15 @@ if ! hash brew 2>/dev/null; then ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" fi -brew install augeas -brew install dialog +if [ -z "$(brew list --versions augeas)" ]; then + echo "augeas Not Installed\nInstalling augeas from Homebrew..." + brew install augeas +fi + +if [ -z "$(brew list --versions dialog)" ]; then + echo "dialog Not Installed\nInstalling dialog from Homebrew..." + brew install dialog +fi if ! hash pip 2>/dev/null; then echo "pip Not Installed\nInstalling python from Homebrew..." From d3fddc351920ffce2a55c55f08b99899942dbf44 Mon Sep 17 00:00:00 2001 From: osirisinferi Date: Fri, 8 Jan 2016 13:38:57 +0100 Subject: [PATCH 04/35] Prevent recording of deps in world set --- bootstrap/_gentoo_common.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bootstrap/_gentoo_common.sh b/bootstrap/_gentoo_common.sh index f49dc00f0..aa0de650c 100755 --- a/bootstrap/_gentoo_common.sh +++ b/bootstrap/_gentoo_common.sh @@ -12,12 +12,12 @@ PACKAGES=" case "$PACKAGE_MANAGER" in (paludis) - cave resolve --keep-targets if-possible $PACKAGES -x + cave resolve --preserve-world --keep-targets if-possible $PACKAGES -x ;; (pkgcore) - pmerge --noreplace $PACKAGES + pmerge --noreplace --oneshot $PACKAGES ;; (portage|*) - emerge --noreplace $PACKAGES + emerge --noreplace --oneshot $PACKAGES ;; esac From aba11814cb666d7d6e1e55fb641d93cc9dad45e4 Mon Sep 17 00:00:00 2001 From: osirisinferi Date: Fri, 8 Jan 2016 13:47:55 +0100 Subject: [PATCH 05/35] Add Gentoo documentation --- docs/using.rst | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/using.rst b/docs/using.rst index 5da13f02c..78967b90c 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -64,7 +64,7 @@ or for full help, type: ``letsencrypt-auto`` is the recommended method of running the Let's Encrypt client beta releases on systems that don't have a packaged version. Debian, -Arch linux, FreeBSD, and OpenBSD now have native packages, so on those +Arch linux, Gentoo, FreeBSD, and OpenBSD now have native packages, so on those systems you can just install ``letsencrypt`` (and perhaps ``letsencrypt-apache``). If you'd like to run the latest copy from Git, or run your own locally modified copy of the client, follow the instructions in @@ -376,6 +376,23 @@ If you don't want to use the Apache plugin, you can omit the Packages for Debian Jessie are coming in the next few weeks. +**Gentoo** + +.. code-block:: shell + + emerge -av app-crypt/letsencrypt + +Currently, the Apache and nginx plugins are not included in Portage. You can +however use Layman to add the mrueg overlay which does include the plugin +packages: + +.. code-block:: shell + + emerge -av app-portage/layman + layman -S + layman -a mrueg + emerge -av app-crypt/letsencrypt-apache app-crypt/letsencrypt-nginx + **Other Operating Systems** OS packaging is an ongoing effort. If you'd like to package From 31a64a0e9ffe2d5cbbfc0f6eb87329ae8c75f007 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sun, 10 Jan 2016 18:01:58 +0000 Subject: [PATCH 06/35] ACME: default to new_authzr_uri form Directory --- acme/acme/client.py | 21 +++++++++++---------- acme/acme/client_test.py | 32 ++++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index c3e28ef47..b8d30461d 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -181,40 +181,41 @@ class Client(object): # pylint: disable=too-many-instance-attributes raise errors.UnexpectedUpdate(authzr) return authzr - def request_challenges(self, identifier, new_authzr_uri): + def request_challenges(self, identifier, new_authzr_uri=None): """Request challenges. - :param identifier: Identifier to be challenged. - :type identifier: `.messages.Identifier` - - :param str new_authzr_uri: new-authorization URI + :param .messages.Identifier identifier: Identifier to be challenged. + :param str new_authzr_uri: ``new-authorization`` URI. If omitted, + will default to value found in ``directory``. :returns: Authorization Resource. :rtype: `.AuthorizationResource` """ new_authz = messages.NewAuthorization(identifier=identifier) - response = self.net.post(new_authzr_uri, new_authz) + response = self.net.post(self.directory.new_authz + if new_authzr_uri is None else new_authzr_uri, + new_authz) # TODO: handle errors assert response.status_code == http_client.CREATED return self._authzr_from_response(response, identifier) - def request_domain_challenges(self, domain, new_authz_uri): + def request_domain_challenges(self, domain, new_authzr_uri=None): """Request challenges for domain names. This is simply a convenience function that wraps around `request_challenges`, but works with domain names instead of - generic identifiers. + generic identifiers. See ``request_challenges`` for more + documentation. :param str domain: Domain name to be challenged. - :param str new_authzr_uri: new-authorization URI :returns: Authorization Resource. :rtype: `.AuthorizationResource` """ return self.request_challenges(messages.Identifier( - typ=messages.IDENTIFIER_FQDN, value=domain), new_authz_uri) + typ=messages.IDENTIFIER_FQDN, value=domain), new_authzr_uri) def answer_challenge(self, challb, response): """Answer challenge. diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 58f55b293..db5dcd6ed 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -36,6 +36,7 @@ class ClientTest(unittest.TestCase): self.directory = messages.Directory({ messages.NewRegistration: 'https://www.letsencrypt-demo.org/acme/new-reg', messages.Revocation: 'https://www.letsencrypt-demo.org/acme/revoke-cert', + messages.NewAuthorization: 'https://www.letsencrypt-demo.org/acme/new-authz', }) from acme.client import Client @@ -133,7 +134,7 @@ class ClientTest(unittest.TestCase): regr = self.client.update_registration.call_args[0][0] self.assertEqual(self.regr.terms_of_service, regr.body.agreement) - def test_request_challenges(self): + def _prepare_response_for_request_challenges(self): self.response.status_code = http_client.CREATED self.response.headers['Location'] = self.authzr.uri self.response.json.return_value = self.authz.to_json() @@ -141,10 +142,20 @@ class ClientTest(unittest.TestCase): 'next': {'url': self.authzr.new_cert_uri}, } - self.client.request_challenges(self.identifier, self.authzr.uri) - # TODO: test POST call arguments + def test_request_challenges(self): + self._prepare_response_for_request_challenges() + self.client.request_challenges(self.identifier) + self.net.post.assert_called_once_with( + self.directory.new_authz, + messages.NewAuthorization(identifier=self.identifier)) - # TODO: split here and separate test + def test_requets_challenges_custom_uri(self): + self._prepare_response_for_request_challenges() + self.client.request_challenges(self.identifier, 'URI') + self.net.post.assert_called_once_with('URI', mock.ANY) + + def test_request_challenges_unexpected_update(self): + self._prepare_response_for_request_challenges() self.response.json.return_value = self.authz.update( identifier=self.identifier.update(value='foo')).to_json() self.assertRaises( @@ -153,15 +164,20 @@ class ClientTest(unittest.TestCase): def test_request_challenges_missing_next(self): self.response.status_code = http_client.CREATED - self.assertRaises( - errors.ClientError, self.client.request_challenges, - self.identifier, self.regr) + self.assertRaises(errors.ClientError, self.client.request_challenges, + self.identifier) def test_request_domain_challenges(self): self.client.request_challenges = mock.MagicMock() self.assertEqual( self.client.request_challenges(self.identifier), - self.client.request_domain_challenges('example.com', self.regr)) + self.client.request_domain_challenges('example.com')) + + def test_request_domain_challenges_custom_uri(self): + self.client.request_challenges = mock.MagicMock() + self.assertEqual( + self.client.request_challenges(self.identifier, 'URI'), + self.client.request_domain_challenges('example.com', 'URI')) def test_answer_challenge(self): self.response.links['up'] = {'url': self.challr.authzr_uri} From 20ab48820aec5762861867422124d7b4df4ba141 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sun, 10 Jan 2016 18:36:24 +0000 Subject: [PATCH 07/35] Remove unused `setup.py dev` alias --- setup.cfg | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index ca4c1b1ca..1ea06661e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,9 +1,6 @@ [easy_install] zip_ok = false -[aliases] -dev = develop easy_install letsencrypt[dev,docs,testing] - [nosetests] nocapture=1 cover-package=letsencrypt,acme,letsencrypt_apache,letsencrypt_nginx From 86d6d2704511819a2974334ae93313229d3cb7d1 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sun, 10 Jan 2016 18:37:41 +0000 Subject: [PATCH 08/35] Clean up dev/testing extras messup (fixes #2140). --- Dockerfile-dev | 2 +- acme/setup.py | 13 +++++++------ bootstrap/dev/venv.sh | 4 ++-- bootstrap/dev/venv3.sh | 2 +- setup.py | 14 +++++--------- tox.ini | 14 +++++++------- 6 files changed, 23 insertions(+), 26 deletions(-) diff --git a/Dockerfile-dev b/Dockerfile-dev index 3c5b53966..0e9e62486 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -58,7 +58,7 @@ RUN virtualenv --no-site-packages -p python2 /opt/letsencrypt/venv && \ -e /opt/letsencrypt/src/letsencrypt-nginx \ -e /opt/letsencrypt/src/letshelp-letsencrypt \ -e /opt/letsencrypt/src/letsencrypt-compatibility-test \ - -e /opt/letsencrypt/src[dev,docs,testing] + -e /opt/letsencrypt/src[dev,docs] # install in editable mode (-e) to save space: it's not possible to # "rm -rf /opt/letsencrypt/src" (it's stays in the underlaying image); diff --git a/acme/setup.py b/acme/setup.py index 372c05b13..e7371e415 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -36,17 +36,18 @@ if sys.version_info < (2, 7, 9): install_requires.append('ndg-httpsclient') install_requires.append('pyasn1') +dev_extras = [ + 'nose', + 'pep8', + 'tox', +] + docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', 'sphinxcontrib-programoutput', ] -testing_extras = [ - 'nose', - 'tox', -] - setup( name='acme', @@ -76,8 +77,8 @@ setup( include_package_data=True, install_requires=install_requires, extras_require={ + 'dev': dev_extras, 'docs': docs_extras, - 'testing': testing_extras, }, entry_points={ 'console_scripts': [ diff --git a/bootstrap/dev/venv.sh b/bootstrap/dev/venv.sh index 11ab417dd..eea79e846 100755 --- a/bootstrap/dev/venv.sh +++ b/bootstrap/dev/venv.sh @@ -4,8 +4,8 @@ export VENV_ARGS="--python python2" ./bootstrap/dev/_venv_common.sh \ - -e acme[testing] \ - -e .[dev,docs,testing] \ + -e acme[dev] \ + -e .[dev,docs] \ -e letsencrypt-apache \ -e letsencrypt-nginx \ -e letshelp-letsencrypt \ diff --git a/bootstrap/dev/venv3.sh b/bootstrap/dev/venv3.sh index ccffffb83..f1d2b581a 100755 --- a/bootstrap/dev/venv3.sh +++ b/bootstrap/dev/venv3.sh @@ -5,4 +5,4 @@ export VENV_NAME="${VENV_NAME:-venv3}" export VENV_ARGS="--python python3" ./bootstrap/dev/_venv_common.sh \ - -e acme[testing] \ + -e acme[dev] \ diff --git a/setup.py b/setup.py index ad7fb6909..370a9cdb5 100644 --- a/setup.py +++ b/setup.py @@ -64,7 +64,12 @@ else: dev_extras = [ # Pin astroid==1.3.5, pylint==1.4.2 as a workaround for #289 'astroid==1.3.5', + 'coverage', + 'nose', + 'nosexcover', + 'pep8', 'pylint==1.4.2', # upstream #248 + 'tox', 'twine', 'wheel', ] @@ -76,14 +81,6 @@ docs_extras = [ 'sphinxcontrib-programoutput', ] -testing_extras = [ - 'coverage', - 'nose', - 'nosexcover', - 'pep8', - 'tox', -] - setup( name='letsencrypt', version=version, @@ -119,7 +116,6 @@ setup( extras_require={ 'dev': dev_extras, 'docs': docs_extras, - 'testing': testing_extras, }, tests_require=install_requires, diff --git a/tox.ini b/tox.ini index c6cefb764..6b05efabd 100644 --- a/tox.ini +++ b/tox.ini @@ -15,9 +15,9 @@ envlist = py{26,27,33,34,35},py{26,27}-oldest,cover,lint # packages installed separately to ensure that dowstream deps problems # are detected, c.f. #1002 commands = - pip install -e acme[testing] + pip install -e acme[dev] nosetests -v acme - pip install -e .[testing] + pip install -e .[dev] nosetests -v letsencrypt pip install -e letsencrypt-apache nosetests -v letsencrypt_apache @@ -40,23 +40,23 @@ deps = [testenv:py33] commands = - pip install -e acme[testing] + pip install -e acme[dev] nosetests -v acme [testenv:py34] commands = - pip install -e acme[testing] + pip install -e acme[dev] nosetests -v acme [testenv:py35] commands = - pip install -e acme[testing] + pip install -e acme[dev] nosetests -v acme [testenv:cover] basepython = python2.7 commands = - pip install -e acme -e .[testing] -e letsencrypt-apache -e letsencrypt-nginx -e letshelp-letsencrypt + pip install -e acme[dev] -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letshelp-letsencrypt ./tox.cover.sh [testenv:lint] @@ -66,7 +66,7 @@ basepython = python2.7 # duplicate code checking; if one of the commands fails, others will # continue, but tox return code will reflect previous error commands = - pip install -e acme -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt + pip install -e acme[dev] -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt ./pep8.travis.sh pylint --rcfile=.pylintrc letsencrypt pylint --rcfile=acme/.pylintrc acme/acme From 15f492946893a6b460ad8ea40cffed323c9de7bd Mon Sep 17 00:00:00 2001 From: osirisinferi Date: Mon, 25 Jan 2016 22:23:30 +0100 Subject: [PATCH 09/35] Update and expansion of Gentoo documentation --- docs/using.rst | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 78967b90c..6370de963 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -378,20 +378,49 @@ Packages for Debian Jessie are coming in the next few weeks. **Gentoo** +The official Let's Encrypt client is available in Gentoo Portage. If you +want to use the Apache plugin, it has to be installed separately: + .. code-block:: shell emerge -av app-crypt/letsencrypt + emerge -av app-crypt/letsencrypt-apache -Currently, the Apache and nginx plugins are not included in Portage. You can -however use Layman to add the mrueg overlay which does include the plugin -packages: +Currently, only the Apache plugin is included in Portage. However, if you +want the nginx plugin, you can use Layman to add the mrueg overlay which +does include the nginx plugin package: .. code-block:: shell emerge -av app-portage/layman layman -S layman -a mrueg - emerge -av app-crypt/letsencrypt-apache app-crypt/letsencrypt-nginx + emerge -av app-crypt/letsencrypt-nginx + +When using the Apache plugin, you will run into a "cannot find a cert or key +directive" error if you're sporting the default Gentoo ``httpd.conf``. +You can fix this by commenting out two lines in ``/etc/apache2/httpd.conf`` +as follows: + +Change + +.. code-block:: shell + + + LoadModule ssl_module modules/mod_ssl.so + + +to + +.. code-block:: shell + + # + LoadModule ssl_module modules/mod_ssl.so + # + +For the time being, this is the only way for the Apache plugin to recognise +the appropriate directives when installing the certificate. +Note: this change is not required for the other plugins. **Other Operating Systems** From f9327d553531ae04de0962a30b3ef05f338f41e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roy=20Wellington=20=E2=85=A3?= Date: Sat, 6 Feb 2016 21:43:52 -0800 Subject: [PATCH 10/35] Make this use of urlparse.urlparse Python 3 compatible. --- letsencrypt/configuration.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/letsencrypt/configuration.py b/letsencrypt/configuration.py index 2bbf1b019..c49751a6c 100644 --- a/letsencrypt/configuration.py +++ b/letsencrypt/configuration.py @@ -1,8 +1,8 @@ """Let's Encrypt user-supplied configuration.""" import copy import os -import urlparse +from six.moves.urllib import parse # pylint: disable=import-error import zope.interface from letsencrypt import constants @@ -50,7 +50,7 @@ class NamespaceConfig(object): @property def server_path(self): """File path based on ``server``.""" - parsed = urlparse.urlparse(self.namespace.server) + parsed = parse.urlparse(self.namespace.server) return (parsed.netloc + parsed.path).replace('/', os.path.sep) @property From 2369f1253bcd5eeb8d31ee135a78d59a5a207458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roy=20Wellington=20=E2=85=A3?= Date: Sun, 7 Feb 2016 12:58:35 -0800 Subject: [PATCH 11/35] Fix import ordering s.t. future versions of pylint won't warn on it. pylint gets more strict about import order in the future, so adjust it now to make upgrading smoother. pylint is following the order from PEP-8: > Imports should be grouped in the following order: > > 1. standard library imports > 2. related third party imports > 3. local application/library specific imports > > You should put a blank line between each group of imports. --- letsencrypt/plugins/common.py | 2 +- letsencrypt/plugins/disco_test.py | 2 +- letsencrypt/tests/storage_test.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/letsencrypt/plugins/common.py b/letsencrypt/plugins/common.py index f18b1fb3b..2e9e15b2f 100644 --- a/letsencrypt/plugins/common.py +++ b/letsencrypt/plugins/common.py @@ -1,11 +1,11 @@ """Plugin common functions.""" import os -import pkg_resources import re import shutil import tempfile import OpenSSL +import pkg_resources import zope.interface from acme.jose import util as jose_util diff --git a/letsencrypt/plugins/disco_test.py b/letsencrypt/plugins/disco_test.py index 0df4f88f1..1aeaf81c1 100644 --- a/letsencrypt/plugins/disco_test.py +++ b/letsencrypt/plugins/disco_test.py @@ -1,8 +1,8 @@ """Tests for letsencrypt.plugins.disco.""" -import pkg_resources import unittest import mock +import pkg_resources import zope.interface from letsencrypt import errors diff --git a/letsencrypt/tests/storage_test.py b/letsencrypt/tests/storage_test.py index 9d402089c..5b9f393fe 100644 --- a/letsencrypt/tests/storage_test.py +++ b/letsencrypt/tests/storage_test.py @@ -1,13 +1,13 @@ """Tests for letsencrypt.storage.""" import datetime -import pytz import os -import tempfile import shutil +import tempfile import unittest import configobj import mock +import pytz from letsencrypt import configuration from letsencrypt import errors From 24fa435f464adf6fe526b00039ff99bcf98b1e61 Mon Sep 17 00:00:00 2001 From: Minn Soe Date: Thu, 11 Feb 2016 00:38:24 +0000 Subject: [PATCH 12/35] Fix broken reference to script in old bootstrap directory --- tools/venv.sh | 2 +- tools/venv3.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/venv.sh b/tools/venv.sh index 11ab417dd..5a09efb0b 100755 --- a/tools/venv.sh +++ b/tools/venv.sh @@ -3,7 +3,7 @@ export VENV_ARGS="--python python2" -./bootstrap/dev/_venv_common.sh \ +./tools/_venv_common.sh \ -e acme[testing] \ -e .[dev,docs,testing] \ -e letsencrypt-apache \ diff --git a/tools/venv3.sh b/tools/venv3.sh index ccffffb83..158605f72 100755 --- a/tools/venv3.sh +++ b/tools/venv3.sh @@ -4,5 +4,5 @@ export VENV_NAME="${VENV_NAME:-venv3}" export VENV_ARGS="--python python3" -./bootstrap/dev/_venv_common.sh \ +./tools/_venv_common.sh \ -e acme[testing] \ From e2a6bdf574d05fde3957a9eced067678051ac3b5 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 10 Feb 2016 20:05:34 -0800 Subject: [PATCH 13/35] letstest: work with a local repo, even if it isn't called letsencrypt * allows test farm tests to be run from release branches --- tests/letstest/multitester.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/letstest/multitester.py b/tests/letstest/multitester.py index 378670071..e27385002 100644 --- a/tests/letstest/multitester.py +++ b/tests/letstest/multitester.py @@ -241,21 +241,21 @@ def local_git_clone(repo_url): "clones master of repo_url" with lcd(LOGDIR): local('if [ -d letsencrypt ]; then rm -rf letsencrypt; fi') - local('git clone %s'% repo_url) + local('git clone %s letsencrypt'% repo_url) local('tar czf le.tar.gz letsencrypt') def local_git_branch(repo_url, branch_name): "clones branch of repo_url" with lcd(LOGDIR): local('if [ -d letsencrypt ]; then rm -rf letsencrypt; fi') - local('git clone %s --branch %s --single-branch'%(repo_url, branch_name)) + local('git clone %s letsencrypt --branch %s --single-branch'%(repo_url, branch_name)) local('tar czf le.tar.gz letsencrypt') def local_git_PR(repo_url, PRnumstr, merge_master=True): "clones specified pull request from repo_url and optionally merges into master" with lcd(LOGDIR): local('if [ -d letsencrypt ]; then rm -rf letsencrypt; fi') - local('git clone %s'% repo_url) + local('git clone %s letsencrypt'% repo_url) local('cd letsencrypt && git fetch origin pull/%s/head:lePRtest'%PRnumstr) local('cd letsencrypt && git co lePRtest') if merge_master: From 180117facb62c78cf91c6ae169249602cd817b7d Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Wed, 10 Feb 2016 22:13:27 -0800 Subject: [PATCH 14/35] Some preliminary documentation updates to mention renew verb --- docs/using.rst | 60 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 9ee16dffd..c2962ea2e 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -71,7 +71,9 @@ Plugin Auth Inst Notes =========== ==== ==== =============================================================== apache_ Y Y Automates obtaining and installing a cert with Apache 2.4 on Debian-based distributions with ``libaugeas0`` 1.0+. -standalone_ Y N Uses a "standalone" webserver to obtain a cert. +standalone_ Y N Uses a "standalone" webserver to obtain a cert. This is useful + on systems with no webserver, or when direct integration with + the local webserver is not supported or not desired. webroot_ Y N Obtains a cert by writing to the webroot directory of an already running webserver. manual_ Y N Helps you obtain a cert by giving you instructions to perform @@ -171,21 +173,59 @@ Renewal days). Make sure you renew the certificates at least once in 3 months. -In order to renew certificates simply call the ``letsencrypt`` (or +The ``letsencrypt`` client now supports a ``renew`` action to check +all installed certificates for impending expiry and attempt to renew +them. The simplest form is simply + +``letsencrypt renew`` + +This will attempt to renew any previously-obtained certificates that +expire in less than 30 days. The same plugin and options that were used +at the time the certificate was originally issued will be used for the +renewal attempt, unless you specify other plugins or options. + +If you're sure that UI doesn't prompt for any details you can add the +command to ``crontab`` (make it less than every 90 days to avoid problems, +say every month); note that the current version provides detailed output +describing either renewal success or failure. + +The ``--force-renew`` flag may be helpful for automating renewal; +it causes the expiration time of the certificate(s) to be ignored when +considering renewal, and attempts to renew each and every installed +certificate regardless of its age. + +Note that options provided to ``letsencrypt renew`` will apply to +*every* certificate for which renewal is attempted; for example, +``letsencrypt renew --rsa-key-size 4096`` would try to replace every +near-expiry certificate with an equivalent certificate using a 4096-bit +RSA public key. If a certificate is successfully renewed using +specified options, those options will be saved and used for future +renewals of that certificate. + + +An alternative form that provides for more fine-grained control over the +renewal process (while renewing specified certificates one at a time), +is ``letsencrypt certonly`` with the complete set of subject domains of +a specific certificate specified via `-d` flags, like + +``letsencrypt certonly -d example.com -d www.example.com`` + +(All of the domains covered by the certificate must be specified in +this case in order to renew and replace the old certificate rather +than obtaining a new one; don't forget any `www.` domains!) The +``certonly`` form attempts to renew one individual certificate. + letsencrypt-auto_) again, and use the same values when prompted. You can automate it slightly by passing necessary flags on the CLI (see `--help -all`), or even further using the :ref:`config-file`. The ``--force-renew`` -flag may be helpful for automating renewal; it causes the expiration time -of the certificate(s) to be ignored when considering renewal. If you're -sure that UI doesn't prompt for any details you can add the command to -``crontab`` (make it less than every 90 days to avoid problems, say -every month). +all`), or even further using the :ref:`config-file`. + Please note that the CA will send notification emails to the address you provide if you do not renew certificates that are about to expire. -Let's Encrypt is working hard on automating the renewal process. Until -the tool is ready, we are sorry for the inconvenience! +Let's Encrypt is working hard on improving the renewal process, and we +apologize for any inconveniences you encounter in integrating these +commands into your individual environment. .. _where-certs: From d791697b93d4e390336b189208e587968bf41d40 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 11 Feb 2016 17:13:08 -0500 Subject: [PATCH 15/35] If le-auto's installation fails, delete the venv. Fix #2332. Leaving broken venvs around can, if it got as far as installing the venv/bin/letsencrypt script, wreck future le-auto runs, since the presence of that script means "a working LE is installed" to it. Waiting until a new version of le-auto comes out and running it would recover, but this lets re-running the same version recover as well. --- letsencrypt-auto-source/letsencrypt-auto | 3 ++- letsencrypt-auto-source/letsencrypt-auto.template | 1 + letsencrypt-auto-source/tests/auto_test.py | 8 +++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 9218bdc52..8cc90b64e 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -19,7 +19,7 @@ XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share} VENV_NAME="letsencrypt" VENV_PATH=${VENV_PATH:-"$XDG_DATA_HOME/$VENV_NAME"} VENV_BIN=${VENV_PATH}/bin -LE_AUTO_VERSION="0.4.0" +LE_AUTO_VERSION="0.5.0.dev0" # This script takes the same arguments as the main letsencrypt program, but it # additionally responds to --verbose (more output) and --debug (allow support @@ -1630,6 +1630,7 @@ UNLIKELY_EOF # Report error. (Otherwise, be quiet.) echo "Had a problem while downloading and verifying Python packages:" echo "$PEEP_OUT" + rm -rf "$VENV_PATH" exit 1 fi fi diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index ad8c97a7f..53838280b 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -207,6 +207,7 @@ UNLIKELY_EOF # Report error. (Otherwise, be quiet.) echo "Had a problem while downloading and verifying Python packages:" echo "$PEEP_OUT" + rm -rf "$VENV_PATH" exit 1 fi fi diff --git a/letsencrypt-auto-source/tests/auto_test.py b/letsencrypt-auto-source/tests/auto_test.py index 32d591190..90e09f57f 100644 --- a/letsencrypt-auto-source/tests/auto_test.py +++ b/letsencrypt-auto-source/tests/auto_test.py @@ -5,7 +5,7 @@ from contextlib import contextmanager from functools import partial from json import dumps from os import chmod, environ -from os.path import abspath, dirname, join +from os.path import abspath, dirname, exists, join import re from shutil import copy, rmtree import socket @@ -338,6 +338,12 @@ class AutoTests(TestCase): self.assertIn("THE FOLLOWING PACKAGES DIDN'T MATCH THE " "HASHES SPECIFIED IN THE REQUIREMENTS", exc.output) + ok_(not exists(join(venv_dir, 'letsencrypt')), + msg="The virtualenv was left around, even though " + "installation didn't succeed. We shouldn't do " + "this, as it foils our detection of whether we " + "need to recreate the virtualenv, which hinges " + "on the presence of $VENV_BIN/letsencrypt.") else: self.fail("Peep didn't detect a bad hash and stop the " "installation.") From 6eb2d60166f142d489f70a2e6076d2fe7c3b3769 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 11 Feb 2016 18:02:27 -0500 Subject: [PATCH 16/35] Let --no-self-upgrade bootstrap OS packages. Fix #2432. --no-self-upgrade metamorphosed from a private flag to a public one, so add a new private flag, --le-auto-phase2 to take its original role of marking the division between phases. This flag must come first and, consequently, can be stripped off the arg list before calling through to letsencrypt, which means the client doesn't need to know about it. The downside is that anyone still (deprecatedly) running le-auto out of the root of a (recently updated) master checkout will get a "Hey, the current release version le-auto I just self-upgraded to doesn't understand the --le-auto-phase2 flag" error from when we merge this until the next release is made, but that's better than a documented option not working right. Also, remove a needless folder creation from the Dockerfile. --- letsencrypt-auto-source/Dockerfile | 2 +- letsencrypt-auto-source/letsencrypt-auto | 54 ++++++++++--------- .../letsencrypt-auto.template | 52 +++++++++--------- 3 files changed, 58 insertions(+), 50 deletions(-) diff --git a/letsencrypt-auto-source/Dockerfile b/letsencrypt-auto-source/Dockerfile index fd7fe4851..ad2465fda 100644 --- a/letsencrypt-auto-source/Dockerfile +++ b/letsencrypt-auto-source/Dockerfile @@ -17,7 +17,7 @@ RUN apt-get update && \ apt-get clean RUN pip install nose -RUN mkdir -p /home/lea/letsencrypt/letsencrypt +RUN mkdir -p /home/lea/letsencrypt # Install fake testing CA: COPY ./tests/certs/ca/my-root-ca.crt.pem /usr/local/share/ca-certificates/ diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 9218bdc52..16466dd89 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -19,7 +19,7 @@ XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share} VENV_NAME="letsencrypt" VENV_PATH=${VENV_PATH:-"$XDG_DATA_HOME/$VENV_NAME"} VENV_BIN=${VENV_PATH}/bin -LE_AUTO_VERSION="0.4.0" +LE_AUTO_VERSION="0.5.0.dev0" # This script takes the same arguments as the main letsencrypt program, but it # additionally responds to --verbose (more output) and --debug (allow support @@ -412,9 +412,10 @@ TempDir() { -if [ "$NO_SELF_UPGRADE" = 1 ]; then +if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. + shift 1 # the --le-auto-phase2 arg if [ -f "$VENV_BIN/letsencrypt" ]; then INSTALLED_VERSION=$("$VENV_BIN/letsencrypt" --version 2>&1 | cut -d " " -f 2) else @@ -1653,10 +1654,11 @@ else exit 0 fi - echo "Checking for new version..." - TEMP_DIR=$(TempDir) - # --------------------------------------------------------------------------- - cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py" + if [ "$NO_SELF_UPGRADE" != 1 ]; then + echo "Checking for new version..." + TEMP_DIR=$(TempDir) + # --------------------------------------------------------------------------- + cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py" """Do downloading and JSON parsing without additional dependencies. :: # Print latest released version of LE to stdout: @@ -1785,25 +1787,27 @@ if __name__ == '__main__': exit(main()) UNLIKELY_EOF - # --------------------------------------------------------------------------- - DeterminePythonVersion - REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` - if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then - echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." + # --------------------------------------------------------------------------- + DeterminePythonVersion + REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` + if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then + echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." - # Now we drop into Python so we don't have to install even more - # dependencies (curl, etc.), for better flow control, and for the option of - # future Windows compatibility. - "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + # Now we drop into Python so we don't have to install even more + # dependencies (curl, etc.), for better flow control, and for the option of + # future Windows compatibility. + "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" - # Install new copy of letsencrypt-auto. This preserves permissions and - # ownership from the old copy. - # TODO: Deal with quotes in pathnames. - echo "Replacing letsencrypt-auto..." - echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" - $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" - # TODO: Clean up temp dir safely, even if it has quotes in its path. - rm -rf "$TEMP_DIR" - fi # should upgrade - "$0" --no-self-upgrade "$@" + # Install new copy of letsencrypt-auto. This preserves permissions and + # ownership from the old copy. + # TODO: Deal with quotes in pathnames. + echo "Replacing letsencrypt-auto..." + echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" + $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" + # TODO: Clean up temp dir safely, even if it has quotes in its path. + rm -rf "$TEMP_DIR" + fi # A newer version is available. + fi # Self-upgrading is allowed. + + "$0" --le-auto-phase2 "$@" fi diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index ad8c97a7f..dbb823263 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -168,9 +168,10 @@ TempDir() { -if [ "$NO_SELF_UPGRADE" = 1 ]; then +if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. + shift 1 # the --le-auto-phase2 arg if [ -f "$VENV_BIN/letsencrypt" ]; then INSTALLED_VERSION=$("$VENV_BIN/letsencrypt" --version 2>&1 | cut -d " " -f 2) else @@ -230,31 +231,34 @@ else exit 0 fi - echo "Checking for new version..." - TEMP_DIR=$(TempDir) - # --------------------------------------------------------------------------- - cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py" + if [ "$NO_SELF_UPGRADE" != 1 ]; then + echo "Checking for new version..." + TEMP_DIR=$(TempDir) + # --------------------------------------------------------------------------- + cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py" {{ fetch.py }} UNLIKELY_EOF - # --------------------------------------------------------------------------- - DeterminePythonVersion - REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` - if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then - echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." + # --------------------------------------------------------------------------- + DeterminePythonVersion + REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` + if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then + echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." - # Now we drop into Python so we don't have to install even more - # dependencies (curl, etc.), for better flow control, and for the option of - # future Windows compatibility. - "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + # Now we drop into Python so we don't have to install even more + # dependencies (curl, etc.), for better flow control, and for the option of + # future Windows compatibility. + "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" - # Install new copy of letsencrypt-auto. This preserves permissions and - # ownership from the old copy. - # TODO: Deal with quotes in pathnames. - echo "Replacing letsencrypt-auto..." - echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" - $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" - # TODO: Clean up temp dir safely, even if it has quotes in its path. - rm -rf "$TEMP_DIR" - fi # should upgrade - "$0" --no-self-upgrade "$@" + # Install new copy of letsencrypt-auto. This preserves permissions and + # ownership from the old copy. + # TODO: Deal with quotes in pathnames. + echo "Replacing letsencrypt-auto..." + echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" + $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" + # TODO: Clean up temp dir safely, even if it has quotes in its path. + rm -rf "$TEMP_DIR" + fi # A newer version is available. + fi # Self-upgrading is allowed. + + "$0" --le-auto-phase2 "$@" fi From a43a21d4e250a8df293b81b73949ae7cf2785d11 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 11 Feb 2016 15:37:17 -0800 Subject: [PATCH 17/35] Use example domains in README --- README.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 57908e90f..522400a1f 100644 --- a/README.rst +++ b/README.rst @@ -51,11 +51,11 @@ client will guide you through the process of obtaining and installing certs interactively. You can also tell it exactly what you want it to do from the command line. -For instance, if you want to obtain a cert for ``thing.com``, -``www.thing.com``, and ``otherthing.net``, using the Apache plugin to both +For instance, if you want to obtain a cert for ``example.com``, +``www.example.com``, and ``other.example.net``, using the Apache plugin to both obtain and install the certs, you could do this:: - ./letsencrypt-auto --apache -d thing.com -d www.thing.com -d otherthing.net + ./letsencrypt-auto --apache -d example.com -d www.example.com -d other.example.net (The first time you run the command, it will make an account, and ask for an email and agreement to the Let's Encrypt Subscriber Agreement; you can @@ -64,7 +64,7 @@ automate those with ``--email`` and ``--agree-tos``) If you want to use a webserver that doesn't have full plugin support yet, you can still use "standalone" or "webroot" plugins to obtain a certificate:: - ./letsencrypt-auto certonly --standalone --email admin@thing.com -d thing.com -d www.thing.com -d otherthing.net + ./letsencrypt-auto certonly --standalone --email admin@example.com -d example.com -d www.example.com -d other.example.net Understanding the client in more depth From eb4e8bf59ebc13dbb9b92f4f4983b6906c0b506a Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Thu, 11 Feb 2016 18:42:27 -0500 Subject: [PATCH 18/35] Add a "success" message after installation. Fix #1621. Close #2214. --- letsencrypt-auto-source/letsencrypt-auto | 3 ++- letsencrypt-auto-source/letsencrypt-auto.template | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 9218bdc52..30d907690 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -19,7 +19,7 @@ XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share} VENV_NAME="letsencrypt" VENV_PATH=${VENV_PATH:-"$XDG_DATA_HOME/$VENV_NAME"} VENV_BIN=${VENV_PATH}/bin -LE_AUTO_VERSION="0.4.0" +LE_AUTO_VERSION="0.5.0.dev0" # This script takes the same arguments as the main letsencrypt program, but it # additionally responds to --verbose (more output) and --debug (allow support @@ -1632,6 +1632,7 @@ UNLIKELY_EOF echo "$PEEP_OUT" exit 1 fi + echo "Installation succeeded." fi echo "Requesting root privileges to run letsencrypt..." echo " " $SUDO "$VENV_BIN/letsencrypt" "$@" diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index ad8c97a7f..1fa12528f 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -209,6 +209,7 @@ UNLIKELY_EOF echo "$PEEP_OUT" exit 1 fi + echo "Installation succeeded." fi echo "Requesting root privileges to run letsencrypt..." echo " " $SUDO "$VENV_BIN/letsencrypt" "$@" From 52eee4fbfb3c583a59b9082e368b9b4f87e52f72 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 11 Feb 2016 15:45:26 -0800 Subject: [PATCH 19/35] Use example domains in using.rst --- docs/using.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 9ee16dffd..15c3df869 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -118,11 +118,11 @@ directory of the files served by your webserver. For example, If you're getting a certificate for many domains at once, each domain will use the most recent ``--webroot-path``. So for instance: -``letsencrypt certonly --webroot -w /var/www/example/ -d www.example.com -d example.com -w /var/www/eg -d eg.is -d www.eg.is`` +``letsencrypt certonly --webroot -w /var/www/example/ -d www.example.com -d example.com -w /var/www/other -d other.example.net -d another.other.example.net`` 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. +``/var/www/other`` 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 From e1e52a9d56f684cf2cb289a0661da65c132843c7 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 11 Feb 2016 17:47:15 -0800 Subject: [PATCH 20/35] Verify both symlink and target --- letsencrypt/storage.py | 37 ++++++++++++++++++++----------- letsencrypt/tests/storage_test.py | 4 ++++ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/letsencrypt/storage.py b/letsencrypt/storage.py index 6f7f54646..6786ac745 100644 --- a/letsencrypt/storage.py +++ b/letsencrypt/storage.py @@ -112,6 +112,21 @@ def update_configuration(lineagename, target, cli_config): return configobj.ConfigObj(config_filename) +def get_link_target(link): + """Get an absolute path to the target of link. + + :param str link: Path to a symbolic link + + :returns: Absolute path to the target of link + :rtype: str + + """ + target = os.readlink(link) + if not os.path.isabs(target): + target = os.path.join(os.path.dirname(link), target) + return os.path.abspath(target) + + class RenewableCert(object): # pylint: disable=too-many-instance-attributes """Renewable certificate. @@ -194,13 +209,15 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes def _check_symlinks(self): """Raises an exception if a symlink doesn't exist""" - def check(link): - """Checks if symlink points to a file that exists""" - return os.path.exists(os.path.realpath(link)) for kind in ALL_FOUR: - if not check(getattr(self, kind)): + link = getattr(self, kind) + if not os.path.islink(link): raise errors.CertStorageError( - "link: {0} does not exist".format(getattr(self, kind))) + "expected {0} to be a symlink".format(link)) + target = get_link_target(link) + if not os.path.exists(target): + raise errors.CertStorageError("target {0} of symlink {1} does " + "not exist".format(target, link)) def _consistent(self): """Are the files associated with this lineage self-consistent? @@ -225,10 +242,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes return False for kind in ALL_FOUR: link = getattr(self, kind) - where = os.path.dirname(link) - target = os.readlink(link) - if not os.path.isabs(target): - target = os.path.join(where, target) + target = get_link_target(link) # Each element's link must point within the cert lineage's # directory within the official archive directory @@ -343,10 +357,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes logger.debug("Expected symlink %s for %s does not exist.", link, kind) return None - target = os.readlink(link) - if not os.path.isabs(target): - target = os.path.join(os.path.dirname(link), target) - return os.path.abspath(target) + return get_link_target(link) def current_version(self, kind): """Returns numerical version of the specified item. diff --git a/letsencrypt/tests/storage_test.py b/letsencrypt/tests/storage_test.py index 9d402089c..071d6d7bb 100644 --- a/letsencrypt/tests/storage_test.py +++ b/letsencrypt/tests/storage_test.py @@ -687,6 +687,10 @@ class RenewableCertTests(BaseRenewableCertTest): self.assertRaises(errors.CertStorageError, storage.RenewableCert, self.config.filename, self.cli_config) + os.symlink("missing", self.config[ALL_FOUR[0]]) + self.assertRaises(errors.CertStorageError, + storage.RenewableCert, + self.config.filename, self.cli_config) if __name__ == "__main__": From 73b81a35c282e520d7c597877c3443bd6a07485b Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Thu, 11 Feb 2016 17:57:46 -0800 Subject: [PATCH 21/35] More documentation edits; prioritize webroot over standalone --- docs/using.rst | 90 +++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index c2962ea2e..22e6b5e5e 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -49,7 +49,7 @@ or for full help, type: ``letsencrypt-auto`` is the recommended method of running the Let's Encrypt client beta releases on systems that don't have a packaged version. Debian, -Arch linux, FreeBSD, and OpenBSD now have native packages, so on those +Arch Linux, FreeBSD, and OpenBSD now have native packages, so on those systems you can just install ``letsencrypt`` (and perhaps ``letsencrypt-apache``). If you'd like to run the latest copy from Git, or run your own locally modified copy of the client, follow the instructions in @@ -93,36 +93,27 @@ This automates both obtaining *and* installing certs on an Apache webserver. To specify this plugin on the command line, simply include ``--apache``. -Standalone ----------- - -To obtain a cert using a "standalone" webserver, you can use the -standalone plugin by including ``certonly`` and ``--standalone`` -on the command line. This plugin needs to bind to port 80 or 443 in -order to perform domain validation, so you may need to stop your -existing webserver. To control which port the plugin uses, include -one of the options shown below on the command line. - - * ``--standalone-supported-challenges http-01`` to use port 80 - * ``--standalone-supported-challenges tls-sni-01`` to use port 443 - Webroot ------- -If you're running a webserver that you don't want to stop to use -standalone, you can use the webroot plugin to obtain a cert by -including ``certonly`` and ``--webroot`` on the command line. In -addition, you'll need to specify ``--webroot-path`` or ``-w`` with the root -directory of the files served by your webserver. For example, -``--webroot-path /var/www/html`` or -``--webroot-path /usr/share/nginx/html`` are two common webroot paths. +If you're running a local webserver for which you have the ability +to modify the content being served, and you'd prefer not to stop the +webserver during the certificate issuance process, you can use the webroot +plugin to obtain a cert by including ``certonly`` and ``--webroot`` on +the command line. In addition, you'll need to specify ``--webroot-path`` +or ``-w`` with the top-level directory ("web root") containing the files +served by your webserver. For example, ``--webroot-path /var/www/html`` +or ``--webroot-path /usr/share/nginx/html`` are two common webroot paths. -If you're getting a certificate for many domains at once, each domain will use -the most recent ``--webroot-path``. So for instance: +If you're getting a certificate for many domains at once, the plugin +needs to know where each domain's files are served from, which could +potentially be a separate directory for each domain. When requested a +certificate for multiple domains, each domain will use the most recently +specified ``--webroot-path``. So, for instance, ``letsencrypt certonly --webroot -w /var/www/example/ -d www.example.com -d example.com -w /var/www/eg -d eg.is -d www.eg.is`` -Would obtain a single certificate for all of those names, using the +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. @@ -137,8 +128,28 @@ 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. +files from hidden directories. If ``/.well-known`` is treated specially by +your webserver configuration, you might need to modify the configuration +to ensure that files inside ``/.well-known/ache-challenge`` are served by +the webserver. +Standalone +---------- + +To obtain a cert using a "standalone" webserver, you can use the +standalone plugin by including ``certonly`` and ``--standalone`` +on the command line. This plugin needs to bind to port 80 or 443 in +order to perform domain validation, so you may need to stop your +existing webserver. To control which port the plugin uses, include +one of the options shown below on the command line. + + * ``--standalone-supported-challenges http-01`` to use port 80 + * ``--standalone-supported-challenges tls-sni-01`` to use port 443 + +The standalone plugin does not rely on any other server software running +on the machine where you obtain the certificate. It must still be possible +for that machine to accept inbound connections from the Internet on the +specified port using each requested domain name. Manual ------ @@ -148,7 +159,8 @@ other than your target webserver or perform the steps for domain validation yourself, you can use the manual plugin. While hidden from the UI, you can use the plugin to obtain a cert by specifying ``certonly`` and ``--manual`` on the command line. This requires you -to copy and paste commands into another terminal session. +to copy and paste commands into another terminal session, which may +be on a different computer. Nginx ----- @@ -159,7 +171,7 @@ is still experimental, however, and is not installed with letsencrypt-auto_. If installed, you can select this plugin on the command line by including ``--nginx``. -Third party plugins +Third-party plugins ------------------- These plugins are listed at @@ -184,15 +196,19 @@ expire in less than 30 days. The same plugin and options that were used at the time the certificate was originally issued will be used for the renewal attempt, unless you specify other plugins or options. -If you're sure that UI doesn't prompt for any details you can add the -command to ``crontab`` (make it less than every 90 days to avoid problems, -say every month); note that the current version provides detailed output -describing either renewal success or failure. +If you're sure that this command executes successfully without human +intervention, you can add the command to ``crontab`` (since certificates +are only renewed when they're determined to be near expiry, the command +can run on a regular basis, like every week or every day); note that +the current version provides detailed output describing either renewal +success or failure. The ``--force-renew`` flag may be helpful for automating renewal; it causes the expiration time of the certificate(s) to be ignored when considering renewal, and attempts to renew each and every installed -certificate regardless of its age. +certificate regardless of its age. (This form is not appropriate to run +daily because each certificate will be renewed every day, which will +quickly run into the certificate authority rate limit.) Note that options provided to ``letsencrypt renew`` will apply to *every* certificate for which renewal is attempted; for example, @@ -212,12 +228,10 @@ a specific certificate specified via `-d` flags, like (All of the domains covered by the certificate must be specified in this case in order to renew and replace the old certificate rather -than obtaining a new one; don't forget any `www.` domains!) The -``certonly`` form attempts to renew one individual certificate. - -letsencrypt-auto_) again, and use the same values when prompted. You can -automate it slightly by passing necessary flags on the CLI (see `--help -all`), or even further using the :ref:`config-file`. +than obtaining a new one; don't forget any `www.` domains! Specifying +a subset of the domains creates a new, separate certificate containing +only those domains, rather than replacing the original certificate.) +The ``certonly`` form attempts to renew one individual certificate. Please note that the CA will send notification emails to the address From c80535b2dfadfb9d700cb03a1d5c8735332567d6 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 12 Feb 2016 09:49:17 +0100 Subject: [PATCH 22/35] Fixed typo in Webroot section --- docs/using.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 7263452b5..be877b17e 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -130,7 +130,7 @@ made to your web server would look like: Note that to use the webroot plugin, your server must be configured to serve files from hidden directories. If ``/.well-known`` is treated specially by your webserver configuration, you might need to modify the configuration -to ensure that files inside ``/.well-known/ache-challenge`` are served by +to ensure that files inside ``/.well-known/acme-challenge`` are served by the webserver. Standalone @@ -439,8 +439,8 @@ want to use the Apache plugin, it has to be installed separately: emerge -av app-crypt/letsencrypt emerge -av app-crypt/letsencrypt-apache -Currently, only the Apache plugin is included in Portage. However, if you -want the nginx plugin, you can use Layman to add the mrueg overlay which +Currently, only the Apache plugin is included in Portage. However, if you +want the nginx plugin, you can use Layman to add the mrueg overlay which does include the nginx plugin package: .. code-block:: shell @@ -450,9 +450,9 @@ does include the nginx plugin package: layman -a mrueg emerge -av app-crypt/letsencrypt-nginx -When using the Apache plugin, you will run into a "cannot find a cert or key +When using the Apache plugin, you will run into a "cannot find a cert or key directive" error if you're sporting the default Gentoo ``httpd.conf``. -You can fix this by commenting out two lines in ``/etc/apache2/httpd.conf`` +You can fix this by commenting out two lines in ``/etc/apache2/httpd.conf`` as follows: Change @@ -471,7 +471,7 @@ to LoadModule ssl_module modules/mod_ssl.so # -For the time being, this is the only way for the Apache plugin to recognise +For the time being, this is the only way for the Apache plugin to recognise the appropriate directives when installing the certificate. Note: this change is not required for the other plugins. From caf959997cbe4c10cf37df47efed2518c0e245b6 Mon Sep 17 00:00:00 2001 From: TheNavigat Date: Thu, 14 Jan 2016 03:10:12 +0200 Subject: [PATCH 23/35] Adding boulder integration support to Vagrant --- Vagrantfile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Vagrantfile b/Vagrantfile index 678abdf72..89b512b8c 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -5,10 +5,20 @@ VAGRANTFILE_API_VERSION = "2" # Setup instructions from docs/contributing.rst +# Script for installing dependencies for tox and boulder integration +# TODO: Check if the GO PATH lines already exist. If they do, don't add them. +# If they don't, add them before the exit line $ubuntu_setup_script = <> ~/.profile +echo "export PATH=\\$GOROOT/bin:\\$PATH" >> ~/.profile +echo "export GOPATH=\\$HOME/go" >> ~/.profile +export DEBIAN_FRONTEND=noninteractive +sudo -E apt-get -q -y install git mysql-server-5.5 libltdl-dev rabbitmq-server make nginx SETUP_SCRIPT Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| From a89b187186aab050cccd04f97f3e034833566e9c Mon Sep 17 00:00:00 2001 From: TheNavigat Date: Tue, 19 Jan 2016 19:15:22 +0200 Subject: [PATCH 24/35] Adding conditions for adding export lines to ~/.profile --- Vagrantfile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 89b512b8c..7cc3fbece 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -5,18 +5,16 @@ VAGRANTFILE_API_VERSION = "2" # Setup instructions from docs/contributing.rst -# Script for installing dependencies for tox and boulder integration -# TODO: Check if the GO PATH lines already exist. If they do, don't add them. -# If they don't, add them before the exit line +# Script installs dependencies for tox and boulder integration $ubuntu_setup_script = <> ~/.profile -echo "export PATH=\\$GOROOT/bin:\\$PATH" >> ~/.profile -echo "export GOPATH=\\$HOME/go" >> ~/.profile +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 +if ! grep -Fxq "export GOPATH=\\$HOME/go" ~/.profile ; then echo "export GOPATH=\\$HOME/go" >> ~/.profile; fi export DEBIAN_FRONTEND=noninteractive sudo -E apt-get -q -y install git mysql-server-5.5 libltdl-dev rabbitmq-server make nginx SETUP_SCRIPT From a4f46aa90a063bea5a2457e66e2ff950bb5cd77f Mon Sep 17 00:00:00 2001 From: TheNavigat Date: Sat, 23 Jan 2016 02:31:50 +0200 Subject: [PATCH 25/35] Replacing MySQL with MariaDB and nginx with nginx-light --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 7cc3fbece..0475761d1 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -16,7 +16,7 @@ if ! grep -Fxq "export GOROOT=/usr/local/go" ~/.profile ; then echo "export GORO if ! grep -Fxq "export PATH=\\$GOROOT/bin:\\$PATH" ~/.profile ; then echo "export PATH=\\$GOROOT/bin:\\$PATH" >> ~/.profile; fi if ! grep -Fxq "export GOPATH=\\$HOME/go" ~/.profile ; then echo "export GOPATH=\\$HOME/go" >> ~/.profile; fi export DEBIAN_FRONTEND=noninteractive -sudo -E apt-get -q -y install git mysql-server-5.5 libltdl-dev rabbitmq-server make nginx +sudo -E apt-get -q -y install git make libltdl-dev mariadb-server rabbitmq-server nginx-light SETUP_SCRIPT Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| From 037cc4e150eff2da9a4830ec27bdd3265e613232 Mon Sep 17 00:00:00 2001 From: TheNavigat Date: Sat, 23 Jan 2016 03:09:49 +0200 Subject: [PATCH 26/35] Adding running boulder-start.sh on boot --- Vagrantfile | 1 + docs/contributing.rst | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/Vagrantfile b/Vagrantfile index 0475761d1..3798085c0 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -15,6 +15,7 @@ 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 if ! grep -Fxq "export GOPATH=\\$HOME/go" ~/.profile ; then echo "export GOPATH=\\$HOME/go" >> ~/.profile; fi +if ! grep -Fxq "cd /vagrant/tests/; ./boulder-start.sh &" /etc/rc.local ; then sed -i -e '$i \cd /vagrant/tests/; ./boulder-start.sh &\n' /etc/rc.local; fi export DEBIAN_FRONTEND=noninteractive sudo -E apt-get -q -y install git make libltdl-dev mariadb-server rabbitmq-server nginx-light SETUP_SCRIPT diff --git a/docs/contributing.rst b/docs/contributing.rst index 36dff01b9..ce4078ea3 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -96,6 +96,14 @@ Integration testing with the boulder CA Generally it is sufficient to open a pull request and let Github and Travis run integration tests for you. +However, if you prefer to run tests, you can use Vagrant, using the Vagrantfile +in Let's Encrypt's repository. To execute the tests on a Vagrant box, the only +command you are required to run is:: + + ./tests/boulder-integration.sh + +Otherwise, please follow the following instructions. + Mac OS X users: Run ``./tests/mac-bootstrap.sh`` instead of ``boulder-start.sh`` to install dependencies, configure the environment, and start boulder. From 14b85c6d6f3e25c5800e8ae4bd19524e835502a0 Mon Sep 17 00:00:00 2001 From: TheNavigat Date: Sat, 23 Jan 2016 03:10:40 +0200 Subject: [PATCH 27/35] Replacing relative ~/.profile paths with absolute /home/vagrant/.profile ones --- Vagrantfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 3798085c0..7c304c227 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -12,9 +12,9 @@ cd /vagrant ./tools/venv.sh wget 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 -if ! grep -Fxq "export GOPATH=\\$HOME/go" ~/.profile ; then echo "export GOPATH=\\$HOME/go" >> ~/.profile; fi +if ! grep -Fxq "export GOROOT=/usr/local/go" /home/vagrant/.profile ; then echo "export GOROOT=/usr/local/go" >> /home/vagrant/.profile; fi +if ! grep -Fxq "export PATH=\\$GOROOT/bin:\\$PATH" /home/vagrant/.profile ; then echo "export PATH=\\$GOROOT/bin:\\$PATH" >> /home/vagrant/.profile; fi +if ! grep -Fxq "export GOPATH=\\$HOME/go" /home/vagrant/.profile ; then echo "export GOPATH=\\$HOME/go" >> /home/vagrant/.profile; fi if ! grep -Fxq "cd /vagrant/tests/; ./boulder-start.sh &" /etc/rc.local ; then sed -i -e '$i \cd /vagrant/tests/; ./boulder-start.sh &\n' /etc/rc.local; fi export DEBIAN_FRONTEND=noninteractive sudo -E apt-get -q -y install git make libltdl-dev mariadb-server rabbitmq-server nginx-light From da1542e57f52801f8b02092707b56217a4109c0e Mon Sep 17 00:00:00 2001 From: TheNavigat Date: Fri, 12 Feb 2016 13:52:05 +0200 Subject: [PATCH 28/35] Fixing path from which boulder-start.sh is executed --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 7c304c227..e5975442f 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -15,7 +15,7 @@ sudo tar -C /usr/local -xzf /tmp/go1.5.3.linux-amd64.tar.gz if ! grep -Fxq "export GOROOT=/usr/local/go" /home/vagrant/.profile ; then echo "export GOROOT=/usr/local/go" >> /home/vagrant/.profile; fi if ! grep -Fxq "export PATH=\\$GOROOT/bin:\\$PATH" /home/vagrant/.profile ; then echo "export PATH=\\$GOROOT/bin:\\$PATH" >> /home/vagrant/.profile; fi if ! grep -Fxq "export GOPATH=\\$HOME/go" /home/vagrant/.profile ; then echo "export GOPATH=\\$HOME/go" >> /home/vagrant/.profile; fi -if ! grep -Fxq "cd /vagrant/tests/; ./boulder-start.sh &" /etc/rc.local ; then sed -i -e '$i \cd /vagrant/tests/; ./boulder-start.sh &\n' /etc/rc.local; fi +if ! grep -Fxq "cd /vagrant/; ./tests/boulder-start.sh &" /etc/rc.local ; then sed -i -e '$i \cd /vagrant/; ./tests/boulder-start.sh &\n' /etc/rc.local; fi export DEBIAN_FRONTEND=noninteractive sudo -E apt-get -q -y install git make libltdl-dev mariadb-server rabbitmq-server nginx-light SETUP_SCRIPT From cedcad137391e277552b9a8a5dbc636b2f081b77 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 12 Feb 2016 11:49:01 -0500 Subject: [PATCH 29/35] Use python -V instead of python --version. Fix #2039. Python 2.4 doesn't support --version, and we want to be able to at least complain that it's too old without crashing. Also, bring built le-auto up to date. --- letsencrypt-auto-source/letsencrypt-auto | 8 ++++---- letsencrypt-auto-source/letsencrypt-auto.template | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 30d907690..4ee16af95 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -104,7 +104,7 @@ DeterminePythonVersion() { exit 1 fi - PYVER=`"$LE_PYTHON" --version 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` + PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` if [ $PYVER -lt 26 ]; then echo "You have an ancient version of Python entombed in your operating system..." echo "This isn't going to work; you'll need at least version 2.6." @@ -324,13 +324,13 @@ BootstrapGentooCommon() { case "$PACKAGE_MANAGER" in (paludis) - "$SUDO" cave resolve --keep-targets if-possible $PACKAGES -x + "$SUDO" cave resolve --preserve-world --keep-targets if-possible $PACKAGES -x ;; (pkgcore) - "$SUDO" pmerge --noreplace $PACKAGES + "$SUDO" pmerge --noreplace --oneshot $PACKAGES ;; (portage|*) - "$SUDO" emerge --noreplace $PACKAGES + "$SUDO" emerge --noreplace --oneshot $PACKAGES ;; esac } diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index 1fa12528f..b65b55163 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -104,7 +104,7 @@ DeterminePythonVersion() { exit 1 fi - PYVER=`"$LE_PYTHON" --version 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` + PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` if [ $PYVER -lt 26 ]; then echo "You have an ancient version of Python entombed in your operating system..." echo "This isn't going to work; you'll need at least version 2.6." From dc8bdfac565d0fbb6920a550ee758000b39cd8dc Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 12 Feb 2016 15:07:01 -0500 Subject: [PATCH 30/35] Quote the remaining variable expansions in le-auto. Refs #1899. ...except for $SUDO, which is always either "sudo", "su_sudo", or "", never having a quote-needing char in it. It's unlikely that $PYVER would have a space in it, but it doesn't hurt. --- letsencrypt-auto-source/letsencrypt-auto | 4 ++-- letsencrypt-auto-source/letsencrypt-auto.template | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index ea3f7a4bb..420e6263b 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -18,7 +18,7 @@ set -e # Work even if somebody does "sh thisscript.sh". XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share} VENV_NAME="letsencrypt" VENV_PATH=${VENV_PATH:-"$XDG_DATA_HOME/$VENV_NAME"} -VENV_BIN=${VENV_PATH}/bin +VENV_BIN="$VENV_PATH/bin" LE_AUTO_VERSION="0.5.0.dev0" # This script takes the same arguments as the main letsencrypt program, but it @@ -105,7 +105,7 @@ DeterminePythonVersion() { fi PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` - if [ $PYVER -lt 26 ]; then + if [ "$PYVER" -lt 26 ]; then echo "You have an ancient version of Python entombed in your operating system..." echo "This isn't going to work; you'll need at least version 2.6." exit 1 diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index b65b55163..042a448f5 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -18,7 +18,7 @@ set -e # Work even if somebody does "sh thisscript.sh". XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share} VENV_NAME="letsencrypt" VENV_PATH=${VENV_PATH:-"$XDG_DATA_HOME/$VENV_NAME"} -VENV_BIN=${VENV_PATH}/bin +VENV_BIN="$VENV_PATH/bin" LE_AUTO_VERSION="{{ LE_AUTO_VERSION }}" # This script takes the same arguments as the main letsencrypt program, but it @@ -105,7 +105,7 @@ DeterminePythonVersion() { fi PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` - if [ $PYVER -lt 26 ]; then + if [ "$PYVER" -lt 26 ]; then echo "You have an ancient version of Python entombed in your operating system..." echo "This isn't going to work; you'll need at least version 2.6." exit 1 From 4c2c80dcdaf78ebdd44185762484f9db9ff147b8 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 12 Feb 2016 17:23:29 -0500 Subject: [PATCH 31/35] Fix DeterminePythonVersion(). Ported from #1751. * Make sure any Python passed in as $LE_PYTHON actually exists. * Dodge a word-splitting bug: `a='a b'; export a=${a:-c}; echo $a` gives `a` instead of `a b` under shells that respect POSIX.1, like dash. --- letsencrypt-auto-source/letsencrypt-auto | 17 +++++++---------- .../letsencrypt-auto.template | 17 +++++++---------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index ea3f7a4bb..bfb41e240 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -91,18 +91,15 @@ ExperimentalBootstrap() { } DeterminePythonVersion() { - if command -v python2.7 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python2.7} - elif command -v python27 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python27} - elif command -v python2 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python2} - elif command -v python > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python} - else - echo "Cannot find any Pythons... please install one!" + for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do + # Break (while keeping the LE_PYTHON value) if found. + command -v "$LE_PYTHON" > /dev/null && break + done + if [ "$?" != "0" ]; then + echo "Cannot find any Pythons; please install one!" exit 1 fi + export LE_PYTHON PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` if [ $PYVER -lt 26 ]; then diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index b65b55163..2572e13d6 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -91,18 +91,15 @@ ExperimentalBootstrap() { } DeterminePythonVersion() { - if command -v python2.7 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python2.7} - elif command -v python27 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python27} - elif command -v python2 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python2} - elif command -v python > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python} - else - echo "Cannot find any Pythons... please install one!" + for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do + # Break (while keeping the LE_PYTHON value) if found. + command -v "$LE_PYTHON" > /dev/null && break + done + if [ "$?" != "0" ]; then + echo "Cannot find any Pythons; please install one!" exit 1 fi + export LE_PYTHON PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` if [ $PYVER -lt 26 ]; then From e08aa36a4ea5d4a1d60364f544e733a8e79fe97a Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 12 Feb 2016 17:36:48 -0500 Subject: [PATCH 32/35] Switch to case statement for arg parsing in le-auto. Ported from #1751. * It's more lines but fewer tokens, less room for quote errors, and more idiomatic (see any init.d script). * Also, fix a bug in which any option containing "-v", e.g. --eat-vertical-pizza, would be construed as --verbose. --- letsencrypt-auto-source/letsencrypt-auto | 30 +++++++++++-------- .../letsencrypt-auto.template | 30 +++++++++++-------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index bfb41e240..1837120e8 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -25,18 +25,24 @@ LE_AUTO_VERSION="0.5.0.dev0" # additionally responds to --verbose (more output) and --debug (allow support # for experimental platforms) for arg in "$@" ; do - # This first clause is redundant with the third, but hedging on portability - if [ "$arg" = "-v" ] || [ "$arg" = "--verbose" ] || echo "$arg" | grep -E -- "-v+$" ; then - VERBOSE=1 - elif [ "$arg" = "--no-self-upgrade" ] ; then - # Do not upgrade this script (also prevents client upgrades, because each - # copy of the script pins a hash of the python client) - NO_SELF_UPGRADE=1 - elif [ "$arg" = "--os-packages-only" ] ; then - OS_PACKAGES_ONLY=1 - elif [ "$arg" = "--debug" ]; then - DEBUG=1 - fi + case "$arg" in + --debug) + DEBUG=1;; + --os-packages-only) + OS_PACKAGES_ONLY=1;; + --no-self-upgrade) + # Do not upgrade this script (also prevents client upgrades, because each + # copy of the script pins a hash of the python client) + NO_SELF_UPGRADE=1;; + --verbose) + VERBOSE=1;; + [!-]*|-*[!v]*|-) + # Anything that isn't -v, -vv, etc.: that is, anything that does not + # start with a -, contains anything that's not a v, or is just "-" + ;; + *) # -v+ remains. + VERBOSE=1;; + esac done # letsencrypt-auto needs root access to bootstrap OS dependencies, and diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index 2572e13d6..f0e87cf14 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -25,18 +25,24 @@ LE_AUTO_VERSION="{{ LE_AUTO_VERSION }}" # additionally responds to --verbose (more output) and --debug (allow support # for experimental platforms) for arg in "$@" ; do - # This first clause is redundant with the third, but hedging on portability - if [ "$arg" = "-v" ] || [ "$arg" = "--verbose" ] || echo "$arg" | grep -E -- "-v+$" ; then - VERBOSE=1 - elif [ "$arg" = "--no-self-upgrade" ] ; then - # Do not upgrade this script (also prevents client upgrades, because each - # copy of the script pins a hash of the python client) - NO_SELF_UPGRADE=1 - elif [ "$arg" = "--os-packages-only" ] ; then - OS_PACKAGES_ONLY=1 - elif [ "$arg" = "--debug" ]; then - DEBUG=1 - fi + case "$arg" in + --debug) + DEBUG=1;; + --os-packages-only) + OS_PACKAGES_ONLY=1;; + --no-self-upgrade) + # Do not upgrade this script (also prevents client upgrades, because each + # copy of the script pins a hash of the python client) + NO_SELF_UPGRADE=1;; + --verbose) + VERBOSE=1;; + [!-]*|-*[!v]*|-) + # Anything that isn't -v, -vv, etc.: that is, anything that does not + # start with a -, contains anything that's not a v, or is just "-" + ;; + *) # -v+ remains. + VERBOSE=1;; + esac done # letsencrypt-auto needs root access to bootstrap OS dependencies, and From 42a61537e6f34b40b458aae44e1a138b8e0d555e Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 12 Feb 2016 14:48:14 -0800 Subject: [PATCH 33/35] Remove unecessary check and use constant --- letsencrypt/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/letsencrypt/cli.py b/letsencrypt/cli.py index bfedea15a..fcc6d3bd5 100644 --- a/letsencrypt/cli.py +++ b/letsencrypt/cli.py @@ -323,7 +323,7 @@ def _handle_identical_cert_request(config, cert): display = zope.component.getUtility(interfaces.IDisplay) response = display.menu(question, choices, "OK", "Cancel", default=0) - if response[0] == "cancel" or response[1] == 2: + if response[0] == display_util.CANCEL: # TODO: Add notification related to command-line options for # skipping the menu for this case. raise errors.Error( From 462d60def9ead9d7d5005c5242c40ece4c206490 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Fri, 12 Feb 2016 15:31:18 -0800 Subject: [PATCH 34/35] Reorder travis matrix by typical runtime Since that makes most efficient use of travis's parallelism --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d2f7b1db..8b298196f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,20 +38,20 @@ matrix: env: TOXENV=py27 BOULDER_INTEGRATION=1 - python: "2.7" env: TOXENV=py27-oldest BOULDER_INTEGRATION=1 - - python: "2.7" - env: TOXENV=cover - python: "2.7" env: TOXENV=lint + - sudo: required + env: TOXENV=le_auto + services: docker + before_install: + - python: "2.7" + env: TOXENV=cover - python: "3.3" env: TOXENV=py33 - python: "3.4" env: TOXENV=py34 - python: "3.5" env: TOXENV=py35 - - sudo: required - env: TOXENV=le_auto - services: docker - before_install: # Only build pushes to the master branch, PRs, and branches beginning with # `test-`. This reduces the number of simultaneous Travis runs, which speeds From 049c1fa114552f074c0206f9ce2a76329bdbeaf5 Mon Sep 17 00:00:00 2001 From: rugk Date: Sun, 14 Feb 2016 14:47:21 +0100 Subject: [PATCH 35/35] Fix typo --- docs/ciphers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ciphers.rst b/docs/ciphers.rst index c8ff26117..ef644b7a0 100644 --- a/docs/ciphers.rst +++ b/docs/ciphers.rst @@ -139,7 +139,7 @@ client's priorities. The Mozilla security team is likely to have more resources and expertise to bring to bear on evaluating reasons why its recommendations should be updated. -The Let's Encrpyt project will entertain proposals to create a *very* +The Let's Encrypt project will entertain proposals to create a *very* small number of alternative configurations (apart from Modern, Intermediate, and Old) that there's reason to believe would be widely used by sysadmins; this would usually be a preferable course to modifying