From 9111faeb942129cf2831be3ae695b5e7b5bc5b06 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 11 Apr 2016 09:44:29 -0700 Subject: [PATCH 01/21] don't lose domain ordering --- letsencrypt/client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/letsencrypt/client.py b/letsencrypt/client.py index 221879080..508117489 100644 --- a/letsencrypt/client.py +++ b/letsencrypt/client.py @@ -245,8 +245,9 @@ class Client(object): domains, self.config.allow_subset_of_names) - domains = [a.body.identifier.value.encode('ascii') - for a in authzr] + auth_domains = set(a.body.identifier.value.encode('ascii') + for a in authzr) + domains = [d for d in domains if d in auth_domains] # Create CSR from names key = crypto_util.init_save_key( From 9008adc1760e889093b618e133caaba0279a18d5 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 12 Apr 2016 12:23:24 -0700 Subject: [PATCH 02/21] add test to prevent regressions --- letsencrypt/tests/client_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/letsencrypt/tests/client_test.py b/letsencrypt/tests/client_test.py index cd6b11158..49fa5b17e 100644 --- a/letsencrypt/tests/client_test.py +++ b/letsencrypt/tests/client_test.py @@ -201,7 +201,8 @@ class ClientTest(unittest.TestCase): authzr = [] - for domain in domains: + # domain ordering should not be affected by authorization order + for domain in reversed(domains): authzr.append( mock.MagicMock( body=mock.MagicMock( From 8502d096711469b647a444461f0c3363e1c4d330 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 15 Apr 2016 14:03:28 -0700 Subject: [PATCH 03/21] Fixes #2831 --- certbot/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/main.py b/certbot/main.py index 72f4fe66e..309889e8e 100644 --- a/certbot/main.py +++ b/certbot/main.py @@ -528,7 +528,7 @@ def obtain_cert(config, plugins, lineage=None): notify("new certificate deployed with reload of {0} server; fullchain is {1}".format( config.installer, lineage.fullchain), pause=False) elif action == "reinstall" and config.verb == "certonly": - notify("Certificate not yet due for renewal; no action taken.") + notify("Certificate not yet due for renewal; no action taken.", pause=False) _suggest_donation_if_appropriate(config, action) From 36a520ed0cbc00c3f5da33c0db21b222fed15f09 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 15 Apr 2016 15:15:43 -0700 Subject: [PATCH 04/21] Add test to prevent regressions --- certbot/tests/main_test.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 certbot/tests/main_test.py diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py new file mode 100644 index 000000000..0e8d8e30b --- /dev/null +++ b/certbot/tests/main_test.py @@ -0,0 +1,35 @@ +"""Tests for certbot.main.""" +import unittest + + +import mock + + +from certbot import cli +from certbot import configuration +from certbot.plugins import disco as plugins_disco + + +class ObtainCertTest(unittest.TestCase): + """Tests for certbot.main.obtain_cert.""" + + def _call(self, args): + plugins = plugins_disco.PluginsRegistry.find_all() + config = configuration.NamespaceConfig( + cli.prepare_and_parse_args(plugins, args)) + + from certbot import main + with mock.patch('certbot.main._init_le_client') as mock_init: + main.obtain_cert(config, plugins) + + return mock_init() # returns the client + + @mock.patch('certbot.main._auth_from_domains') + def test_no_reinstall_text_pause(self, mock_auth): + mock_auth.return_value = (mock.ANY, 'reinstall') + # This hangs if the reinstallation notification pauses + self._call('certonly --webroot -d example.com -t'.split()) + + +if __name__ == '__main__': + unittest.main() # pragma: no cover From 82ee461e348051872c753416ab65f36f766af17d Mon Sep 17 00:00:00 2001 From: Amjad Mashaal Date: Fri, 8 Apr 2016 02:48:45 +0200 Subject: [PATCH 05/21] Adding renewal interval along with comment to the renewal configuration file --- certbot/storage.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/certbot/storage.py b/certbot/storage.py index 4ef614a8e..9462ad545 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -78,6 +78,9 @@ def write_renewal_config(o_filename, n_filename, target, relevant_data): if k not in relevant_data: del config["renewalparams"][k] + config["renew_before_expiry"] = constants.RENEWER_DEFAULTS["renew_before_expiry"] + config.comments["renew_before_expiry"] = "Renewal interval" + # TODO: add human-readable comments explaining other available # parameters logger.debug("Writing new config %s.", n_filename) From cafcffb86e259eaac29bb0dc88197b1b2e9df294 Mon Sep 17 00:00:00 2001 From: Amjad Mashaal Date: Sat, 9 Apr 2016 02:20:31 +0200 Subject: [PATCH 06/21] Fixing errors --- certbot/storage.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/certbot/storage.py b/certbot/storage.py index 9462ad545..fdbdf7a0e 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -78,8 +78,10 @@ def write_renewal_config(o_filename, n_filename, target, relevant_data): if k not in relevant_data: del config["renewalparams"][k] - config["renew_before_expiry"] = constants.RENEWER_DEFAULTS["renew_before_expiry"] - config.comments["renew_before_expiry"] = "Renewal interval" + if "renew_before_expiry" not in config["renewalparams"]: + config["renewalparams"]["renew_before_expiry"] = ( + constants.RENEWER_DEFAULTS["renew_before_expiry"]) + config["renewalparams"].comments["renew_before_expiry"] = ["Renewal interval"] # TODO: add human-readable comments explaining other available # parameters From d34b5fee0dcaaaaa499aeb669eb9b7b71586cc96 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 18 Apr 2016 18:08:55 -0400 Subject: [PATCH 07/21] Fix problem with godep and vendor directories --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5d70ca799..16b5700e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ env: global: - GOPATH=/tmp/go - PATH=$GOPATH/bin:$PATH + - GO15VENDOREXPERIMENT=1 # Fixes problems with vendor directories matrix: include: From 8ceaf29fb837f70764ef2a9dd5e1a2eb30a17329 Mon Sep 17 00:00:00 2001 From: Kevin Burke Date: Sun, 17 Apr 2016 17:42:51 -0700 Subject: [PATCH 08/21] Pass a single argument to append() The other notify() calls in this block all pass the output of report(), but this one attempts to pass two arguments, which results in the stack trace described in #2822. --- certbot/renewal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/renewal.py b/certbot/renewal.py index 180499387..3682c50d5 100644 --- a/certbot/renewal.py +++ b/certbot/renewal.py @@ -287,7 +287,7 @@ def _renew_describe_results(config, renew_successes, renew_failures, if parse_failures: notify("\nAdditionally, the following renewal configuration files " "were invalid: ") - notify(parse_failures, "parsefail") + notify(report(parse_failures, "parsefail")) if config.dry_run: notify("** DRY RUN: simulating 'certbot renew' close to cert expiry") From 1ceea35669fd8e6eff5252ef6607289619f0f3c2 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 19 Apr 2016 06:56:46 -0400 Subject: [PATCH 09/21] Improve obtain_cert no pause test --- certbot/tests/main_test.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 0e8d8e30b..66cba64a3 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -13,6 +13,14 @@ from certbot.plugins import disco as plugins_disco class ObtainCertTest(unittest.TestCase): """Tests for certbot.main.obtain_cert.""" + def setUp(self): + self.get_utility_patch = mock.patch( + 'certbot.main.zope.component.getUtility') + self.mock_get_utility = self.get_utility_patch.start() + + def tearDown(self): + self.get_utility_patch.stop() + def _call(self, args): plugins = plugins_disco.PluginsRegistry.find_all() config = configuration.NamespaceConfig( @@ -26,10 +34,15 @@ class ObtainCertTest(unittest.TestCase): @mock.patch('certbot.main._auth_from_domains') def test_no_reinstall_text_pause(self, mock_auth): + mock_notification = self.mock_get_utility().notification + mock_notification.side_effect = self._assert_no_pause mock_auth.return_value = (mock.ANY, 'reinstall') - # This hangs if the reinstallation notification pauses self._call('certonly --webroot -d example.com -t'.split()) + def _assert_no_pause(self, message, height=42, pause=True): + # pylint: disable=unused-argument + self.assertFalse(pause) + if __name__ == '__main__': unittest.main() # pragma: no cover From 3780d068d17b6872826d8665d69652ac5d69a1e5 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 19 Apr 2016 14:11:17 -0400 Subject: [PATCH 10/21] Fix test farm tests --- tests/letstest/multitester.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/letstest/multitester.py b/tests/letstest/multitester.py index 02dfc4410..d9491939c 100644 --- a/tests/letstest/multitester.py +++ b/tests/letstest/multitester.py @@ -349,7 +349,7 @@ def test_client_process(inqueue, outqueue): print(env.host_string) try: - install_and_launch_letsencrypt(instances[ii], boulder_url, target) + install_and_launch_certbot(instances[ii], boulder_url, target) outqueue.put((ii, target, 'pass')) print("%s - %s SUCCESS"%(target['ami'], target['name'])) except: From 771f5cfe49bc43e43870cc11a390c0c646353290 Mon Sep 17 00:00:00 2001 From: Amjad Mashaal Date: Tue, 26 Apr 2016 04:20:50 +0200 Subject: [PATCH 11/21] Implementing schoen's correction --- certbot/storage.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/certbot/storage.py b/certbot/storage.py index fdbdf7a0e..42cbfc2c9 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -79,9 +79,8 @@ def write_renewal_config(o_filename, n_filename, target, relevant_data): del config["renewalparams"][k] if "renew_before_expiry" not in config["renewalparams"]: - config["renewalparams"]["renew_before_expiry"] = ( + config["renewalparams"].comments["renew_before_expiry"] = ( constants.RENEWER_DEFAULTS["renew_before_expiry"]) - config["renewalparams"].comments["renew_before_expiry"] = ["Renewal interval"] # TODO: add human-readable comments explaining other available # parameters From 070642faafd2eb5fccac04dd8f14c6b7c1d0528d Mon Sep 17 00:00:00 2001 From: Amjad Mashaal Date: Tue, 26 Apr 2016 05:26:07 +0200 Subject: [PATCH 12/21] Fixing renew_before_expiry comment --- certbot/storage.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/certbot/storage.py b/certbot/storage.py index 42cbfc2c9..82f07e3c5 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -79,8 +79,7 @@ def write_renewal_config(o_filename, n_filename, target, relevant_data): del config["renewalparams"][k] if "renew_before_expiry" not in config["renewalparams"]: - config["renewalparams"].comments["renew_before_expiry"] = ( - constants.RENEWER_DEFAULTS["renew_before_expiry"]) + config.final_comment = ["renew_before_expiry = 30 days"] # TODO: add human-readable comments explaining other available # parameters From e3ad290dff710152f95b1418245dcb2247c72f38 Mon Sep 17 00:00:00 2001 From: Amjad Mashaal Date: Wed, 27 Apr 2016 02:50:36 +0200 Subject: [PATCH 13/21] Moving renew_before_expiry comment to initial_comment --- certbot/storage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot/storage.py b/certbot/storage.py index 82f07e3c5..caf268933 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -78,8 +78,8 @@ def write_renewal_config(o_filename, n_filename, target, relevant_data): if k not in relevant_data: del config["renewalparams"][k] - if "renew_before_expiry" not in config["renewalparams"]: - config.final_comment = ["renew_before_expiry = 30 days"] + if "renew_before_expiry" not in config: + config.initial_comment = ["renew_before_expiry = 30 days"] # TODO: add human-readable comments explaining other available # parameters From bf6f6b636cf70f964dcd7d3fed5e31d88eabce8d Mon Sep 17 00:00:00 2001 From: Amjad Mashaal Date: Thu, 28 Apr 2016 02:32:53 +0200 Subject: [PATCH 14/21] Setting value of commented renew_before_expiry to default value --- certbot/storage.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/certbot/storage.py b/certbot/storage.py index caf268933..c4bfb3e28 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -79,7 +79,8 @@ def write_renewal_config(o_filename, n_filename, target, relevant_data): del config["renewalparams"][k] if "renew_before_expiry" not in config: - config.initial_comment = ["renew_before_expiry = 30 days"] + default_interval = constants.RENEWER_DEFAULTS["renew_before_expiry"] + config.initial_comment = ["renew_before_expiry = " + default_interval] # TODO: add human-readable comments explaining other available # parameters From 4e19f9eae0c0cdf6def576bd98949fee12e23b7c Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 4 May 2016 17:28:16 -0700 Subject: [PATCH 15/21] venv is still named letsencrypt --- certbot/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/cli.py b/certbot/cli.py index e2c57595b..97b1a5399 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -37,7 +37,7 @@ helpful_parser = None # should only be used for purposes where inability to detect letsencrypt-auto # fails safely -fragment = os.path.join(".local", "share", "certbot") +fragment = os.path.join(".local", "share", "letsencrypt") cli_command = "letsencrypt-auto" if fragment in sys.argv[0] else "certbot" # Argparse's help formatting has a lot of unhelpful peculiarities, so we want From f3172bcfeed8666c9904bdabfcfbb28fd17c947a Mon Sep 17 00:00:00 2001 From: Jeremy Gillula Date: Thu, 5 May 2016 08:55:49 -0700 Subject: [PATCH 16/21] Changing some "will happen"s to "hopefully will happen"s --- README.rst | 4 ++-- docs/using.rst | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.rst b/README.rst index 050cde82b..cc4e53bda 100644 --- a/README.rst +++ b/README.rst @@ -128,8 +128,8 @@ System Requirements =================== The Let's Encrypt Client presently only runs on Unix-ish OSes that include -Python 2.6 or 2.7; Python 3.x support will be added after the Public Beta -launch. The client requires root access in order to write to +Python 2.6 or 2.7; Python 3.x support will hopefully be added after the Public +Beta launch. The client requires root access in order to write to ``/etc/letsencrypt``, ``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443 (if you use the ``standalone`` plugin) and to read and modify webserver configurations (if you use the ``apache`` or ``nginx`` diff --git a/docs/using.rst b/docs/using.rst index 66c5907ae..8f56554ce 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -124,7 +124,7 @@ or ``--webroot-path /usr/share/nginx/html`` are two common webroot paths. 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 +potentially be a separate directory for each domain. When requesting a certificate for multiple domains, each domain will use the most recently specified ``--webroot-path``. So, for instance, @@ -184,11 +184,11 @@ be on a different computer. Nginx ----- -In the future, if you're running Nginx you can use this plugin to -automatically obtain and install your certificate. The Nginx plugin -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``. +In the future, if you're running Nginx you will hopefully be able to use this +plugin to automatically obtain and install your certificate. The Nginx plugin 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 ------------------- @@ -446,7 +446,7 @@ If you run Debian Stretch or Debian Sid, you can install letsencrypt packages. If you don't want to use the Apache plugin, you can omit the ``python-letsencrypt-apache`` package. -Packages for Debian Jessie are coming in the next few weeks. +Packages for Debian Jessie will hopefully be coming in the next few weeks. **Fedora** From 127ba71c43770d233d1604ab8a2b32e574c12e8b Mon Sep 17 00:00:00 2001 From: Jeremy Gillula Date: Thu, 5 May 2016 11:17:47 -0700 Subject: [PATCH 17/21] Adding the fact that we actually have backports for Debian Jessie to the docs --- docs/using.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/using.rst b/docs/using.rst index 8f56554ce..60c074d75 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -446,7 +446,13 @@ If you run Debian Stretch or Debian Sid, you can install letsencrypt packages. If you don't want to use the Apache plugin, you can omit the ``python-letsencrypt-apache`` package. -Packages for Debian Jessie will hopefully be coming in the next few weeks. +Packages exist for Debian Jessie via backports. First you'll have to follow the +instructions at http://backports.debian.org/Instructions/ to enable the Jessie backports +repo, if you have not already done so. Then run: + +.. code-block:: shell + + sudo apt-get install certbot python-certbot-apache -t jessie-backports **Fedora** From fbbbb5b51634d348f82f893e1a02e98c0fcf3606 Mon Sep 17 00:00:00 2001 From: Jeremy Gillula Date: Thu, 5 May 2016 11:31:28 -0700 Subject: [PATCH 18/21] Turns out the public beta is over, but still no Python 3.0 support. We over-promised! --- README.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index cc4e53bda..236bdf8f4 100644 --- a/README.rst +++ b/README.rst @@ -128,16 +128,15 @@ System Requirements =================== The Let's Encrypt Client presently only runs on Unix-ish OSes that include -Python 2.6 or 2.7; Python 3.x support will hopefully be added after the Public -Beta launch. The client requires root access in order to write to -``/etc/letsencrypt``, ``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to -bind to ports 80 and 443 (if you use the ``standalone`` plugin) and to read and -modify webserver configurations (if you use the ``apache`` or ``nginx`` -plugins). If none of these apply to you, it is theoretically possible to run -without root privileges, but for most users who want to avoid running an ACME -client as root, either `letsencrypt-nosudo -`_ or `simp_le -`_ are more appropriate choices. +Python 2.6 or 2.7; Python 3.x support will hopefully be added in the future. The +client requires root access in order to write to ``/etc/letsencrypt``, +``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443 +(if you use the ``standalone`` plugin) and to read and modify webserver +configurations (if you use the ``apache`` or ``nginx`` plugins). If none of +these apply to you, it is theoretically possible to run without root privileges, +but for most users who want to avoid running an ACME client as root, either +`letsencrypt-nosudo `_ or +`simp_le `_ are more appropriate choices. The Apache plugin currently requires a Debian-based OS with augeas version 1.0; this includes Ubuntu 12.04+ and Debian 7+. From a65fca486cf65e88cdc8c8881c3e9f0c20db76ed Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 6 May 2016 11:57:12 -0700 Subject: [PATCH 19/21] Specify minimum parsedatetime version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 67cefdc48..4ee56576b 100644 --- a/setup.py +++ b/setup.py @@ -39,7 +39,7 @@ install_requires = [ 'ConfigArgParse>=0.9.3', 'configobj', 'cryptography>=0.7', # load_pem_x509_certificate - 'parsedatetime', + 'parsedatetime>=1.3', # Calendar.parseDT 'psutil>=2.1.0', # net_connections introduced in 2.1.0 'PyOpenSSL', 'pyrfc3339', From 495371a3b8d150f989d92820e3d30abbe26ac96a Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 6 May 2016 12:33:52 -0700 Subject: [PATCH 20/21] Use --force-reinstall to fix bad virtualenv package --- tools/_venv_common.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/_venv_common.sh b/tools/_venv_common.sh index a121af82d..dc6ca3dd2 100755 --- a/tools/_venv_common.sh +++ b/tools/_venv_common.sh @@ -18,7 +18,8 @@ virtualenv --no-site-packages $VENV_NAME $VENV_ARGS # Separately install setuptools and pip to make sure following # invocations use latest pip install -U setuptools -pip install -U pip +# --force-reinstall used to fix broken pip installation on some systems +pip install --force-reinstall -U pip pip install "$@" set +x From 785010fe5001a3c1472bf3ef47e99fb1da32f802 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Fri, 6 May 2016 12:45:51 -0700 Subject: [PATCH 21/21] Welcome to Certbot! --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 236bdf8f4..91a3cfcb5 100644 --- a/README.rst +++ b/README.rst @@ -3,9 +3,9 @@ Disclaimer ========== -The Let's Encrypt Client is **BETA SOFTWARE**. It contains plenty of bugs and -rough edges, and should be tested thoroughly in staging environments before use -on production systems. +Certbot (previously, the Let's Encrypt client) is **BETA SOFTWARE**. It +contains plenty of bugs and rough edges, and should be tested thoroughly in +staging environments before use on production systems. For more information regarding the status of the project, please see https://letsencrypt.org. Be sure to checkout the