From 7383fc6bf0702aa7fcbac1b54ce3508e0900cd08 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 11 Jul 2018 17:25:48 -0700 Subject: [PATCH 001/114] move values to pytest.ini --- pytest.ini | 2 ++ tools/install_and_test.sh | 3 ++- tox.cover.sh | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 pytest.ini diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..3ecec1912 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = --numprocesses auto --pyargs diff --git a/tools/install_and_test.sh b/tools/install_and_test.sh index 819f683aa..e84fbc99e 100755 --- a/tools/install_and_test.sh +++ b/tools/install_and_test.sh @@ -14,6 +14,7 @@ fi temp_cwd=$(mktemp -d) trap "rm -rf $temp_cwd" EXIT +cp pytest.ini "$temp_cwd" set -x for requirement in "$@" ; do @@ -24,6 +25,6 @@ for requirement in "$@" ; do pkg="certbot" fi cd "$temp_cwd" - pytest --numprocesses auto --quiet --pyargs $pkg + pytest --quiet $pkg cd - done diff --git a/tox.cover.sh b/tox.cover.sh index c713327c5..7da2d6b1f 100755 --- a/tox.cover.sh +++ b/tox.cover.sh @@ -61,7 +61,7 @@ cover () { fi pkg_dir=$(echo "$1" | tr _ -) - pytest --cov "$pkg_dir" --cov-append --cov-report= --numprocesses auto --pyargs "$1" + pytest --cov "$pkg_dir" --cov-append --cov-report= "$1" coverage report --fail-under="$min" --include="$pkg_dir/*" --show-missing } From 32676f02c322128263b659d7e34aeb1b12d3ac04 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 11 Jul 2018 17:32:48 -0700 Subject: [PATCH 002/114] warnings are errors --- pytest.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index 3ecec1912..085c7258e 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,2 @@ [pytest] -addopts = --numprocesses auto --pyargs +addopts = -Werror --numprocesses auto --pyargs From fdb3c8df4ba181997bb124f7eaf1795ea9f6a1cd Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 11 Jul 2018 17:33:04 -0700 Subject: [PATCH 003/114] s/assertEquals/assertEqual --- acme/acme/client_test.py | 2 +- acme/acme/crypto_util_test.py | 6 +++--- .../certbot_apache/tests/autohsts_test.py | 12 ++++++------ .../certbot_apache/tests/centos_test.py | 8 ++++---- .../certbot_apache/tests/configurator_test.py | 18 +++++++++--------- .../certbot_apache/tests/gentoo_test.py | 6 +++--- .../certbot_apache/tests/parser_test.py | 4 ++-- .../certbot_dns_google/dns_google_test.py | 4 ++-- .../certbot_nginx/tests/configurator_test.py | 10 +++++----- .../certbot_postfix/tests/postconf_test.py | 2 +- certbot/plugins/enhancements_test.py | 6 +++--- certbot/plugins/selection_test.py | 2 +- certbot/tests/cert_manager_test.py | 12 ++++++------ certbot/tests/client_test.py | 4 ++-- certbot/tests/display/ops_test.py | 12 ++++++------ certbot/tests/main_test.py | 2 +- certbot/tests/renewupdater_test.py | 4 ++-- 17 files changed, 57 insertions(+), 57 deletions(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index cd31c4ac3..b85aba518 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -659,7 +659,7 @@ class ClientTest(ClientTestBase): def test_revocation_payload(self): obj = messages.Revocation(certificate=self.certr.body, reason=self.rsn) self.assertTrue('reason' in obj.to_partial_json().keys()) - self.assertEquals(self.rsn, obj.to_partial_json()['reason']) + self.assertEqual(self.rsn, obj.to_partial_json()['reason']) def test_revoke_bad_status_raises_error(self): self.response.status_code = http_client.METHOD_NOT_ALLOWED diff --git a/acme/acme/crypto_util_test.py b/acme/acme/crypto_util_test.py index 168489d86..44b245bbe 100644 --- a/acme/acme/crypto_util_test.py +++ b/acme/acme/crypto_util_test.py @@ -209,8 +209,8 @@ class MakeCSRTest(unittest.TestCase): # have a get_extensions() method, so we skip this test if the method # isn't available. if hasattr(csr, 'get_extensions'): - self.assertEquals(len(csr.get_extensions()), 1) - self.assertEquals(csr.get_extensions()[0].get_data(), + self.assertEqual(len(csr.get_extensions()), 1) + self.assertEqual(csr.get_extensions()[0].get_data(), OpenSSL.crypto.X509Extension( b'subjectAltName', critical=False, @@ -227,7 +227,7 @@ class MakeCSRTest(unittest.TestCase): # have a get_extensions() method, so we skip this test if the method # isn't available. if hasattr(csr, 'get_extensions'): - self.assertEquals(len(csr.get_extensions()), 2) + self.assertEqual(len(csr.get_extensions()), 2) # NOTE: Ideally we would filter by the TLS Feature OID, but # OpenSSL.crypto.X509Extension doesn't give us the extension's raw OID, # and the shortname field is just "UNDEF" diff --git a/certbot-apache/certbot_apache/tests/autohsts_test.py b/certbot-apache/certbot_apache/tests/autohsts_test.py index 73da33f15..aa35dbe30 100644 --- a/certbot-apache/certbot_apache/tests/autohsts_test.py +++ b/certbot-apache/certbot_apache/tests/autohsts_test.py @@ -64,12 +64,12 @@ class AutoHSTSTest(util.ApacheTest): self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"]) # Verify initial value - self.assertEquals(self.get_autohsts_value(self.vh_truth[7].path), + self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), initial_val) # Increase self.config.update_autohsts(mock.MagicMock()) # Verify increased value - self.assertEquals(self.get_autohsts_value(self.vh_truth[7].path), + self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), inc_val) self.assertTrue(mock_prepare.called) @@ -80,7 +80,7 @@ class AutoHSTSTest(util.ApacheTest): initial_val = maxage.format(constants.AUTOHSTS_STEPS[0]) self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"]) # Verify initial value - self.assertEquals(self.get_autohsts_value(self.vh_truth[7].path), + self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), initial_val) self.config.update_autohsts(mock.MagicMock()) @@ -117,11 +117,11 @@ class AutoHSTSTest(util.ApacheTest): self.config.update_autohsts(mock.MagicMock()) # Value should match pre-permanent increment step cur_val = maxage.format(constants.AUTOHSTS_STEPS[i+1]) - self.assertEquals(self.get_autohsts_value(self.vh_truth[7].path), + self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), cur_val) # Make permanent self.config.deploy_autohsts(mock_lineage) - self.assertEquals(self.get_autohsts_value(self.vh_truth[7].path), + self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), max_val) def test_autohsts_update_noop(self): @@ -153,7 +153,7 @@ class AutoHSTSTest(util.ApacheTest): mock_id.return_value = "1234567" self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com", "ocspvhost.com"]) - self.assertEquals(mock_id.call_count, 1) + self.assertEqual(mock_id.call_count, 1) def test_autohsts_remove_orphaned(self): # pylint: disable=protected-access diff --git a/certbot-apache/certbot_apache/tests/centos_test.py b/certbot-apache/certbot_apache/tests/centos_test.py index 4ee8b5dcf..bc15fc6c7 100644 --- a/certbot-apache/certbot_apache/tests/centos_test.py +++ b/certbot-apache/certbot_apache/tests/centos_test.py @@ -81,9 +81,9 @@ class MultipleVhostsTestCentOS(util.ApacheTest): mock_osi.return_value = ("centos", "7") self.config.parser.update_runtime_variables() - self.assertEquals(mock_get.call_count, 3) - self.assertEquals(len(self.config.parser.modules), 4) - self.assertEquals(len(self.config.parser.variables), 2) + self.assertEqual(mock_get.call_count, 3) + self.assertEqual(len(self.config.parser.modules), 4) + self.assertEqual(len(self.config.parser.variables), 2) self.assertTrue("TEST2" in self.config.parser.variables.keys()) self.assertTrue("mod_another.c" in self.config.parser.modules) @@ -127,7 +127,7 @@ class MultipleVhostsTestCentOS(util.ApacheTest): def test_alt_restart_works(self, mock_run_script): mock_run_script.side_effect = [None, errors.SubprocessError, None] self.config.restart() - self.assertEquals(mock_run_script.call_count, 3) + self.assertEqual(mock_run_script.call_count, 3) @mock.patch("certbot_apache.configurator.util.run_script") def test_alt_restart_errors(self, mock_run_script): diff --git a/certbot-apache/certbot_apache/tests/configurator_test.py b/certbot-apache/certbot_apache/tests/configurator_test.py index 350262634..ed61f5cf8 100644 --- a/certbot-apache/certbot_apache/tests/configurator_test.py +++ b/certbot-apache/certbot_apache/tests/configurator_test.py @@ -1401,11 +1401,11 @@ class MultipleVhostsTest(util.ApacheTest): vhs = self.config._choose_vhosts_wildcard("*.certbot.demo", create_ssl=True) # Check that the dialog was called with one vh: certbot.demo - self.assertEquals(mock_select_vhs.call_args[0][0][0], self.vh_truth[3]) - self.assertEquals(len(mock_select_vhs.call_args_list), 1) + self.assertEqual(mock_select_vhs.call_args[0][0][0], self.vh_truth[3]) + self.assertEqual(len(mock_select_vhs.call_args_list), 1) # And the actual returned values - self.assertEquals(len(vhs), 1) + self.assertEqual(len(vhs), 1) self.assertTrue(vhs[0].name == "certbot.demo") self.assertTrue(vhs[0].ssl) @@ -1420,7 +1420,7 @@ class MultipleVhostsTest(util.ApacheTest): vhs = self.config._choose_vhosts_wildcard("*.certbot.demo", create_ssl=False) self.assertFalse(mock_makessl.called) - self.assertEquals(vhs[0], self.vh_truth[1]) + self.assertEqual(vhs[0], self.vh_truth[1]) @mock.patch("certbot_apache.configurator.ApacheConfigurator._vhosts_for_wildcard") @mock.patch("certbot_apache.configurator.ApacheConfigurator.make_vhost_ssl") @@ -1433,15 +1433,15 @@ class MultipleVhostsTest(util.ApacheTest): mock_select_vhs.return_value = [self.vh_truth[7]] vhs = self.config._choose_vhosts_wildcard("whatever", create_ssl=True) - self.assertEquals(mock_select_vhs.call_args[0][0][0], self.vh_truth[7]) - self.assertEquals(len(mock_select_vhs.call_args_list), 1) + self.assertEqual(mock_select_vhs.call_args[0][0][0], self.vh_truth[7]) + self.assertEqual(len(mock_select_vhs.call_args_list), 1) # Ensure that make_vhost_ssl was not called, vhost.ssl == true self.assertFalse(mock_makessl.called) # And the actual returned values - self.assertEquals(len(vhs), 1) + self.assertEqual(len(vhs), 1) self.assertTrue(vhs[0].ssl) - self.assertEquals(vhs[0], self.vh_truth[7]) + self.assertEqual(vhs[0], self.vh_truth[7]) def test_deploy_cert_wildcard(self): @@ -1454,7 +1454,7 @@ class MultipleVhostsTest(util.ApacheTest): self.config.deploy_cert("*.wildcard.example.org", "/tmp/path", "/tmp/path", "/tmp/path", "/tmp/path") self.assertTrue(mock_dep.called) - self.assertEquals(len(mock_dep.call_args_list), 1) + self.assertEqual(len(mock_dep.call_args_list), 1) self.assertEqual(self.vh_truth[7], mock_dep.call_args_list[0][0][0]) @mock.patch("certbot_apache.display_ops.select_vhost_multiple") diff --git a/certbot-apache/certbot_apache/tests/gentoo_test.py b/certbot-apache/certbot_apache/tests/gentoo_test.py index d32551267..54b4d6532 100644 --- a/certbot-apache/certbot_apache/tests/gentoo_test.py +++ b/certbot-apache/certbot_apache/tests/gentoo_test.py @@ -121,15 +121,15 @@ class MultipleVhostsTestGentoo(util.ApacheTest): mock_osi.return_value = ("gentoo", "123") self.config.parser.update_runtime_variables() - self.assertEquals(mock_get.call_count, 1) - self.assertEquals(len(self.config.parser.modules), 4) + self.assertEqual(mock_get.call_count, 1) + self.assertEqual(len(self.config.parser.modules), 4) self.assertTrue("mod_another.c" in self.config.parser.modules) @mock.patch("certbot_apache.configurator.util.run_script") def test_alt_restart_works(self, mock_run_script): mock_run_script.side_effect = [None, errors.SubprocessError, None] self.config.restart() - self.assertEquals(mock_run_script.call_count, 3) + self.assertEqual(mock_run_script.call_count, 3) if __name__ == "__main__": unittest.main() # pragma: no cover diff --git a/certbot-apache/certbot_apache/tests/parser_test.py b/certbot-apache/certbot_apache/tests/parser_test.py index f95f1b346..88eb55d22 100644 --- a/certbot-apache/certbot_apache/tests/parser_test.py +++ b/certbot-apache/certbot_apache/tests/parser_test.py @@ -84,7 +84,7 @@ class BasicParserTest(util.ParserTest): self.assertEqual(self.parser.aug.get(match), str(i + 1)) def test_empty_arg(self): - self.assertEquals(None, + self.assertEqual(None, self.parser.get_arg("/files/whatever/nonexistent")) def test_add_dir_to_ifmodssl(self): @@ -303,7 +303,7 @@ class BasicParserTest(util.ParserTest): from certbot_apache.parser import get_aug_path self.parser.add_comment(get_aug_path(self.parser.loc["name"]), "123456") comm = self.parser.find_comments("123456") - self.assertEquals(len(comm), 1) + self.assertEqual(len(comm), 1) self.assertTrue(self.parser.loc["name"] in comm[0]) diff --git a/certbot-dns-google/certbot_dns_google/dns_google_test.py b/certbot-dns-google/certbot_dns_google/dns_google_test.py index b6f6e08b6..2b081885b 100644 --- a/certbot-dns-google/certbot_dns_google/dns_google_test.py +++ b/certbot-dns-google/certbot_dns_google/dns_google_test.py @@ -276,9 +276,9 @@ class GoogleClientTest(unittest.TestCase): [{'managedZones': [{'id': self.zone}]}]) # Record name mocked in setUp found = client.get_existing_txt_rrset(self.zone, "_acme-challenge.example.org") - self.assertEquals(found, ["\"example-txt-contents\""]) + self.assertEqual(found, ["\"example-txt-contents\""]) not_found = client.get_existing_txt_rrset(self.zone, "nonexistent.tld") - self.assertEquals(not_found, None) + self.assertEqual(not_found, None) @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google.dns_google.open', diff --git a/certbot-nginx/certbot_nginx/tests/configurator_test.py b/certbot-nginx/certbot_nginx/tests/configurator_test.py index 4d23f3518..3dada2399 100644 --- a/certbot-nginx/certbot_nginx/tests/configurator_test.py +++ b/certbot-nginx/certbot_nginx/tests/configurator_test.py @@ -177,9 +177,9 @@ class NginxConfiguratorTest(util.NginxTest): def test_ipv6only(self): # ipv6_info: (ipv6_active, ipv6only_present) - self.assertEquals((True, False), self.config.ipv6_info("80")) + self.assertEqual((True, False), self.config.ipv6_info("80")) # Port 443 has ipv6only=on because of ipv6ssl.com vhost - self.assertEquals((True, True), self.config.ipv6_info("443")) + self.assertEqual((True, True), self.config.ipv6_info("443")) def test_ipv6only_detection(self): self.config.version = (1, 3, 1) @@ -790,7 +790,7 @@ class NginxConfiguratorTest(util.NginxTest): self.assertTrue(vhost in mock_select_vhs.call_args[0][0]) # And the actual returned values - self.assertEquals(len(vhs), 1) + self.assertEqual(len(vhs), 1) self.assertEqual(vhs[0], vhost) def test_choose_vhosts_wildcard_redirect(self): @@ -806,7 +806,7 @@ class NginxConfiguratorTest(util.NginxTest): self.assertTrue(vhost in mock_select_vhs.call_args[0][0]) # And the actual returned values - self.assertEquals(len(vhs), 1) + self.assertEqual(len(vhs), 1) self.assertEqual(vhs[0], vhost) def test_deploy_cert_wildcard(self): @@ -821,7 +821,7 @@ class NginxConfiguratorTest(util.NginxTest): self.config.deploy_cert("*.com", "/tmp/path", "/tmp/path", "/tmp/path", "/tmp/path") self.assertTrue(mock_dep.called) - self.assertEquals(len(mock_dep.call_args_list), 1) + self.assertEqual(len(mock_dep.call_args_list), 1) self.assertEqual(vhost, mock_dep.call_args_list[0][0][0]) @mock.patch("certbot_nginx.display_ops.select_vhost_multiple") diff --git a/certbot-postfix/certbot_postfix/tests/postconf_test.py b/certbot-postfix/certbot_postfix/tests/postconf_test.py index 91617d410..01a43773d 100644 --- a/certbot-postfix/certbot_postfix/tests/postconf_test.py +++ b/certbot-postfix/certbot_postfix/tests/postconf_test.py @@ -85,7 +85,7 @@ class PostConfTest(unittest.TestCase): self.config.set('extra_param', 'another_value') self.config.flush() arguments = mock_out.call_args_list[-1][0][0] - self.assertEquals('-e', arguments[0]) + self.assertEqual('-e', arguments[0]) self.assertTrue('default_parameter=new_value' in arguments) self.assertTrue('extra_param=another_value' in arguments) diff --git a/certbot/plugins/enhancements_test.py b/certbot/plugins/enhancements_test.py index b69dc9836..22f6f54e9 100644 --- a/certbot/plugins/enhancements_test.py +++ b/certbot/plugins/enhancements_test.py @@ -37,11 +37,11 @@ class EnhancementTest(test_util.ConfigTestCase): self.assertTrue([i for i in enabled if i["name"] == "somethingelse"]) def test_are_requested(self): - self.assertEquals( + self.assertEqual( len([i for i in enhancements.enabled_enhancements(self.config)]), 0) self.assertFalse(enhancements.are_requested(self.config)) self.config.auto_hsts = True - self.assertEquals( + self.assertEqual( len([i for i in enhancements.enabled_enhancements(self.config)]), 1) self.assertTrue(enhancements.are_requested(self.config)) @@ -57,7 +57,7 @@ class EnhancementTest(test_util.ConfigTestCase): lineage = "lineage" enhancements.enable(lineage, domains, self.mockinstaller, self.config) self.assertTrue(self.mockinstaller.enable_autohsts.called) - self.assertEquals(self.mockinstaller.enable_autohsts.call_args[0], + self.assertEqual(self.mockinstaller.enable_autohsts.call_args[0], (lineage, domains)) diff --git a/certbot/plugins/selection_test.py b/certbot/plugins/selection_test.py index 44d64ab8e..5f8e42516 100644 --- a/certbot/plugins/selection_test.py +++ b/certbot/plugins/selection_test.py @@ -197,7 +197,7 @@ class GetUnpreparedInstallerTest(test_util.ConfigTestCase): def test_no_installer_defined(self): self.config.configurator = None - self.assertEquals(self._call(), None) + self.assertEqual(self._call(), None) def test_no_available_installers(self): self.config.configurator = "apache" diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index 6ec1d4f5c..3ef1709f5 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -589,7 +589,7 @@ class GetCertnameTest(unittest.TestCase): from certbot import cert_manager prompt = "Which certificate would you" self.mock_get_utility().menu.return_value = (display_util.OK, 0) - self.assertEquals( + self.assertEqual( cert_manager.get_certnames( self.config, "verb", allow_multiple=False), ['example.com']) self.assertTrue( @@ -603,11 +603,11 @@ class GetCertnameTest(unittest.TestCase): from certbot import cert_manager prompt = "custom prompt" self.mock_get_utility().menu.return_value = (display_util.OK, 0) - self.assertEquals( + self.assertEqual( cert_manager.get_certnames( self.config, "verb", allow_multiple=False, custom_prompt=prompt), ['example.com']) - self.assertEquals(self.mock_get_utility().menu.call_args[0][0], + self.assertEqual(self.mock_get_utility().menu.call_args[0][0], prompt) @mock.patch('certbot.storage.renewal_conf_files') @@ -631,7 +631,7 @@ class GetCertnameTest(unittest.TestCase): prompt = "Which certificate(s) would you" self.mock_get_utility().checklist.return_value = (display_util.OK, ['example.com']) - self.assertEquals( + self.assertEqual( cert_manager.get_certnames( self.config, "verb", allow_multiple=True), ['example.com']) self.assertTrue( @@ -646,11 +646,11 @@ class GetCertnameTest(unittest.TestCase): prompt = "custom prompt" self.mock_get_utility().checklist.return_value = (display_util.OK, ['example.com']) - self.assertEquals( + self.assertEqual( cert_manager.get_certnames( self.config, "verb", allow_multiple=True, custom_prompt=prompt), ['example.com']) - self.assertEquals( + self.assertEqual( self.mock_get_utility().checklist.call_args[0][0], prompt) diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index 70ab4c798..a4e70ce35 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -487,7 +487,7 @@ class EnhanceConfigTest(ClientTestCommon): self.config.hsts = True self._test_with_already_existing() self.assertTrue(mock_log.warning.called) - self.assertEquals(mock_log.warning.call_args[0][1], + self.assertEqual(mock_log.warning.call_args[0][1], 'Strict-Transport-Security') @mock.patch("certbot.client.logger") @@ -495,7 +495,7 @@ class EnhanceConfigTest(ClientTestCommon): self.config.redirect = True self._test_with_already_existing() self.assertTrue(mock_log.warning.called) - self.assertEquals(mock_log.warning.call_args[0][1], + self.assertEqual(mock_log.warning.call_args[0][1], 'redirect') def test_no_ask_hsts(self): diff --git a/certbot/tests/display/ops_test.py b/certbot/tests/display/ops_test.py index 9de8c5e9a..9ad0ce87a 100644 --- a/certbot/tests/display/ops_test.py +++ b/certbot/tests/display/ops_test.py @@ -502,9 +502,9 @@ class ChooseValuesTest(unittest.TestCase): items = ["first", "second", "third"] mock_util().checklist.return_value = (display_util.OK, [items[2]]) result = self._call(items, None) - self.assertEquals(result, [items[2]]) + self.assertEqual(result, [items[2]]) self.assertTrue(mock_util().checklist.called) - self.assertEquals(mock_util().checklist.call_args[0][0], None) + self.assertEqual(mock_util().checklist.call_args[0][0], None) @test_util.patch_get_utility("certbot.display.ops.z_util") def test_choose_names_success_question(self, mock_util): @@ -512,9 +512,9 @@ class ChooseValuesTest(unittest.TestCase): question = "Which one?" mock_util().checklist.return_value = (display_util.OK, [items[1]]) result = self._call(items, question) - self.assertEquals(result, [items[1]]) + self.assertEqual(result, [items[1]]) self.assertTrue(mock_util().checklist.called) - self.assertEquals(mock_util().checklist.call_args[0][0], question) + self.assertEqual(mock_util().checklist.call_args[0][0], question) @test_util.patch_get_utility("certbot.display.ops.z_util") def test_choose_names_user_cancel(self, mock_util): @@ -522,9 +522,9 @@ class ChooseValuesTest(unittest.TestCase): question = "Want to cancel?" mock_util().checklist.return_value = (display_util.CANCEL, []) result = self._call(items, question) - self.assertEquals(result, []) + self.assertEqual(result, []) self.assertTrue(mock_util().checklist.called) - self.assertEquals(mock_util().checklist.call_args[0][0], question) + self.assertEqual(mock_util().checklist.call_args[0][0], question) if __name__ == "__main__": diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index cc4e6c293..b4e0d5581 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -1712,7 +1712,7 @@ class EnhanceTest(test_util.ConfigTestCase): mock_lineage.return_value = mock.MagicMock(chain_path="/tmp/nonexistent") self._call(['enhance', '--auto-hsts']) self.assertTrue(self.mockinstaller.enable_autohsts.called) - self.assertEquals(self.mockinstaller.enable_autohsts.call_args[0][1], + self.assertEqual(self.mockinstaller.enable_autohsts.call_args[0][1], ["example.com", "another.tld"]) @mock.patch('certbot.cert_manager.lineage_for_certname') diff --git a/certbot/tests/renewupdater_test.py b/certbot/tests/renewupdater_test.py index 5a362072c..5fe188c42 100644 --- a/certbot/tests/renewupdater_test.py +++ b/certbot/tests/renewupdater_test.py @@ -53,7 +53,7 @@ class RenewUpdaterTest(test_util.ConfigTestCase): self.config.dry_run = True updater.run_generic_updaters(self.config, None, None) self.assertTrue(mock_log.called) - self.assertEquals(mock_log.call_args[0][0], + self.assertEqual(mock_log.call_args[0][0], "Skipping updaters in dry-run mode.") @mock.patch("certbot.updater.logger.debug") @@ -61,7 +61,7 @@ class RenewUpdaterTest(test_util.ConfigTestCase): self.config.dry_run = True updater.run_renewal_deployer(self.config, None, None) self.assertTrue(mock_log.called) - self.assertEquals(mock_log.call_args[0][0], + self.assertEqual(mock_log.call_args[0][0], "Skipping renewal deployer in dry-run mode.") @mock.patch('certbot.plugins.selection.get_unprepared_installer') From aad266369597281c79022cc4d807bc2be2b08b43 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Tue, 30 Oct 2018 17:13:40 -0700 Subject: [PATCH 004/114] Only error on DeprecationWarnings --- pytest.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index 085c7258e..2669c1105 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,4 @@ [pytest] -addopts = -Werror --numprocesses auto --pyargs +addopts = --numprocesses auto --pyargs +filterwarnings = + error::DeprecationWarning From b0b871083559e45b8f935748bb101783348613b4 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Tue, 30 Oct 2018 17:24:29 -0700 Subject: [PATCH 005/114] Move back to using a warning whitelist --- pytest.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index 2669c1105..4a1dcca16 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,4 @@ [pytest] addopts = --numprocesses auto --pyargs filterwarnings = - error::DeprecationWarning + error From 090a1bd44da1e11f45cefe7aa6c5b9743ca3ab9d Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 31 Oct 2018 17:20:31 -0700 Subject: [PATCH 006/114] getargspec is deprecated in python 3 --- certbot/tests/display/util_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index 5672a20bd..f7d1a8a37 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -16,6 +16,11 @@ CHOICES = [("First", "Description1"), ("Second", "Description2")] TAGS = ["tag1", "tag2", "tag3"] TAGS_CHOICES = [("1", "tag1"), ("2", "tag2"), ("3", "tag3")] +if six.PY2: + getargspec = inspect.getargspec +else: + getargspec = inspect.getfullargspec + class InputWithTimeoutTest(unittest.TestCase): """Tests for certbot.display.util.input_with_timeout.""" @@ -314,7 +319,7 @@ class FileOutputDisplayTest(unittest.TestCase): # Every IDisplay method implemented by FileDisplay must take # force_interactive to prevent workflow regressions. for name in interfaces.IDisplay.names(): # pylint: disable=no-member - arg_spec = inspect.getargspec(getattr(self.displayer, name)) + arg_spec = getargspec(getattr(self.displayer, name)) self.assertTrue("force_interactive" in arg_spec.args) @@ -371,7 +376,7 @@ class NoninteractiveDisplayTest(unittest.TestCase): for name in interfaces.IDisplay.names(): # pylint: disable=no-member method = getattr(self.displayer, name) # asserts method accepts arbitrary keyword arguments - self.assertFalse(inspect.getargspec(method).keywords is None) + self.assertFalse(getargspec(method).keywords is None) class SeparateListInputTest(unittest.TestCase): From 2ddf47e3cce6433d361717267b6c6ab48db20163 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 31 Oct 2018 17:28:47 -0700 Subject: [PATCH 007/114] assertEquals --> assertEqual --- .../certbot_apache/tests/autohsts_test.py | 2 +- .../certbot_nginx/tests/parser_obj_test.py | 58 +++++++++---------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/certbot-apache/certbot_apache/tests/autohsts_test.py b/certbot-apache/certbot_apache/tests/autohsts_test.py index 8a7c7ee76..fd9927b60 100644 --- a/certbot-apache/certbot_apache/tests/autohsts_test.py +++ b/certbot-apache/certbot_apache/tests/autohsts_test.py @@ -120,7 +120,7 @@ class AutoHSTSTest(util.ApacheTest): self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), cur_val) # Ensure that the value is raised to max - self.assertEquals(self.get_autohsts_value(self.vh_truth[7].path), + self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), maxage.format(constants.AUTOHSTS_STEPS[-1])) # Make permanent self.config.deploy_autohsts(mock_lineage) diff --git a/certbot-nginx/certbot_nginx/tests/parser_obj_test.py b/certbot-nginx/certbot_nginx/tests/parser_obj_test.py index c9c9dd440..2217be54f 100644 --- a/certbot-nginx/certbot_nginx/tests/parser_obj_test.py +++ b/certbot-nginx/certbot_nginx/tests/parser_obj_test.py @@ -103,37 +103,37 @@ class SentenceTest(unittest.TestCase): def test_parse_sentence_words_hides_spaces(self): og_sentence = ['\r\n', 'hello', ' ', ' ', '\t\n ', 'lol', ' ', 'spaces'] self.sentence.parse(og_sentence) - self.assertEquals(self.sentence.words, ['hello', 'lol', 'spaces']) - self.assertEquals(self.sentence.dump(), ['hello', 'lol', 'spaces']) - self.assertEquals(self.sentence.dump(True), og_sentence) + self.assertEqual(self.sentence.words, ['hello', 'lol', 'spaces']) + self.assertEqual(self.sentence.dump(), ['hello', 'lol', 'spaces']) + self.assertEqual(self.sentence.dump(True), og_sentence) def test_parse_sentence_with_add_spaces(self): self.sentence.parse(['hi', 'there'], add_spaces=True) - self.assertEquals(self.sentence.dump(True), ['hi', ' ', 'there']) + self.assertEqual(self.sentence.dump(True), ['hi', ' ', 'there']) self.sentence.parse(['one', ' ', 'space', 'none'], add_spaces=True) - self.assertEquals(self.sentence.dump(True), ['one', ' ', 'space', ' ', 'none']) + self.assertEqual(self.sentence.dump(True), ['one', ' ', 'space', ' ', 'none']) def test_iterate(self): expected = [['1', '2', '3']] self.sentence.parse(['1', ' ', '2', ' ', '3']) for i, sentence in enumerate(self.sentence.iterate()): - self.assertEquals(sentence.dump(), expected[i]) + self.assertEqual(sentence.dump(), expected[i]) def test_set_tabs(self): self.sentence.parse(['tabs', 'pls'], add_spaces=True) self.sentence.set_tabs() - self.assertEquals(self.sentence.dump(True)[0], '\n ') + self.assertEqual(self.sentence.dump(True)[0], '\n ') self.sentence.parse(['tabs', 'pls'], add_spaces=True) def test_get_tabs(self): self.sentence.parse(['no', 'tabs']) - self.assertEquals(self.sentence.get_tabs(), '') + self.assertEqual(self.sentence.get_tabs(), '') self.sentence.parse(['\n \n ', 'tabs']) - self.assertEquals(self.sentence.get_tabs(), ' ') + self.assertEqual(self.sentence.get_tabs(), ' ') self.sentence.parse(['\n\t ', 'tabs']) - self.assertEquals(self.sentence.get_tabs(), '\t ') + self.assertEqual(self.sentence.get_tabs(), '\t ') self.sentence.parse(['\n\t \n', 'tabs']) - self.assertEquals(self.sentence.get_tabs(), '') + self.assertEqual(self.sentence.get_tabs(), '') class BlockTest(unittest.TestCase): def setUp(self): @@ -145,11 +145,11 @@ class BlockTest(unittest.TestCase): def test_iterate(self): # Iterates itself normally - self.assertEquals(self.bloc, next(self.bloc.iterate())) + self.assertEqual(self.bloc, next(self.bloc.iterate())) # Iterates contents while expanded expected = [self.bloc.dump()] + self.contents for i, elem in enumerate(self.bloc.iterate(expanded=True)): - self.assertEquals(expected[i], elem.dump()) + self.assertEqual(expected[i], elem.dump()) def test_iterate_match(self): # can match on contents while expanded @@ -157,17 +157,17 @@ class BlockTest(unittest.TestCase): expected = [['thing', '1'], ['thing', '2']] for i, elem in enumerate(self.bloc.iterate(expanded=True, match=lambda x: isinstance(x, Sentence) and 'thing' in x.words)): - self.assertEquals(expected[i], elem.dump()) + self.assertEqual(expected[i], elem.dump()) # can match on self - self.assertEquals(self.bloc, next(self.bloc.iterate( + self.assertEqual(self.bloc, next(self.bloc.iterate( expanded=True, match=lambda x: isinstance(x, Block) and 'server' in x.names))) def test_parse_with_added_spaces(self): import copy self.bloc.parse([copy.copy(self.name), self.contents], add_spaces=True) - self.assertEquals(self.bloc.dump(), [self.name, self.contents]) - self.assertEquals(self.bloc.dump(True), [ + self.assertEqual(self.bloc.dump(), [self.name, self.contents]) + self.assertEqual(self.bloc.dump(True), [ ['server', ' ', 'name', ' '], [['thing', ' ', '1'], ['thing', ' ', '2'], @@ -181,14 +181,14 @@ class BlockTest(unittest.TestCase): def test_set_tabs(self): self.bloc.set_tabs() - self.assertEquals(self.bloc.names.dump(True)[0], '\n ') + self.assertEqual(self.bloc.names.dump(True)[0], '\n ') for elem in self.bloc.contents.dump(True)[:-1]: - self.assertEquals(elem[0], '\n ') - self.assertEquals(self.bloc.contents.dump(True)[-1][0], '\n') + self.assertEqual(elem[0], '\n ') + self.assertEqual(self.bloc.contents.dump(True)[-1][0], '\n') def test_get_tabs(self): self.bloc.parse([[' \n \t', 'lol'], []]) - self.assertEquals(self.bloc.get_tabs(), ' \t') + self.assertEqual(self.bloc.get_tabs(), ' \t') class StatementsTest(unittest.TestCase): def setUp(self): @@ -210,7 +210,7 @@ class StatementsTest(unittest.TestCase): self.statements.parse(self.raw) self.statements.set_tabs() for statement in self.statements.iterate(): - self.assertEquals(statement.dump(True)[0], '\n ') + self.assertEqual(statement.dump(True)[0], '\n ') def test_set_tabs_with_parent(self): # Trailing whitespace should inherit from parent tabbing. @@ -219,19 +219,19 @@ class StatementsTest(unittest.TestCase): self.statements.parent.get_tabs.return_value = '\t\t' self.statements.set_tabs() for statement in self.statements.iterate(): - self.assertEquals(statement.dump(True)[0], '\n ') - self.assertEquals(self.statements.dump(True)[-1], '\n\t\t') + self.assertEqual(statement.dump(True)[0], '\n ') + self.assertEqual(self.statements.dump(True)[-1], '\n\t\t') def test_get_tabs(self): self.raw[0].insert(0, '\n \n \t') self.statements.parse(self.raw) - self.assertEquals(self.statements.get_tabs(), ' \t') + self.assertEqual(self.statements.get_tabs(), ' \t') self.statements.parse([]) - self.assertEquals(self.statements.get_tabs(), '') + self.assertEqual(self.statements.get_tabs(), '') def test_parse_with_added_spaces(self): self.statements.parse(self.raw, add_spaces=True) - self.assertEquals(self.statements.dump(True)[0], ['sentence', ' ', 'one']) + self.assertEqual(self.statements.dump(True)[0], ['sentence', ' ', 'one']) def test_parse_bad_list_raises_error(self): from certbot import errors @@ -241,13 +241,13 @@ class StatementsTest(unittest.TestCase): self.statements.parse(self.raw + ['\n\n ']) self.assertTrue(isinstance(self.statements.dump()[-1], list)) self.assertTrue(self.statements.dump(True)[-1].isspace()) - self.assertEquals(self.statements.dump(True)[-1], '\n\n ') + self.assertEqual(self.statements.dump(True)[-1], '\n\n ') def test_iterate(self): self.statements.parse(self.raw) expected = [['sentence', 'one'], ['sentence', 'two']] for i, elem in enumerate(self.statements.iterate(match=lambda x: 'sentence' in x)): - self.assertEquals(expected[i], elem.dump()) + self.assertEqual(expected[i], elem.dump()) if __name__ == "__main__": unittest.main() # pragma: no cover From 594fbe3ae8cb4a81032cb85884dabe36dcccffeb Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 31 Oct 2018 17:33:39 -0700 Subject: [PATCH 008/114] disable pylint no-member for x-version --- certbot/tests/display/util_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index f7d1a8a37..36ea91027 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -17,9 +17,9 @@ TAGS = ["tag1", "tag2", "tag3"] TAGS_CHOICES = [("1", "tag1"), ("2", "tag2"), ("3", "tag3")] if six.PY2: - getargspec = inspect.getargspec + getargspec = inspect.getargspec # pylint:disable=no-member else: - getargspec = inspect.getfullargspec + getargspec = inspect.getfullargspec # pylint:disable=no-member class InputWithTimeoutTest(unittest.TestCase): From a5e0e801be7194db5894d0d3cc4313b85b7eb3aa Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 31 Oct 2018 17:49:50 -0700 Subject: [PATCH 009/114] correctly use getfullargspec --- certbot/tests/display/util_test.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index 36ea91027..eccffa47a 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -16,11 +16,6 @@ CHOICES = [("First", "Description1"), ("Second", "Description2")] TAGS = ["tag1", "tag2", "tag3"] TAGS_CHOICES = [("1", "tag1"), ("2", "tag2"), ("3", "tag3")] -if six.PY2: - getargspec = inspect.getargspec # pylint:disable=no-member -else: - getargspec = inspect.getfullargspec # pylint:disable=no-member - class InputWithTimeoutTest(unittest.TestCase): """Tests for certbot.display.util.input_with_timeout.""" @@ -319,6 +314,10 @@ class FileOutputDisplayTest(unittest.TestCase): # Every IDisplay method implemented by FileDisplay must take # force_interactive to prevent workflow regressions. for name in interfaces.IDisplay.names(): # pylint: disable=no-member + if six.PY2: + getargspec = inspect.getargspec + else: + getargspec = inspect.getfullargspec arg_spec = getargspec(getattr(self.displayer, name)) self.assertTrue("force_interactive" in arg_spec.args) @@ -376,7 +375,10 @@ class NoninteractiveDisplayTest(unittest.TestCase): for name in interfaces.IDisplay.names(): # pylint: disable=no-member method = getattr(self.displayer, name) # asserts method accepts arbitrary keyword arguments - self.assertFalse(getargspec(method).keywords is None) + if six.PY2: + self.assertFalse(inspect.getargspec(method).keywords is None) + else: + self.assertFalse(inspect.getfullargspec(method).varkw is None) class SeparateListInputTest(unittest.TestCase): From b837f218c9e8755fbc5e4a6d47a68c5fe8f7f81c Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 31 Oct 2018 17:59:24 -0700 Subject: [PATCH 010/114] U mode on open --> newline=None --- certbot/crypto_util.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/certbot/crypto_util.py b/certbot/crypto_util.py index 942f8502f..7b558b060 100644 --- a/certbot/crypto_util.py +++ b/certbot/crypto_util.py @@ -458,8 +458,12 @@ def sha256sum(filename): :rtype: str """ sha256 = hashlib.sha256() - with open(filename, 'rU') as file_d: - sha256.update(file_d.read().encode('UTF-8')) + if six.PY2: + with open(filename, 'rU') as file_d: + sha256.update(file_d.read().encode('UTF-8')) + else: + with open(filename, 'r', newline=None) as file_d: + sha256.update(file_d.read().encode('UTF-8')) return sha256.hexdigest() def cert_and_chain_from_fullchain(fullchain_pem): From 35510bfc6cafa5c5d02446bed8d783b2959b579b Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 31 Oct 2018 17:59:44 -0700 Subject: [PATCH 011/114] assertNotEquals --> assertNotEqual --- certbot-apache/certbot_apache/tests/autohsts_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-apache/certbot_apache/tests/autohsts_test.py b/certbot-apache/certbot_apache/tests/autohsts_test.py index fd9927b60..bf92a13ff 100644 --- a/certbot-apache/certbot_apache/tests/autohsts_test.py +++ b/certbot-apache/certbot_apache/tests/autohsts_test.py @@ -112,7 +112,7 @@ class AutoHSTSTest(util.ApacheTest): for i in range(len(constants.AUTOHSTS_STEPS)-1): # Ensure that value is not made permanent prematurely self.config.deploy_autohsts(mock_lineage) - self.assertNotEquals(self.get_autohsts_value(self.vh_truth[7].path), + self.assertNotEqual(self.get_autohsts_value(self.vh_truth[7].path), max_val) self.config.update_autohsts(mock.MagicMock()) # Value should match pre-permanent increment step From 1eabb4bae39b9567f987f6740cd554029c157492 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 31 Oct 2018 18:05:00 -0700 Subject: [PATCH 012/114] warn-->warning --- .../certbot_dns_cloudflare/dns_cloudflare.py | 2 +- .../certbot_dns_digitalocean/dns_digitalocean.py | 2 +- certbot-dns-google/certbot_dns_google/dns_google.py | 4 ++-- certbot-nginx/certbot_nginx/parser.py | 2 +- certbot/ocsp.py | 2 +- certbot/storage.py | 2 +- certbot/tests/ocsp_test.py | 6 +++--- certbot/tests/storage_test.py | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/dns_cloudflare.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/dns_cloudflare.py index f1156642f..7604a8baf 100644 --- a/certbot-dns-cloudflare/certbot_dns_cloudflare/dns_cloudflare.py +++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/dns_cloudflare.py @@ -122,7 +122,7 @@ class _CloudflareClient(object): self.cf.zones.dns_records.delete(zone_id, record_id) logger.debug('Successfully deleted TXT record.') except CloudFlare.exceptions.CloudFlareAPIError as e: - logger.warn('Encountered CloudFlareAPIError deleting TXT record: %s', e) + logger.warning('Encountered CloudFlareAPIError deleting TXT record: %s', e) else: logger.debug('TXT record not found; no cleanup needed.') else: diff --git a/certbot-dns-digitalocean/certbot_dns_digitalocean/dns_digitalocean.py b/certbot-dns-digitalocean/certbot_dns_digitalocean/dns_digitalocean.py index 4bf279279..5a4f22327 100644 --- a/certbot-dns-digitalocean/certbot_dns_digitalocean/dns_digitalocean.py +++ b/certbot-dns-digitalocean/certbot_dns_digitalocean/dns_digitalocean.py @@ -134,7 +134,7 @@ class _DigitalOceanClient(object): logger.debug('Removing TXT record with id: %s', record.id) record.destroy() except digitalocean.Error as e: - logger.warn('Error deleting TXT record %s using the DigitalOcean API: %s', + logger.warning('Error deleting TXT record %s using the DigitalOcean API: %s', record.id, e) def _find_domain(self, domain_name): diff --git a/certbot-dns-google/certbot_dns_google/dns_google.py b/certbot-dns-google/certbot_dns_google/dns_google.py index c204cb0ca..0b84dddb0 100644 --- a/certbot-dns-google/certbot_dns_google/dns_google.py +++ b/certbot-dns-google/certbot_dns_google/dns_google.py @@ -179,7 +179,7 @@ class _GoogleClient(object): try: zone_id = self._find_managed_zone_id(domain) except errors.PluginError as e: - logger.warn('Error finding zone. Skipping cleanup.') + logger.warning('Error finding zone. Skipping cleanup.') return record_contents = self.get_existing_txt_rrset(zone_id, record_name) @@ -219,7 +219,7 @@ class _GoogleClient(object): request = changes.create(project=self.project_id, managedZone=zone_id, body=data) request.execute() except googleapiclient_errors.Error as e: - logger.warn('Encountered error deleting TXT record: %s', e) + logger.warning('Encountered error deleting TXT record: %s', e) def get_existing_txt_rrset(self, zone_id, record_name): """ diff --git a/certbot-nginx/certbot_nginx/parser.py b/certbot-nginx/certbot_nginx/parser.py index a5cf2892e..622eb8d55 100644 --- a/certbot-nginx/certbot_nginx/parser.py +++ b/certbot-nginx/certbot_nginx/parser.py @@ -415,7 +415,7 @@ def _parse_ssl_options(ssl_options): with open(ssl_options) as _file: return nginxparser.load(_file) except IOError: - logger.warn("Missing NGINX TLS options file: %s", ssl_options) + logger.warning("Missing NGINX TLS options file: %s", ssl_options) except pyparsing.ParseBaseException as err: logger.debug("Could not parse file: %s due to %s", ssl_options, err) return [] diff --git a/certbot/ocsp.py b/certbot/ocsp.py index d34110f88..049e14827 100644 --- a/certbot/ocsp.py +++ b/certbot/ocsp.py @@ -114,7 +114,7 @@ def _translate_ocsp_query(cert_path, ocsp_output, ocsp_errors): logger.info("OCSP revocation warning: %s", warning) return True else: - logger.warn("Unable to properly parse OCSP output: %s\nstderr:%s", + logger.warning("Unable to properly parse OCSP output: %s\nstderr:%s", ocsp_output, ocsp_errors) return False diff --git a/certbot/storage.py b/certbot/storage.py index c16ea35b8..2aadaa67a 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -791,7 +791,7 @@ class RenewableCert(object): May need to recover from rare interrupted / crashed states.""" if self.has_pending_deployment(): - logger.warn("Found a new cert /archive/ that was not linked to in /live/; " + logger.warning("Found a new cert /archive/ that was not linked to in /live/; " "fixing...") self.update_all_links_to(self.latest_common_version()) return False diff --git a/certbot/tests/ocsp_test.py b/certbot/tests/ocsp_test.py index 2d54274f0..55cd24adb 100644 --- a/certbot/tests/ocsp_test.py +++ b/certbot/tests/ocsp_test.py @@ -96,15 +96,15 @@ class OCSPTest(unittest.TestCase): self.assertEqual(ocsp._translate_ocsp_query(*openssl_happy), False) self.assertEqual(ocsp._translate_ocsp_query(*openssl_confused), False) self.assertEqual(mock_log.debug.call_count, 1) - self.assertEqual(mock_log.warn.call_count, 0) + self.assertEqual(mock_log.warning.call_count, 0) mock_log.debug.call_count = 0 self.assertEqual(ocsp._translate_ocsp_query(*openssl_unknown), False) self.assertEqual(mock_log.debug.call_count, 1) - self.assertEqual(mock_log.warn.call_count, 0) + self.assertEqual(mock_log.warning.call_count, 0) self.assertEqual(ocsp._translate_ocsp_query(*openssl_expired_ocsp), False) self.assertEqual(mock_log.debug.call_count, 2) self.assertEqual(ocsp._translate_ocsp_query(*openssl_broken), False) - self.assertEqual(mock_log.warn.call_count, 1) + self.assertEqual(mock_log.warning.call_count, 1) mock_log.info.call_count = 0 self.assertEqual(ocsp._translate_ocsp_query(*openssl_revoked), True) self.assertEqual(mock_log.info.call_count, 0) diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 03d595652..912cd7984 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -264,12 +264,12 @@ class RenewableCertTests(BaseRenewableCertTest): mock_has_pending.return_value = False self.assertEqual(self.test_rc.ensure_deployed(), True) self.assertEqual(mock_update.call_count, 0) - self.assertEqual(mock_logger.warn.call_count, 0) + self.assertEqual(mock_logger.warning.call_count, 0) mock_has_pending.return_value = True self.assertEqual(self.test_rc.ensure_deployed(), False) self.assertEqual(mock_update.call_count, 1) - self.assertEqual(mock_logger.warn.call_count, 1) + self.assertEqual(mock_logger.warning.call_count, 1) def test_update_link_to(self): From 6f662fa489dd48548cde5ec739bddf19720dd8d2 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 1 Nov 2018 16:39:01 -0700 Subject: [PATCH 013/114] ignore deprecation and resource warnings in certbot-dns-rfc2136, which are inherited from dnspython --- certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py index 89ce3d93e..9d3a0fbfd 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py @@ -7,6 +7,7 @@ import dns.flags import dns.rcode import dns.tsig import mock +import pytest from certbot import errors from certbot.plugins import dns_test_common @@ -70,6 +71,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.perform([self.achall]) +@pytest.mark.filterwarnings("ignore::ResourceWarning", "ignore:decodestring:DeprecationWarning") class RFC2136ClientTest(unittest.TestCase): def setUp(self): From 49619fc0ab467f5ce7a6eed1404855e1201cd1ed Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 1 Nov 2018 16:39:29 -0700 Subject: [PATCH 014/114] Error on warning, unless it's a ResourceWarning --- pytest.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytest.ini b/pytest.ini index 4a1dcca16..7d0b19223 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,6 @@ [pytest] addopts = --numprocesses auto --pyargs +# ResourceWarnings are ignored as errors, since they're raised at close filterwarnings = error + always::ResourceWarning From 36e8d748a15044047054577f341f37bff621f63d Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 1 Nov 2018 16:39:54 -0700 Subject: [PATCH 015/114] Clean up many warnings --- .../certbot_apache/tests/configurator_test.py | 6 ++-- certbot/cli.py | 4 ++- certbot/plugins/standalone_test.py | 2 ++ certbot/renewal.py | 4 ++- certbot/storage.py | 2 ++ certbot/tests/cert_manager_test.py | 5 ++-- certbot/tests/display/util_test.py | 1 + certbot/tests/log_test.py | 1 + certbot/tests/storage_test.py | 5 ++-- certbot/tests/util_test.py | 28 ++++++++++++++----- 10 files changed, 41 insertions(+), 17 deletions(-) diff --git a/certbot-apache/certbot_apache/tests/configurator_test.py b/certbot-apache/certbot_apache/tests/configurator_test.py index f18d3aac8..a77dbf637 100644 --- a/certbot-apache/certbot_apache/tests/configurator_test.py +++ b/certbot-apache/certbot_apache/tests/configurator_test.py @@ -1651,7 +1651,8 @@ class MultiVhostsTest(util.ApacheTest): self.assertTrue(self.config.parser.find_dir( "RewriteEngine", "on", ssl_vhost.path, False)) - conf_text = open(ssl_vhost.filep).read() + with open(ssl_vhost.filep) as the_file: + conf_text = the_file.read() commented_rewrite_rule = ("# RewriteRule \"^/secrets/(.+)\" " "\"https://new.example.com/docs/$1\" [R,L]") uncommented_rewrite_rule = ("RewriteRule \"^/docs/(.+)\" " @@ -1667,7 +1668,8 @@ class MultiVhostsTest(util.ApacheTest): ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[3]) - conf_lines = open(ssl_vhost.filep).readlines() + with open(ssl_vhost.filep) as the_file: + conf_lines = the_file.readlines() conf_line_set = [l.strip() for l in conf_lines] not_commented_cond1 = ("RewriteCond " "%{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f") diff --git a/certbot/cli.py b/certbot/cli.py index 99bf33180..6502d2987 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -286,7 +286,9 @@ def read_file(filename, mode="rb"): """ try: filename = os.path.abspath(filename) - return filename, open(filename, mode).read() + with open(filename, mode) as the_file: + contents = the_file.read() + return filename, contents except IOError as exc: raise argparse.ArgumentTypeError(exc.strerror) diff --git a/certbot/plugins/standalone_test.py b/certbot/plugins/standalone_test.py index 47f44ff77..9b741fc6f 100644 --- a/certbot/plugins/standalone_test.py +++ b/certbot/plugins/standalone_test.py @@ -72,6 +72,8 @@ class ServerManagerTest(unittest.TestCase): errors.StandaloneBindError, self.mgr.run, port, challenge_type=challenges.HTTP01) self.assertEqual(self.mgr.running(), {}) + some_server.close() + maybe_another_server.close() class SupportedChallengesActionTest(unittest.TestCase): diff --git a/certbot/renewal.py b/certbot/renewal.py index a1508fa60..5b2e00740 100644 --- a/certbot/renewal.py +++ b/certbot/renewal.py @@ -276,8 +276,10 @@ def _avoid_invalidating_lineage(config, lineage, original_server): "Do not renew a valid cert with one from a staging server!" # Some lineages may have begun with --staging, but then had production certs # added to them + with open(lineage.cert) as the_file: + contents = the_file.read() latest_cert = OpenSSL.crypto.load_certificate( - OpenSSL.crypto.FILETYPE_PEM, open(lineage.cert).read()) + OpenSSL.crypto.FILETYPE_PEM, contents) # all our test certs are from happy hacker fake CA, though maybe one day # we should test more methodically now_valid = "fake" not in repr(latest_cert.get_issuer()).lower() diff --git a/certbot/storage.py b/certbot/storage.py index 2aadaa67a..2a7ccee02 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -1034,9 +1034,11 @@ class RenewableCert(object): archive = full_archive_path(None, cli_config, lineagename) live_dir = _full_live_path(cli_config, lineagename) if os.path.exists(archive): + config_file.close() raise errors.CertStorageError( "archive directory exists for " + lineagename) if os.path.exists(live_dir): + config_file.close() raise errors.CertStorageError( "live directory exists for " + lineagename) os.mkdir(archive) diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index 7c3f4c85a..84774ca77 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -39,9 +39,8 @@ class BaseCertManagerTest(test_util.ConfigTestCase): # We also create a file that isn't a renewal config in the same # location to test that logic that reads in all-and-only renewal # configs will ignore it and NOT attempt to parse it. - junk = open(os.path.join(self.config.renewal_configs_dir, "IGNORE.THIS"), "w") - junk.write("This file should be ignored!") - junk.close() + with open(os.path.join(self.config.renewal_configs_dir, "IGNORE.THIS"), "w") as junk: + junk.write("This file should be ignored!") def _set_up_config(self, domain, custom_archive): # TODO: maybe provide NamespaceConfig.make_dirs? diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index eccffa47a..60131d853 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -49,6 +49,7 @@ class InputWithTimeoutTest(unittest.TestCase): stdin.listen(1) with mock.patch("certbot.display.util.sys.stdin", stdin): self.assertRaises(errors.Error, self._call, timeout=0.001) + stdin.close() class FileOutputDisplayTest(unittest.TestCase): diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index 6588bf5ca..b82cc6ca1 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -86,6 +86,7 @@ class PostArgParseSetupTest(test_util.ConfigTestCase): self.memory_handler.close() self.stream_handler.close() self.temp_handler.close() + self.devnull.close() super(PostArgParseSetupTest, self).tearDown() def test_common(self): diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 912cd7984..484ad7e16 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -73,9 +73,8 @@ class BaseRenewableCertTest(test_util.ConfigTestCase): # We also create a file that isn't a renewal config in the same # location to test that logic that reads in all-and-only renewal # configs will ignore it and NOT attempt to parse it. - junk = open(os.path.join(self.config.config_dir, "renewal", "IGNORE.THIS"), "w") - junk.write("This file should be ignored!") - junk.close() + with open(os.path.join(self.config.config_dir, "renewal", "IGNORE.THIS"), "w") as junk: + junk.write("This file should be ignored!") self.defaults = configobj.ConfigObj() diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index 45cc55249..6685b88c6 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -210,16 +210,21 @@ class UniqueFileTest(test_util.TempDirTestCase): fd, name = self._call() fd.write("bar") fd.close() - self.assertEqual(open(name).read(), "bar") + with open(name) as f: + self.assertEqual(f.read(), "bar") def test_right_mode(self): - self.assertTrue(compat.compare_file_modes(0o700, os.stat(self._call(0o700)[1]).st_mode)) - self.assertTrue(compat.compare_file_modes(0o600, os.stat(self._call(0o600)[1]).st_mode)) + fd1, name1 = self._call(0o700) + fd2, name2 = self._call(0o600) + self.assertTrue(compat.compare_file_modes(0o700, os.stat(name1).st_mode)) + self.assertTrue(compat.compare_file_modes(0o600, os.stat(name2).st_mode)) + fd1.close() + fd2.close() def test_default_exists(self): - name1 = self._call()[1] # create 0000_foo.txt - name2 = self._call()[1] - name3 = self._call()[1] + fd1, name1 = self._call() # create 0000_foo.txt + fd2, name2 = self._call() + fd3, name3 = self._call() self.assertNotEqual(name1, name2) self.assertNotEqual(name1, name3) @@ -236,6 +241,10 @@ class UniqueFileTest(test_util.TempDirTestCase): basename3 = os.path.basename(name3) self.assertTrue(basename3.endswith("foo.txt")) + fd1.close() + fd2.close() + fd3.close() + try: file_type = file @@ -255,13 +264,18 @@ class UniqueLineageNameTest(test_util.TempDirTestCase): f, path = self._call("wow") self.assertTrue(isinstance(f, file_type)) self.assertEqual(os.path.join(self.tempdir, "wow.conf"), path) + f.close() def test_multiple(self): + items = [] for _ in six.moves.range(10): - f, name = self._call("wow") + items.append(self._call("wow")) + f, name = items[-1] self.assertTrue(isinstance(f, file_type)) self.assertTrue(isinstance(name, six.string_types)) self.assertTrue("wow-0009.conf" in name) + for f, _ in items: + f.close() @mock.patch("certbot.util.os.fdopen") def test_failure(self, mock_fdopen): From 6e7d42f2980586028bec94373c2b4614027c4cc7 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 1 Nov 2018 17:17:19 -0700 Subject: [PATCH 016/114] ignore ResourceWarnings in acme tests --- acme/acme/crypto_util_test.py | 4 ++++ acme/acme/messages_test.py | 2 ++ acme/acme/standalone_test.py | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/acme/acme/crypto_util_test.py b/acme/acme/crypto_util_test.py index 44b245bbe..ea39fd0fa 100644 --- a/acme/acme/crypto_util_test.py +++ b/acme/acme/crypto_util_test.py @@ -10,11 +10,15 @@ from six.moves import socketserver #type: ignore # pylint: disable=import-erro import josepy as jose import OpenSSL +import pytest from acme import errors from acme import test_util from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module +# turns all warnings into errors for this module +pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + class SSLSocketAndProbeSNITest(unittest.TestCase): """Tests for acme.crypto_util.SSLSocket/probe_sni.""" diff --git a/acme/acme/messages_test.py b/acme/acme/messages_test.py index 876fbe825..4518da9b9 100644 --- a/acme/acme/messages_test.py +++ b/acme/acme/messages_test.py @@ -3,6 +3,7 @@ import unittest import josepy as jose import mock +import pytest from acme import challenges from acme import test_util @@ -166,6 +167,7 @@ class DirectoryTest(unittest.TestCase): from acme.messages import Directory Directory.from_json({'foo': 'bar'}) + @pytest.mark.filterwarnings("ignore::ResourceWarning") def test_iter_meta(self): result = False for k in self.dir.meta: diff --git a/acme/acme/standalone_test.py b/acme/acme/standalone_test.py index ee527782a..fa0426563 100644 --- a/acme/acme/standalone_test.py +++ b/acme/acme/standalone_test.py @@ -12,6 +12,7 @@ from six.moves import socketserver # type: ignore # pylint: disable=import-err import josepy as jose import mock +import pytest import requests from acme import challenges @@ -19,6 +20,9 @@ from acme import crypto_util from acme import test_util from acme.magic_typing import Set # pylint: disable=unused-import, no-name-in-module +# turns all warnings into errors for this module +pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + class TLSServerTest(unittest.TestCase): """Tests for acme.standalone.TLSServer.""" From de1554f78517589357de35ae936ac2b24e11591f Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 1 Nov 2018 17:28:40 -0700 Subject: [PATCH 017/114] Ignore more warnings. These are the ones I'm less sure about --- certbot/tests/log_test.py | 3 +++ certbot/tests/main_test.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index b82cc6ca1..db453f88f 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -7,6 +7,7 @@ import time import unittest import mock +import pytest import six from acme import messages @@ -89,6 +90,7 @@ class PostArgParseSetupTest(test_util.ConfigTestCase): self.devnull.close() super(PostArgParseSetupTest, self).tearDown() + @pytest.mark.filterwarnings("ignore::ResourceWarning") def test_common(self): with mock.patch('certbot.log.logging.getLogger') as mock_get_logger: mock_get_logger.return_value = self.root_logger @@ -267,6 +269,7 @@ class TempHandlerTest(unittest.TestCase): self.handler.close() self.assertFalse(os.path.exists(self.handler.path)) + @pytest.mark.filterwarnings("ignore::ResourceWarning") def test_no_delete(self): self.handler.emit(mock.MagicMock()) self.handler.close() diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index f42319c4f..25613b3b9 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -16,6 +16,7 @@ import tempfile import sys import josepy as jose +import pytest import six from six.moves import reload_module # pylint: disable=import-error @@ -1359,6 +1360,7 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met self.assertTrue(mocked_run.called) @test_util.broken_on_windows + @pytest.mark.filterwarnings("ignore::ResourceWarning") def test_register(self): with mock.patch('certbot.main.client') as mocked_client: acc = mock.MagicMock() From a5e26ca89008afebdc255873b81212c38f819499 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 1 Nov 2018 17:32:59 -0700 Subject: [PATCH 018/114] Ignore all ResourceWarnings in main_test.py, since they're flaky --- certbot/tests/main_test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 25613b3b9..3aabb8d32 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -48,6 +48,9 @@ JWK = jose.JWKRSA.load(test_util.load_vector('rsa512_key.pem')) RSA2048_KEY_PATH = test_util.vector_path('rsa2048_key.pem') SS_CERT_PATH = test_util.vector_path('cert_2048.pem') +# turns all warnings into errors for this module +pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + class TestHandleIdenticalCerts(unittest.TestCase): """Test for certbot.main._handle_identical_cert_request""" @@ -1360,7 +1363,6 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met self.assertTrue(mocked_run.called) @test_util.broken_on_windows - @pytest.mark.filterwarnings("ignore::ResourceWarning") def test_register(self): with mock.patch('certbot.main.client') as mocked_client: acc = mock.MagicMock() From c699a50983ef9422a4723709d9aa1b428e162656 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 1 Nov 2018 17:35:12 -0700 Subject: [PATCH 019/114] Ignore all ResourceWarnings in log_test.py --- certbot/tests/log_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index db453f88f..87b12246e 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -19,6 +19,9 @@ from certbot import errors from certbot import util from certbot.tests import util as test_util +# turns all warnings into errors for this module +pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + class PreArgParseSetupTest(unittest.TestCase): """Tests for certbot.log.pre_arg_parse_setup.""" @@ -90,7 +93,6 @@ class PostArgParseSetupTest(test_util.ConfigTestCase): self.devnull.close() super(PostArgParseSetupTest, self).tearDown() - @pytest.mark.filterwarnings("ignore::ResourceWarning") def test_common(self): with mock.patch('certbot.log.logging.getLogger') as mock_get_logger: mock_get_logger.return_value = self.root_logger @@ -269,7 +271,6 @@ class TempHandlerTest(unittest.TestCase): self.handler.close() self.assertFalse(os.path.exists(self.handler.path)) - @pytest.mark.filterwarnings("ignore::ResourceWarning") def test_no_delete(self): self.handler.emit(mock.MagicMock()) self.handler.close() From 36b6328acded5b1e5340524f652d7c8c90428024 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 1 Nov 2018 17:56:01 -0700 Subject: [PATCH 020/114] Ignore ResourceWarnings in various modules in a 2-compatible way. Sometimes tests are flaky about giving this warning, particularly in ACME. I recommend just ignoring them. --- acme/acme/crypto_util_test.py | 5 +++-- acme/acme/messages_test.py | 6 +++++- acme/acme/standalone_test.py | 6 ++++-- acme/acme/util_test.py | 7 +++++++ .../certbot_dns_rfc2136/dns_rfc2136_test.py | 7 ++++++- certbot/tests/log_test.py | 5 +++-- certbot/tests/main_test.py | 5 +++-- 7 files changed, 31 insertions(+), 10 deletions(-) diff --git a/acme/acme/crypto_util_test.py b/acme/acme/crypto_util_test.py index ea39fd0fa..58cb1cd69 100644 --- a/acme/acme/crypto_util_test.py +++ b/acme/acme/crypto_util_test.py @@ -16,8 +16,9 @@ from acme import errors from acme import test_util from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module -# turns all warnings into errors for this module -pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") +# turns all ResourceWarnings into errors for this module +if six.PY3: + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") class SSLSocketAndProbeSNITest(unittest.TestCase): diff --git a/acme/acme/messages_test.py b/acme/acme/messages_test.py index 4518da9b9..7124f8bd1 100644 --- a/acme/acme/messages_test.py +++ b/acme/acme/messages_test.py @@ -4,6 +4,7 @@ import unittest import josepy as jose import mock import pytest +import six from acme import challenges from acme import test_util @@ -14,6 +15,10 @@ CERT = test_util.load_comparable_cert('cert.der') CSR = test_util.load_comparable_csr('csr.der') KEY = test_util.load_rsa_private_key('rsa512_key.pem') +# turns all ResourceWarnings into errors for this module +if six.PY3: + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + class ErrorTest(unittest.TestCase): """Tests for acme.messages.Error.""" @@ -167,7 +172,6 @@ class DirectoryTest(unittest.TestCase): from acme.messages import Directory Directory.from_json({'foo': 'bar'}) - @pytest.mark.filterwarnings("ignore::ResourceWarning") def test_iter_meta(self): result = False for k in self.dir.meta: diff --git a/acme/acme/standalone_test.py b/acme/acme/standalone_test.py index fa0426563..4e93157d0 100644 --- a/acme/acme/standalone_test.py +++ b/acme/acme/standalone_test.py @@ -6,6 +6,7 @@ import threading import tempfile import unittest +import six from six.moves import http_client # pylint: disable=import-error from six.moves import queue # pylint: disable=import-error from six.moves import socketserver # type: ignore # pylint: disable=import-error @@ -20,8 +21,9 @@ from acme import crypto_util from acme import test_util from acme.magic_typing import Set # pylint: disable=unused-import, no-name-in-module -# turns all warnings into errors for this module -pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") +# turns all ResourceWarnings into errors for this module +if six.PY3: + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") class TLSServerTest(unittest.TestCase): diff --git a/acme/acme/util_test.py b/acme/acme/util_test.py index 00aa8b02d..7bb308635 100644 --- a/acme/acme/util_test.py +++ b/acme/acme/util_test.py @@ -1,6 +1,13 @@ """Tests for acme.util.""" import unittest +import pytest +import six + +# turns all ResourceWarnings into errors for this module +if six.PY3: + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + class MapKeysTest(unittest.TestCase): """Tests for acme.util.map_keys.""" diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py index 9d3a0fbfd..4af8ab9ef 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py @@ -8,6 +8,7 @@ import dns.rcode import dns.tsig import mock import pytest +import six from certbot import errors from certbot.plugins import dns_test_common @@ -20,6 +21,10 @@ NAME = 'a-tsig-key.' SECRET = 'SSB3b25kZXIgd2hvIHdpbGwgYm90aGVyIHRvIGRlY29kZSB0aGlzIHRleHQK' VALID_CONFIG = {"rfc2136_server": SERVER, "rfc2136_name": NAME, "rfc2136_secret": SECRET} +# turns all ResourceWarnings into errors for this module +if six.PY3: + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthenticatorTest): @@ -71,7 +76,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.perform([self.achall]) -@pytest.mark.filterwarnings("ignore::ResourceWarning", "ignore:decodestring:DeprecationWarning") +@pytest.mark.filterwarnings("ignore:decodestring:DeprecationWarning") class RFC2136ClientTest(unittest.TestCase): def setUp(self): diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index 87b12246e..f722f2c97 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -19,8 +19,9 @@ from certbot import errors from certbot import util from certbot.tests import util as test_util -# turns all warnings into errors for this module -pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") +# turns all ResourceWarnings into errors for this module +if six.PY3: + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") class PreArgParseSetupTest(unittest.TestCase): diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 3aabb8d32..bf0e6b1ca 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -48,8 +48,9 @@ JWK = jose.JWKRSA.load(test_util.load_vector('rsa512_key.pem')) RSA2048_KEY_PATH = test_util.vector_path('rsa2048_key.pem') SS_CERT_PATH = test_util.vector_path('cert_2048.pem') -# turns all warnings into errors for this module -pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") +# turns all ResourceWarnings into errors for this module +if six.PY3: + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") class TestHandleIdenticalCerts(unittest.TestCase): From 28c117abe0b332cec0eb4d67c14a0091745e9d1f Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 12:31:55 -0700 Subject: [PATCH 021/114] If ResourceWarning is specified in pytest.ini, tests fail on Python3. We should be catching all of them, and they usually fail to successfully error anyway, so this just means we get sligthly worse error messages when they do occur. --- pytest.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index 7d0b19223..c35e0de7c 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,4 +3,3 @@ addopts = --numprocesses auto --pyargs # ResourceWarnings are ignored as errors, since they're raised at close filterwarnings = error - always::ResourceWarning From d02ea812a596cb96c7c44b42102f32c5d9beb7b1 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 12:36:42 -0700 Subject: [PATCH 022/114] Cover is run on 2.7, so mark 3-only lines as no cover --- acme/acme/crypto_util_test.py | 2 +- acme/acme/messages_test.py | 2 +- acme/acme/standalone_test.py | 2 +- acme/acme/util_test.py | 2 +- certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py | 2 +- certbot/tests/log_test.py | 2 +- certbot/tests/main_test.py | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/acme/acme/crypto_util_test.py b/acme/acme/crypto_util_test.py index 58cb1cd69..05d9f419e 100644 --- a/acme/acme/crypto_util_test.py +++ b/acme/acme/crypto_util_test.py @@ -18,7 +18,7 @@ from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-m # turns all ResourceWarnings into errors for this module if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover class SSLSocketAndProbeSNITest(unittest.TestCase): diff --git a/acme/acme/messages_test.py b/acme/acme/messages_test.py index 7124f8bd1..5b257836a 100644 --- a/acme/acme/messages_test.py +++ b/acme/acme/messages_test.py @@ -17,7 +17,7 @@ KEY = test_util.load_rsa_private_key('rsa512_key.pem') # turns all ResourceWarnings into errors for this module if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover class ErrorTest(unittest.TestCase): diff --git a/acme/acme/standalone_test.py b/acme/acme/standalone_test.py index 4e93157d0..7224515d4 100644 --- a/acme/acme/standalone_test.py +++ b/acme/acme/standalone_test.py @@ -23,7 +23,7 @@ from acme.magic_typing import Set # pylint: disable=unused-import, no-name-in-mo # turns all ResourceWarnings into errors for this module if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover class TLSServerTest(unittest.TestCase): diff --git a/acme/acme/util_test.py b/acme/acme/util_test.py index 7bb308635..58e8aeb83 100644 --- a/acme/acme/util_test.py +++ b/acme/acme/util_test.py @@ -6,7 +6,7 @@ import six # turns all ResourceWarnings into errors for this module if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover class MapKeysTest(unittest.TestCase): diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py index 4af8ab9ef..3e8c1e6ee 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py @@ -23,7 +23,7 @@ VALID_CONFIG = {"rfc2136_server": SERVER, "rfc2136_name": NAME, "rfc2136_secret" # turns all ResourceWarnings into errors for this module if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthenticatorTest): diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index f722f2c97..35cd6b388 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -21,7 +21,7 @@ from certbot.tests import util as test_util # turns all ResourceWarnings into errors for this module if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover class PreArgParseSetupTest(unittest.TestCase): diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index bf0e6b1ca..90de986bb 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -50,7 +50,7 @@ SS_CERT_PATH = test_util.vector_path('cert_2048.pem') # turns all ResourceWarnings into errors for this module if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") + pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover class TestHandleIdenticalCerts(unittest.TestCase): From e37a8fbded9e21512dd8fda4200db4faee50f1b5 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 13:01:14 -0700 Subject: [PATCH 023/114] Use a newer version of requests because of the upcoming Callable import Deprecation in Python 3.8 that warns in Python 3.7 --- acme/setup.py | 2 +- letsencrypt-auto-source/pieces/dependency-requirements.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 85492d9a3..75f889648 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -17,7 +17,7 @@ install_requires = [ 'PyOpenSSL>=0.13', 'pyrfc3339', 'pytz', - 'requests[security]>=2.4.1', # security extras added in 2.4.1 + 'requests[security]>=2.20.0', # DeprecationWarning on Callable in Python3.7 'requests-toolbelt>=0.3.0', 'setuptools', 'six>=1.9.0', # needed for python_2_unicode_compatible diff --git a/letsencrypt-auto-source/pieces/dependency-requirements.txt b/letsencrypt-auto-source/pieces/dependency-requirements.txt index ae6079d96..f4a6f30d1 100644 --- a/letsencrypt-auto-source/pieces/dependency-requirements.txt +++ b/letsencrypt-auto-source/pieces/dependency-requirements.txt @@ -150,9 +150,9 @@ pytz==2015.7 \ --hash=sha256:fbd26746772c24cb93c8b97cbdad5cb9e46c86bbdb1b9d8a743ee00e2fb1fc5d \ --hash=sha256:99266ef30a37e43932deec2b7ca73e83c8dbc3b9ff703ec73eca6b1dae6befea \ --hash=sha256:8b6ce1c993909783bc96e0b4f34ea223bff7a4df2c90bdb9c4e0f1ac928689e3 -requests==2.12.1 \ - --hash=sha256:3f3f27a9d0f9092935efc78054ef324eb9f8166718270aefe036dfa1e4f68e1e \ - --hash=sha256:2109ecea94df90980be040490ff1d879971b024861539abb00054062388b612e +requests==2.20.0 \ + --hash=sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c \ + --hash=sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279 six==1.10.0 \ --hash=sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1 \ --hash=sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a From a83afb61350fd5109e4b501bdde5ea71ec29b084 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 13:31:04 -0700 Subject: [PATCH 024/114] properly disable no-member --- certbot/tests/display/util_test.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index 60131d853..726eb0b0f 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -316,9 +316,9 @@ class FileOutputDisplayTest(unittest.TestCase): # force_interactive to prevent workflow regressions. for name in interfaces.IDisplay.names(): # pylint: disable=no-member if six.PY2: - getargspec = inspect.getargspec + getargspec = inspect.getargspec # pylint: disable=no-member else: - getargspec = inspect.getfullargspec + getargspec = inspect.getfullargspec # pylint: disable=no-member arg_spec = getargspec(getattr(self.displayer, name)) self.assertTrue("force_interactive" in arg_spec.args) @@ -377,9 +377,11 @@ class NoninteractiveDisplayTest(unittest.TestCase): method = getattr(self.displayer, name) # asserts method accepts arbitrary keyword arguments if six.PY2: - self.assertFalse(inspect.getargspec(method).keywords is None) + result = inspect.getargspec(method).keywords # pylint: disable=no-member + self.assertFalse(result is None) else: - self.assertFalse(inspect.getfullargspec(method).varkw is None) + result = inspect.getfullargspec(method).varkw # pylint: disable=no-member + self.assertFalse(result is None) class SeparateListInputTest(unittest.TestCase): From 1b595f26d867e6ee292f319ff93a2d8bf8ce3f0f Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 13:31:48 -0700 Subject: [PATCH 025/114] Requests no longer vendorizes urllib3 --- acme/acme/client.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index bd86657b9..7a8a15219 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -32,11 +32,8 @@ logger = logging.getLogger(__name__) # for SSL, which does allow these options to be configured. # https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning if sys.version_info < (2, 7, 9): # pragma: no cover - try: - requests.packages.urllib3.contrib.pyopenssl.inject_into_urllib3() # type: ignore - except AttributeError: - import urllib3.contrib.pyopenssl # pylint: disable=import-error - urllib3.contrib.pyopenssl.inject_into_urllib3() + import urllib3.contrib.pyopenssl # pylint: disable=import-error + urllib3.contrib.pyopenssl.inject_into_urllib3() DEFAULT_NETWORK_TIMEOUT = 45 From 64a61fa6d4b7ea0bb5bc7b6e59fb02d748a2614a Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 14:53:55 -0700 Subject: [PATCH 026/114] Use a newer version of botocore that doesn't vendor requests, which we need because newer versions of requests don't have the DeprecationWarning --- tools/dev_constraints.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/dev_constraints.txt b/tools/dev_constraints.txt index 00ecee03e..6fb8ed0d9 100644 --- a/tools/dev_constraints.txt +++ b/tools/dev_constraints.txt @@ -7,8 +7,8 @@ astroid==1.3.5 attrs==17.3.0 Babel==2.5.1 backports.shutil-get-terminal-size==1.0.0 -boto3==1.4.7 -botocore==1.7.41 +boto3==1.9.36 +botocore==1.12.36 cloudflare==1.5.1 coverage==4.4.2 decorator==4.1.2 From 1228f5da9995ef47f58ddd1c4d09f5dfad4a411e Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 14:59:29 -0700 Subject: [PATCH 027/114] update letsencrypt-auto --- letsencrypt-auto-source/letsencrypt-auto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 740cb9c73..2e45a32f7 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -1146,9 +1146,9 @@ pytz==2015.7 \ --hash=sha256:fbd26746772c24cb93c8b97cbdad5cb9e46c86bbdb1b9d8a743ee00e2fb1fc5d \ --hash=sha256:99266ef30a37e43932deec2b7ca73e83c8dbc3b9ff703ec73eca6b1dae6befea \ --hash=sha256:8b6ce1c993909783bc96e0b4f34ea223bff7a4df2c90bdb9c4e0f1ac928689e3 -requests==2.12.1 \ - --hash=sha256:3f3f27a9d0f9092935efc78054ef324eb9f8166718270aefe036dfa1e4f68e1e \ - --hash=sha256:2109ecea94df90980be040490ff1d879971b024861539abb00054062388b612e +requests==2.20.0 \ + --hash=sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c \ + --hash=sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279 six==1.10.0 \ --hash=sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1 \ --hash=sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a From ac8d6f58bb655d78fa819be98c2c3d3dea06459b Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 15:30:42 -0700 Subject: [PATCH 028/114] Update requests version in oldest-constraints.txt --- tools/oldest_constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/oldest_constraints.txt b/tools/oldest_constraints.txt index de2b83ad8..6722d7f15 100644 --- a/tools/oldest_constraints.txt +++ b/tools/oldest_constraints.txt @@ -43,7 +43,7 @@ oauth2client==2.0 parsedatetime==1.3 pyparsing==1.5.5 python-digitalocean==1.11 -requests[security]==2.4.1 +requests[security]==2.20.0 # Ubuntu Xenial constraints ConfigArgParse==0.10.0 From 0caaf872fbc72f099e254f0da2cace129b7288af Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 15:53:44 -0700 Subject: [PATCH 029/114] bring requests back down to 2.4.1 in setup and oldest constraints --- acme/setup.py | 2 +- tools/oldest_constraints.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 75f889648..85492d9a3 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -17,7 +17,7 @@ install_requires = [ 'PyOpenSSL>=0.13', 'pyrfc3339', 'pytz', - 'requests[security]>=2.20.0', # DeprecationWarning on Callable in Python3.7 + 'requests[security]>=2.4.1', # security extras added in 2.4.1 'requests-toolbelt>=0.3.0', 'setuptools', 'six>=1.9.0', # needed for python_2_unicode_compatible diff --git a/tools/oldest_constraints.txt b/tools/oldest_constraints.txt index 6722d7f15..de2b83ad8 100644 --- a/tools/oldest_constraints.txt +++ b/tools/oldest_constraints.txt @@ -43,7 +43,7 @@ oauth2client==2.0 parsedatetime==1.3 pyparsing==1.5.5 python-digitalocean==1.11 -requests[security]==2.20.0 +requests[security]==2.4.1 # Ubuntu Xenial constraints ConfigArgParse==0.10.0 From c98bf18a770c12e7f393847425eaad4f2158bdb0 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 16:00:32 -0700 Subject: [PATCH 030/114] Use older version of boto in oldest tests, because new versions can't handle old versions of requests --- tools/oldest_constraints.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/oldest_constraints.txt b/tools/oldest_constraints.txt index de2b83ad8..8dd96dfea 100644 --- a/tools/oldest_constraints.txt +++ b/tools/oldest_constraints.txt @@ -49,3 +49,7 @@ requests[security]==2.4.1 ConfigArgParse==0.10.0 funcsigs==0.4 zope.hookable==4.0.4 + +# Plugin constraints +boto3==1.4.7 +botocore==1.7.41 From eab7aa7bf158db1d33029b90176141add5f9df75 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Fri, 2 Nov 2018 16:14:10 -0700 Subject: [PATCH 031/114] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f033b3691..fa0fcd334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). * Stop caching the results of ipv6_info in http01.py * Test fix for Route53 plugin to prevent boto3 making outgoing connections. * The grammar used by Augeas parser in Apache plugin was updated to fix various parsing errors. +* Update code and dependencies to clean up Resource and Deprecation Warnings. ## 0.27.1 - 2018-09-06 From 94f0a915c0f0034cfc93965ada76617ae183bd01 Mon Sep 17 00:00:00 2001 From: Georgio Nicolas Date: Sun, 4 Nov 2018 01:23:47 -0400 Subject: [PATCH 032/114] Remove mentioning of TLS-SNI-01 --- docs/challenges.rst | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/docs/challenges.rst b/docs/challenges.rst index 25d190147..034f79956 100644 --- a/docs/challenges.rst +++ b/docs/challenges.rst @@ -5,8 +5,7 @@ To receive a certificate from Let's Encrypt certificate authority (CA), you must prove you control each of the domain names that will be listed in the certificate. A challenge is one of three tasks that only someone who controls the domain should be able to accomplish: -* Posting a specified file in a specified location on a web site (the HTTP-01 challenge) -* Offering a specified temporary certificate on a web site (the TLS-SNI-01 challenge) +* Posting a specified file in a specified location on a web site (the HTTP-01 challenge) * Posting a specified DNS record in the domain name system (the DNS-01 challenge) It’s possible to complete each type of challenge *automatically* (Certbot directly makes the necessary @@ -16,18 +15,12 @@ design favors performing challenges automatically, and this is the normal case f Some plugins offer an *authenticator*, meaning that they can satisfy challenges: -* Apache plugin: (TLS-SNI-01) Tries to edit your Apache configuration files to temporarily serve - a Certbot-generated certificate for a specified name. Use the Apache plugin when you're running - Certbot on a web server with Apache listening on port 443. -* NGINX plugin: (TLS-SNI-01) Tries to edit your NGINX configuration files to temporarily serve a - Certbot-generated certificate for a specified name. Use the NGINX plugin when you're running - Certbot on a web server with NGINX listening on port 443. * Webroot plugin: (HTTP-01) Tries to place a file where it can be served over HTTP on port 80 by a web server running on your system. Use the Webroot plugin when you're running Certbot on a web server with any server application listening on port 80 serving files from a folder on disk in response. -* Standalone plugin: (TLS-SNI-01 or HTTP-01) Tries to run a temporary web server listening on either HTTP on - port 80 (for HTTP-01) or HTTPS on port 443 (for TLS-SNI-01). Use the Standalone plugin if no existing program - is listening to these ports. Choose TLS-SNI-01 or HTTP-01 using the `--preferred-challenges` option. +* Standalone plugin: (HTTP-01) Tries to run a temporary web server listening on HTTP on + port 80 (for HTTP-01). Use the Standalone plugin if no existing program + is listening to these ports. Choose HTTP-01 using the `--preferred-challenges` option. * Manual plugin: (DNS-01 or HTTP-01) Either tells you what changes to make to your configuration or updates your DNS records using an external script (for DNS-01) or your webroot (for HTTP-01). Use the Manual plugin if you have the technical knowledge to make configuration changes yourself when asked to do so. @@ -63,20 +56,6 @@ HTTP-01 Challenge * When using the Standalone plugin, make sure another program is not already listening to port 80 on the server. * When using the Webroot plugin, make sure there is a web server listening on port 80. -TLS-SNI-01 Challenge -~~~~~~~~~~~~~~~~~~~~ - -* The TLS-SNI-01 challenge doesn’t work with content delivery networks (CDNs) - like CloudFlare and Akamai because the domain name is pointed at the CDN, not directly at your server. -* Make sure port 443 is open, publicly reachable from the Internet, and not blocked by a router or firewall. -* When using the Apache plugin, make sure you are running Apache and no other web server on port 443. -* When using the NGINX plugin, make sure you are running NGINX and no other web server on port 443. -* With either the Apache or NGINX plugin, certbot modifies your web server configuration. If you get - an error after successfully completing the challenge, then you have received a certificate but the - plugin was unable to modify your web server configuration, meaning that you'll have to install the certificate manually. - In that case, please file a bug to help us improve certbot! -* When using the Standalone plugin, make sure another program is not already listening to port 443 on the server. - DNS-01 Challenge ~~~~~~~~~~~~~~~~ From 9fa0a58545caad4b23e77e3e969bf66b398a92cc Mon Sep 17 00:00:00 2001 From: Georgio Nicolas Date: Sun, 4 Nov 2018 01:29:38 -0400 Subject: [PATCH 033/114] Remove mention of TLS-SNI-01 --- docs/using.rst | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 1fa13e022..64def5c06 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -44,14 +44,10 @@ a combination_ of distinct authenticator and installer plugins. =========== ==== ==== =============================================================== ============================= Plugin Auth Inst Notes Challenge types (and port) =========== ==== ==== =============================================================== ============================= -apache_ Y Y | Automates obtaining and installing a certificate with Apache tls-sni-01_ (443) - | 2.4 on OSes with ``libaugeas0`` 1.0+. webroot_ Y N | Obtains a certificate by writing to the webroot directory of http-01_ (80) | an already running webserver. -nginx_ Y Y | Automates obtaining and installing a certificate with Nginx. tls-sni-01_ (443) - | Shipped with Certbot 0.9.0. -standalone_ Y N | Uses a "standalone" webserver to obtain a certificate. http-01_ (80) or - | Requires port 80 or 443 to be available. This is useful on tls-sni-01_ (443) +standalone_ Y N | Uses a "standalone" webserver to obtain a certificate. http-01_ (80) + | Requires port 80 to be available. This is useful on | systems with no webserver, or when direct integration with | the local webserver is not supported or not desired. |dns_plugs| Y N | This category of plugins automates obtaining a certificate by dns-01_ (53) @@ -59,9 +55,9 @@ standalone_ Y N | Uses a "standalone" webserver to obtain a certificate. | domain. Doing domain validation in this way is | the only way to obtain wildcard certificates from Let's | Encrypt. -manual_ Y N | Helps you obtain a certificate by giving you instructions to http-01_ (80), - | perform domain validation yourself. Additionally allows you dns-01_ (53) or - | to specify scripts to automate the validation task in a tls-sni-01_ (443) +manual_ Y N | Helps you obtain a certificate by giving you instructions to http-01_ (80) or + | perform domain validation yourself. Additionally allows you dns-01_ (53) + | to specify scripts to automate the validation task in a | customized way. =========== ==== ==== =============================================================== ============================= @@ -69,7 +65,7 @@ manual_ Y N | Helps you obtain a certificate by giving you instruction Under the hood, plugins use one of several ACME protocol challenges_ to prove you control a domain. The options are http-01_ (which uses port 80), -tls-sni-01_ (port 443) and dns-01_ (requiring configuration of a DNS server on +and dns-01_ (requiring configuration of a DNS server on port 53, though that's often not the same machine as your webserver). A few plugins support more than one challenge type, in which case you can choose one with ``--preferred-challenges``. @@ -78,7 +74,6 @@ There are also many third-party-plugins_ available. Below we describe in more de the circumstances in which each plugin can be used, and how to use it. .. _challenges: https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7 -.. _tls-sni-01: https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3 .. _http-01: https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.2 .. _dns-01: https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.4 @@ -159,13 +154,12 @@ software running on the machine where you obtain the certificate. To obtain a certificate 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 +on the command line. This plugin needs to bind to port 80 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. * ``--preferred-challenges http`` to use port 80 - * ``--preferred-challenges tls-sni`` to use port 443 It must still be possible for your machine to accept inbound connections from the Internet on the specified port using each requested domain name. @@ -222,8 +216,7 @@ the UI, you can use the plugin to obtain a certificate by specifying to copy and paste commands into another terminal session, which may be on a different computer. -The manual plugin can use either the ``http``, ``dns`` or the -``tls-sni`` challenge. You can use the ``--preferred-challenges`` option +The manual plugin can use either the ``http`` or the ``dns`` challenge. You can use the ``--preferred-challenges`` option to choose the challenge of your preference. The ``http`` challenge will ask you to place a file with a specific name and @@ -241,11 +234,6 @@ For example, for the domain ``example.com``, a zone file entry would look like: _acme-challenge.example.com. 300 IN TXT "gfj9Xq...Rg85nM" -When using the ``tls-sni`` challenge, ``certbot`` will prepare a self-signed -SSL certificate for you with the challenge validation appropriately -encoded into a subjectAlternatNames entry. You will need to configure -your SSL server to present this challenge SSL certificate to the ACME -server using SNI. Additionally you can specify scripts to prepare for validation and perform the authentication procedure and/or clean up after it by using @@ -265,8 +253,7 @@ installer plugins. To do so, specify the authenticator plugin with For instance, you may want to create a certificate using the webroot_ plugin for authentication and the apache_ plugin for installation, perhaps because you use a proxy or CDN for SSL and only want to secure the connection between them -and your origin server, which cannot use the tls-sni-01_ challenge due to the -intermediate proxy. +and your origin server. :: @@ -775,9 +762,6 @@ variables to these scripts: - ``CERTBOT_DOMAIN``: The domain being authenticated - ``CERTBOT_VALIDATION``: The validation string (HTTP-01 and DNS-01 only) - ``CERTBOT_TOKEN``: Resource name part of the HTTP-01 challenge (HTTP-01 only) -- ``CERTBOT_CERT_PATH``: The challenge SSL certificate (TLS-SNI-01 only) -- ``CERTBOT_KEY_PATH``: The private key associated with the aforementioned SSL certificate (TLS-SNI-01 only) -- ``CERTBOT_SNI_DOMAIN``: The SNI name for which the ACME server expects to be presented the self-signed certificate located at ``$CERTBOT_CERT_PATH`` (TLS-SNI-01 only) Additionally for cleanup: From 79b2ea19fbd5b360eabf6abe56530d45e1f2bcd8 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Mon, 5 Nov 2018 17:19:57 -0800 Subject: [PATCH 034/114] no need for U flag because we won't support py2 on windows --- certbot/crypto_util.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/certbot/crypto_util.py b/certbot/crypto_util.py index 7b558b060..820bcd805 100644 --- a/certbot/crypto_util.py +++ b/certbot/crypto_util.py @@ -458,12 +458,8 @@ def sha256sum(filename): :rtype: str """ sha256 = hashlib.sha256() - if six.PY2: - with open(filename, 'rU') as file_d: - sha256.update(file_d.read().encode('UTF-8')) - else: - with open(filename, 'r', newline=None) as file_d: - sha256.update(file_d.read().encode('UTF-8')) + with open(filename, 'r', newline=None) as file_d: + sha256.update(file_d.read().encode('UTF-8')) return sha256.hexdigest() def cert_and_chain_from_fullchain(fullchain_pem): From b7f4b33ffbe8afb5084d95758b122861e3626d50 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Mon, 5 Nov 2018 17:28:26 -0800 Subject: [PATCH 035/114] Remove module-level ignore::ResourceWarnings --- acme/acme/crypto_util_test.py | 5 ----- acme/acme/messages_test.py | 5 ----- acme/acme/standalone_test.py | 5 ----- acme/acme/util_test.py | 5 ----- certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py | 5 ----- certbot/tests/log_test.py | 5 ----- certbot/tests/main_test.py | 5 ----- 7 files changed, 35 deletions(-) diff --git a/acme/acme/crypto_util_test.py b/acme/acme/crypto_util_test.py index 05d9f419e..44b245bbe 100644 --- a/acme/acme/crypto_util_test.py +++ b/acme/acme/crypto_util_test.py @@ -10,16 +10,11 @@ from six.moves import socketserver #type: ignore # pylint: disable=import-erro import josepy as jose import OpenSSL -import pytest from acme import errors from acme import test_util from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module -# turns all ResourceWarnings into errors for this module -if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover - class SSLSocketAndProbeSNITest(unittest.TestCase): """Tests for acme.crypto_util.SSLSocket/probe_sni.""" diff --git a/acme/acme/messages_test.py b/acme/acme/messages_test.py index 5b257836a..1daf0299b 100644 --- a/acme/acme/messages_test.py +++ b/acme/acme/messages_test.py @@ -3,7 +3,6 @@ import unittest import josepy as jose import mock -import pytest import six from acme import challenges @@ -15,10 +14,6 @@ CERT = test_util.load_comparable_cert('cert.der') CSR = test_util.load_comparable_csr('csr.der') KEY = test_util.load_rsa_private_key('rsa512_key.pem') -# turns all ResourceWarnings into errors for this module -if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover - class ErrorTest(unittest.TestCase): """Tests for acme.messages.Error.""" diff --git a/acme/acme/standalone_test.py b/acme/acme/standalone_test.py index 7224515d4..799376cb6 100644 --- a/acme/acme/standalone_test.py +++ b/acme/acme/standalone_test.py @@ -13,7 +13,6 @@ from six.moves import socketserver # type: ignore # pylint: disable=import-err import josepy as jose import mock -import pytest import requests from acme import challenges @@ -21,10 +20,6 @@ from acme import crypto_util from acme import test_util from acme.magic_typing import Set # pylint: disable=unused-import, no-name-in-module -# turns all ResourceWarnings into errors for this module -if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover - class TLSServerTest(unittest.TestCase): """Tests for acme.standalone.TLSServer.""" diff --git a/acme/acme/util_test.py b/acme/acme/util_test.py index 58e8aeb83..101936091 100644 --- a/acme/acme/util_test.py +++ b/acme/acme/util_test.py @@ -1,13 +1,8 @@ """Tests for acme.util.""" import unittest -import pytest import six -# turns all ResourceWarnings into errors for this module -if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover - class MapKeysTest(unittest.TestCase): """Tests for acme.util.map_keys.""" diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py index 3e8c1e6ee..ce500c0cb 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py @@ -7,7 +7,6 @@ import dns.flags import dns.rcode import dns.tsig import mock -import pytest import six from certbot import errors @@ -21,10 +20,6 @@ NAME = 'a-tsig-key.' SECRET = 'SSB3b25kZXIgd2hvIHdpbGwgYm90aGVyIHRvIGRlY29kZSB0aGlzIHRleHQK' VALID_CONFIG = {"rfc2136_server": SERVER, "rfc2136_name": NAME, "rfc2136_secret": SECRET} -# turns all ResourceWarnings into errors for this module -if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover - class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthenticatorTest): diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index 35cd6b388..b82cc6ca1 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -7,7 +7,6 @@ import time import unittest import mock -import pytest import six from acme import messages @@ -19,10 +18,6 @@ from certbot import errors from certbot import util from certbot.tests import util as test_util -# turns all ResourceWarnings into errors for this module -if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover - class PreArgParseSetupTest(unittest.TestCase): """Tests for certbot.log.pre_arg_parse_setup.""" diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 90de986bb..f42319c4f 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -16,7 +16,6 @@ import tempfile import sys import josepy as jose -import pytest import six from six.moves import reload_module # pylint: disable=import-error @@ -48,10 +47,6 @@ JWK = jose.JWKRSA.load(test_util.load_vector('rsa512_key.pem')) RSA2048_KEY_PATH = test_util.vector_path('rsa2048_key.pem') SS_CERT_PATH = test_util.vector_path('cert_2048.pem') -# turns all ResourceWarnings into errors for this module -if six.PY3: - pytestmark = pytest.mark.filterwarnings("ignore::ResourceWarning") # pragma: no cover - class TestHandleIdenticalCerts(unittest.TestCase): """Test for certbot.main._handle_identical_cert_request""" From 6c8652a0a68df61a59cc7edf2f813c69ed68df29 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Mon, 5 Nov 2018 17:30:26 -0800 Subject: [PATCH 036/114] add comment explaining about boto* in oldest_constraints.txt --- tools/oldest_constraints.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/oldest_constraints.txt b/tools/oldest_constraints.txt index 8dd96dfea..80fce8b33 100644 --- a/tools/oldest_constraints.txt +++ b/tools/oldest_constraints.txt @@ -51,5 +51,7 @@ funcsigs==0.4 zope.hookable==4.0.4 # Plugin constraints +# These aren't necessarily the oldest versions we need to support +# Tracking at https://github.com/certbot/certbot/issues/6473 boto3==1.4.7 botocore==1.7.41 From 5dc9dd8deaa330c34a48805eacb14d654205c81f Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Mon, 5 Nov 2018 17:34:33 -0800 Subject: [PATCH 037/114] Pin requests' dependencies in certbot-auto --- letsencrypt-auto-source/letsencrypt-auto | 9 +++++++++ .../pieces/dependency-requirements.txt | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 2e45a32f7..25c293898 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -1185,6 +1185,15 @@ zope.interface==4.1.3 \ requests-toolbelt==0.8.0 \ --hash=sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237 \ --hash=sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5 +chardet==3.0.2 \ + --hash=sha256:4f7832e7c583348a9eddd927ee8514b3bf717c061f57b21dbe7697211454d9bb \ + --hash=sha256:6ebf56457934fdce01fb5ada5582762a84eed94cad43ed877964aebbdd8174c0 +urllib3==1.21.1 \ + --hash=sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1 \ + --hash=sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5 +certifi==2017.4.17 \ + --hash=sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010 \ + --hash=sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a # Contains the requirements for the letsencrypt package. # diff --git a/letsencrypt-auto-source/pieces/dependency-requirements.txt b/letsencrypt-auto-source/pieces/dependency-requirements.txt index f4a6f30d1..78f430210 100644 --- a/letsencrypt-auto-source/pieces/dependency-requirements.txt +++ b/letsencrypt-auto-source/pieces/dependency-requirements.txt @@ -189,3 +189,12 @@ zope.interface==4.1.3 \ requests-toolbelt==0.8.0 \ --hash=sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237 \ --hash=sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5 +chardet==3.0.2 \ + --hash=sha256:4f7832e7c583348a9eddd927ee8514b3bf717c061f57b21dbe7697211454d9bb \ + --hash=sha256:6ebf56457934fdce01fb5ada5582762a84eed94cad43ed877964aebbdd8174c0 +urllib3==1.21.1 \ + --hash=sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1 \ + --hash=sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5 +certifi==2017.4.17 \ + --hash=sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010 \ + --hash=sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a From c3fa05ba7416319fbc8c00b3bb8fb5d08c48322c Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Mon, 5 Nov 2018 17:38:29 -0800 Subject: [PATCH 038/114] remove unused six imports --- acme/acme/messages_test.py | 1 - acme/acme/standalone_test.py | 1 - acme/acme/util_test.py | 2 -- certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py | 1 - 4 files changed, 5 deletions(-) diff --git a/acme/acme/messages_test.py b/acme/acme/messages_test.py index 1daf0299b..876fbe825 100644 --- a/acme/acme/messages_test.py +++ b/acme/acme/messages_test.py @@ -3,7 +3,6 @@ import unittest import josepy as jose import mock -import six from acme import challenges from acme import test_util diff --git a/acme/acme/standalone_test.py b/acme/acme/standalone_test.py index 799376cb6..ee527782a 100644 --- a/acme/acme/standalone_test.py +++ b/acme/acme/standalone_test.py @@ -6,7 +6,6 @@ import threading import tempfile import unittest -import six from six.moves import http_client # pylint: disable=import-error from six.moves import queue # pylint: disable=import-error from six.moves import socketserver # type: ignore # pylint: disable=import-error diff --git a/acme/acme/util_test.py b/acme/acme/util_test.py index 101936091..00aa8b02d 100644 --- a/acme/acme/util_test.py +++ b/acme/acme/util_test.py @@ -1,8 +1,6 @@ """Tests for acme.util.""" import unittest -import six - class MapKeysTest(unittest.TestCase): """Tests for acme.util.map_keys.""" diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py index ce500c0cb..7cb98b25e 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py @@ -7,7 +7,6 @@ import dns.flags import dns.rcode import dns.tsig import mock -import six from certbot import errors from certbot.plugins import dns_test_common From 91b3c5d61cbdfd7853bd14d509370e28f0f1ee15 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Mon, 5 Nov 2018 17:41:26 -0800 Subject: [PATCH 039/114] remove pytest.mark, move to specific ignore in pytest.ini --- certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py | 1 - pytest.ini | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py index 7cb98b25e..89ce3d93e 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/dns_rfc2136_test.py @@ -70,7 +70,6 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.perform([self.achall]) -@pytest.mark.filterwarnings("ignore:decodestring:DeprecationWarning") class RFC2136ClientTest(unittest.TestCase): def setUp(self): diff --git a/pytest.ini b/pytest.ini index c35e0de7c..a55d72301 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,5 +1,7 @@ [pytest] addopts = --numprocesses auto --pyargs # ResourceWarnings are ignored as errors, since they're raised at close +# decodestring: https://github.com/rthalley/dnspython/issues/338 filterwarnings = error + ignore:decodestring:DeprecationWarning From 39a008eb834b6eecaf6314ab1a1e2c299f7c9c09 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Mon, 5 Nov 2018 17:42:19 -0800 Subject: [PATCH 040/114] ignore our own TLS-SNI-01 warning --- pytest.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytest.ini b/pytest.ini index a55d72301..de1ecf267 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,6 +2,8 @@ addopts = --numprocesses auto --pyargs # ResourceWarnings are ignored as errors, since they're raised at close # decodestring: https://github.com/rthalley/dnspython/issues/338 +# ignore our own TLS-SNI-01 warning filterwarnings = error ignore:decodestring:DeprecationWarning + ignore:TLS-SNI-01:DeprecationWarning \ No newline at end of file From 92989956f91878bc58e3bd5eec5a8496400135b2 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Mon, 5 Nov 2018 17:47:38 -0800 Subject: [PATCH 041/114] no newline in py27 --- certbot/crypto_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/crypto_util.py b/certbot/crypto_util.py index 820bcd805..c4a389cd5 100644 --- a/certbot/crypto_util.py +++ b/certbot/crypto_util.py @@ -458,7 +458,7 @@ def sha256sum(filename): :rtype: str """ sha256 = hashlib.sha256() - with open(filename, 'r', newline=None) as file_d: + with open(filename, 'r') as file_d: sha256.update(file_d.read().encode('UTF-8')) return sha256.hexdigest() From ee6f20d93d8d24662cab2c41d74ccf8f049d08f3 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 8 Nov 2018 15:39:24 -0800 Subject: [PATCH 042/114] Clarify letsencrypt-auto to certbot-auto message --- certbot/cli.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/certbot/cli.py b/certbot/cli.py index 99bf33180..2e9880505 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -172,10 +172,11 @@ def possible_deprecation_warning(config): # need warnings return if "CERTBOT_AUTO" not in os.environ: - logger.warning("You are running with an old copy of letsencrypt-auto that does " - "not receive updates, and is less reliable than more recent versions. " - "We recommend upgrading to the latest certbot-auto script, or using native " - "OS packages.") + logger.warning("You are running with an old copy of letsencrypt-auto" + " that does not receive updates, and is less reliable than more" + " recent versions. The letsencrypt client has also been renamed" + " to Certbot. We recommend upgrading to the latest certbot-auto" + " script, or using native OS packages.") logger.debug("Deprecation warning circumstances: %s / %s", sys.argv[0], os.environ) From b3d2ac5161b44d2f09c211048056248be224100a Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Wed, 14 Nov 2018 22:57:40 +0100 Subject: [PATCH 043/114] Fail-fast in test/cover/lint scripts (#6487) After #6485 and #6435, it appears that there is no good reason to not fail fast when test, cover or linting scripts are executed. This PR ensures to fail fast by invoking commands throught subprocess.check_call instead of subprocess.call, and by removing the handling of non-zero exit code at the end of theses scripts. As now coverage on Windows is executed with thresholds, I added specific thresholds for this platform. Because some portions of code that are done for Unix platform will not be executed on Windows. Note that coverage reports from Travis and AppVeyor are accumulated on Codecov. So if a file is covered up to 50 % on Linux, and all other parts are covered on Windows, then coverage is 100 % for Codecov. Note: that PR also fixes the ability of coverage tests to fail if thresholds are exceeded. * Use check_call to fail fast in all scripts related to tests/lint/coverage/deploy * Make specific coverage threshold for windows --- tests/modification-check.py | 4 +-- tools/_venv_common.py | 24 +++++++---------- tools/install_and_test.py | 14 ++++------ tools/pip_install.py | 14 ++++------ tools/pip_install_editable.py | 4 +-- tools/venv.py | 4 +-- tools/venv3.py | 4 +-- tox.cover.py | 49 ++++++++++++++++------------------- 8 files changed, 51 insertions(+), 66 deletions(-) diff --git a/tests/modification-check.py b/tests/modification-check.py index e00994b04..8abc0fbfe 100755 --- a/tests/modification-check.py +++ b/tests/modification-check.py @@ -70,7 +70,7 @@ def validate_scripts_content(repo_path, temp_cwd): # Compare file against the latest released version latest_version = subprocess.check_output( [sys.executable, 'fetch.py', '--latest-version'], cwd=temp_cwd) - subprocess.call( + subprocess.check_call( [sys.executable, 'fetch.py', '--le-auto-script', 'v{0}'.format(latest_version.decode().strip())], cwd=temp_cwd) if compare_files( @@ -95,7 +95,7 @@ def main(): os.path.normpath(os.path.join(repo_path, 'letsencrypt-auto-source/letsencrypt-auto')), os.path.join(temp_cwd, 'original-lea') ) - subprocess.call([sys.executable, os.path.normpath(os.path.join( + subprocess.check_call([sys.executable, os.path.normpath(os.path.join( repo_path, 'letsencrypt-auto-source/build.py'))]) shutil.copyfile( os.path.normpath(os.path.join(repo_path, 'letsencrypt-auto-source/letsencrypt-auto')), diff --git a/tools/_venv_common.py b/tools/_venv_common.py index b180518f9..6134bd29d 100755 --- a/tools/_venv_common.py +++ b/tools/_venv_common.py @@ -11,13 +11,13 @@ import sys def subprocess_with_print(command): print(command) - return subprocess.call(command, shell=True) + subprocess.check_call(command, shell=True) def get_venv_python(venv_path): python_linux = os.path.join(venv_path, 'bin/python') - python_windows = os.path.join(venv_path, 'Scripts\\python.exe') if os.path.isfile(python_linux): return python_linux + python_windows = os.path.join(venv_path, 'Scripts\\python.exe') if os.path.isfile(python_windows): return python_windows @@ -35,19 +35,17 @@ def main(venv_name, venv_args, args): if os.path.isdir(venv_name): os.rename(venv_name, '{0}.{1}.bak'.format(venv_name, int(time.time()))) - exit_code = 0 - - exit_code = subprocess_with_print(' '.join([ + subprocess_with_print(' '.join([ sys.executable, '-m', 'virtualenv', '--no-site-packages', '--setuptools', - venv_name, venv_args])) or exit_code + venv_name, venv_args])) python_executable = get_venv_python(venv_name) - exit_code = subprocess_with_print(' '.join([ + subprocess_with_print(' '.join([ python_executable, os.path.normpath('./letsencrypt-auto-source/pieces/pipstrap.py')])) - command = [python_executable, os.path.normpath('./tools/pip_install.py')] or exit_code + command = [python_executable, os.path.normpath('./tools/pip_install.py')] command.extend(args) - exit_code = subprocess_with_print(' '.join(command)) or exit_code + subprocess_with_print(' '.join(command)) if os.path.isdir(os.path.join(venv_name, 'bin')): # Linux/OSX specific @@ -65,9 +63,7 @@ def main(venv_name, venv_args, args): else: raise ValueError('Error, directory {0} is not a valid venv.'.format(venv_name)) - return exit_code - if __name__ == '__main__': - sys.exit(main(os.environ.get('VENV_NAME', 'venv'), - os.environ.get('VENV_ARGS', ''), - sys.argv[1:])) + main(os.environ.get('VENV_NAME', 'venv'), + os.environ.get('VENV_ARGS', ''), + sys.argv[1:]) diff --git a/tools/install_and_test.py b/tools/install_and_test.py index 149ffc776..2842ec069 100755 --- a/tools/install_and_test.py +++ b/tools/install_and_test.py @@ -19,7 +19,7 @@ SKIP_PROJECTS_ON_WINDOWS = [ def call_with_print(command, cwd=None): print(command) - return subprocess.call(command, shell=True, cwd=cwd or os.getcwd()) + subprocess.check_call(command, shell=True, cwd=cwd or os.getcwd()) def main(args): if os.environ.get('CERTBOT_NO_PIN') == '1': @@ -37,12 +37,10 @@ def main(args): else: new_args.append(arg) - exit_code = 0 - for requirement in new_args: current_command = command[:] current_command.append(requirement) - exit_code = call_with_print(' '.join(current_command)) or exit_code + call_with_print(' '.join(current_command)) pkg = re.sub(r'\[\w+\]', '', requirement) if pkg == '.': @@ -50,13 +48,11 @@ def main(args): temp_cwd = tempfile.mkdtemp() try: - exit_code = call_with_print(' '.join([ + call_with_print(' '.join([ sys.executable, '-m', 'pytest', '--numprocesses', 'auto', - '--quiet', '--pyargs', pkg.replace('-', '_')]), cwd=temp_cwd) or exit_code + '--quiet', '--pyargs', pkg.replace('-', '_')]), cwd=temp_cwd) finally: shutil.rmtree(temp_cwd) - return exit_code - if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) + main(sys.argv[1:]) diff --git a/tools/pip_install.py b/tools/pip_install.py index 273ce5ec2..2c4a47c21 100755 --- a/tools/pip_install.py +++ b/tools/pip_install.py @@ -59,14 +59,12 @@ def merge_requirements(tools_path, test_constraints, all_constraints): def call_with_print(command, cwd=None): print(command) - return subprocess.call(command, shell=True, cwd=cwd or os.getcwd()) + subprocess.check_call(command, shell=True, cwd=cwd or os.getcwd()) def main(args): tools_path = find_tools_path() working_dir = tempfile.mkdtemp() - exit_code = 0 - try: test_constraints = os.path.join(working_dir, 'test_constraints.txt') all_constraints = os.path.join(working_dir, 'all_constraints.txt') @@ -79,17 +77,15 @@ def main(args): merge_requirements(tools_path, test_constraints, all_constraints) if requirements: - exit_code = call_with_print(' '.join([ + call_with_print(' '.join([ sys.executable, '-m', 'pip', 'install', '-q', '--constraint', all_constraints, - '--requirement', requirements])) or exit_code + '--requirement', requirements])) command = [sys.executable, '-m', 'pip', 'install', '-q', '--constraint', all_constraints] command.extend(args) - exit_code = call_with_print(' '.join(command)) or exit_code + call_with_print(' '.join(command)) finally: shutil.rmtree(working_dir) - return exit_code - if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) + main(sys.argv[1:]) diff --git a/tools/pip_install_editable.py b/tools/pip_install_editable.py index 35cc2264d..8eaf3a9fa 100755 --- a/tools/pip_install_editable.py +++ b/tools/pip_install_editable.py @@ -14,7 +14,7 @@ def main(args): new_args.append('-e') new_args.append(arg) - return pip_install.main(new_args) + pip_install.main(new_args) if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) + main(sys.argv[1:]) diff --git a/tools/venv.py b/tools/venv.py index 2cc43251d..8b6f92a56 100755 --- a/tools/venv.py +++ b/tools/venv.py @@ -53,7 +53,7 @@ def main(): venv_args = get_venv_args() - return _venv_common.main('venv', venv_args, REQUIREMENTS) + _venv_common.main('venv', venv_args, REQUIREMENTS) if __name__ == '__main__': - sys.exit(main()) + main() diff --git a/tools/venv3.py b/tools/venv3.py index 1bacc9c9a..9710806c5 100755 --- a/tools/venv3.py +++ b/tools/venv3.py @@ -48,7 +48,7 @@ def get_venv_args(): def main(): venv_args = get_venv_args() - return _venv_common.main('venv3', venv_args, REQUIREMENTS) + _venv_common.main('venv3', venv_args, REQUIREMENTS) if __name__ == '__main__': - sys.exit(main()) + main() diff --git a/tox.cover.py b/tox.cover.py index 8bbce2d09..ad6bb1a39 100755 --- a/tox.cover.py +++ b/tox.cover.py @@ -12,36 +12,33 @@ DEFAULT_PACKAGES = [ 'certbot_dns_sakuracloud', 'certbot_nginx', 'certbot_postfix', 'letshelp_certbot'] COVER_THRESHOLDS = { - 'certbot': 98, - 'acme': 100, - 'certbot_apache': 100, - 'certbot_dns_cloudflare': 98, - 'certbot_dns_cloudxns': 99, - 'certbot_dns_digitalocean': 98, - 'certbot_dns_dnsimple': 98, - 'certbot_dns_dnsmadeeasy': 99, - 'certbot_dns_gehirn': 97, - 'certbot_dns_google': 99, - 'certbot_dns_linode': 98, - 'certbot_dns_luadns': 98, - 'certbot_dns_nsone': 99, - 'certbot_dns_ovh': 97, - 'certbot_dns_rfc2136': 99, - 'certbot_dns_route53': 92, - 'certbot_dns_sakuracloud': 97, - 'certbot_nginx': 97, - 'certbot_postfix': 100, - 'letshelp_certbot': 100 + 'certbot': {'linux': 98, 'windows': 94}, + 'acme': {'linux': 100, 'windows': 99}, + 'certbot_apache': {'linux': 100, 'windows': 100}, + 'certbot_dns_cloudflare': {'linux': 98, 'windows': 98}, + 'certbot_dns_cloudxns': {'linux': 99, 'windows': 99}, + 'certbot_dns_digitalocean': {'linux': 98, 'windows': 98}, + 'certbot_dns_dnsimple': {'linux': 98, 'windows': 98}, + 'certbot_dns_dnsmadeeasy': {'linux': 99, 'windows': 99}, + 'certbot_dns_gehirn': {'linux': 97, 'windows': 97}, + 'certbot_dns_google': {'linux': 99, 'windows': 99}, + 'certbot_dns_linode': {'linux': 98, 'windows': 98}, + 'certbot_dns_luadns': {'linux': 98, 'windows': 98}, + 'certbot_dns_nsone': {'linux': 99, 'windows': 99}, + 'certbot_dns_ovh': {'linux': 97, 'windows': 97}, + 'certbot_dns_rfc2136': {'linux': 99, 'windows': 99}, + 'certbot_dns_route53': {'linux': 92, 'windows': 92}, + 'certbot_dns_sakuracloud': {'linux': 97, 'windows': 97}, + 'certbot_nginx': {'linux': 97, 'windows': 97}, + 'certbot_postfix': {'linux': 100, 'windows': 100}, + 'letshelp_certbot': {'linux': 100, 'windows': 100} } SKIP_PROJECTS_ON_WINDOWS = [ 'certbot-apache', 'certbot-nginx', 'certbot-postfix', 'letshelp-certbot'] def cover(package): - threshold = COVER_THRESHOLDS.get(package) - - if not threshold: - raise ValueError('Unrecognized package: {0}'.format(package)) + threshold = COVER_THRESHOLDS.get(package)['windows' if os.name == 'nt' else 'linux'] pkg_dir = package.replace('_', '-') @@ -51,10 +48,10 @@ def cover(package): .format(pkg_dir))) return - subprocess.call([ + subprocess.check_call([ sys.executable, '-m', 'pytest', '--cov', pkg_dir, '--cov-append', '--cov-report=', '--numprocesses', 'auto', '--pyargs', package]) - subprocess.call([ + subprocess.check_call([ sys.executable, '-m', 'coverage', 'report', '--fail-under', str(threshold), '--include', '{0}/*'.format(pkg_dir), '--show-missing']) From 5073090a20fa59fae45b4d90bfb41635bc181911 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Fri, 16 Nov 2018 00:17:36 +0100 Subject: [PATCH 044/114] Update tools/venv3.py to support py launcher on Windows (#6493) Following some inconsistencies occurred during by developments, and in the light of #6508, it decided to wrote a PR that will take fully advantage of the conversion from bash to python to the development setup tools. This PR adresses several issues when trying to use the development setup tools (`tools/venv.py` and `tools/venv3.py`: * on Windows, `python` executable is not always in PATH (default behavior) * even if the option is checked, the `python` executable is not associated to the usually symlink `python3` on Windows * on Windows again, really powerful introspection of the available Python environments can be done with `py`, the Windows Python launcher * in general for all systems, `tools/venv.py` and `tools/venv3.py` ensures that the respective Python major version will be used to setup the virtual environment if available. * finally, the best and first candidate to test should be the Python executable used to launch the `tools/venv*.py` script. It was not relevant before because it was shell scripts, but do it is. The logic is shared in `_venv_common.py`, and will be called appropriately for both scripts. In priority decreasing order, python executable will be search and tested: * from the current Python executable, as exposed by `sys.executable` * from any python or pythonX (X as a python version like 2, 3 or 2.7 or 3.4) executable available in PATH * from the Windows Python launched `py` if available Individual changes were: * Update tools/venv3.py to support py launcher on Windows * Fix typo in help message * More explicit calls with space protection * Complete refactoring to take advantage of the python runtime, and control of the compatible version to use. --- tools/_venv_common.py | 104 ++++++++++++++++++++++++++++++++++++++---- tools/pip_install.py | 17 ++++--- tools/venv.py | 22 +-------- tools/venv3.py | 22 +-------- 4 files changed, 110 insertions(+), 55 deletions(-) diff --git a/tools/_venv_common.py b/tools/_venv_common.py index 6134bd29d..c44d05bf7 100755 --- a/tools/_venv_common.py +++ b/tools/_venv_common.py @@ -8,11 +8,94 @@ import glob import time import subprocess import sys +import re + +VERSION_PATTERN = re.compile(r'^(\d+)\.(\d+).*$') + + +class PythonExecutableNotFoundError(Exception): + pass + + +def find_python_executable(python_major): + # type: (int) -> str + """ + Find the relevant python executable that is of the given python major version. + Will test, in decreasing priority order: + * the current Python interpreter + * 'pythonX' executable in PATH (with X the given major version) if available + * 'python' executable in PATH if available + * Windows Python launcher 'py' executable in PATH if available + Incompatible python versions for Certbot will be evicted (eg. Python < 3.5 on Windows) + :param int python_major: the Python major version to target (2 or 3) + :rtype: str + :return: the relevant python executable path + :raise RuntimeError: if no relevant python executable path could be found + """ + python_executable_path = None + + # First try, current python executable + if _check_version('{0}.{1}.{2}'.format( + sys.version_info[0], sys.version_info[1], sys.version_info[2]), python_major): + return sys.executable + + # Second try, with python executables in path + versions_to_test = ['2.7', '2', ''] if python_major == 2 else ['3', ''] + for one_version in versions_to_test: + try: + one_python = 'python{0}'.format(one_version) + output = subprocess.check_output([one_python, '--version'], + universal_newlines=True, stderr=subprocess.STDOUT) + if _check_version(output.strip().split()[1], python_major): + return subprocess.check_output([one_python, '-c', + 'import sys; sys.stdout.write(sys.executable);'], + universal_newlines=True) + except (subprocess.CalledProcessError, OSError): + pass + + # Last try, with Windows Python launcher + try: + env_arg = '-{0}'.format(python_major) + output_version = subprocess.check_output(['py', env_arg, '--version'], + universal_newlines=True, stderr=subprocess.STDOUT) + if _check_version(output_version.strip().split()[1], python_major): + return subprocess.check_output(['py', env_arg, '-c', + 'import sys; sys.stdout.write(sys.executable);'], + universal_newlines=True) + except (subprocess.CalledProcessError, OSError): + pass + + if not python_executable_path: + raise RuntimeError('Error, no compatible Python {0} executable for Certbot could be found.' + .format(python_major)) + + +def _check_version(version_str, major_version): + search = VERSION_PATTERN.search(version_str) + + if not search: + return False + + version = (int(search.group(1)), int(search.group(2))) + + minimal_version_supported = (2, 7) + if major_version == 3 and os.name == 'nt': + minimal_version_supported = (3, 5) + elif major_version == 3: + minimal_version_supported = (3, 4) + + if version >= minimal_version_supported: + return True + + print('Incompatible python version for Certbot found: {0}'.format(version_str)) + return False + def subprocess_with_print(command): print(command) subprocess.check_call(command, shell=True) + def get_venv_python(venv_path): python_linux = os.path.join(venv_path, 'bin/python') if os.path.isfile(python_linux): @@ -25,6 +108,7 @@ def get_venv_python(venv_path): 'Error, could not find python executable in venv path {0}: is it a valid venv ?' .format(venv_path))) + def main(venv_name, venv_args, args): for path in glob.glob('*.egg-info'): if os.path.isdir(path): @@ -35,17 +119,18 @@ def main(venv_name, venv_args, args): if os.path.isdir(venv_name): os.rename(venv_name, '{0}.{1}.bak'.format(venv_name, int(time.time()))) - subprocess_with_print(' '.join([ - sys.executable, '-m', 'virtualenv', '--no-site-packages', '--setuptools', - venv_name, venv_args])) + subprocess_with_print('"{0}" -m virtualenv --no-site-packages --setuptools {1} {2}' + .format(sys.executable, venv_name, venv_args)) python_executable = get_venv_python(venv_name) - subprocess_with_print(' '.join([ - python_executable, os.path.normpath('./letsencrypt-auto-source/pieces/pipstrap.py')])) - command = [python_executable, os.path.normpath('./tools/pip_install.py')] - command.extend(args) - subprocess_with_print(' '.join(command)) + subprocess_with_print('"{0}" {1}'.format( + python_executable, + os.path.normpath('./letsencrypt-auto-source/pieces/pipstrap.py'))) + subprocess_with_print('"{0}" {1} {2}'.format( + python_executable, + os.path.normpath('./tools/pip_install.py'), + ' '.join(args))) if os.path.isdir(os.path.join(venv_name, 'bin')): # Linux/OSX specific @@ -57,12 +142,13 @@ def main(venv_name, venv_args, args): # Windows specific print('---------------------------------------------------------------------------') print('Please run one of the following commands to activate developer environment:') - print('{0}\\bin\\activate.bat (for Batch)'.format(venv_name)) + print('{0}\\Scripts\\activate.bat (for Batch)'.format(venv_name)) print('.\\{0}\\Scripts\\Activate.ps1 (for Powershell)'.format(venv_name)) print('---------------------------------------------------------------------------') else: raise ValueError('Error, directory {0} is not a valid venv.'.format(venv_name)) + if __name__ == '__main__': main(os.environ.get('VENV_NAME', 'venv'), os.environ.get('VENV_ARGS', ''), diff --git a/tools/pip_install.py b/tools/pip_install.py index 2c4a47c21..8878674c9 100755 --- a/tools/pip_install.py +++ b/tools/pip_install.py @@ -20,9 +20,11 @@ import tempfile import merge_requirements as merge_module import readlink + def find_tools_path(): return os.path.dirname(readlink.main(__file__)) + def certbot_oldest_processing(tools_path, args, test_constraints): if args[0] != '-e' or len(args) != 2: raise ValueError('When CERTBOT_OLDEST is set, this script must be run ' @@ -37,6 +39,7 @@ def certbot_oldest_processing(tools_path, args, test_constraints): return requirements + def certbot_normal_processing(tools_path, test_constraints): repo_path = os.path.dirname(tools_path) certbot_requirements = os.path.normpath(os.path.join( @@ -49,6 +52,7 @@ def certbot_normal_processing(tools_path, test_constraints): if search: fd.write('{0}{1}'.format(search.group(1), os.linesep)) + def merge_requirements(tools_path, test_constraints, all_constraints): merged_requirements = merge_module.main( os.path.join(tools_path, 'dev_constraints.txt'), @@ -57,10 +61,12 @@ def merge_requirements(tools_path, test_constraints, all_constraints): with open(all_constraints, 'w') as fd: fd.write(merged_requirements) + def call_with_print(command, cwd=None): print(command) subprocess.check_call(command, shell=True, cwd=cwd or os.getcwd()) + def main(args): tools_path = find_tools_path() working_dir = tempfile.mkdtemp() @@ -77,15 +83,14 @@ def main(args): merge_requirements(tools_path, test_constraints, all_constraints) if requirements: - call_with_print(' '.join([ - sys.executable, '-m', 'pip', 'install', '-q', '--constraint', all_constraints, - '--requirement', requirements])) + call_with_print('"{0}" -m pip install -q --constraint "{1}" --requirement "{2}"' + .format(sys.executable, all_constraints, requirements)) - command = [sys.executable, '-m', 'pip', 'install', '-q', '--constraint', all_constraints] - command.extend(args) - call_with_print(' '.join(command)) + call_with_print('"{0}" -m pip install -q --constraint "{1}" {2}' + .format(sys.executable, all_constraints, ' '.join(args))) finally: shutil.rmtree(working_dir) + if __name__ == '__main__': main(sys.argv[1:]) diff --git a/tools/venv.py b/tools/venv.py index 8b6f92a56..93b012e76 100755 --- a/tools/venv.py +++ b/tools/venv.py @@ -1,11 +1,6 @@ #!/usr/bin/env python # Developer virtualenv setup for Certbot client - -from __future__ import absolute_import - import os -import subprocess -import sys import _venv_common @@ -33,27 +28,14 @@ REQUIREMENTS = [ '-e certbot-compatibility-test', ] -def get_venv_args(): - with open(os.devnull, 'w') as fnull: - command_python2_st_code = subprocess.call( - 'command -v python2', shell=True, stdout=fnull, stderr=fnull) - if not command_python2_st_code: - return '--python python2' - - command_python27_st_code = subprocess.call( - 'command -v python2.7', shell=True, stdout=fnull, stderr=fnull) - if not command_python27_st_code: - return '--python python2.7' - - raise ValueError('Couldn\'t find python2 or python2.7 in {0}'.format(os.environ.get('PATH'))) def main(): if os.name == 'nt': raise ValueError('Certbot for Windows is not supported on Python 2.x.') - venv_args = get_venv_args() - + venv_args = '--python "{0}"'.format(_venv_common.find_python_executable(2)) _venv_common.main('venv', venv_args, REQUIREMENTS) + if __name__ == '__main__': main() diff --git a/tools/venv3.py b/tools/venv3.py index 9710806c5..c2374ba5a 100755 --- a/tools/venv3.py +++ b/tools/venv3.py @@ -1,12 +1,5 @@ #!/usr/bin/env python # Developer virtualenv setup for Certbot client - -from __future__ import absolute_import - -import os -import subprocess -import sys - import _venv_common REQUIREMENTS = [ @@ -33,22 +26,11 @@ REQUIREMENTS = [ '-e certbot-compatibility-test', ] -def get_venv_args(): - with open(os.devnull, 'w') as fnull: - where_python3_st_code = subprocess.call( - 'where python3', shell=True, stdout=fnull, stderr=fnull) - command_python3_st_code = subprocess.call( - 'command -v python3', shell=True, stdout=fnull, stderr=fnull) - - if not where_python3_st_code or not command_python3_st_code: - return '--python python3' - - raise ValueError('Couldn\'t find python3 in {0}'.format(os.environ.get('PATH'))) def main(): - venv_args = get_venv_args() - + venv_args = '--python "{0}"'.format(_venv_common.find_python_executable(3)) _venv_common.main('venv3', venv_args, REQUIREMENTS) + if __name__ == '__main__': main() From 7fe64c3b9bdc01bafcbeeea874a29c23c3cf4064 Mon Sep 17 00:00:00 2001 From: Ye Wang Date: Fri, 16 Nov 2018 12:37:06 -0500 Subject: [PATCH 045/114] Add clarification of what means in the case of creating a SAN cert. --- docs/using.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/using.rst b/docs/using.rst index 1fa13e022..8adf00d4d 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -696,7 +696,9 @@ Where are my certificates? ========================== All generated keys and issued certificates can be found in -``/etc/letsencrypt/live/$domain``. Rather than copying, please point +``/etc/letsencrypt/live/$domain`` In the case of creating a SAN certificate +with multiple alternative names, ``$domain`` is the first domain passed in +via -d parameter. Rather than copying, please point your (web) server configuration directly to those files (or create symlinks). During the renewal_, ``/etc/letsencrypt/live`` is updated with the latest necessary files. From ca12921a60eee87eba9eba275390171810b34258 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 16 Nov 2018 14:28:29 -0800 Subject: [PATCH 046/114] Don't mention _venv_common.sh in certbot-auto. This wasn't always the case, but nowadays, _venv_common is a developer tool and has nothing to do with certbot-auto. --- letsencrypt-auto-source/letsencrypt-auto | 3 +-- letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 12be26e19..6c98b71d4 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -593,8 +593,7 @@ BootstrapArchCommon() { # - ArchLinux (x86_64) # # "python-virtualenv" is Python3, but "python2-virtualenv" provides - # only "virtualenv2" binary, not "virtualenv" necessary in - # ./tools/_venv_common.py + # only "virtualenv2" binary, not "virtualenv". deps=" python2 diff --git a/letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh b/letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh index c55527590..3be78d3f8 100755 --- a/letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh +++ b/letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh @@ -7,8 +7,7 @@ BootstrapArchCommon() { # - ArchLinux (x86_64) # # "python-virtualenv" is Python3, but "python2-virtualenv" provides - # only "virtualenv2" binary, not "virtualenv" necessary in - # ./tools/_venv_common.py + # only "virtualenv2" binary, not "virtualenv". deps=" python2 From 4e1c22779e95a9c86c70640309482b4f5113a4d1 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 19 Nov 2018 11:47:14 -0800 Subject: [PATCH 047/114] Fix up environment variable use in venv creation scripts (#6518) This PR has the value of VENV_NAME override any value set in the tools/venv* scripts. I also removed the use of VENV_ARGS. This was used in _venv_common.sh as a means of passing arguments for virtualenv between the scripts, however, there is no other use of the variable in this repository and passing the arguments through a function call is much more natural in Python. * Respect VENV_NAME in tools/venv*. * Stop using VENV_ARGS * Remove VENV_NAME_ENV_VAR and add docstrings. --- tools/_venv_common.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/tools/_venv_common.py b/tools/_venv_common.py index c44d05bf7..bddda6302 100755 --- a/tools/_venv_common.py +++ b/tools/_venv_common.py @@ -1,4 +1,14 @@ #!/usr/bin/env python +"""Aids in creating a developer virtual environment for Certbot. + +When this module is run as a script, it takes the arguments that should +be passed to pip to install the Certbot packages as command line +arguments. The virtual environment will be created with the name "venv" +in the current working directory and will use the default version of +Python for the virtualenv executable in your PATH. You can change the +name of the virtual environment by setting the environment variable +VENV_NAME. +""" from __future__ import print_function @@ -110,12 +120,27 @@ def get_venv_python(venv_path): def main(venv_name, venv_args, args): + """Creates a virtual environment and installs packages. + + :param str venv_name: The name or path at where the virtual + environment should be created. + :param str venv_args: Command line arguments for virtualenv + :param str args: Command line arguments that should be given to pip + to install packages + """ + for path in glob.glob('*.egg-info'): if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) + env_venv_name = os.environ.get('VENV_NAME') + if env_venv_name: + print('Creating venv at {0}' + ' as specified in VENV_NAME'.format(env_venv_name)) + venv_name = env_venv_name + if os.path.isdir(venv_name): os.rename(venv_name, '{0}.{1}.bak'.format(venv_name, int(time.time()))) @@ -150,6 +175,6 @@ def main(venv_name, venv_args, args): if __name__ == '__main__': - main(os.environ.get('VENV_NAME', 'venv'), - os.environ.get('VENV_ARGS', ''), + main('venv', + '', sys.argv[1:]) From 78cf8ec4de0a4030ac4c2dd45113e456acb1621f Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Mon, 19 Nov 2018 23:28:59 +0100 Subject: [PATCH 048/114] Protect certbot-auto against automated downgrades (#6448) With current code, the certbot-auto self-upgrade process can make it actually to downgrade itself, because the comparison done is an equality test between local certbot-auto version and the remote one. This is a flaw for attackers, that could make certbot-auto break itself by falsely advertising it about an old version as the latest one available. A function is added to make a more advanced comparison between version. Certbot-auto will upgrade itself only if the local version is strictly inferior to the latest one available. For instance, a version 0.28.0 will not upgrade itself if the latest one available on internet is 0.27.1. Similarly, non-official versions like 0.28.0.dev0 will never trigger a self-upgrade, to help development workflows. This implementation relies only on the Python distribution installed by certbot-auto (supporting 2.7+) and basic shell operations, to be compatible with any UNIX-based system. * Check version with protection again downgrade * Create a stable version of letsencrypt-auto to use correctly self-upgrade functionality * Update letsencrypt-auto-source/letsencrypt-auto.template --- letsencrypt-auto-source/letsencrypt-auto | 36 ++++++++++++++++++- .../letsencrypt-auto.template | 36 ++++++++++++++++++- letsencrypt-auto-source/tests/auto_test.py | 15 +++++++- 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 12be26e19..9973607be 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -912,6 +912,35 @@ OldVenvExists() { [ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ] } +# Given python path, version 1 and version 2, check if version 1 is outdated compared to version 2. +# An unofficial version provided as version 1 (eg. 0.28.0.dev0) will be treated +# specifically by printing "UNOFFICIAL". Otherwise, print "OUTDATED" if version 1 +# is outdated, and "UP_TO_DATE" if not. +# This function relies only on installed python environment (2.x or 3.x) by certbot-auto. +CompareVersions() { + "$1" - "$2" "$3" << "UNLIKELY_EOF" +import sys +from distutils.version import StrictVersion + +try: + current = StrictVersion(sys.argv[1]) +except ValueError: + sys.stdout.write('UNOFFICIAL') + sys.exit() + +try: + remote = StrictVersion(sys.argv[2]) +except ValueError: + sys.stdout.write('UP_TO_DATE') + sys.exit() + +if current < remote: + sys.stdout.write('OUTDATED') +else: + sys.stdout.write('UP_TO_DATE') +UNLIKELY_EOF +} + if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. @@ -1640,7 +1669,12 @@ UNLIKELY_EOF error "WARNING: couldn't find Python $MIN_PYTHON_VERSION+ to check for updates." elif ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then error "WARNING: unable to check for updates." - elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then + fi + + LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` + if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then + say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" + elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." # Now we drop into Python so we don't have to install even more diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index 6d2977832..f431e32e4 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -451,6 +451,35 @@ OldVenvExists() { [ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ] } +# Given python path, version 1 and version 2, check if version 1 is outdated compared to version 2. +# An unofficial version provided as version 1 (eg. 0.28.0.dev0) will be treated +# specifically by printing "UNOFFICIAL". Otherwise, print "OUTDATED" if version 1 +# is outdated, and "UP_TO_DATE" if not. +# This function relies only on installed python environment (2.x or 3.x) by certbot-auto. +CompareVersions() { + "$1" - "$2" "$3" << "UNLIKELY_EOF" +import sys +from distutils.version import StrictVersion + +try: + current = StrictVersion(sys.argv[1]) +except ValueError: + sys.stdout.write('UNOFFICIAL') + sys.exit() + +try: + remote = StrictVersion(sys.argv[2]) +except ValueError: + sys.stdout.write('UP_TO_DATE') + sys.exit() + +if current < remote: + sys.stdout.write('OUTDATED') +else: + sys.stdout.write('UP_TO_DATE') +UNLIKELY_EOF +} + if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. @@ -635,7 +664,12 @@ UNLIKELY_EOF error "WARNING: couldn't find Python $MIN_PYTHON_VERSION+ to check for updates." elif ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then error "WARNING: unable to check for updates." - elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then + fi + + LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` + if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then + say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" + elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." # Now we drop into Python so we don't have to install even more diff --git a/letsencrypt-auto-source/tests/auto_test.py b/letsencrypt-auto-source/tests/auto_test.py index c5109e208..16c478f20 100644 --- a/letsencrypt-auto-source/tests/auto_test.py +++ b/letsencrypt-auto-source/tests/auto_test.py @@ -27,6 +27,19 @@ def tests_dir(): return dirname(abspath(__file__)) +def copy_stable(src, dst): + """ + Copy letsencrypt-auto, and replace its current version to its equivalent stable one. + This is needed to test correctly the self-upgrade functionality. + """ + copy(src, dst) + with open(dst, 'r') as file: + filedata = file.read() + filedata = re.sub(r'LE_AUTO_VERSION="(.*)\.dev0"', r'LE_AUTO_VERSION="\1"', filedata) + with open(dst, 'w') as file: + file.write(filedata) + + sys.path.insert(0, dirname(tests_dir())) from build import build as build_le_auto @@ -343,7 +356,7 @@ class AutoTests(TestCase): 'v99.9.9/letsencrypt-auto': build_le_auto(version='99.9.9'), 'v99.9.9/letsencrypt-auto.sig': signed('something else')} with serving(resources) as base_url: - copy(LE_AUTO_PATH, le_auto_path) + copy_stable(LE_AUTO_PATH, le_auto_path) try: out, err = run_le_auto(le_auto_path, venv_dir, base_url) except CalledProcessError as exc: From 1dd7db12e05c7a52f1b1092d76a14caf0bf4c4cc Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Tue, 20 Nov 2018 00:38:37 +0100 Subject: [PATCH 049/114] Workaround for old pip versions that are not exposed as importable modules. (#6500) Fallback to pipstrap 1.5.0. Manipulate PATH variable on higher level to activate the virtual environment before calling pipstrap. --- letsencrypt-auto-source/letsencrypt-auto | 13 +++----- letsencrypt-auto-source/pieces/pipstrap.py | 14 +++------ tools/_venv_common.py | 36 ++++++++++++---------- 3 files changed, 29 insertions(+), 34 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 9973607be..1417811f3 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -1244,13 +1244,11 @@ UNLIKELY_EOF cat << "UNLIKELY_EOF" > "$TEMP_DIR/pipstrap.py" #!/usr/bin/env python """A small script that can act as a trust root for installing pip >=8 - Embed this in your project, and your VCS checkout is all you have to trust. In a post-peep era, this lets you claw your way to a hash-checking version of pip, with which you can install the rest of your dependencies safely. All it assumes is Python 2.6 or better and *some* version of pip already installed. If anything goes wrong, it will exit with a non-zero status code. - """ # This is here so embedded copies are MIT-compliant: # Copyright (c) 2016 Erik Rose @@ -1289,7 +1287,7 @@ except ImportError: cmd = popenargs[0] raise CalledProcessError(retcode, cmd) return output -from sys import exit, version_info, executable +from sys import exit, version_info from tempfile import mkdtemp try: from urllib2 import build_opener, HTTPHandler, HTTPSHandler @@ -1301,7 +1299,7 @@ except ImportError: from urllib.parse import urlparse # 3.4 -__version__ = 2, 0, 0 +__version__ = 1, 5, 1 PIP_VERSION = '9.0.1' DEFAULT_INDEX_BASE = 'https://pypi.python.org' @@ -1377,10 +1375,8 @@ def hashed_download(url, temp, digest): def get_index_base(): """Return the URL to the dir containing the "packages" folder. - Try to wring something out of PIP_INDEX_URL, if set. Hack "/simple" off the end if it's there; that is likely to give us the right dir. - """ env_var = environ.get('PIP_INDEX_URL', '').rstrip('/') if env_var: @@ -1394,7 +1390,7 @@ def get_index_base(): def main(): - pip_version = StrictVersion(check_output([executable, '-m', 'pip', '--version']) + pip_version = StrictVersion(check_output(['pip', '--version']) .decode('utf-8').split()[1]) min_pip_version = StrictVersion(PIP_VERSION) if pip_version >= min_pip_version: @@ -1407,7 +1403,7 @@ def main(): temp, digest) for path, digest in PACKAGES] - check_output('{0} -m pip install --no-index --no-deps -U '.format(quote(executable)) + + check_output('pip install --no-index --no-deps -U ' + # Disable cache since we're not using it and it otherwise # sometimes throws permission warnings: ('--no-cache-dir ' if has_pip_cache else '') + @@ -1426,6 +1422,7 @@ def main(): if __name__ == '__main__': exit(main()) + UNLIKELY_EOF # ------------------------------------------------------------------------- # Set PATH so pipstrap upgrades the right (v)env: diff --git a/letsencrypt-auto-source/pieces/pipstrap.py b/letsencrypt-auto-source/pieces/pipstrap.py index f21d36657..727040c3c 100755 --- a/letsencrypt-auto-source/pieces/pipstrap.py +++ b/letsencrypt-auto-source/pieces/pipstrap.py @@ -1,12 +1,10 @@ #!/usr/bin/env python """A small script that can act as a trust root for installing pip >=8 - Embed this in your project, and your VCS checkout is all you have to trust. In a post-peep era, this lets you claw your way to a hash-checking version of pip, with which you can install the rest of your dependencies safely. All it assumes is Python 2.6 or better and *some* version of pip already installed. If anything goes wrong, it will exit with a non-zero status code. - """ # This is here so embedded copies are MIT-compliant: # Copyright (c) 2016 Erik Rose @@ -45,7 +43,7 @@ except ImportError: cmd = popenargs[0] raise CalledProcessError(retcode, cmd) return output -from sys import exit, version_info, executable +from sys import exit, version_info from tempfile import mkdtemp try: from urllib2 import build_opener, HTTPHandler, HTTPSHandler @@ -57,7 +55,7 @@ except ImportError: from urllib.parse import urlparse # 3.4 -__version__ = 2, 0, 0 +__version__ = 1, 5, 1 PIP_VERSION = '9.0.1' DEFAULT_INDEX_BASE = 'https://pypi.python.org' @@ -133,10 +131,8 @@ def hashed_download(url, temp, digest): def get_index_base(): """Return the URL to the dir containing the "packages" folder. - Try to wring something out of PIP_INDEX_URL, if set. Hack "/simple" off the end if it's there; that is likely to give us the right dir. - """ env_var = environ.get('PIP_INDEX_URL', '').rstrip('/') if env_var: @@ -150,7 +146,7 @@ def get_index_base(): def main(): - pip_version = StrictVersion(check_output([executable, '-m', 'pip', '--version']) + pip_version = StrictVersion(check_output(['pip', '--version']) .decode('utf-8').split()[1]) min_pip_version = StrictVersion(PIP_VERSION) if pip_version >= min_pip_version: @@ -163,7 +159,7 @@ def main(): temp, digest) for path, digest in PACKAGES] - check_output('{0} -m pip install --no-index --no-deps -U '.format(quote(executable)) + + check_output('pip install --no-index --no-deps -U ' + # Disable cache since we're not using it and it otherwise # sometimes throws permission warnings: ('--no-cache-dir ' if has_pip_cache else '') + @@ -181,4 +177,4 @@ def main(): if __name__ == '__main__': - exit(main()) \ No newline at end of file + exit(main()) diff --git a/tools/_venv_common.py b/tools/_venv_common.py index bddda6302..2a48b0d2e 100755 --- a/tools/_venv_common.py +++ b/tools/_venv_common.py @@ -19,6 +19,7 @@ import time import subprocess import sys import re +import shlex VERSION_PATTERN = re.compile(r'^(\d+)\.(\d+).*$') @@ -101,18 +102,18 @@ def _check_version(version_str, major_version): return False -def subprocess_with_print(command): - print(command) - subprocess.check_call(command, shell=True) +def subprocess_with_print(cmd, env=os.environ, shell=False): + print('+ {0}'.format(subprocess.list2cmdline(cmd)) if isinstance(cmd, list) else cmd) + subprocess.check_call(cmd, env=env, shell=shell) -def get_venv_python(venv_path): +def get_venv_bin_path(venv_path): python_linux = os.path.join(venv_path, 'bin/python') if os.path.isfile(python_linux): - return python_linux + return os.path.abspath(os.path.dirname(python_linux)) python_windows = os.path.join(venv_path, 'Scripts\\python.exe') if os.path.isfile(python_windows): - return python_windows + return os.path.abspath(os.path.dirname(python_windows)) raise ValueError(( 'Error, could not find python executable in venv path {0}: is it a valid venv ?' @@ -144,18 +145,19 @@ def main(venv_name, venv_args, args): if os.path.isdir(venv_name): os.rename(venv_name, '{0}.{1}.bak'.format(venv_name, int(time.time()))) - subprocess_with_print('"{0}" -m virtualenv --no-site-packages --setuptools {1} {2}' - .format(sys.executable, venv_name, venv_args)) + command = [sys.executable, '-m', 'virtualenv', '--no-site-packages', '--setuptools', venv_name] + command.extend(shlex.split(venv_args)) + subprocess_with_print(command) - python_executable = get_venv_python(venv_name) - - subprocess_with_print('"{0}" {1}'.format( - python_executable, - os.path.normpath('./letsencrypt-auto-source/pieces/pipstrap.py'))) - subprocess_with_print('"{0}" {1} {2}'.format( - python_executable, - os.path.normpath('./tools/pip_install.py'), - ' '.join(args))) + # We execute the two following commands in the context of the virtual environment, to install + # the packages in it. To do so, we append the venv binary to the PATH that will be used for + # these commands. With this trick, correct python executable will be selected. + new_environ = os.environ.copy() + new_environ['PATH'] = os.pathsep.join([get_venv_bin_path(venv_name), new_environ['PATH']]) + subprocess_with_print('python {0}'.format('./letsencrypt-auto-source/pieces/pipstrap.py'), + env=new_environ, shell=True) + subprocess_with_print('python {0} {1}'.format('./tools/pip_install.py', ' '.join(args)), + env=new_environ, shell=True) if os.path.isdir(os.path.join(venv_name, 'bin')): # Linux/OSX specific From fce5af50fdb0736ad7c19efcf2031b84dbda636d Mon Sep 17 00:00:00 2001 From: Benjamin Akhras Date: Tue, 20 Nov 2018 21:48:20 +0100 Subject: [PATCH 050/114] Fixed Typo in the examples section since .ini files are not supported. --- certbot-dns-google/certbot_dns_google/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-dns-google/certbot_dns_google/__init__.py b/certbot-dns-google/certbot_dns_google/__init__.py index f19266737..b88260b07 100644 --- a/certbot-dns-google/certbot_dns_google/__init__.py +++ b/certbot-dns-google/certbot_dns_google/__init__.py @@ -98,7 +98,7 @@ Examples certbot certonly \\ --dns-google \\ - --dns-google-credentials ~/.secrets/certbot/google.ini \\ + --dns-google-credentials ~/.secrets/certbot/google.json \\ --dns-google-propagation-seconds 120 \\ -d example.com From a23d76beb0e2c9539670766045314a5d50f582a2 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Tue, 20 Nov 2018 23:06:09 +0100 Subject: [PATCH 051/114] [Windows] Change default paths for Certbot when run on Windows (#6416) Defaults path of Certbot are the following: config: /etc/letsencrypt workdir: /var/letsencrypt/lib logs: /var/letsencrypt/log On Windows, this translate into: config: C:\etc\letsencrypt workdir: C:\var\letsencrypt\lib logs: C:\var\letsencrypt\log As Windows does not follow the standard POSIX filesystem layout, theses paths do not have a lot of sense in this case. This PR sets the following default paths when Certbot is run on Windows: config: C:\Certbot workdir: C:\Certbot\lib logs: C:\Certbot\log Better to decide the default paths for Certbot before users start to run it on Windows, to avoid future migration procedures. --- certbot/compat.py | 27 +++++++++++++++++++++++++++ certbot/constants.py | 10 +++++----- certbot/display/ops.py | 5 ++++- certbot/tests/main_test.py | 7 ++++--- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/certbot/compat.py b/certbot/compat.py index d42febe81..7e509206f 100644 --- a/certbot/compat.py +++ b/certbot/compat.py @@ -172,3 +172,30 @@ def compare_file_modes(mode1, mode2): # Windows specific: most of mode bits are ignored on Windows. Only check user R/W rights. return (stat.S_IMODE(mode1) & stat.S_IREAD == stat.S_IMODE(mode2) & stat.S_IREAD and stat.S_IMODE(mode1) & stat.S_IWRITE == stat.S_IMODE(mode2) & stat.S_IWRITE) + +WINDOWS_DEFAULT_FOLDERS = { + 'config': 'C:\\Certbot', + 'work': 'C:\\Certbot\\lib', + 'logs': 'C:\\Certbot\\log', +} +LINUX_DEFAULT_FOLDERS = { + 'config': '/etc/letsencrypt', + 'work': '/var/letsencrypt/lib', + 'logs': '/var/letsencrypt/log', +} + +def get_default_folder(folder_type): + """ + Return the relevant default folder for the current OS + + :param str folder_type: The type of folder to retrieve (config, work or logs) + + :returns: The relevant default folder. + :rtype: str + + """ + if 'fcntl' in sys.modules: + # Linux specific + return LINUX_DEFAULT_FOLDERS[folder_type] + # Windows specific + return WINDOWS_DEFAULT_FOLDERS[folder_type] diff --git a/certbot/constants.py b/certbot/constants.py index a2de2d27a..5bf68589d 100644 --- a/certbot/constants.py +++ b/certbot/constants.py @@ -4,7 +4,7 @@ import os import pkg_resources from acme import challenges - +from certbot import compat SETUPTOOLS_PLUGINS_ENTRY_POINT = "certbot.plugins" """Setuptools entry point group name for plugins.""" @@ -14,7 +14,7 @@ OLD_SETUPTOOLS_PLUGINS_ENTRY_POINT = "letsencrypt.plugins" CLI_DEFAULTS = dict( config_files=[ - "/etc/letsencrypt/cli.ini", + os.path.join(compat.get_default_folder('config'), 'cli.ini'), # http://freedesktop.org/wiki/Software/xdg-user-dirs/ os.path.join(os.environ.get("XDG_CONFIG_HOME", "~/.config"), "letsencrypt", "cli.ini"), @@ -85,9 +85,9 @@ CLI_DEFAULTS = dict( auth_cert_path="./cert.pem", auth_chain_path="./chain.pem", key_path=None, - config_dir="/etc/letsencrypt", - work_dir="/var/lib/letsencrypt", - logs_dir="/var/log/letsencrypt", + config_dir=compat.get_default_folder('config'), + work_dir=compat.get_default_folder('work'), + logs_dir=compat.get_default_folder('logs'), server="https://acme-v02.api.letsencrypt.org/directory", # Plugins parsers diff --git a/certbot/display/ops.py b/certbot/display/ops.py index 1e15a8474..3dae1070b 100644 --- a/certbot/display/ops.py +++ b/certbot/display/ops.py @@ -4,9 +4,11 @@ import os import zope.component +from certbot import compat from certbot import errors from certbot import interfaces from certbot import util + from certbot.display import util as display_util logger = logging.getLogger(__name__) @@ -33,7 +35,8 @@ def get_email(invalid=False, optional=True): unsafe_suggestion = ("\n\nIf you really want to skip this, you can run " "the client with --register-unsafely-without-email " "but make sure you then backup your account key from " - "/etc/letsencrypt/accounts\n\n") + "{0}\n\n".format(os.path.join( + compat.get_default_folder('config'), 'accounts'))) if optional: if invalid: msg += unsafe_suggestion diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 8d6a3e7ae..6c35f1fdb 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -944,8 +944,8 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met @mock.patch('certbot.crypto_util.notAfter') @test_util.patch_get_utility() def test_certonly_new_request_success(self, mock_get_utility, mock_notAfter): - cert_path = '/etc/letsencrypt/live/foo.bar' - key_path = '/etc/letsencrypt/live/baz.qux' + cert_path = os.path.normpath(os.path.join(self.config.config_dir, 'live/foo.bar')) + key_path = os.path.normpath(os.path.join(self.config.config_dir, 'live/baz.qux')) date = '1970-01-01' mock_notAfter().date.return_value = date @@ -975,7 +975,8 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met reuse_key=False): # pylint: disable=too-many-locals,too-many-arguments,too-many-branches cert_path = test_util.vector_path('cert_512.pem') - chain_path = '/etc/letsencrypt/live/foo.bar/fullchain.pem' + chain_path = os.path.normpath(os.path.join(self.config.config_dir, + 'live/foo.bar/fullchain.pem')) mock_lineage = mock.MagicMock(cert=cert_path, fullchain=chain_path, cert_path=cert_path, fullchain_path=chain_path) mock_lineage.should_autorenew.return_value = due_for_renewal From ca42945264c9a5d0663bae89949b0aa062895eba Mon Sep 17 00:00:00 2001 From: ohemorange Date: Tue, 20 Nov 2018 18:39:12 -0500 Subject: [PATCH 052/114] Fix test_sdists test farm test (#6524) * Switch to using _venv_common.py in test_sdists.sh * Upgrade setuptools in _venv_common.py * Upgrade setuptools before running pip_install --- tests/letstest/scripts/test_sdists.sh | 2 +- tools/_venv_common.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/letstest/scripts/test_sdists.sh b/tests/letstest/scripts/test_sdists.sh index f18a64065..0b9a91ffd 100755 --- a/tests/letstest/scripts/test_sdists.sh +++ b/tests/letstest/scripts/test_sdists.sh @@ -10,7 +10,7 @@ VERSION=$(letsencrypt-auto-source/version.py) export VENV_ARGS="-p $PYTHON" # setup venv -tools/_venv_common.sh --requirement letsencrypt-auto-source/pieces/dependency-requirements.txt +tools/_venv_common.py --requirement letsencrypt-auto-source/pieces/dependency-requirements.txt . ./venv/bin/activate # build sdists diff --git a/tools/_venv_common.py b/tools/_venv_common.py index 2a48b0d2e..ecd438f94 100755 --- a/tools/_venv_common.py +++ b/tools/_venv_common.py @@ -149,13 +149,15 @@ def main(venv_name, venv_args, args): command.extend(shlex.split(venv_args)) subprocess_with_print(command) - # We execute the two following commands in the context of the virtual environment, to install + # We execute the following commands in the context of the virtual environment, to install # the packages in it. To do so, we append the venv binary to the PATH that will be used for # these commands. With this trick, correct python executable will be selected. new_environ = os.environ.copy() new_environ['PATH'] = os.pathsep.join([get_venv_bin_path(venv_name), new_environ['PATH']]) subprocess_with_print('python {0}'.format('./letsencrypt-auto-source/pieces/pipstrap.py'), env=new_environ, shell=True) + subprocess_with_print("python -m pip install --upgrade 'setuptools>=30.3'", + env=new_environ, shell=True) subprocess_with_print('python {0} {1}'.format('./tools/pip_install.py', ' '.join(args)), env=new_environ, shell=True) From e8e3534335d09288ee84e93c0a3e9c044387c593 Mon Sep 17 00:00:00 2001 From: schoen Date: Tue, 20 Nov 2018 20:55:51 -0800 Subject: [PATCH 053/114] Add a random sleep for noninteractive renewals (#6393) * WIP on adding a random sleep for noninteractive renewal * Update changelog * Log the fact that we're randomly sleeping * stdin may better define interactivity than stdout * Try mocking time.sleep for all tests * Move mocked sleep elsewhere * mock the right object * Somewhat ugly synthetic PTY trick * Move set -u down below self-exec * Revert "Move set -u down below self-exec" This reverts commit 6bde65a7384131052a5c90abaca5028615fc5186. * Revert "Somewhat ugly synthetic PTY trick" This reverts commit 89c704a4be5722dc0babaf3358be1cdcfea240e3. * Log specific duration of random sleep * Test coverage for random sleep() logic in main.py --- CHANGELOG.md | 4 +++- certbot/main.py | 12 ++++++++++++ certbot/tests/main_test.py | 22 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a25890929..2bb08d4e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). ### Added -* +* Noninteractive renewals with `certbot renew` (those not started from a + terminal) now randomly sleep 1-480 seconds before beginning work in + order to spread out load spikes on the server side. ### Changed diff --git a/certbot/main.py b/certbot/main.py index 5d5251dd2..692dafeed 100644 --- a/certbot/main.py +++ b/certbot/main.py @@ -4,7 +4,9 @@ from __future__ import print_function import functools import logging.handlers import os +import random import sys +import time import configobj import josepy as jose @@ -1243,6 +1245,16 @@ def renew(config, unused_plugins): :rtype: None """ + if not sys.stdin.isatty(): + # Noninteractive renewals include a random delay in order to spread + # out the load on the certificate authority servers, even if many + # users all pick the same time for renewals. This delay precedes + # running any hooks, so that side effects of the hooks (such as + # shutting down a web service) aren't prolonged unnecessarily. + sleep_time = random.randint(1, 60*8) + logger.info("Non-interactive renewal: random delay of %s seconds", sleep_time) + time.sleep(sleep_time) + try: renewal.handle_renewal_request(config) finally: diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 6c35f1fdb..2e53606a2 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -520,6 +520,8 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met '--work-dir', self.config.work_dir, '--logs-dir', self.config.logs_dir, '--text'] + self.mock_sleep = mock.patch('time.sleep').start() + def tearDown(self): # Reset globals in cli reload_module(cli) @@ -1093,6 +1095,26 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met args = ["renew", "--reuse-key"] self._test_renewal_common(True, [], args=args, should_renew=True, reuse_key=True) + @mock.patch('sys.stdin') + def test_noninteractive_renewal_delay(self, stdin): + stdin.isatty.return_value = False + test_util.make_lineage(self.config.config_dir, 'sample-renewal.conf') + args = ["renew", "--dry-run", "-tvv"] + self._test_renewal_common(True, [], args=args, should_renew=True) + self.assertEqual(self.mock_sleep.call_count, 1) + # in main.py: + # sleep_time = random.randint(1, 60*8) + sleep_call_arg = self.mock_sleep.call_args[0][0] + self.assertTrue(1 <= sleep_call_arg <= 60*8) + + @mock.patch('sys.stdin') + def test_interactive_no_renewal_delay(self, stdin): + stdin.isatty.return_value = True + test_util.make_lineage(self.config.config_dir, 'sample-renewal.conf') + args = ["renew", "--dry-run", "-tvv"] + self._test_renewal_common(True, [], args=args, should_renew=True) + self.assertEqual(self.mock_sleep.call_count, 0) + @mock.patch('certbot.renewal.should_renew') def test_renew_skips_recent_certs(self, should_renew): should_renew.return_value = False From 41bf9c70f67ccbebe2d318d49e79da974ad96c7e Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Wed, 21 Nov 2018 23:49:04 +0100 Subject: [PATCH 054/114] Update pinned version of cffi to 1.11.5 (#6512) Current pinned version of cffi is 1.10.0. This version does not provide pre-compiled wheels for latest Python versions on Windows. This implies on this plateform, when certbot is installed, to compile cffi from sources. But for that, the computer will need to have the Visual C compiler available locally. This environnement is really heavy to setup, and totally outside of the scope. This PR updates cffi to version 1.11.5, that has the required wheels, and makes certbot installable without a full .NET dev profile. --- letsencrypt-auto-source/letsencrypt-auto | 70 +++++++++---------- .../pieces/dependency-requirements.txt | 70 +++++++++---------- 2 files changed, 66 insertions(+), 74 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 1417811f3..891aab85e 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -1046,43 +1046,39 @@ pycparser==2.14 \ asn1crypto==0.22.0 \ --hash=sha256:d232509fefcfcdb9a331f37e9c9dc20441019ad927c7d2176cf18ed5da0ba097 \ --hash=sha256:cbbadd640d3165ab24b06ef25d1dca09a3441611ac15f6a6b452474fdf0aed1a -cffi==1.10.0 \ - --hash=sha256:446699c10f3c390633d0722bc19edbc7ac4b94761918a4a4f7908a24e86ebbd0 \ - --hash=sha256:562326fc7f55a59ef3fef5e82908fe938cdc4bbda32d734c424c7cd9ed73e93a \ - --hash=sha256:7f732ad4a30db0b39400c3f7011249f7d0701007d511bf09604729aea222871f \ - --hash=sha256:94fb8410c6c4fc48e7ea759d3d1d9ca561171a88d00faddd4aa0306f698ad6a0 \ - --hash=sha256:587a5043df4b00a2130e09fed42da02a4ed3c688bd9bf07a3ac89d2271f4fb07 \ - --hash=sha256:ec08b88bef627ec1cea210e1608c85d3cf44893bcde74e41b7f7dbdfd2c1bad6 \ - --hash=sha256:a41406f6d62abcdf3eef9fd998d8dcff04fd2a7746644143045feeebd76352d1 \ - --hash=sha256:b560916546b2f209d74b82bdbc3223cee9a165b0242fa00a06dfc48a2054864a \ - --hash=sha256:e74896774e437f4715c57edeb5cf3d3a40d7727f541c2c12156617b5a15d1829 \ - --hash=sha256:9a31c18ba4881a116e448c52f3f5d3e14401cf7a9c43cc88f06f2a7f5428da0e \ - --hash=sha256:80796ea68e11624a0279d3b802f88a7fe7214122b97a15a6c97189934a2cc776 \ - --hash=sha256:f4019826a2dec066c909a1f483ef0dcf9325d6740cc0bd15308942b28b0930f7 \ - --hash=sha256:7248506981eeba23888b4140a69a53c4c0c0a386abcdca61ed8dd790a73e64b9 \ - --hash=sha256:a8955265d146e86fe2ce116394be4eaf0cb40314a79b19f11c4fa574cd639572 \ - --hash=sha256:c49187260043bd4c1d6a52186f9774f17d9b1da0a406798ebf4bfc12da166ade \ - --hash=sha256:c1d8b3d8dcb5c23ac1a8bf56422036f3f305a3c5a8bc8c354256579a1e2aa2c1 \ - --hash=sha256:9e389615bcecb8c782a87939d752340bb0a3a097e90bae54d7f0915bc12f45bd \ - --hash=sha256:d09ff358f75a874f69fa7d1c2b4acecf4282a950293fcfcf89aa606da8a9a500 \ - --hash=sha256:b69b4557aae7de18b7c174a917fe19873529d927ac592762d9771661875bbd40 \ - --hash=sha256:5de52b081a2775e76b971de9d997d85c4457fc0a09079e12d66849548ae60981 \ - --hash=sha256:e7d88fecb7b6250a1fd432e6dc64890342c372fce13dbfe4bb6f16348ad00c14 \ - --hash=sha256:1426e67e855ef7f5030c9184f4f1a9f4bfa020c31c962cd41fd129ec5aef4a6a \ - --hash=sha256:267dd2c66a5760c5f4d47e2ebcf8eeac7ef01e1ae6ae7a6d0d241a290068bc38 \ - --hash=sha256:e553eb489511cacf19eda6e52bc9e151316f0d721724997dda2c4d3079b778db \ - --hash=sha256:98b89b2c57f97ce2db7aeba60db173c84871d73b40e41a11ea95de1500ddc57e \ - --hash=sha256:e2b7e090188833bc58b2ae03fb864c22688654ebd2096bcf38bc860c4f38a3d8 \ - --hash=sha256:afa7d8b8d38ad40db8713ee053d41b36d87d6ae5ec5ad36f9210b548a18dc214 \ - --hash=sha256:4fc9c2ff7924b3a1fa326e1799e5dd58cac585d7fb25fe53ccaa1333b0453d65 \ - --hash=sha256:937db39a1ec5af3003b16357b2042bba67c88d43bc11aaa203fa8a5924524209 \ - --hash=sha256:ab22285797631df3b513b2cd3ecdc51cd8e3d36788e3991d93d0759d6883b027 \ - --hash=sha256:96e599b924ef009aa867f725b3249ee51d76489f484d3a45b4bd219c5ec6ed59 \ - --hash=sha256:bea842a0512be6a8007e585790bccd5d530520fc025ce63b03e139be373b0063 \ - --hash=sha256:e7175287f7fe7b1cc203bb958b17db40abd732690c1e18e700f10e0843a58598 \ - --hash=sha256:285ab352552f52f1398c912556d4d36d4ea9b8450e5c65d03809bf9886755533 \ - --hash=sha256:5576644b859197da7bbd8f8c7c2fb5dcc6cd505cadb42992d5f104c013f8a214 \ - --hash=sha256:b3b02911eb1f6ada203b0763ba924234629b51586f72a21faacc638269f4ced5 +cffi==1.11.5 \ + --hash=sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50 \ + --hash=sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596 \ + --hash=sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef \ + --hash=sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743 \ + --hash=sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f \ + --hash=sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31 \ + --hash=sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04 \ + --hash=sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6 \ + --hash=sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3 \ + --hash=sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6 \ + --hash=sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b \ + --hash=sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca \ + --hash=sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e \ + --hash=sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb \ + --hash=sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd \ + --hash=sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1 \ + --hash=sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917 \ + --hash=sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359 \ + --hash=sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f \ + --hash=sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95 \ + --hash=sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801 \ + --hash=sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257 \ + --hash=sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184 \ + --hash=sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc \ + --hash=sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085 \ + --hash=sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93 \ + --hash=sha256:ca1bd81f40adc59011f58159e4aa6445fc585a32bb8ac9badf7a2c1aa23822f2 \ + --hash=sha256:3bb6bd7266598f318063e584378b8e27c67de998a43362e8fce664c54ee52d30 \ + --hash=sha256:a6a5cb8809091ec9ac03edde9304b3ad82ad4466333432b16d78ef40e0cce0d5 \ + --hash=sha256:57b2533356cb2d8fac1555815929f7f5f14d68ac77b085d2326b571310f34f6e \ + --hash=sha256:495c5c2d43bf6cebe0178eb3e88f9c4aa48d8934aa6e3cddb865c058da76756b \ + --hash=sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4 ConfigArgParse==0.12.0 \ --hash=sha256:28cd7d67669651f2a4518367838c49539457504584a139709b2b8f6c208ef339 \ --no-binary ConfigArgParse diff --git a/letsencrypt-auto-source/pieces/dependency-requirements.txt b/letsencrypt-auto-source/pieces/dependency-requirements.txt index ae6079d96..eee0dd329 100644 --- a/letsencrypt-auto-source/pieces/dependency-requirements.txt +++ b/letsencrypt-auto-source/pieces/dependency-requirements.txt @@ -21,43 +21,39 @@ pycparser==2.14 \ asn1crypto==0.22.0 \ --hash=sha256:d232509fefcfcdb9a331f37e9c9dc20441019ad927c7d2176cf18ed5da0ba097 \ --hash=sha256:cbbadd640d3165ab24b06ef25d1dca09a3441611ac15f6a6b452474fdf0aed1a -cffi==1.10.0 \ - --hash=sha256:446699c10f3c390633d0722bc19edbc7ac4b94761918a4a4f7908a24e86ebbd0 \ - --hash=sha256:562326fc7f55a59ef3fef5e82908fe938cdc4bbda32d734c424c7cd9ed73e93a \ - --hash=sha256:7f732ad4a30db0b39400c3f7011249f7d0701007d511bf09604729aea222871f \ - --hash=sha256:94fb8410c6c4fc48e7ea759d3d1d9ca561171a88d00faddd4aa0306f698ad6a0 \ - --hash=sha256:587a5043df4b00a2130e09fed42da02a4ed3c688bd9bf07a3ac89d2271f4fb07 \ - --hash=sha256:ec08b88bef627ec1cea210e1608c85d3cf44893bcde74e41b7f7dbdfd2c1bad6 \ - --hash=sha256:a41406f6d62abcdf3eef9fd998d8dcff04fd2a7746644143045feeebd76352d1 \ - --hash=sha256:b560916546b2f209d74b82bdbc3223cee9a165b0242fa00a06dfc48a2054864a \ - --hash=sha256:e74896774e437f4715c57edeb5cf3d3a40d7727f541c2c12156617b5a15d1829 \ - --hash=sha256:9a31c18ba4881a116e448c52f3f5d3e14401cf7a9c43cc88f06f2a7f5428da0e \ - --hash=sha256:80796ea68e11624a0279d3b802f88a7fe7214122b97a15a6c97189934a2cc776 \ - --hash=sha256:f4019826a2dec066c909a1f483ef0dcf9325d6740cc0bd15308942b28b0930f7 \ - --hash=sha256:7248506981eeba23888b4140a69a53c4c0c0a386abcdca61ed8dd790a73e64b9 \ - --hash=sha256:a8955265d146e86fe2ce116394be4eaf0cb40314a79b19f11c4fa574cd639572 \ - --hash=sha256:c49187260043bd4c1d6a52186f9774f17d9b1da0a406798ebf4bfc12da166ade \ - --hash=sha256:c1d8b3d8dcb5c23ac1a8bf56422036f3f305a3c5a8bc8c354256579a1e2aa2c1 \ - --hash=sha256:9e389615bcecb8c782a87939d752340bb0a3a097e90bae54d7f0915bc12f45bd \ - --hash=sha256:d09ff358f75a874f69fa7d1c2b4acecf4282a950293fcfcf89aa606da8a9a500 \ - --hash=sha256:b69b4557aae7de18b7c174a917fe19873529d927ac592762d9771661875bbd40 \ - --hash=sha256:5de52b081a2775e76b971de9d997d85c4457fc0a09079e12d66849548ae60981 \ - --hash=sha256:e7d88fecb7b6250a1fd432e6dc64890342c372fce13dbfe4bb6f16348ad00c14 \ - --hash=sha256:1426e67e855ef7f5030c9184f4f1a9f4bfa020c31c962cd41fd129ec5aef4a6a \ - --hash=sha256:267dd2c66a5760c5f4d47e2ebcf8eeac7ef01e1ae6ae7a6d0d241a290068bc38 \ - --hash=sha256:e553eb489511cacf19eda6e52bc9e151316f0d721724997dda2c4d3079b778db \ - --hash=sha256:98b89b2c57f97ce2db7aeba60db173c84871d73b40e41a11ea95de1500ddc57e \ - --hash=sha256:e2b7e090188833bc58b2ae03fb864c22688654ebd2096bcf38bc860c4f38a3d8 \ - --hash=sha256:afa7d8b8d38ad40db8713ee053d41b36d87d6ae5ec5ad36f9210b548a18dc214 \ - --hash=sha256:4fc9c2ff7924b3a1fa326e1799e5dd58cac585d7fb25fe53ccaa1333b0453d65 \ - --hash=sha256:937db39a1ec5af3003b16357b2042bba67c88d43bc11aaa203fa8a5924524209 \ - --hash=sha256:ab22285797631df3b513b2cd3ecdc51cd8e3d36788e3991d93d0759d6883b027 \ - --hash=sha256:96e599b924ef009aa867f725b3249ee51d76489f484d3a45b4bd219c5ec6ed59 \ - --hash=sha256:bea842a0512be6a8007e585790bccd5d530520fc025ce63b03e139be373b0063 \ - --hash=sha256:e7175287f7fe7b1cc203bb958b17db40abd732690c1e18e700f10e0843a58598 \ - --hash=sha256:285ab352552f52f1398c912556d4d36d4ea9b8450e5c65d03809bf9886755533 \ - --hash=sha256:5576644b859197da7bbd8f8c7c2fb5dcc6cd505cadb42992d5f104c013f8a214 \ - --hash=sha256:b3b02911eb1f6ada203b0763ba924234629b51586f72a21faacc638269f4ced5 +cffi==1.11.5 \ + --hash=sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50 \ + --hash=sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596 \ + --hash=sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef \ + --hash=sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743 \ + --hash=sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f \ + --hash=sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31 \ + --hash=sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04 \ + --hash=sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6 \ + --hash=sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3 \ + --hash=sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6 \ + --hash=sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b \ + --hash=sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca \ + --hash=sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e \ + --hash=sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb \ + --hash=sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd \ + --hash=sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1 \ + --hash=sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917 \ + --hash=sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359 \ + --hash=sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f \ + --hash=sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95 \ + --hash=sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801 \ + --hash=sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257 \ + --hash=sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184 \ + --hash=sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc \ + --hash=sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085 \ + --hash=sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93 \ + --hash=sha256:ca1bd81f40adc59011f58159e4aa6445fc585a32bb8ac9badf7a2c1aa23822f2 \ + --hash=sha256:3bb6bd7266598f318063e584378b8e27c67de998a43362e8fce664c54ee52d30 \ + --hash=sha256:a6a5cb8809091ec9ac03edde9304b3ad82ad4466333432b16d78ef40e0cce0d5 \ + --hash=sha256:57b2533356cb2d8fac1555815929f7f5f14d68ac77b085d2326b571310f34f6e \ + --hash=sha256:495c5c2d43bf6cebe0178eb3e88f9c4aa48d8934aa6e3cddb865c058da76756b \ + --hash=sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4 ConfigArgParse==0.12.0 \ --hash=sha256:28cd7d67669651f2a4518367838c49539457504584a139709b2b8f6c208ef339 \ --no-binary ConfigArgParse From 3edb36c4cca925fec02c6133e9af7ee0dde324ae Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 22 Nov 2018 03:43:25 +0000 Subject: [PATCH 055/114] Revert acme/acme/client.py --- acme/acme/client.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index 54ae58764..adc8ad9e3 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -32,8 +32,11 @@ logger = logging.getLogger(__name__) # for SSL, which does allow these options to be configured. # https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning if sys.version_info < (2, 7, 9): # pragma: no cover - import urllib3.contrib.pyopenssl # pylint: disable=import-error - urllib3.contrib.pyopenssl.inject_into_urllib3() + try: + requests.packages.urllib3.contrib.pyopenssl.inject_into_urllib3() # type: ignore + except AttributeError: + import urllib3.contrib.pyopenssl # pylint: disable=import-error + urllib3.contrib.pyopenssl.inject_into_urllib3() DEFAULT_NETWORK_TIMEOUT = 45 From ff66b641e3b58eb732104d4dc9a2993417fefd6c Mon Sep 17 00:00:00 2001 From: schoen Date: Mon, 26 Nov 2018 11:46:57 -0800 Subject: [PATCH 056/114] Re-adding period --- docs/using.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/using.rst b/docs/using.rst index 8adf00d4d..20c2c0a36 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -696,7 +696,7 @@ Where are my certificates? ========================== All generated keys and issued certificates can be found in -``/etc/letsencrypt/live/$domain`` In the case of creating a SAN certificate +``/etc/letsencrypt/live/$domain``. In the case of creating a SAN certificate with multiple alternative names, ``$domain`` is the first domain passed in via -d parameter. Rather than copying, please point your (web) server configuration directly to those files (or create From f65cb070b3b75a04580f6d53561f88cfbd2a42ff Mon Sep 17 00:00:00 2001 From: ohemorange Date: Mon, 26 Nov 2018 17:48:59 -0500 Subject: [PATCH 057/114] Automation for changelog changes during release (#6489) * Automation for changelog changes during release * Update changelog during release before modifying version numbers * don't link to the GitHub repo * no need to sign the commit bumping version numbers * simplify tail call --- tools/_changelog_top.txt | 21 +++++++++++++++++++++ tools/_release.sh | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tools/_changelog_top.txt diff --git a/tools/_changelog_top.txt b/tools/_changelog_top.txt new file mode 100644 index 000000000..6983b3a43 --- /dev/null +++ b/tools/_changelog_top.txt @@ -0,0 +1,21 @@ +## nextversion - master + +### Added + +* + +### Changed + +* + +### Fixed + +* + +Despite us having broken lockstep, we are continuing to release new versions of +all Certbot components during releases for the time being, however, the only +package with changes other than its version number was: + +* + +More details about these changes can be found on our GitHub repo. diff --git a/tools/_release.sh b/tools/_release.sh index dab4eec3a..97e6e9c63 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -65,12 +65,19 @@ if [ "$RELEASE_BRANCH" != "candidate-$version" ] ; then fi git checkout "$RELEASE_BRANCH" +# Update changelog +sed -i "s/master/$(date +'%Y-%m-%d')/" CHANGELOG.md +git add CHANGELOG.md +git diff --cached +git commit -m "Update changelog for $version release" + for pkg_dir in $SUBPKGS_NO_CERTBOT certbot-compatibility-test . do sed -i 's/\.dev0//' "$pkg_dir/setup.py" git add "$pkg_dir/setup.py" done + SetVersion() { ver="$1" # bumping Certbot's version number is done differently @@ -232,6 +239,19 @@ echo tar cJvf $name.$rev.tar.xz $name.$rev echo gpg2 -U $RELEASE_GPG_KEY --detach-sign --armor $name.$rev.tar.xz cd ~- +# Add master section to CHANGELOG.md +header=$(head -n 4 CHANGELOG.md) +body=$(sed s/nextversion/$nextversion/ tools/_changelog_top.txt) +footer=$(tail -n +5 CHANGELOG.md) +echo "$header + +$body + +$footer" > CHANGELOG.md +git add CHANGELOG.md +git diff --cached +git commit -m "Add contents to CHANGELOG.md for next version" + echo "New root: $root" echo "Test commands (in the letstest repo):" echo 'python multitester.py targets.yaml $AWS_KEY $USERNAME scripts/test_leauto_upgrades.sh --alt_pip $YOUR_PIP_REPO --branch public-beta' From 1c23fea076caf7462096e35600058eaf200ca695 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Tue, 27 Nov 2018 17:24:34 -0800 Subject: [PATCH 058/114] ignore erroneously no-member lint error --- acme/acme/client.py | 1 + 1 file changed, 1 insertion(+) diff --git a/acme/acme/client.py b/acme/acme/client.py index adc8ad9e3..af52b44ed 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -33,6 +33,7 @@ logger = logging.getLogger(__name__) # https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning if sys.version_info < (2, 7, 9): # pragma: no cover try: + # pylint: disable=no-member requests.packages.urllib3.contrib.pyopenssl.inject_into_urllib3() # type: ignore except AttributeError: import urllib3.contrib.pyopenssl # pylint: disable=import-error From 7527a6c95908af7862d8bb2d91ddde2755e8ce16 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Wed, 28 Nov 2018 19:01:05 -0800 Subject: [PATCH 059/114] Remove "beta" label from Apache plugin. (#6537) --- certbot-apache/certbot_apache/configurator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-apache/certbot_apache/configurator.py b/certbot-apache/certbot_apache/configurator.py index f431b9dab..16de3a3d8 100644 --- a/certbot-apache/certbot_apache/configurator.py +++ b/certbot-apache/certbot_apache/configurator.py @@ -91,7 +91,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): """ - description = "Apache Web Server plugin - Beta" + description = "Apache Web Server plugin" OS_DEFAULTS = dict( server_root="/etc/apache2", From 7d0ac4713936193d35cc9e99f4dd99500d1ab718 Mon Sep 17 00:00:00 2001 From: sydneyli Date: Thu, 29 Nov 2018 09:33:05 -0800 Subject: [PATCH 060/114] Change default privkey permissions while preserving group permissions (#6480) Fixes #1473. writes privkey.pem to 0600 by default for new lineages on renewals where a new privkey is generated, preserves group mode and gid Things this PR does not do: we talked about forcing 0600 on privkeys when a Certbot upgrade is detected. Instead, this PR only creates new lineages with the more restrictive permission to prevent renewal breakages. this doesn't solve many of the problems mentioned in #1473 that are not directly related to the title issue! * safe_open on archive keyfiles * keep group from current lineage * clean up integration test * safe_open can follow symlinks * fix tests on windows, maybe * Address Brad's comments * Revert changes to safe_open * Test chown is called when saving new key * Reorder chown operation * Changelog and documentation * Fix documentation style --- CHANGELOG.md | 4 ++- certbot/storage.py | 22 ++++++++++---- certbot/tests/storage_test.py | 45 ++++++++++++++++++++++++++++ docs/using.rst | 4 +++ tests/certbot-boulder-integration.sh | 30 +++++++++++++++++++ 5 files changed, 98 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cec3eded3..4b10a5805 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,9 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). ### Changed -* +* Private key permissioning changes: Renewal preserves existing group mode + & gid of previous private key material. Private keys for new + lineages (i.e. new certs, not renewed) default to 0o600. ### Fixed diff --git a/certbot/storage.py b/certbot/storage.py index 664ff172a..c90a95a73 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -29,6 +29,7 @@ logger = logging.getLogger(__name__) ALL_FOUR = ("cert", "privkey", "chain", "fullchain") README = "README" CURRENT_VERSION = util.get_strict_version(certbot.__version__) +BASE_PRIVKEY_MODE = 0o600 def renewal_conf_files(config): @@ -1050,13 +1051,14 @@ class RenewableCert(object): # Put the data into the appropriate files on disk target = dict([(kind, os.path.join(live_dir, kind + ".pem")) for kind in ALL_FOUR]) + archive_target = dict([(kind, os.path.join(archive, kind + "1.pem")) + for kind in ALL_FOUR]) for kind in ALL_FOUR: - os.symlink(os.path.join(_relpath_from_file(archive, target[kind]), kind + "1.pem"), - target[kind]) + os.symlink(_relpath_from_file(archive_target[kind], target[kind]), target[kind]) with open(target["cert"], "wb") as f: logger.debug("Writing certificate to %s.", target["cert"]) f.write(cert) - with open(target["privkey"], "wb") as f: + with util.safe_open(archive_target["privkey"], "wb", chmod=BASE_PRIVKEY_MODE) as f: logger.debug("Writing private key to %s.", target["privkey"]) f.write(privkey) # XXX: Let's make sure to get the file permissions right here @@ -1120,14 +1122,15 @@ class RenewableCert(object): os.path.join(self.archive_dir, "{0}{1}.pem".format(kind, target_version))) for kind in ALL_FOUR]) + old_privkey = os.path.join( + self.archive_dir, "privkey{0}.pem".format(prior_version)) + # Distinguish the cases where the privkey has changed and where it # has not changed (in the latter case, making an appropriate symlink # to an earlier privkey version) if new_privkey is None: # The behavior below keeps the prior key by creating a new # symlink to the old key or the target of the old key symlink. - old_privkey = os.path.join( - self.archive_dir, "privkey{0}.pem".format(prior_version)) if os.path.islink(old_privkey): old_privkey = os.readlink(old_privkey) else: @@ -1135,9 +1138,16 @@ class RenewableCert(object): logger.debug("Writing symlink to old private key, %s.", old_privkey) os.symlink(old_privkey, target["privkey"]) else: - with open(target["privkey"], "wb") as f: + with util.safe_open(target["privkey"], "wb", chmod=BASE_PRIVKEY_MODE) as f: logger.debug("Writing new private key to %s.", target["privkey"]) f.write(new_privkey) + # If the previous privkey in this lineage has an existing gid or group mode > 0, + # let's keep those. + group_mode = stat.S_IMODE(os.stat(old_privkey).st_mode) & \ + (stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP) + mode = BASE_PRIVKEY_MODE | group_mode + os.chown(target["privkey"], -1, os.stat(old_privkey).st_gid) + os.chmod(target["privkey"], mode) # Save everything else with open(target["cert"], "wb") as f: diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 484ad7e16..5fd7746ed 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -13,6 +13,7 @@ import six import certbot from certbot import cli +from certbot import compat from certbot import errors from certbot.storage import ALL_FOUR @@ -91,6 +92,8 @@ class BaseRenewableCertTest(test_util.ConfigTestCase): link) with open(link, "wb") as f: f.write(kind.encode('ascii') if value is None else value) + if kind == "privkey": + os.chmod(link, 0o600) def _write_out_ex_kinds(self): for kind in ALL_FOUR: @@ -543,6 +546,47 @@ class RenewableCertTests(BaseRenewableCertTest): self.assertFalse(os.path.islink(self.test_rc.version("privkey", 10))) self.assertFalse(os.path.exists(temp_config_file)) + @test_util.broken_on_windows + @mock.patch("certbot.storage.relevant_values") + def test_save_successor_maintains_group_mode(self, mock_rv): + # Mock relevant_values() to claim that all values are relevant here + # (to avoid instantiating parser) + mock_rv.side_effect = lambda x: x + for kind in ALL_FOUR: + self._write_out_kind(kind, 1) + self.test_rc.update_all_links_to(1) + self.assertTrue(compat.compare_file_modes( + os.stat(self.test_rc.version("privkey", 1)).st_mode, 0o600)) + os.chmod(self.test_rc.version("privkey", 1), 0o444) + # If no new key, permissions should be the same (we didn't write any keys) + self.test_rc.save_successor(1, b"newcert", None, b"new chain", self.config) + self.assertTrue(compat.compare_file_modes( + os.stat(self.test_rc.version("privkey", 2)).st_mode, 0o444)) + # If new key, permissions should be rest to 600 + preserved group + self.test_rc.save_successor(2, b"newcert", b"new_privkey", b"new chain", self.config) + self.assertTrue(compat.compare_file_modes( + os.stat(self.test_rc.version("privkey", 3)).st_mode, 0o640)) + # If permissions reverted, next renewal will also revert permissions of new key + os.chmod(self.test_rc.version("privkey", 3), 0o404) + self.test_rc.save_successor(3, b"newcert", b"new_privkey", b"new chain", self.config) + self.assertTrue(compat.compare_file_modes( + os.stat(self.test_rc.version("privkey", 4)).st_mode, 0o600)) + + @test_util.broken_on_windows + @mock.patch("certbot.storage.relevant_values") + @mock.patch("certbot.storage.os.chown") + def test_save_successor_maintains_gid(self, mock_chown, mock_rv): + # Mock relevant_values() to claim that all values are relevant here + # (to avoid instantiating parser) + mock_rv.side_effect = lambda x: x + for kind in ALL_FOUR: + self._write_out_kind(kind, 1) + self.test_rc.update_all_links_to(1) + self.test_rc.save_successor(1, b"newcert", None, b"new chain", self.config) + self.assertFalse(mock_chown.called) + self.test_rc.save_successor(2, b"newcert", b"new_privkey", b"new chain", self.config) + self.assertTrue(mock_chown.called) + def _test_relevant_values_common(self, values): defaults = dict((option, cli.flag_default(option)) for option in ("authenticator", "installer", @@ -629,6 +673,7 @@ class RenewableCertTests(BaseRenewableCertTest): self.config.live_dir, "README"))) self.assertTrue(os.path.exists(os.path.join( self.config.live_dir, "the-lineage.com", "README"))) + self.assertTrue(compat.compare_file_modes(os.stat(result.key_path).st_mode, 0o600)) with open(result.fullchain, "rb") as f: self.assertEqual(f.read(), b"cert" + b"chain") # Let's do it again and make sure it makes a different lineage diff --git a/docs/using.rst b/docs/using.rst index 20c2c0a36..bd6bb5f8f 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -717,6 +717,10 @@ The following files are available: put it into a safe, however - your server still needs to access this file in order for SSL/TLS to work. + .. note:: As of Certbot version 0.29.0, private keys for new certificate + default to ``0600``. Any changes to the group mode or group owner (gid) + of this file will be preserved on renewals. + This is what Apache needs for `SSLCertificateKeyFile `_, and Nginx for `ssl_certificate_key diff --git a/tests/certbot-boulder-integration.sh b/tests/certbot-boulder-integration.sh index 73e668e28..709daa217 100755 --- a/tests/certbot-boulder-integration.sh +++ b/tests/certbot-boulder-integration.sh @@ -280,7 +280,29 @@ CheckCertCount() { fi } +CheckGroup() { + group_mode() { echo $((0`stat -c %a $1` & 070)); } + group_owner() { echo `stat -c %G $1`; } + if [ `group_mode $1` -ne `group_mode $2` ] ; then + echo "Expected group permission `group_mode $1`, got `group_mode $2` on file $2" + exit 1 + fi + if [ `group_owner $1` != `group_owner $2` ] ; then + echo "Expected group owner `group_owner $1`, got `group_owner $2` on file $2" + exit 1 + fi +} + +CheckOthersPermission() { + other_permission=$((0`stat -c %a $1` & 07)) + if [ $other_permission -ne 0 ] ; then + echo "Expected file $1 not to be accessible by others" + exit 1 + fi +} + CheckCertCount "le.wtf" 1 + # This won't renew (because it's not time yet) common_no_force_renew renew CheckCertCount "le.wtf" 1 @@ -294,6 +316,11 @@ rm -rf "$renewal_hooks_root" common renew --cert-name le.wtf --authenticator manual CheckCertCount "le.wtf" 2 +CheckOthersPermission "${root}/conf/archive/le.wtf/privkey1.pem" +CheckOthersPermission "${root}/conf/archive/le.wtf/privkey2.pem" +CheckGroup "${root}/conf/archive/le.wtf/privkey1.pem" "${root}/conf/archive/le.wtf/privkey2.pem" +chmod 0444 "${root}/conf/archive/le.wtf/privkey2.pem" + # test renewal with no executables in hook directories for hook_dir in $renewal_hooks_dirs; do touch "$hook_dir/file" @@ -310,6 +337,9 @@ CreateDirHooks sed -i "4arenew_before_expiry = 4 years" "$root/conf/renewal/le.wtf.conf" common_no_force_renew renew --rsa-key-size 2048 --no-directory-hooks CheckCertCount "le.wtf" 3 +CheckGroup "${root}/conf/archive/le.wtf/privkey2.pem" "${root}/conf/archive/le.wtf/privkey3.pem" +CheckOthersPermission "${root}/conf/archive/le.wtf/privkey3.pem" + if [ -s "$HOOK_DIRS_TEST" ]; then echo "Directory hooks were executed with --no-directory-hooks!" >&2 exit 1 From 8b5ac9e2573de9dfd4182bdcd98d7262a2bdc8f0 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 29 Nov 2018 15:42:08 -0800 Subject: [PATCH 061/114] Ask people not to rewrite commits. (#6538) --- docs/contributing.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index ead4d7e2b..f05b0fa9a 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -359,7 +359,10 @@ Steps: 4. Run ``tox --skip-missing-interpreters`` to run the entire test suite including coverage. The ``--skip-missing-interpreters`` argument ignores missing versions of Python needed for running the tests. Fix any errors. -5. Submit the PR. +5. Submit the PR. Once your PR is open, please do not force push to the branch + containing your pull request to squash or amend commits. We use `squash + merges `_ on PRs and + rewriting commits makes changes harder to track between reviews. 6. Did your tests pass on Travis? If they didn't, fix any errors. Asking for help From 0b5468e992ab57fa028ddf33ca2351cb37c8e1ee Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Fri, 30 Nov 2018 01:42:06 +0100 Subject: [PATCH 062/114] Implement POST-as-GET requests (#6522) * Setup an integration tests env against Pebble, that enforce post-as-get * Implement POST-as-GET requests, with fallback to GET. * Fix unit tests * Fix coverage. * Fix or ignore lint errors * Corrections after review * Correct test * Try a simple delegate approach * Add a test * Simplify test mocking * Clean comment --- acme/acme/client.py | 92 ++++++++++++++++++++--------- acme/acme/client_test.py | 30 +++++++++- tests/certbot-pebble-integration.sh | 16 +++++ tests/pebble-fetch.sh | 41 +++++++++++++ 4 files changed, 150 insertions(+), 29 deletions(-) create mode 100755 tests/certbot-pebble-integration.sh create mode 100755 tests/pebble-fetch.sh diff --git a/acme/acme/client.py b/acme/acme/client.py index af52b44ed..88938e999 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -200,22 +200,6 @@ class ClientBase(object): # pylint: disable=too-many-instance-attributes return datetime.datetime.now() + datetime.timedelta(seconds=seconds) - def poll(self, authzr): - """Poll Authorization Resource for status. - - :param authzr: Authorization Resource - :type authzr: `.AuthorizationResource` - - :returns: Updated Authorization Resource and HTTP response. - - :rtype: (`.AuthorizationResource`, `requests.Response`) - - """ - response = self.net.get(authzr.uri) - updated_authzr = self._authzr_from_response( - response, authzr.body.identifier, authzr.uri) - return updated_authzr, response - def _revoke(self, cert, rsn, url): """Revoke certificate. @@ -237,6 +221,7 @@ class ClientBase(object): # pylint: disable=too-many-instance-attributes raise errors.ClientError( 'Successful revocation must return HTTP OK status') + class Client(ClientBase): """ACME client for a v1 API. @@ -389,6 +374,22 @@ class Client(ClientBase): body=jose.ComparableX509(OpenSSL.crypto.load_certificate( OpenSSL.crypto.FILETYPE_ASN1, response.content))) + def poll(self, authzr): + """Poll Authorization Resource for status. + + :param authzr: Authorization Resource + :type authzr: `.AuthorizationResource` + + :returns: Updated Authorization Resource and HTTP response. + + :rtype: (`.AuthorizationResource`, `requests.Response`) + + """ + response = self.net.get(authzr.uri) + updated_authzr = self._authzr_from_response( + response, authzr.body.identifier, authzr.uri) + return updated_authzr, response + def poll_and_request_issuance( self, csr, authzrs, mintime=5, max_attempts=10): """Poll and request issuance. @@ -652,13 +653,29 @@ class ClientV2(ClientBase): body = messages.Order.from_json(response.json()) authorizations = [] for url in body.authorizations: - authorizations.append(self._authzr_from_response(self.net.get(url), uri=url)) + authorizations.append(self._authzr_from_response(self._post_as_get(url), uri=url)) return messages.OrderResource( body=body, uri=response.headers.get('Location'), authorizations=authorizations, csr_pem=csr_pem) + def poll(self, authzr): + """Poll Authorization Resource for status. + + :param authzr: Authorization Resource + :type authzr: `.AuthorizationResource` + + :returns: Updated Authorization Resource and HTTP response. + + :rtype: (`.AuthorizationResource`, `requests.Response`) + + """ + response = self._post_as_get(authzr.uri) + updated_authzr = self._authzr_from_response( + response, authzr.body.identifier, authzr.uri) + return updated_authzr, response + def poll_and_finalize(self, orderr, deadline=None): """Poll authorizations and finalize the order. @@ -682,7 +699,7 @@ class ClientV2(ClientBase): responses = [] for url in orderr.body.authorizations: while datetime.datetime.now() < deadline: - authzr = self._authzr_from_response(self.net.get(url), uri=url) + authzr = self._authzr_from_response(self._post_as_get(url), uri=url) if authzr.body.status != messages.STATUS_PENDING: responses.append(authzr) break @@ -717,12 +734,12 @@ class ClientV2(ClientBase): self._post(orderr.body.finalize, wrapped_csr) while datetime.datetime.now() < deadline: time.sleep(1) - response = self.net.get(orderr.uri) + response = self._post_as_get(orderr.uri) body = messages.Order.from_json(response.json()) if body.error is not None: raise errors.IssuanceError(body.error) if body.certificate is not None: - certificate_response = self.net.get(body.certificate, + certificate_response = self._post_as_get(body.certificate, content_type=DER_CONTENT_TYPE).text return orderr.update(body=body, fullchain_pem=certificate_response) raise errors.TimeoutError() @@ -740,6 +757,32 @@ class ClientV2(ClientBase): """ return self._revoke(cert, rsn, self.directory['revokeCert']) + def _post_as_get(self, *args, **kwargs): + """ + Send GET request using the POST-as-GET protocol if needed. + The request will be first issued using POST-as-GET for ACME v2. If the ACME CA servers do + not support this yet and return an error, request will be retried using GET. + For ACME v1, only GET request will be tried, as POST-as-GET is not supported. + :param args: + :param kwargs: + :return: + """ + if self.acme_version >= 2: + # We add an empty payload for POST-as-GET requests + new_args = args[:1] + (None,) + args[1:] + try: + return self._post(*new_args, **kwargs) # pylint: disable=star-args + except messages.Error as error: + if error.code == 'malformed': + logger.debug('Error during a POST-as-GET request, ' + 'your ACME CA may not support it:\n%s', error) + logger.debug('Retrying request with GET.') + else: # pragma: no cover + raise + + # If POST-as-GET is not supported yet, we use a GET instead. + return self.net.get(*args, **kwargs) + class BackwardsCompatibleClientV2(object): """ACME client wrapper that tends towards V2-style calls, but @@ -769,12 +812,7 @@ class BackwardsCompatibleClientV2(object): self.client = ClientV2(directory, net=net) def __getattr__(self, name): - if name in vars(self.client): - return getattr(self.client, name) - elif name in dir(ClientBase): - return getattr(self.client, name) - else: - raise AttributeError() + return getattr(self.client, name) def new_account_and_tos(self, regr, check_tos_cb=None): """Combined register and agree_tos for V1, new_account for V2 @@ -944,7 +982,7 @@ class ClientNetwork(object): # pylint: disable=too-many-instance-attributes :rtype: `josepy.JWS` """ - jobj = obj.json_dumps(indent=2).encode() + jobj = obj.json_dumps(indent=2).encode() if obj else b'' logger.debug('JWS payload:\n%s', jobj) kwargs = { "alg": self.alg, diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 18b61d537..8b6cda47e 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -1,4 +1,5 @@ """Tests for acme.client.""" +# pylint: disable=too-many-lines import copy import datetime import json @@ -730,9 +731,10 @@ class ClientV2Test(ClientTestBase): authz_response2 = self.response authz_response2.json.return_value = self.authz2.to_json() authz_response2.headers['Location'] = self.authzr2.uri - self.net.get.side_effect = (authz_response, authz_response2) - self.assertEqual(self.client.new_order(CSR_SAN_PEM), self.orderr) + with mock.patch('acme.client.ClientV2._post_as_get') as mock_post_as_get: + mock_post_as_get.side_effect = (authz_response, authz_response2) + self.assertEqual(self.client.new_order(CSR_SAN_PEM), self.orderr) @mock.patch('acme.client.datetime') def test_poll_and_finalize(self, mock_datetime): @@ -821,6 +823,30 @@ class ClientV2Test(ClientTestBase): self.response.json.return_value = self.regr.body.update( contact=()).to_json() + def test_post_as_get(self): + with mock.patch('acme.client.ClientV2._authzr_from_response') as mock_client: + mock_client.return_value = self.authzr2 + + self.client.poll(self.authzr2) # pylint: disable=protected-access + + self.client.net.post.assert_called_once_with( + self.authzr2.uri, None, acme_version=2, + new_nonce_url='https://www.letsencrypt-demo.org/acme/new-nonce') + self.client.net.get.assert_not_called() + + class FakeError(messages.Error): # pylint: disable=too-many-ancestors + """Fake error to reproduce a malformed request ACME error""" + def __init__(self): # pylint: disable=super-init-not-called + pass + @property + def code(self): + return 'malformed' + self.client.net.post.side_effect = FakeError() + + self.client.poll(self.authzr2) # pylint: disable=protected-access + + self.client.net.get.assert_called_once_with(self.authzr2.uri) + class MockJSONDeSerializable(jose.JSONDeSerializable): # pylint: disable=missing-docstring diff --git a/tests/certbot-pebble-integration.sh b/tests/certbot-pebble-integration.sh new file mode 100755 index 000000000..8711f72c1 --- /dev/null +++ b/tests/certbot-pebble-integration.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Simple integration test. Make sure to activate virtualenv beforehand +# (source venv/bin/activate) and that you are running Pebble test +# instance (see ./pebble-fetch.sh). + +cleanup_and_exit() { + EXIT_STATUS=$? + unset SERVER + exit $EXIT_STATUS +} + +trap cleanup_and_exit EXIT + +export SERVER=https://localhost:14000/dir + +./tests/certbot-boulder-integration.sh diff --git a/tests/pebble-fetch.sh b/tests/pebble-fetch.sh new file mode 100755 index 000000000..b0ba08961 --- /dev/null +++ b/tests/pebble-fetch.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Download and run Pebble instance for integration testing +set -xe + +PEBBLE_VERSION=2018-11-02 + +# We reuse the same GOPATH-style directory than for Boulder. +# Pebble does not need it, but it will make the installation consistent with Boulder's one. +export GOPATH=${GOPATH:-$HOME/gopath} +PEBBLEPATH=${PEBBLEPATH:-$GOPATH/src/github.com/letsencrypt/pebble} + +mkdir -p ${PEBBLEPATH} + +cat << UNLIKELY_EOF > "$PEBBLEPATH/docker-compose.yml" +version: '3' + +services: + pebble: + image: letsencrypt/pebble:${PEBBLE_VERSION} + command: pebble -strict ${PEBBLE_STRICT:-false} -dnsserver 10.77.77.1 + ports: + - 14000:14000 + environment: + - PEBBLE_VA_NOSLEEP=1 +UNLIKELY_EOF + +docker-compose -f "$PEBBLEPATH/docker-compose.yml" up -d pebble + +set +x # reduce verbosity while waiting for boulder +for n in `seq 1 150` ; do + if curl -k https://localhost:14000/dir 2>/dev/null; then + break + else + sleep 1 + fi +done + +if ! curl -k https://localhost:14000/dir 2>/dev/null; then + echo "timed out waiting for pebble to start" + exit 1 +fi From 73458daac92c56bb211517a333e52fc1fef09715 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 30 Nov 2018 14:44:47 -0800 Subject: [PATCH 063/114] whitelist docker-compose (#6516) --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index e38f1311e..61cee8eff 100644 --- a/tox.ini +++ b/tox.ini @@ -241,5 +241,5 @@ passenv = DOCKER_* commands = docker-compose run --rm --service-ports development bash -c 'tox -e lint' whitelist_externals = - docker + docker-compose passenv = DOCKER_* From d461655ec60c172544ddcdccde972d4bbd4f6ceb Mon Sep 17 00:00:00 2001 From: hannay Mohanna Date: Fri, 30 Nov 2018 17:59:19 -0600 Subject: [PATCH 064/114] removed unused sys imports (#6546) --- certbot-dns-gehirn/setup.py | 2 -- certbot-dns-linode/setup.py | 2 -- certbot-dns-ovh/setup.py | 2 -- certbot-dns-sakuracloud/setup.py | 2 -- 4 files changed, 8 deletions(-) diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 94ca74761..97d7ca699 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -1,5 +1,3 @@ -import sys - from setuptools import setup from setuptools import find_packages diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 4c2571f96..5cff50196 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -1,5 +1,3 @@ -import sys - from setuptools import setup from setuptools import find_packages diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 68ede8006..a0e62caa5 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -1,5 +1,3 @@ -import sys - from setuptools import setup from setuptools import find_packages diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 5af4c8a00..2222999d5 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -1,5 +1,3 @@ -import sys - from setuptools import setup from setuptools import find_packages From 11dae13c2f95a36e3d0715b8626a6e7663e33a41 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 30 Nov 2018 17:40:30 -0800 Subject: [PATCH 065/114] Fix oldest Certbot version that works with Apache. (#6549) --- certbot-apache/local-oldest-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-apache/local-oldest-requirements.txt b/certbot-apache/local-oldest-requirements.txt index e70ac0c7f..fd8869f7c 100644 --- a/certbot-apache/local-oldest-requirements.txt +++ b/certbot-apache/local-oldest-requirements.txt @@ -1,2 +1,2 @@ acme[dev]==0.25.0 --e .[dev] +certbot[dev]==0.26.0 From 37d4b983c8abea179874b7d7c83d7dc8f4e41d0b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 30 Nov 2018 17:40:55 -0800 Subject: [PATCH 066/114] Don't use pytest.ini during the release. (#6550) Currently the release script in master fails for a few reasons. First, it's trying to use --numprocesses which comes from a pytest plugin that we're not installing in the release script. Second, many new warnings are raised when we're not using pinned versions of our dependencies. I'm not sure I agree, but one could argue that we should fix these issues and use the file during the release. I'm particularly hesitant for us to do this when it comes to warnings. We currently do not pin our dependencies in the release script. Do we really want to stop the release because a new package was released and is warning about something? One could argue we do because these warnings may be visible to the user, but they very rarely are and I think this makes the release process much too painful. I especially do not think we should block the release on this now as we are not up to date on the warnings raised by the latest versions of our packages so there is a lot to work through. * Don't use pytest.ini during the release. * State that pytest.ini isn't used in release script. --- pytest.ini | 5 ++++- tools/_release.sh | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pytest.ini b/pytest.ini index de1ecf267..9a5807f34 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,6 @@ +# This file isn't used while testing packages in tools/_release.sh so any +# settings we want to also change there must be added to the release script +# directly. [pytest] addopts = --numprocesses auto --pyargs # ResourceWarnings are ignored as errors, since they're raised at close @@ -6,4 +9,4 @@ addopts = --numprocesses auto --pyargs filterwarnings = error ignore:decodestring:DeprecationWarning - ignore:TLS-SNI-01:DeprecationWarning \ No newline at end of file + ignore:TLS-SNI-01:DeprecationWarning diff --git a/tools/_release.sh b/tools/_release.sh index 97e6e9c63..dd08974ae 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -169,7 +169,8 @@ pip freeze | tee $kgs pip install pytest for module in $subpkgs_modules ; do echo testing $module - pytest --pyargs $module + # use an empty configuration file rather than the one in the repo root + pytest -c <(echo '') --pyargs $module done cd ~- From 1f4297d0edc46801176bc072276db59126483f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20K=C3=A4stel?= Date: Tue, 4 Dec 2018 00:27:35 +0100 Subject: [PATCH 067/114] WIP External Account Binding (#6059) * Rough draft of External Account Binding. * Remove parameter --eab and namespace kid and hmac. Also add parameters to "register" subcommand. * Refactor as much as possible of the EAB functionality into ExternalAccountBinding class. * Remove debug line. * Added external account binding to Directory.Meta. * Rename to account_public_key, hmac_key and make some non-optional. Rename command line argument to --eab-hmac-key. * Error out when the server requires External Account Binding and the user has not supplied kid and hmac key. * Remove whitespace. * Refactor a bit to make it possible to set the url argument. * Move from_data method into client. * Revert "Move from_data method into client." This reverts commit 8963fae * Refactored to use json field on Registration. * Inherit from object according to Google Python Style Guide. * Move to two separate ifs. * Get tests to pass after External Account Binding additions. * messages.py back to 100% test coverage with some EAB tests. * .encode() this JSON key. * Set eab parameter default values to None. * * Remove unnecessary public key mock on most of the test. * Restructure the directory mock to be able to mock both True and False for externalAccountRequired easily. * Add EAB client tests. * Move external_account_required check into BackwardsCompatibleClientV2 to be able to mock it. * Update versions. * Try 0.29.0. * Revert "Try 0.29.0." This reverts commit 5779509 * Try 0.29.0 again. * Try this. * Fix pylint failures. * Add tests for external_account_required method. * Test not needed, avoid: ************* Module acme.client_test C: 1, 0: Too many lines in module (1258/1250) (too-many-lines) * Move real external_account_required method into ClientV2 and pass through to it in BackwardsCompatibleClientV2. * Handle missing meta key in server ACME directory. * Add docstring for BackwardsCompatibleClientV2.external_account_required(). * Add tests for BackwardsCompatibleClientV2.external_account_required(). * Fix coverage for ACMEv1 code in BackwardsCompatibleClientV2. * Disable pylint too-many-lines check for client_test.py. * Fix versions. * Remove whitespace that accidently snuck into an earlier commit. * Remove these two stray whitespaces also. * And the last couple of whitespaces. * Add External Account Binding to changelog. * Add dev0 suffix to setup.py. Co-Authored-By: robaman * Set to "-e acme[dev]" again. Co-Authored-By: robaman --- CHANGELOG.md | 2 + acme/acme/client.py | 16 ++++++++ acme/acme/client_test.py | 48 +++++++++++++++++++++++ acme/acme/messages.py | 29 +++++++++++++- acme/acme/messages_test.py | 34 +++++++++++++++++ certbot/cli.py | 12 ++++++ certbot/client.py | 22 ++++++++++- certbot/constants.py | 2 + certbot/tests/client_test.py | 72 ++++++++++++++++++++++++++++++++++- local-oldest-requirements.txt | 2 +- setup.py | 2 +- 11 files changed, 234 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b10a5805..03f93a881 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). * Noninteractive renewals with `certbot renew` (those not started from a terminal) now randomly sleep 1-480 seconds before beginning work in order to spread out load spikes on the server side. +* Added External Account Binding support in cli and acme library. + Command line arguments --eab-kid and --eab-hmac-key added. ### Changed diff --git a/acme/acme/client.py b/acme/acme/client.py index 88938e999..41338e17e 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -757,6 +757,13 @@ class ClientV2(ClientBase): """ return self._revoke(cert, rsn, self.directory['revokeCert']) + def external_account_required(self): + """Checks if ACME server requires External Account Binding authentication.""" + if hasattr(self.directory, 'meta') and self.directory.meta.external_account_required: + return True + else: + return False + def _post_as_get(self, *args, **kwargs): """ Send GET request using the POST-as-GET protocol if needed. @@ -919,6 +926,15 @@ class BackwardsCompatibleClientV2(object): else: return 1 + def external_account_required(self): + """Checks if the server requires an external account for ACMEv2 servers. + + Always return False for ACMEv1 servers, as it doesn't use External Account Binding.""" + if self.acme_version == 1: + return False + else: + return self.client.external_account_required() + class ClientNetwork(object): # pylint: disable=too-many-instance-attributes """Wrapper around requests that signs POSTs for authentication. diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 8b6cda47e..33ae3886b 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -284,6 +284,37 @@ class BackwardsCompatibleClientV2Test(ClientTestBase): client.update_registration(mock.sentinel.regr, None) mock_client().update_registration.assert_called_once_with(mock.sentinel.regr, None) + # newNonce present means it will pick acme_version 2 + def test_external_account_required_true(self): + self.response.json.return_value = messages.Directory({ + 'newNonce': 'http://letsencrypt-test.com/acme/new-nonce', + 'meta': messages.Directory.Meta(external_account_required=True), + }).to_json() + + client = self._init() + + self.assertTrue(client.external_account_required()) + + # newNonce present means it will pick acme_version 2 + def test_external_account_required_false(self): + self.response.json.return_value = messages.Directory({ + 'newNonce': 'http://letsencrypt-test.com/acme/new-nonce', + 'meta': messages.Directory.Meta(external_account_required=False), + }).to_json() + + client = self._init() + + self.assertFalse(client.external_account_required()) + + def test_external_account_required_false_v1(self): + self.response.json.return_value = messages.Directory({ + 'meta': messages.Directory.Meta(external_account_required=False), + }).to_json() + + client = self._init() + + self.assertFalse(client.external_account_required()) + class ClientTest(ClientTestBase): """Tests for acme.client.Client.""" @@ -823,6 +854,23 @@ class ClientV2Test(ClientTestBase): self.response.json.return_value = self.regr.body.update( contact=()).to_json() + def test_external_account_required_true(self): + self.client.directory = messages.Directory({ + 'meta': messages.Directory.Meta(external_account_required=True) + }) + + self.assertTrue(self.client.external_account_required()) + + def test_external_account_required_false(self): + self.client.directory = messages.Directory({ + 'meta': messages.Directory.Meta(external_account_required=False) + }) + + self.assertFalse(self.client.external_account_required()) + + def test_external_account_required_default(self): + self.assertFalse(self.client.external_account_required()) + def test_post_as_get(self): with mock.patch('acme.client.ClientV2._authzr_from_response') as mock_client: mock_client.return_value = self.authzr2 diff --git a/acme/acme/messages.py b/acme/acme/messages.py index 7e86b0c3b..4400a6c31 100644 --- a/acme/acme/messages.py +++ b/acme/acme/messages.py @@ -1,6 +1,7 @@ """ACME protocol messages.""" import collections import six +import json import josepy as jose @@ -8,6 +9,7 @@ from acme import challenges from acme import errors from acme import fields from acme import util +from acme import jws OLD_ERROR_PREFIX = "urn:acme:error:" ERROR_PREFIX = "urn:ietf:params:acme:error:" @@ -27,6 +29,7 @@ ERROR_CODES = { 'tls': 'The server experienced a TLS error during domain verification', 'unauthorized': 'The client lacks sufficient authorization', 'unknownHost': 'The server could not resolve a domain name', + 'externalAccountRequired': 'The server requires external account binding', } ERROR_TYPE_DESCRIPTIONS = dict( @@ -176,6 +179,7 @@ class Directory(jose.JSONDeSerializable): _terms_of_service_v2 = jose.Field('termsOfService', omitempty=True) website = jose.Field('website', omitempty=True) caa_identities = jose.Field('caaIdentities', omitempty=True) + external_account_required = jose.Field('externalAccountRequired', omitempty=True) def __init__(self, **kwargs): kwargs = dict((self._internal_name(k), v) for k, v in kwargs.items()) @@ -258,6 +262,24 @@ class ResourceBody(jose.JSONObjectWithFields): """ACME Resource Body.""" +class ExternalAccountBinding(object): + """ACME External Account Binding""" + + @classmethod + def from_data(cls, account_public_key, kid, hmac_key, directory): + """Create External Account Binding Resource from contact details, kid and hmac.""" + + key_json = json.dumps(account_public_key.to_partial_json()).encode() + decoded_hmac_key = jose.b64.b64decode(hmac_key) + url = directory["newAccount"] + + eab = jws.JWS.sign(key_json, jose.jwk.JWKOct(key=decoded_hmac_key), + jose.jwa.HS256, None, + url, kid) + + return eab.to_partial_json() + + class Registration(ResourceBody): """Registration Resource Body. @@ -275,12 +297,13 @@ class Registration(ResourceBody): status = jose.Field('status', omitempty=True) terms_of_service_agreed = jose.Field('termsOfServiceAgreed', omitempty=True) only_return_existing = jose.Field('onlyReturnExisting', omitempty=True) + external_account_binding = jose.Field('externalAccountBinding', omitempty=True) phone_prefix = 'tel:' email_prefix = 'mailto:' @classmethod - def from_data(cls, phone=None, email=None, **kwargs): + def from_data(cls, phone=None, email=None, external_account_binding=None, **kwargs): """Create registration resource from contact details.""" details = list(kwargs.pop('contact', ())) if phone is not None: @@ -288,6 +311,10 @@ class Registration(ResourceBody): if email is not None: details.extend([cls.email_prefix + mail for mail in email.split(',')]) kwargs['contact'] = tuple(details) + + if external_account_binding: + kwargs['external_account_binding'] = external_account_binding + return cls(**kwargs) def _filter_contact(self, prefix): diff --git a/acme/acme/messages_test.py b/acme/acme/messages_test.py index 876fbe825..7efaaa1a3 100644 --- a/acme/acme/messages_test.py +++ b/acme/acme/messages_test.py @@ -174,6 +174,24 @@ class DirectoryTest(unittest.TestCase): self.assertTrue(result) +class ExternalAccountBindingTest(unittest.TestCase): + def setUp(self): + from acme.messages import Directory + self.key = jose.jwk.JWKRSA(key=KEY.public_key()) + self.kid = "kid-for-testing" + self.hmac_key = "hmac-key-for-testing" + self.dir = Directory({ + 'newAccount': 'http://url/acme/new-account', + }) + + def test_from_data(self): + from acme.messages import ExternalAccountBinding + eab = ExternalAccountBinding.from_data(self.key, self.kid, self.hmac_key, self.dir) + + self.assertEqual(len(eab), 3) + self.assertEqual(sorted(eab.keys()), sorted(['protected', 'payload', 'signature'])) + + class RegistrationTest(unittest.TestCase): """Tests for acme.messages.Registration.""" @@ -205,6 +223,22 @@ class RegistrationTest(unittest.TestCase): 'mailto:admin@foo.com', )) + def test_new_registration_from_data_with_eab(self): + from acme.messages import NewRegistration, ExternalAccountBinding, Directory + key = jose.jwk.JWKRSA(key=KEY.public_key()) + kid = "kid-for-testing" + hmac_key = "hmac-key-for-testing" + directory = Directory({ + 'newAccount': 'http://url/acme/new-account', + }) + eab = ExternalAccountBinding.from_data(key, kid, hmac_key, directory) + reg = NewRegistration.from_data(email='admin@foo.com', external_account_binding=eab) + self.assertEqual(reg.contact, ( + 'mailto:admin@foo.com', + )) + self.assertEqual(sorted(reg.external_account_binding.keys()), + sorted(['protected', 'payload', 'signature'])) + def test_phones(self): self.assertEqual(('1234',), self.reg.phones) diff --git a/certbot/cli.py b/certbot/cli.py index 882ddba86..7d2a6ccfc 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -944,6 +944,18 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis "specified or you already have a certificate with the same " "name. In the case of a name collision it will append a number " "like 0001 to the file path name. (default: Ask)") + helpful.add( + [None, "run", "certonly", "register"], + "--eab-kid", dest="eab_kid", + metavar="EAB_KID", + help="Key Identifier for External Account Binding" + ) + helpful.add( + [None, "run", "certonly", "register"], + "--eab-hmac-key", dest="eab_hmac_key", + metavar="EAB_HMAC_KEY", + help="HMAC key for External Account Binding" + ) helpful.add( [None, "run", "certonly", "manage", "delete", "certificates", "renew", "enhance"], "--cert-name", dest="certname", diff --git a/certbot/client.py b/certbot/client.py index e634b6bd9..38b77a772 100644 --- a/certbot/client.py +++ b/certbot/client.py @@ -203,9 +203,27 @@ def perform_registration(acme, config, tos_cb): :returns: Registration Resource. :rtype: `acme.messages.RegistrationResource` """ + + eab_credentials_supplied = config.eab_kid and config.eab_hmac_key + if eab_credentials_supplied: + account_public_key = acme.client.net.key.public_key() + eab = messages.ExternalAccountBinding.from_data(account_public_key=account_public_key, + kid=config.eab_kid, + hmac_key=config.eab_hmac_key, + directory=acme.client.directory) + else: + eab = None + + if acme.external_account_required(): + if not eab_credentials_supplied: + msg = ("Server requires external account binding." + " Please use --eab-kid and --eab-hmac-key.") + raise errors.Error(msg) + try: - return acme.new_account_and_tos(messages.NewRegistration.from_data(email=config.email), - tos_cb) + newreg = messages.NewRegistration.from_data(email=config.email, + external_account_binding=eab) + return acme.new_account_and_tos(newreg, tos_cb) except messages.Error as e: if e.code == "invalidEmail" or e.code == "invalidContact": if config.noninteractive_mode: diff --git a/certbot/constants.py b/certbot/constants.py index 5bf68589d..eb4105f82 100644 --- a/certbot/constants.py +++ b/certbot/constants.py @@ -68,6 +68,8 @@ CLI_DEFAULTS = dict( directory_hooks=True, reuse_key=False, disable_renew_updates=False, + eab_hmac_key=None, + eab_kid=None, # Subparsers num=None, diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index a4e70ce35..330529fc6 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -13,6 +13,8 @@ from certbot import util import certbot.tests.util as test_util +from josepy import interfaces + KEY = test_util.load_vector("rsa512_key.pem") CSR_SAN = test_util.load_vector("csr-san_512.pem") @@ -64,9 +66,28 @@ class RegisterTest(test_util.ConfigTestCase): tos_cb = mock.MagicMock() return register(self.config, self.account_storage, tos_cb) + @staticmethod + def _public_key_mock(): + m = mock.Mock(__class__=interfaces.JSONDeSerializable) + m.to_partial_json.return_value = '{"a": 1}' + return m + + @staticmethod + def _new_acct_dir_mock(): + return "/acme/new-account" + + @staticmethod + def _true_mock(): + return True + + @staticmethod + def _false_mock(): + return False + def test_no_tos(self): with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: mock_client.new_account_and_tos().terms_of_service = "http://tos" + mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot.eff.handle_subscription") as mock_handle: with mock.patch("certbot.account.report_new_account"): mock_client().new_account_and_tos.side_effect = errors.Error @@ -78,7 +99,8 @@ class RegisterTest(test_util.ConfigTestCase): self.assertTrue(mock_handle.called) def test_it(self): - with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2"): + with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: + mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot.account.report_new_account"): with mock.patch("certbot.eff.handle_subscription"): self._call() @@ -91,6 +113,7 @@ class RegisterTest(test_util.ConfigTestCase): msg = "DNS problem: NXDOMAIN looking up MX for example.com" mx_err = messages.Error.with_code('invalidContact', detail=msg) with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: + mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot.eff.handle_subscription") as mock_handle: mock_client().new_account_and_tos.side_effect = [mx_err, mock.MagicMock()] self._call() @@ -104,6 +127,7 @@ class RegisterTest(test_util.ConfigTestCase): msg = "DNS problem: NXDOMAIN looking up MX for example.com" mx_err = messages.Error.with_code('invalidContact', detail=msg) with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: + mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot.eff.handle_subscription"): mock_client().new_account_and_tos.side_effect = [mx_err, mock.MagicMock()] self.assertRaises(errors.Error, self._call) @@ -115,7 +139,8 @@ class RegisterTest(test_util.ConfigTestCase): @mock.patch("certbot.client.logger") def test_without_email(self, mock_logger): with mock.patch("certbot.eff.handle_subscription") as mock_handle: - with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2"): + with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_clnt: + mock_clnt().external_account_required.side_effect = self._false_mock with mock.patch("certbot.account.report_new_account"): self.config.email = None self.config.register_unsafely_without_email = True @@ -129,6 +154,7 @@ class RegisterTest(test_util.ConfigTestCase): def test_dry_run_no_staging_account(self, _rep, mock_get_email): """Tests dry-run for no staging account, expect account created with no email""" with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: + mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot.eff.handle_subscription"): with mock.patch("certbot.account.report_new_account"): self.config.dry_run = True @@ -138,11 +164,53 @@ class RegisterTest(test_util.ConfigTestCase): # check Certbot created an account with no email. Contact should return empty self.assertFalse(mock_client().new_account_and_tos.call_args[0][0].contact) + def test_with_eab_arguments(self): + with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: + mock_client().client.directory.__getitem__ = mock.Mock( + side_effect=self._new_acct_dir_mock + ) + mock_client().external_account_required.side_effect = self._false_mock + with mock.patch("certbot.eff.handle_subscription"): + target = "certbot.client.messages.ExternalAccountBinding.from_data" + with mock.patch(target) as mock_eab_from_data: + self.config.eab_kid = "test-kid" + self.config.eab_hmac_key = "J2OAqW4MHXsrHVa_PVg0Y-L_R4SYw0_aL1le6mfblbE" + self._call() + + self.assertTrue(mock_eab_from_data.called) + + def test_without_eab_arguments(self): + with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: + mock_client().external_account_required.side_effect = self._false_mock + with mock.patch("certbot.eff.handle_subscription"): + target = "certbot.client.messages.ExternalAccountBinding.from_data" + with mock.patch(target) as mock_eab_from_data: + self.config.eab_kid = None + self.config.eab_hmac_key = None + self._call() + + self.assertFalse(mock_eab_from_data.called) + + def test_external_account_required_without_eab_arguments(self): + with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: + mock_client().client.net.key.public_key = mock.Mock(side_effect=self._public_key_mock) + mock_client().external_account_required.side_effect = self._true_mock + with mock.patch("certbot.eff.handle_subscription"): + with mock.patch("certbot.client.messages.ExternalAccountBinding.from_data"): + self.config.eab_kid = None + self.config.eab_hmac_key = None + + self.assertRaises(errors.Error, self._call) + def test_unsupported_error(self): from acme import messages msg = "Test" mx_err = messages.Error(detail=msg, typ="malformed", title="title") with mock.patch("certbot.client.acme_client.BackwardsCompatibleClientV2") as mock_client: + mock_client().client.directory.__getitem__ = mock.Mock( + side_effect=self._new_acct_dir_mock + ) + mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot.eff.handle_subscription") as mock_handle: mock_client().new_account_and_tos.side_effect = [mx_err, mock.MagicMock()] self.assertRaises(messages.Error, self._call) diff --git a/local-oldest-requirements.txt b/local-oldest-requirements.txt index 03226fc84..2346300a3 100644 --- a/local-oldest-requirements.txt +++ b/local-oldest-requirements.txt @@ -1 +1 @@ -acme[dev]==0.26.0 +-e acme[dev] diff --git a/setup.py b/setup.py index f8f5feadc..768501b82 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ version = meta['version'] # specified here to avoid masking the more specific request requirements in # acme. See https://github.com/pypa/pip/issues/988 for more info. install_requires = [ - 'acme>=0.26.0', + 'acme>=0.29.0.dev0', # We technically need ConfigArgParse 0.10.0 for Python 2.6 support, but # saying so here causes a runtime error against our temporary fork of 0.9.3 # in which we added 2.6 support (see #2243), so we relax the requirement. From d30afbea5782bdb30c36661f1a9cbaea0bfc5bc8 Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 3 Dec 2018 23:32:47 +0000 Subject: [PATCH 068/114] Remove duplicate route53 options (#6405) * Remove duplicate route53 options Duplicate route53 option (certbot-route53:auth) removed. * Remove duplicate route53 options from help Removed duplicate route53 options from help by adding a couple of if statements in cli.py. * Fix formatting * Use cleaner solution to remove duplicate route53 options from help Used a cleaner method to remove the duplicate option from the help text * Fix line too long * Add regression test Added a regression test and fixed a couple of minor issues. * Fix trailing whitespace * Add missing newline * Put newline in correct place --- certbot/cli.py | 4 +++- certbot/tests/cli_test.py | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/certbot/cli.py b/certbot/cli.py index 7d2a6ccfc..8557b12c8 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -859,7 +859,9 @@ class HelpfulArgumentParser(object): if chosen_topic == "everything": chosen_topic = "run" if chosen_topic == "all": - return dict([(t, True) for t in self.help_topics]) + # Addition of condition closes #6209 (removal of duplicate route53 option). + return dict([(t, True) if t != 'certbot-route53:auth' else (t, False) + for t in self.help_topics]) elif not chosen_topic: return dict([(t, False) for t in self.help_topics]) else: diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py index 69ef16597..1448b86e7 100644 --- a/certbot/tests/cli_test.py +++ b/certbot/tests/cli_test.py @@ -431,6 +431,11 @@ class ParseTest(unittest.TestCase): # pylint: disable=too-many-public-methods self.assertRaises(errors.Error, self.parse, "--allow-subset-of-names -d *.example.org".split()) + def test_route53_no_revert(self): + for help_flag in ['-h', '--help']: + for topic in ['all', 'plugins', 'dns-route53']: + self.assertFalse('certbot-route53:auth' in self._help_output([help_flag, topic])) + class DefaultTest(unittest.TestCase): """Tests for certbot.cli._Default.""" From daa77b502353424244050b0fb8c6daf6276cc1d6 Mon Sep 17 00:00:00 2001 From: ohemorange Date: Mon, 3 Dec 2018 16:42:52 -0800 Subject: [PATCH 069/114] During the release, reset local-oldest-requirements.txts that might have been changed during development. (#6547) * During the release, reset local-oldest-requirements.txts that might have been changed during development. * only modify the file if it exists * no need to specifically add certbot-compatibility-test because it doesn't have the file anyway * Use double quotes instead of single * escape dots and brackets * Escape and quote correctly --- tools/_release.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/_release.sh b/tools/_release.sh index dd08974ae..90c176b0e 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -265,6 +265,16 @@ if [ "$RELEASE_BRANCH" = candidate-"$version" ] ; then SetVersion "$nextversion".dev0 letsencrypt-auto-source/build.py git add letsencrypt-auto-source/letsencrypt-auto + for pkg_dir in $SUBPKGS_NO_CERTBOT . + do + if [ -f "$pkg_dir/local-oldest-requirements.txt" ]; then + sed -i "s/-e acme\[dev\]/acme[dev]==$version/" "$pkg_dir/local-oldest-requirements.txt" + sed -i "s/-e acme/acme[dev]==$version/" "$pkg_dir/local-oldest-requirements.txt" + sed -i "s/-e \.\[dev\]/certbot[dev]==$version/" "$pkg_dir/local-oldest-requirements.txt" + sed -i "s/-e \./certbot[dev]==$version/" "$pkg_dir/local-oldest-requirements.txt" + git add "$pkg_dir/local-oldest-requirements.txt" + fi + done git diff git commit -m "Bump version to $nextversion" fi From f5aad1440f8143f003698670177fabfc5fa7bb9c Mon Sep 17 00:00:00 2001 From: sydneyli Date: Tue, 4 Dec 2018 10:56:15 -0800 Subject: [PATCH 070/114] Conditionally depend on imgconverter for newer versions of Sphinx (#6536) Fixes #6343. * conditionally depend on imgconverter * Pin docutils dependency for old Sphinx bug --- CHANGELOG.md | 1 + docs/conf.py | 8 ++++++-- setup.py | 5 +++-- tools/dev_constraints.txt | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03f93a881..6d9447ae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). ### Fixed * Update code and dependencies to clean up Resource and Deprecation Warnings. +* Only depend on imgconverter extension for Sphinx >= 1.6 Despite us having broken lockstep, we are continuing to release new versions of all Certbot components during releases for the time being, however, the only diff --git a/docs/conf.py b/docs/conf.py index 2e6c5a9b7..c72d1c1cf 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,6 +17,8 @@ import os import re import sys +import sphinx + here = os.path.abspath(os.path.dirname(__file__)) @@ -33,14 +35,13 @@ sys.path.insert(0, os.path.abspath(os.path.join(here, '..'))) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.0' +needs_sphinx = '1.2' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', - 'sphinx.ext.imgconverter', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', @@ -48,6 +49,9 @@ extensions = [ 'repoze.sphinx.autointerface', ] +if sphinx.version_info >= (1, 6): + extensions.append('sphinx.ext.imgconverter') + autodoc_member_order = 'bysource' autodoc_default_flags = ['show-inheritance', 'private-members'] diff --git a/setup.py b/setup.py index 768501b82..382149054 100644 --- a/setup.py +++ b/setup.py @@ -68,9 +68,10 @@ dev3_extras = [ ] docs_extras = [ + # If you have Sphinx<1.5.1, you need docutils<0.13.1 + # https://github.com/sphinx-doc/sphinx/issues/3212 'repoze.sphinx.autointerface', - # sphinx.ext.imgconverter - 'Sphinx >=1.6', + 'Sphinx>=1.2', # Annotation support 'sphinx_rtd_theme', ] diff --git a/tools/dev_constraints.txt b/tools/dev_constraints.txt index 65182bcde..778012d31 100644 --- a/tools/dev_constraints.txt +++ b/tools/dev_constraints.txt @@ -14,7 +14,7 @@ coverage==4.4.2 decorator==4.1.2 dns-lexicon==2.7.14 dnspython==1.15.0 -docutils==0.14 +docutils==0.12 execnet==1.5.0 future==0.16.0 futures==3.1.1 From 9c0b27de6826fdcbfc26d588460ea02426a5d492 Mon Sep 17 00:00:00 2001 From: sydneyli Date: Tue, 4 Dec 2018 10:59:23 -0800 Subject: [PATCH 071/114] Preserve other-read bit on private keys too (#6544) Not updating the guidelines in using.rst-- I don't want to encourage people to use this. now that Certbot preserves gid, the better way to set permissions is to change the group permisisons! * Preserve other-read bit on private keys too * fix integration test * fix and rename permission routines in integration tests --- certbot/storage.py | 10 ++++---- certbot/tests/storage_test.py | 6 ++--- tests/certbot-boulder-integration.sh | 35 ++++++++++++++++++---------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/certbot/storage.py b/certbot/storage.py index c90a95a73..eb17e1d38 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -1141,11 +1141,11 @@ class RenewableCert(object): with util.safe_open(target["privkey"], "wb", chmod=BASE_PRIVKEY_MODE) as f: logger.debug("Writing new private key to %s.", target["privkey"]) f.write(new_privkey) - # If the previous privkey in this lineage has an existing gid or group mode > 0, - # let's keep those. - group_mode = stat.S_IMODE(os.stat(old_privkey).st_mode) & \ - (stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP) - mode = BASE_PRIVKEY_MODE | group_mode + # Preserve gid and (mode & 074) from previous privkey in this lineage. + old_mode = stat.S_IMODE(os.stat(old_privkey).st_mode) & \ + (stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | \ + stat.S_IROTH) + mode = BASE_PRIVKEY_MODE | old_mode os.chown(target["privkey"], -1, os.stat(old_privkey).st_gid) os.chmod(target["privkey"], mode) diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 5fd7746ed..d75f4f595 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -562,12 +562,12 @@ class RenewableCertTests(BaseRenewableCertTest): self.test_rc.save_successor(1, b"newcert", None, b"new chain", self.config) self.assertTrue(compat.compare_file_modes( os.stat(self.test_rc.version("privkey", 2)).st_mode, 0o444)) - # If new key, permissions should be rest to 600 + preserved group + # If new key, permissions should be kept as 644 self.test_rc.save_successor(2, b"newcert", b"new_privkey", b"new chain", self.config) self.assertTrue(compat.compare_file_modes( - os.stat(self.test_rc.version("privkey", 3)).st_mode, 0o640)) + os.stat(self.test_rc.version("privkey", 3)).st_mode, 0o644)) # If permissions reverted, next renewal will also revert permissions of new key - os.chmod(self.test_rc.version("privkey", 3), 0o404) + os.chmod(self.test_rc.version("privkey", 3), 0o400) self.test_rc.save_successor(3, b"newcert", b"new_privkey", b"new chain", self.config) self.assertTrue(compat.compare_file_modes( os.stat(self.test_rc.version("privkey", 4)).st_mode, 0o600)) diff --git a/tests/certbot-boulder-integration.sh b/tests/certbot-boulder-integration.sh index 709daa217..87e3cc319 100755 --- a/tests/certbot-boulder-integration.sh +++ b/tests/certbot-boulder-integration.sh @@ -280,13 +280,20 @@ CheckCertCount() { fi } -CheckGroup() { - group_mode() { echo $((0`stat -c %a $1` & 070)); } - group_owner() { echo `stat -c %G $1`; } - if [ `group_mode $1` -ne `group_mode $2` ] ; then - echo "Expected group permission `group_mode $1`, got `group_mode $2` on file $2" +CheckPermissions() { +# Args: +# Checks mode of two files match under + masked_mode() { echo $((0`stat -c %a $1` & 0$2)); } + if [ `masked_mode $1 $3` -ne `masked_mode $2 $3` ] ; then + echo "With $3 mask, expected mode `masked_mode $1 $3`, got `masked_mode $2 $3` on file $2" exit 1 fi +} + +CheckGID() { +# Args: +# Checks group owner of two files match + group_owner() { echo `stat -c %G $1`; } if [ `group_owner $1` != `group_owner $2` ] ; then echo "Expected group owner `group_owner $1`, got `group_owner $2` on file $2" exit 1 @@ -294,9 +301,11 @@ CheckGroup() { } CheckOthersPermission() { +# Args: +# Tests file's other/world permission against expected mode other_permission=$((0`stat -c %a $1` & 07)) - if [ $other_permission -ne 0 ] ; then - echo "Expected file $1 not to be accessible by others" + if [ $other_permission -ne $2 ] ; then + echo "Expected file $1 to have others mode $2, got $other_permission instead" exit 1 fi } @@ -316,9 +325,10 @@ rm -rf "$renewal_hooks_root" common renew --cert-name le.wtf --authenticator manual CheckCertCount "le.wtf" 2 -CheckOthersPermission "${root}/conf/archive/le.wtf/privkey1.pem" -CheckOthersPermission "${root}/conf/archive/le.wtf/privkey2.pem" -CheckGroup "${root}/conf/archive/le.wtf/privkey1.pem" "${root}/conf/archive/le.wtf/privkey2.pem" +CheckOthersPermission "${root}/conf/archive/le.wtf/privkey1.pem" 0 +CheckOthersPermission "${root}/conf/archive/le.wtf/privkey2.pem" 0 +CheckPermissions "${root}/conf/archive/le.wtf/privkey1.pem" "${root}/conf/archive/le.wtf/privkey2.pem" 074 +CheckGID "${root}/conf/archive/le.wtf/privkey1.pem" "${root}/conf/archive/le.wtf/privkey2.pem" chmod 0444 "${root}/conf/archive/le.wtf/privkey2.pem" # test renewal with no executables in hook directories @@ -337,8 +347,9 @@ CreateDirHooks sed -i "4arenew_before_expiry = 4 years" "$root/conf/renewal/le.wtf.conf" common_no_force_renew renew --rsa-key-size 2048 --no-directory-hooks CheckCertCount "le.wtf" 3 -CheckGroup "${root}/conf/archive/le.wtf/privkey2.pem" "${root}/conf/archive/le.wtf/privkey3.pem" -CheckOthersPermission "${root}/conf/archive/le.wtf/privkey3.pem" +CheckGID "${root}/conf/archive/le.wtf/privkey2.pem" "${root}/conf/archive/le.wtf/privkey3.pem" +CheckPermissions "${root}/conf/archive/le.wtf/privkey2.pem" "${root}/conf/archive/le.wtf/privkey3.pem" 074 +CheckOthersPermission "${root}/conf/archive/le.wtf/privkey3.pem" 04 if [ -s "$HOOK_DIRS_TEST" ]; then echo "Directory hooks were executed with --no-directory-hooks!" >&2 From 9b9ba9b5fe4af5e0a76df001bd4fb9ca7690b4c0 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 5 Dec 2018 10:52:02 -0800 Subject: [PATCH 072/114] List packages that changed in CHANGELOG. --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d9447ae2..f2c89a4ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,13 @@ Despite us having broken lockstep, we are continuing to release new versions of all Certbot components during releases for the time being, however, the only package with changes other than its version number was: -* +* acme +* certbot +* certbot-apache +* certbot-dns-cloudflare +* certbot-dns-digitalocean +* certbot-dns-google +* certbot-nginx More details about these changes can be found on our GitHub repo: https://github.com/certbot/certbot/milestone/62?closed=1 From d151481dea200f99f65c67488124a5be7be53f2b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 5 Dec 2018 10:52:20 -0800 Subject: [PATCH 073/114] Update changelog for 0.29.0 release --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2c89a4ff..cf83679e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). -## 0.29.0 - master +## 0.29.0 - 2018-12-05 ### Added From 6476663516b9c84d67964f1af58e868fa3f70431 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 5 Dec 2018 10:57:43 -0800 Subject: [PATCH 074/114] Release 0.29.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-auto | 154 +++++++++++------- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/__init__.py | 2 +- docs/cli-help.txt | 21 +-- letsencrypt-auto | 154 +++++++++++------- letsencrypt-auto-source/certbot-auto.asc | 16 +- letsencrypt-auto-source/letsencrypt-auto | 26 +-- letsencrypt-auto-source/letsencrypt-auto.sig | Bin 256 -> 256 bytes .../pieces/certbot-requirements.txt | 24 +-- setup.py | 2 +- 27 files changed, 249 insertions(+), 186 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index ad70c2947..635a98a32 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages from setuptools.command.test import test as TestCommand import sys -version = '0.29.0.dev0' +version = '0.29.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index e6f6f1e23..250db9a16 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-auto b/certbot-auto index fe87317a7..8d9528559 100755 --- a/certbot-auto +++ b/certbot-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.28.0" +LE_AUTO_VERSION="0.29.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -593,8 +593,7 @@ BootstrapArchCommon() { # - ArchLinux (x86_64) # # "python-virtualenv" is Python3, but "python2-virtualenv" provides - # only "virtualenv2" binary, not "virtualenv" necessary in - # ./tools/_venv_common.sh + # only "virtualenv2" binary, not "virtualenv". deps=" python2 @@ -912,6 +911,35 @@ OldVenvExists() { [ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ] } +# Given python path, version 1 and version 2, check if version 1 is outdated compared to version 2. +# An unofficial version provided as version 1 (eg. 0.28.0.dev0) will be treated +# specifically by printing "UNOFFICIAL". Otherwise, print "OUTDATED" if version 1 +# is outdated, and "UP_TO_DATE" if not. +# This function relies only on installed python environment (2.x or 3.x) by certbot-auto. +CompareVersions() { + "$1" - "$2" "$3" << "UNLIKELY_EOF" +import sys +from distutils.version import StrictVersion + +try: + current = StrictVersion(sys.argv[1]) +except ValueError: + sys.stdout.write('UNOFFICIAL') + sys.exit() + +try: + remote = StrictVersion(sys.argv[2]) +except ValueError: + sys.stdout.write('UP_TO_DATE') + sys.exit() + +if current < remote: + sys.stdout.write('OUTDATED') +else: + sys.stdout.write('UP_TO_DATE') +UNLIKELY_EOF +} + if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. @@ -1017,43 +1045,39 @@ pycparser==2.14 \ asn1crypto==0.22.0 \ --hash=sha256:d232509fefcfcdb9a331f37e9c9dc20441019ad927c7d2176cf18ed5da0ba097 \ --hash=sha256:cbbadd640d3165ab24b06ef25d1dca09a3441611ac15f6a6b452474fdf0aed1a -cffi==1.10.0 \ - --hash=sha256:446699c10f3c390633d0722bc19edbc7ac4b94761918a4a4f7908a24e86ebbd0 \ - --hash=sha256:562326fc7f55a59ef3fef5e82908fe938cdc4bbda32d734c424c7cd9ed73e93a \ - --hash=sha256:7f732ad4a30db0b39400c3f7011249f7d0701007d511bf09604729aea222871f \ - --hash=sha256:94fb8410c6c4fc48e7ea759d3d1d9ca561171a88d00faddd4aa0306f698ad6a0 \ - --hash=sha256:587a5043df4b00a2130e09fed42da02a4ed3c688bd9bf07a3ac89d2271f4fb07 \ - --hash=sha256:ec08b88bef627ec1cea210e1608c85d3cf44893bcde74e41b7f7dbdfd2c1bad6 \ - --hash=sha256:a41406f6d62abcdf3eef9fd998d8dcff04fd2a7746644143045feeebd76352d1 \ - --hash=sha256:b560916546b2f209d74b82bdbc3223cee9a165b0242fa00a06dfc48a2054864a \ - --hash=sha256:e74896774e437f4715c57edeb5cf3d3a40d7727f541c2c12156617b5a15d1829 \ - --hash=sha256:9a31c18ba4881a116e448c52f3f5d3e14401cf7a9c43cc88f06f2a7f5428da0e \ - --hash=sha256:80796ea68e11624a0279d3b802f88a7fe7214122b97a15a6c97189934a2cc776 \ - --hash=sha256:f4019826a2dec066c909a1f483ef0dcf9325d6740cc0bd15308942b28b0930f7 \ - --hash=sha256:7248506981eeba23888b4140a69a53c4c0c0a386abcdca61ed8dd790a73e64b9 \ - --hash=sha256:a8955265d146e86fe2ce116394be4eaf0cb40314a79b19f11c4fa574cd639572 \ - --hash=sha256:c49187260043bd4c1d6a52186f9774f17d9b1da0a406798ebf4bfc12da166ade \ - --hash=sha256:c1d8b3d8dcb5c23ac1a8bf56422036f3f305a3c5a8bc8c354256579a1e2aa2c1 \ - --hash=sha256:9e389615bcecb8c782a87939d752340bb0a3a097e90bae54d7f0915bc12f45bd \ - --hash=sha256:d09ff358f75a874f69fa7d1c2b4acecf4282a950293fcfcf89aa606da8a9a500 \ - --hash=sha256:b69b4557aae7de18b7c174a917fe19873529d927ac592762d9771661875bbd40 \ - --hash=sha256:5de52b081a2775e76b971de9d997d85c4457fc0a09079e12d66849548ae60981 \ - --hash=sha256:e7d88fecb7b6250a1fd432e6dc64890342c372fce13dbfe4bb6f16348ad00c14 \ - --hash=sha256:1426e67e855ef7f5030c9184f4f1a9f4bfa020c31c962cd41fd129ec5aef4a6a \ - --hash=sha256:267dd2c66a5760c5f4d47e2ebcf8eeac7ef01e1ae6ae7a6d0d241a290068bc38 \ - --hash=sha256:e553eb489511cacf19eda6e52bc9e151316f0d721724997dda2c4d3079b778db \ - --hash=sha256:98b89b2c57f97ce2db7aeba60db173c84871d73b40e41a11ea95de1500ddc57e \ - --hash=sha256:e2b7e090188833bc58b2ae03fb864c22688654ebd2096bcf38bc860c4f38a3d8 \ - --hash=sha256:afa7d8b8d38ad40db8713ee053d41b36d87d6ae5ec5ad36f9210b548a18dc214 \ - --hash=sha256:4fc9c2ff7924b3a1fa326e1799e5dd58cac585d7fb25fe53ccaa1333b0453d65 \ - --hash=sha256:937db39a1ec5af3003b16357b2042bba67c88d43bc11aaa203fa8a5924524209 \ - --hash=sha256:ab22285797631df3b513b2cd3ecdc51cd8e3d36788e3991d93d0759d6883b027 \ - --hash=sha256:96e599b924ef009aa867f725b3249ee51d76489f484d3a45b4bd219c5ec6ed59 \ - --hash=sha256:bea842a0512be6a8007e585790bccd5d530520fc025ce63b03e139be373b0063 \ - --hash=sha256:e7175287f7fe7b1cc203bb958b17db40abd732690c1e18e700f10e0843a58598 \ - --hash=sha256:285ab352552f52f1398c912556d4d36d4ea9b8450e5c65d03809bf9886755533 \ - --hash=sha256:5576644b859197da7bbd8f8c7c2fb5dcc6cd505cadb42992d5f104c013f8a214 \ - --hash=sha256:b3b02911eb1f6ada203b0763ba924234629b51586f72a21faacc638269f4ced5 +cffi==1.11.5 \ + --hash=sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50 \ + --hash=sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596 \ + --hash=sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef \ + --hash=sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743 \ + --hash=sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f \ + --hash=sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31 \ + --hash=sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04 \ + --hash=sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6 \ + --hash=sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3 \ + --hash=sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6 \ + --hash=sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b \ + --hash=sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca \ + --hash=sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e \ + --hash=sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb \ + --hash=sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd \ + --hash=sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1 \ + --hash=sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917 \ + --hash=sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359 \ + --hash=sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f \ + --hash=sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95 \ + --hash=sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801 \ + --hash=sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257 \ + --hash=sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184 \ + --hash=sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc \ + --hash=sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085 \ + --hash=sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93 \ + --hash=sha256:ca1bd81f40adc59011f58159e4aa6445fc585a32bb8ac9badf7a2c1aa23822f2 \ + --hash=sha256:3bb6bd7266598f318063e584378b8e27c67de998a43362e8fce664c54ee52d30 \ + --hash=sha256:a6a5cb8809091ec9ac03edde9304b3ad82ad4466333432b16d78ef40e0cce0d5 \ + --hash=sha256:57b2533356cb2d8fac1555815929f7f5f14d68ac77b085d2326b571310f34f6e \ + --hash=sha256:495c5c2d43bf6cebe0178eb3e88f9c4aa48d8934aa6e3cddb865c058da76756b \ + --hash=sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4 ConfigArgParse==0.12.0 \ --hash=sha256:28cd7d67669651f2a4518367838c49539457504584a139709b2b8f6c208ef339 \ --no-binary ConfigArgParse @@ -1146,9 +1170,9 @@ pytz==2015.7 \ --hash=sha256:fbd26746772c24cb93c8b97cbdad5cb9e46c86bbdb1b9d8a743ee00e2fb1fc5d \ --hash=sha256:99266ef30a37e43932deec2b7ca73e83c8dbc3b9ff703ec73eca6b1dae6befea \ --hash=sha256:8b6ce1c993909783bc96e0b4f34ea223bff7a4df2c90bdb9c4e0f1ac928689e3 -requests==2.12.1 \ - --hash=sha256:3f3f27a9d0f9092935efc78054ef324eb9f8166718270aefe036dfa1e4f68e1e \ - --hash=sha256:2109ecea94df90980be040490ff1d879971b024861539abb00054062388b612e +requests==2.20.0 \ + --hash=sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c \ + --hash=sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279 six==1.10.0 \ --hash=sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1 \ --hash=sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a @@ -1185,6 +1209,15 @@ zope.interface==4.1.3 \ requests-toolbelt==0.8.0 \ --hash=sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237 \ --hash=sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5 +chardet==3.0.2 \ + --hash=sha256:4f7832e7c583348a9eddd927ee8514b3bf717c061f57b21dbe7697211454d9bb \ + --hash=sha256:6ebf56457934fdce01fb5ada5582762a84eed94cad43ed877964aebbdd8174c0 +urllib3==1.21.1 \ + --hash=sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1 \ + --hash=sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5 +certifi==2017.4.17 \ + --hash=sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010 \ + --hash=sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a # Contains the requirements for the letsencrypt package. # @@ -1197,31 +1230,29 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.28.0 \ - --hash=sha256:f2f7c816acd695cbcda713a779b0db2b08e9de407146b46e1c4ef5561e0f5417 \ - --hash=sha256:31e3e2ee2a25c009a621c59ac9182f85d937a897c7bd1d47d0e01f3c712a090a -acme==0.28.0 \ - --hash=sha256:d3a564031155fece3f6edce8c5246d4cf34be0977b4c7c5ce84e86c68601c895 \ - --hash=sha256:bf7c2f1c24a26ab5b9fce3a6abca1d74a5914d46919649ae00ad5817db62bb85 -certbot-apache==0.28.0 \ - --hash=sha256:a57d7bac4f13ae5ecea4f4cbd479d381c02316c4832b25ab5a9d7c6826166370 \ - --hash=sha256:3f93f5de4a548e973c493a6cac5eeeb3dbbcae2988b61299ea0727d04a00f5bb -certbot-nginx==0.28.0 \ - --hash=sha256:1822a65910f0801087fa20a3af3fc94f878f93e0f11809483bb5387df861e296 \ - --hash=sha256:426fb403b0a7b203629f4e350a862cbc3bc1f69936fdab8ec7eafe0d8a3b5ddb +certbot==0.29.0 \ + --hash=sha256:fd055f3c132f966bf72bca653a52cf5974395cea6ce4f3f727f304bd52a332e3 \ + --hash=sha256:3c9f18cc502ff3b3bc8811ee1e90b73021fcf3891e13003fbe3d499fe7384753 +acme==0.29.0 \ + --hash=sha256:d7e80231b17a8fd31d625ec4be964583b7aa08824fbfcd7e35b3185ecf342d28 \ + --hash=sha256:37a2f933ee07c0f12dcaea519e6549f6f68145788a1f5db594afaabb592a6b79 +certbot-apache==0.29.0 \ + --hash=sha256:0db527c8664a4e9cd3989e947f32dda499cc779ac0626ba6a12c1f96f9d1bbe3 \ + --hash=sha256:bd55e5d7ece13f30935d6454cc32ffcc50229a3ed39eb2a6724e5db2e53549cd +certbot-nginx==0.29.0 \ + --hash=sha256:c788ea49542959210b88c5dfb3d0e29cbf2a04bbf7f424533812ec0d47e1627b \ + --hash=sha256:675b8a9acc3945c539f6a0582d1cf9e2cd5bed183f0db262810724365812d5a5 UNLIKELY_EOF # ------------------------------------------------------------------------- cat << "UNLIKELY_EOF" > "$TEMP_DIR/pipstrap.py" #!/usr/bin/env python """A small script that can act as a trust root for installing pip >=8 - Embed this in your project, and your VCS checkout is all you have to trust. In a post-peep era, this lets you claw your way to a hash-checking version of pip, with which you can install the rest of your dependencies safely. All it assumes is Python 2.6 or better and *some* version of pip already installed. If anything goes wrong, it will exit with a non-zero status code. - """ # This is here so embedded copies are MIT-compliant: # Copyright (c) 2016 Erik Rose @@ -1348,10 +1379,8 @@ def hashed_download(url, temp, digest): def get_index_base(): """Return the URL to the dir containing the "packages" folder. - Try to wring something out of PIP_INDEX_URL, if set. Hack "/simple" off the end if it's there; that is likely to give us the right dir. - """ env_var = environ.get('PIP_INDEX_URL', '').rstrip('/') if env_var: @@ -1641,7 +1670,12 @@ UNLIKELY_EOF error "WARNING: couldn't find Python $MIN_PYTHON_VERSION+ to check for updates." elif ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then error "WARNING: unable to check for updates." - elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then + fi + + LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` + if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then + say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" + elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." # Now we drop into Python so we don't have to install even more diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index bfbbe0625..1c2a65dc0 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -4,7 +4,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index d615fa999..2743b9cd2 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index f9880270a..9bdedc418 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index a9d46d128..0de673a34 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index ac7bb1090..a1af50d91 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index ab944d40d..61da2ca29 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 97d7ca699..42e08c062 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index aa1afdc93..93521c018 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 5cff50196..a19d4ef25 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index d0735d1ec..665108da6 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index aebff5304..b1fdd6dd5 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index a0e62caa5..3776ad518 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 914bfb6e6..2d8cb2293 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 6318cbb81..1461c6d02 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 2222999d5..59803256b 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 0908c4c52..eea680f62 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0.dev0' +version = '0.29.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/__init__.py b/certbot/__init__.py index f6b7defbd..464474c2a 100644 --- a/certbot/__init__.py +++ b/certbot/__init__.py @@ -1,4 +1,4 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '0.29.0.dev0' +__version__ = '0.29.0' diff --git a/docs/cli-help.txt b/docs/cli-help.txt index d26da361b..1dc8c5cd9 100644 --- a/docs/cli-help.txt +++ b/docs/cli-help.txt @@ -67,6 +67,10 @@ optional arguments: with the same name. In the case of a name collision it will append a number like 0001 to the file path name. (default: Ask) + --eab-kid EAB_KID Key Identifier for External Account Binding (default: + None) + --eab-hmac-key EAB_HMAC_KEY + HMAC key for External Account Binding (default: None) --cert-name CERTNAME Certificate name to apply. This name is used by Certbot for housekeeping and in file paths; it doesn't affect the content of the certificate itself. To see @@ -108,7 +112,7 @@ optional arguments: case, and to know when to deprecate support for past Python versions and flags. If you wish to hide this information from the Let's Encrypt server, set this to - "". (default: CertbotACMEClient/0.28.0 + "". (default: CertbotACMEClient/0.29.0 (certbot(-auto); OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). The flags encoded in the @@ -248,8 +252,8 @@ paths: None) --config-dir CONFIG_DIR Configuration directory. (default: /etc/letsencrypt) - --work-dir WORK_DIR Working directory. (default: /var/lib/letsencrypt) - --logs-dir LOGS_DIR Logs directory. (default: /var/log/letsencrypt) + --work-dir WORK_DIR Working directory. (default: /var/letsencrypt/lib) + --logs-dir LOGS_DIR Logs directory. (default: /var/letsencrypt/log) --server SERVER ACME Directory Resource URI. (default: https://acme-v02.api.letsencrypt.org/directory) @@ -473,7 +477,7 @@ plugins: using Sakura Cloud for DNS). (default: False) apache: - Apache Web Server plugin - Beta + Apache Web Server plugin --apache-enmod APACHE_ENMOD Path to the Apache 'a2enmod' binary (default: None) @@ -503,15 +507,6 @@ apache: Full path to Apache control script (default: apachectl) -certbot-route53:auth: - Obtain certificates using a DNS TXT record (if you are using AWS Route53 - for DNS). - - --certbot-route53:auth-propagation-seconds CERTBOT_ROUTE53:AUTH_PROPAGATION_SECONDS - The number of seconds to wait for DNS to propagate - before asking the ACME server to verify the DNS - record. (default: 10) - dns-cloudflare: Obtain certificates using a DNS TXT record (if you are using Cloudflare for DNS). diff --git a/letsencrypt-auto b/letsencrypt-auto index fe87317a7..8d9528559 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.28.0" +LE_AUTO_VERSION="0.29.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -593,8 +593,7 @@ BootstrapArchCommon() { # - ArchLinux (x86_64) # # "python-virtualenv" is Python3, but "python2-virtualenv" provides - # only "virtualenv2" binary, not "virtualenv" necessary in - # ./tools/_venv_common.sh + # only "virtualenv2" binary, not "virtualenv". deps=" python2 @@ -912,6 +911,35 @@ OldVenvExists() { [ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ] } +# Given python path, version 1 and version 2, check if version 1 is outdated compared to version 2. +# An unofficial version provided as version 1 (eg. 0.28.0.dev0) will be treated +# specifically by printing "UNOFFICIAL". Otherwise, print "OUTDATED" if version 1 +# is outdated, and "UP_TO_DATE" if not. +# This function relies only on installed python environment (2.x or 3.x) by certbot-auto. +CompareVersions() { + "$1" - "$2" "$3" << "UNLIKELY_EOF" +import sys +from distutils.version import StrictVersion + +try: + current = StrictVersion(sys.argv[1]) +except ValueError: + sys.stdout.write('UNOFFICIAL') + sys.exit() + +try: + remote = StrictVersion(sys.argv[2]) +except ValueError: + sys.stdout.write('UP_TO_DATE') + sys.exit() + +if current < remote: + sys.stdout.write('OUTDATED') +else: + sys.stdout.write('UP_TO_DATE') +UNLIKELY_EOF +} + if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. @@ -1017,43 +1045,39 @@ pycparser==2.14 \ asn1crypto==0.22.0 \ --hash=sha256:d232509fefcfcdb9a331f37e9c9dc20441019ad927c7d2176cf18ed5da0ba097 \ --hash=sha256:cbbadd640d3165ab24b06ef25d1dca09a3441611ac15f6a6b452474fdf0aed1a -cffi==1.10.0 \ - --hash=sha256:446699c10f3c390633d0722bc19edbc7ac4b94761918a4a4f7908a24e86ebbd0 \ - --hash=sha256:562326fc7f55a59ef3fef5e82908fe938cdc4bbda32d734c424c7cd9ed73e93a \ - --hash=sha256:7f732ad4a30db0b39400c3f7011249f7d0701007d511bf09604729aea222871f \ - --hash=sha256:94fb8410c6c4fc48e7ea759d3d1d9ca561171a88d00faddd4aa0306f698ad6a0 \ - --hash=sha256:587a5043df4b00a2130e09fed42da02a4ed3c688bd9bf07a3ac89d2271f4fb07 \ - --hash=sha256:ec08b88bef627ec1cea210e1608c85d3cf44893bcde74e41b7f7dbdfd2c1bad6 \ - --hash=sha256:a41406f6d62abcdf3eef9fd998d8dcff04fd2a7746644143045feeebd76352d1 \ - --hash=sha256:b560916546b2f209d74b82bdbc3223cee9a165b0242fa00a06dfc48a2054864a \ - --hash=sha256:e74896774e437f4715c57edeb5cf3d3a40d7727f541c2c12156617b5a15d1829 \ - --hash=sha256:9a31c18ba4881a116e448c52f3f5d3e14401cf7a9c43cc88f06f2a7f5428da0e \ - --hash=sha256:80796ea68e11624a0279d3b802f88a7fe7214122b97a15a6c97189934a2cc776 \ - --hash=sha256:f4019826a2dec066c909a1f483ef0dcf9325d6740cc0bd15308942b28b0930f7 \ - --hash=sha256:7248506981eeba23888b4140a69a53c4c0c0a386abcdca61ed8dd790a73e64b9 \ - --hash=sha256:a8955265d146e86fe2ce116394be4eaf0cb40314a79b19f11c4fa574cd639572 \ - --hash=sha256:c49187260043bd4c1d6a52186f9774f17d9b1da0a406798ebf4bfc12da166ade \ - --hash=sha256:c1d8b3d8dcb5c23ac1a8bf56422036f3f305a3c5a8bc8c354256579a1e2aa2c1 \ - --hash=sha256:9e389615bcecb8c782a87939d752340bb0a3a097e90bae54d7f0915bc12f45bd \ - --hash=sha256:d09ff358f75a874f69fa7d1c2b4acecf4282a950293fcfcf89aa606da8a9a500 \ - --hash=sha256:b69b4557aae7de18b7c174a917fe19873529d927ac592762d9771661875bbd40 \ - --hash=sha256:5de52b081a2775e76b971de9d997d85c4457fc0a09079e12d66849548ae60981 \ - --hash=sha256:e7d88fecb7b6250a1fd432e6dc64890342c372fce13dbfe4bb6f16348ad00c14 \ - --hash=sha256:1426e67e855ef7f5030c9184f4f1a9f4bfa020c31c962cd41fd129ec5aef4a6a \ - --hash=sha256:267dd2c66a5760c5f4d47e2ebcf8eeac7ef01e1ae6ae7a6d0d241a290068bc38 \ - --hash=sha256:e553eb489511cacf19eda6e52bc9e151316f0d721724997dda2c4d3079b778db \ - --hash=sha256:98b89b2c57f97ce2db7aeba60db173c84871d73b40e41a11ea95de1500ddc57e \ - --hash=sha256:e2b7e090188833bc58b2ae03fb864c22688654ebd2096bcf38bc860c4f38a3d8 \ - --hash=sha256:afa7d8b8d38ad40db8713ee053d41b36d87d6ae5ec5ad36f9210b548a18dc214 \ - --hash=sha256:4fc9c2ff7924b3a1fa326e1799e5dd58cac585d7fb25fe53ccaa1333b0453d65 \ - --hash=sha256:937db39a1ec5af3003b16357b2042bba67c88d43bc11aaa203fa8a5924524209 \ - --hash=sha256:ab22285797631df3b513b2cd3ecdc51cd8e3d36788e3991d93d0759d6883b027 \ - --hash=sha256:96e599b924ef009aa867f725b3249ee51d76489f484d3a45b4bd219c5ec6ed59 \ - --hash=sha256:bea842a0512be6a8007e585790bccd5d530520fc025ce63b03e139be373b0063 \ - --hash=sha256:e7175287f7fe7b1cc203bb958b17db40abd732690c1e18e700f10e0843a58598 \ - --hash=sha256:285ab352552f52f1398c912556d4d36d4ea9b8450e5c65d03809bf9886755533 \ - --hash=sha256:5576644b859197da7bbd8f8c7c2fb5dcc6cd505cadb42992d5f104c013f8a214 \ - --hash=sha256:b3b02911eb1f6ada203b0763ba924234629b51586f72a21faacc638269f4ced5 +cffi==1.11.5 \ + --hash=sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50 \ + --hash=sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596 \ + --hash=sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef \ + --hash=sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743 \ + --hash=sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f \ + --hash=sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31 \ + --hash=sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04 \ + --hash=sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6 \ + --hash=sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3 \ + --hash=sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6 \ + --hash=sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b \ + --hash=sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca \ + --hash=sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e \ + --hash=sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb \ + --hash=sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd \ + --hash=sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1 \ + --hash=sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917 \ + --hash=sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359 \ + --hash=sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f \ + --hash=sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95 \ + --hash=sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801 \ + --hash=sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257 \ + --hash=sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184 \ + --hash=sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc \ + --hash=sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085 \ + --hash=sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93 \ + --hash=sha256:ca1bd81f40adc59011f58159e4aa6445fc585a32bb8ac9badf7a2c1aa23822f2 \ + --hash=sha256:3bb6bd7266598f318063e584378b8e27c67de998a43362e8fce664c54ee52d30 \ + --hash=sha256:a6a5cb8809091ec9ac03edde9304b3ad82ad4466333432b16d78ef40e0cce0d5 \ + --hash=sha256:57b2533356cb2d8fac1555815929f7f5f14d68ac77b085d2326b571310f34f6e \ + --hash=sha256:495c5c2d43bf6cebe0178eb3e88f9c4aa48d8934aa6e3cddb865c058da76756b \ + --hash=sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4 ConfigArgParse==0.12.0 \ --hash=sha256:28cd7d67669651f2a4518367838c49539457504584a139709b2b8f6c208ef339 \ --no-binary ConfigArgParse @@ -1146,9 +1170,9 @@ pytz==2015.7 \ --hash=sha256:fbd26746772c24cb93c8b97cbdad5cb9e46c86bbdb1b9d8a743ee00e2fb1fc5d \ --hash=sha256:99266ef30a37e43932deec2b7ca73e83c8dbc3b9ff703ec73eca6b1dae6befea \ --hash=sha256:8b6ce1c993909783bc96e0b4f34ea223bff7a4df2c90bdb9c4e0f1ac928689e3 -requests==2.12.1 \ - --hash=sha256:3f3f27a9d0f9092935efc78054ef324eb9f8166718270aefe036dfa1e4f68e1e \ - --hash=sha256:2109ecea94df90980be040490ff1d879971b024861539abb00054062388b612e +requests==2.20.0 \ + --hash=sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c \ + --hash=sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279 six==1.10.0 \ --hash=sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1 \ --hash=sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a @@ -1185,6 +1209,15 @@ zope.interface==4.1.3 \ requests-toolbelt==0.8.0 \ --hash=sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237 \ --hash=sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5 +chardet==3.0.2 \ + --hash=sha256:4f7832e7c583348a9eddd927ee8514b3bf717c061f57b21dbe7697211454d9bb \ + --hash=sha256:6ebf56457934fdce01fb5ada5582762a84eed94cad43ed877964aebbdd8174c0 +urllib3==1.21.1 \ + --hash=sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1 \ + --hash=sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5 +certifi==2017.4.17 \ + --hash=sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010 \ + --hash=sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a # Contains the requirements for the letsencrypt package. # @@ -1197,31 +1230,29 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.28.0 \ - --hash=sha256:f2f7c816acd695cbcda713a779b0db2b08e9de407146b46e1c4ef5561e0f5417 \ - --hash=sha256:31e3e2ee2a25c009a621c59ac9182f85d937a897c7bd1d47d0e01f3c712a090a -acme==0.28.0 \ - --hash=sha256:d3a564031155fece3f6edce8c5246d4cf34be0977b4c7c5ce84e86c68601c895 \ - --hash=sha256:bf7c2f1c24a26ab5b9fce3a6abca1d74a5914d46919649ae00ad5817db62bb85 -certbot-apache==0.28.0 \ - --hash=sha256:a57d7bac4f13ae5ecea4f4cbd479d381c02316c4832b25ab5a9d7c6826166370 \ - --hash=sha256:3f93f5de4a548e973c493a6cac5eeeb3dbbcae2988b61299ea0727d04a00f5bb -certbot-nginx==0.28.0 \ - --hash=sha256:1822a65910f0801087fa20a3af3fc94f878f93e0f11809483bb5387df861e296 \ - --hash=sha256:426fb403b0a7b203629f4e350a862cbc3bc1f69936fdab8ec7eafe0d8a3b5ddb +certbot==0.29.0 \ + --hash=sha256:fd055f3c132f966bf72bca653a52cf5974395cea6ce4f3f727f304bd52a332e3 \ + --hash=sha256:3c9f18cc502ff3b3bc8811ee1e90b73021fcf3891e13003fbe3d499fe7384753 +acme==0.29.0 \ + --hash=sha256:d7e80231b17a8fd31d625ec4be964583b7aa08824fbfcd7e35b3185ecf342d28 \ + --hash=sha256:37a2f933ee07c0f12dcaea519e6549f6f68145788a1f5db594afaabb592a6b79 +certbot-apache==0.29.0 \ + --hash=sha256:0db527c8664a4e9cd3989e947f32dda499cc779ac0626ba6a12c1f96f9d1bbe3 \ + --hash=sha256:bd55e5d7ece13f30935d6454cc32ffcc50229a3ed39eb2a6724e5db2e53549cd +certbot-nginx==0.29.0 \ + --hash=sha256:c788ea49542959210b88c5dfb3d0e29cbf2a04bbf7f424533812ec0d47e1627b \ + --hash=sha256:675b8a9acc3945c539f6a0582d1cf9e2cd5bed183f0db262810724365812d5a5 UNLIKELY_EOF # ------------------------------------------------------------------------- cat << "UNLIKELY_EOF" > "$TEMP_DIR/pipstrap.py" #!/usr/bin/env python """A small script that can act as a trust root for installing pip >=8 - Embed this in your project, and your VCS checkout is all you have to trust. In a post-peep era, this lets you claw your way to a hash-checking version of pip, with which you can install the rest of your dependencies safely. All it assumes is Python 2.6 or better and *some* version of pip already installed. If anything goes wrong, it will exit with a non-zero status code. - """ # This is here so embedded copies are MIT-compliant: # Copyright (c) 2016 Erik Rose @@ -1348,10 +1379,8 @@ def hashed_download(url, temp, digest): def get_index_base(): """Return the URL to the dir containing the "packages" folder. - Try to wring something out of PIP_INDEX_URL, if set. Hack "/simple" off the end if it's there; that is likely to give us the right dir. - """ env_var = environ.get('PIP_INDEX_URL', '').rstrip('/') if env_var: @@ -1641,7 +1670,12 @@ UNLIKELY_EOF error "WARNING: couldn't find Python $MIN_PYTHON_VERSION+ to check for updates." elif ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then error "WARNING: unable to check for updates." - elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then + fi + + LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` + if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then + say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" + elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." # Now we drop into Python so we don't have to install even more diff --git a/letsencrypt-auto-source/certbot-auto.asc b/letsencrypt-auto-source/certbot-auto.asc index 57745758b..a75e1a59f 100644 --- a/letsencrypt-auto-source/certbot-auto.asc +++ b/letsencrypt-auto-source/certbot-auto.asc @@ -1,11 +1,11 @@ -----BEGIN PGP SIGNATURE----- -iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAlvjV5wACgkQTRfJlc2X -dfKkRwf+MJ/Yo5ix7rxGMoliJl3GUUC2KvuYxObvbsAZW69Zl4aZVNeUP3Pe/EZj -zJlSMuiCPeTMmmr0+q78dk5Qk0vf+9D5qSQyy2U+RvPvX6z1PfaFXwjETwOEhE4i -7pABP4m/rIhlZbh336gou4XZK8sXsKHXBLQEyqmzPm6YFZ+5vowIoEinrN73PBuq -rgvoTFKi2NTjYNkQffYUeCIgO0pXlaOa8hkaupqoejHHEjjiXS2C9m0gAT2Wk2cO -zya5WQNcCCLWy/ChhPE2M7yRSpwqrszsHP0qo7QGL8vvsdXvNeJ7vwpAlq/9aipg -PpzSXy/ek8YAgApaj8+/w4OfdDhQ4Q== -=1hD2 +iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAlwIH5YACgkQTRfJlc2X +dfLonwgAt8cgnRz0rLefTJSG+Zc4SnDK+zLqtn1RjlVTtoLC+vZYpAQPqG4SVjqS +plDkyZD/9vu4tlrH9BIFCUUb2r6l4RKbfxdJMMkUfF1yYAvQbGRRtSmPDANdbVjG +9HXFMXwc7smthzHkTR4PV1GvEpNfbXRUau+h4KrPUK5pKD3Sc8PFlOZ39v9PkIxR +yyuBNYsYGxgIkmQ2zFG/877Hj/gIm18uAZtLC9ojSzra0VfmLlmegoMrs4DnuJEx +nN0Hsh979kaHV1O0yItT+oRYqONTIgvO2UG/VOqFDvpTNM53BelwnLQHLgpQkhgH +bljL/pDdu4ga+Ydz0UR0V1ExaPn/2Q== +=gc2V -----END PGP SIGNATURE----- diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index a804af523..8d9528559 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.29.0.dev0" +LE_AUTO_VERSION="0.29.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1230,18 +1230,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.28.0 \ - --hash=sha256:f2f7c816acd695cbcda713a779b0db2b08e9de407146b46e1c4ef5561e0f5417 \ - --hash=sha256:31e3e2ee2a25c009a621c59ac9182f85d937a897c7bd1d47d0e01f3c712a090a -acme==0.28.0 \ - --hash=sha256:d3a564031155fece3f6edce8c5246d4cf34be0977b4c7c5ce84e86c68601c895 \ - --hash=sha256:bf7c2f1c24a26ab5b9fce3a6abca1d74a5914d46919649ae00ad5817db62bb85 -certbot-apache==0.28.0 \ - --hash=sha256:a57d7bac4f13ae5ecea4f4cbd479d381c02316c4832b25ab5a9d7c6826166370 \ - --hash=sha256:3f93f5de4a548e973c493a6cac5eeeb3dbbcae2988b61299ea0727d04a00f5bb -certbot-nginx==0.28.0 \ - --hash=sha256:1822a65910f0801087fa20a3af3fc94f878f93e0f11809483bb5387df861e296 \ - --hash=sha256:426fb403b0a7b203629f4e350a862cbc3bc1f69936fdab8ec7eafe0d8a3b5ddb +certbot==0.29.0 \ + --hash=sha256:fd055f3c132f966bf72bca653a52cf5974395cea6ce4f3f727f304bd52a332e3 \ + --hash=sha256:3c9f18cc502ff3b3bc8811ee1e90b73021fcf3891e13003fbe3d499fe7384753 +acme==0.29.0 \ + --hash=sha256:d7e80231b17a8fd31d625ec4be964583b7aa08824fbfcd7e35b3185ecf342d28 \ + --hash=sha256:37a2f933ee07c0f12dcaea519e6549f6f68145788a1f5db594afaabb592a6b79 +certbot-apache==0.29.0 \ + --hash=sha256:0db527c8664a4e9cd3989e947f32dda499cc779ac0626ba6a12c1f96f9d1bbe3 \ + --hash=sha256:bd55e5d7ece13f30935d6454cc32ffcc50229a3ed39eb2a6724e5db2e53549cd +certbot-nginx==0.29.0 \ + --hash=sha256:c788ea49542959210b88c5dfb3d0e29cbf2a04bbf7f424533812ec0d47e1627b \ + --hash=sha256:675b8a9acc3945c539f6a0582d1cf9e2cd5bed183f0db262810724365812d5a5 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/letsencrypt-auto.sig b/letsencrypt-auto-source/letsencrypt-auto.sig index 33f5b2c00007bde13d9f58cf7e48ad17d6998502..fc93a7804072c78caabc97212f6ba77f84fa52a3 100644 GIT binary patch literal 256 zcmV+b0ssDy@;uZPVg}NwjsPtP`?lI<{(s>aCE|BAx52f)1j#5-4sDvGoyw*QT|osS z7(iG`@e3YWpZ$J379OHLQ8iQ~K{MyXiRXaLxRU_Uu`KVrPgJU?Ev1~>h3@rj0I6X?6}bYFPUfoD%JUw!xxqUi Gz0>!iiGPRy literal 256 zcmV+b0ssC{t4ydxm0o9{N03G=j7lT5c_4fvp=Ak0G{=zFl<_N_YV;M+5gCs_o{c#_ zk}R?1daPA6KJFO+@o7i}i@E(nx&;8|8w zwwanT<%NEK7%&NBc6_9#QU}r> diff --git a/letsencrypt-auto-source/pieces/certbot-requirements.txt b/letsencrypt-auto-source/pieces/certbot-requirements.txt index 401a8e25c..d8be0dc96 100644 --- a/letsencrypt-auto-source/pieces/certbot-requirements.txt +++ b/letsencrypt-auto-source/pieces/certbot-requirements.txt @@ -1,12 +1,12 @@ -certbot==0.28.0 \ - --hash=sha256:f2f7c816acd695cbcda713a779b0db2b08e9de407146b46e1c4ef5561e0f5417 \ - --hash=sha256:31e3e2ee2a25c009a621c59ac9182f85d937a897c7bd1d47d0e01f3c712a090a -acme==0.28.0 \ - --hash=sha256:d3a564031155fece3f6edce8c5246d4cf34be0977b4c7c5ce84e86c68601c895 \ - --hash=sha256:bf7c2f1c24a26ab5b9fce3a6abca1d74a5914d46919649ae00ad5817db62bb85 -certbot-apache==0.28.0 \ - --hash=sha256:a57d7bac4f13ae5ecea4f4cbd479d381c02316c4832b25ab5a9d7c6826166370 \ - --hash=sha256:3f93f5de4a548e973c493a6cac5eeeb3dbbcae2988b61299ea0727d04a00f5bb -certbot-nginx==0.28.0 \ - --hash=sha256:1822a65910f0801087fa20a3af3fc94f878f93e0f11809483bb5387df861e296 \ - --hash=sha256:426fb403b0a7b203629f4e350a862cbc3bc1f69936fdab8ec7eafe0d8a3b5ddb +certbot==0.29.0 \ + --hash=sha256:fd055f3c132f966bf72bca653a52cf5974395cea6ce4f3f727f304bd52a332e3 \ + --hash=sha256:3c9f18cc502ff3b3bc8811ee1e90b73021fcf3891e13003fbe3d499fe7384753 +acme==0.29.0 \ + --hash=sha256:d7e80231b17a8fd31d625ec4be964583b7aa08824fbfcd7e35b3185ecf342d28 \ + --hash=sha256:37a2f933ee07c0f12dcaea519e6549f6f68145788a1f5db594afaabb592a6b79 +certbot-apache==0.29.0 \ + --hash=sha256:0db527c8664a4e9cd3989e947f32dda499cc779ac0626ba6a12c1f96f9d1bbe3 \ + --hash=sha256:bd55e5d7ece13f30935d6454cc32ffcc50229a3ed39eb2a6724e5db2e53549cd +certbot-nginx==0.29.0 \ + --hash=sha256:c788ea49542959210b88c5dfb3d0e29cbf2a04bbf7f424533812ec0d47e1627b \ + --hash=sha256:675b8a9acc3945c539f6a0582d1cf9e2cd5bed183f0db262810724365812d5a5 diff --git a/setup.py b/setup.py index 382149054..2a9b2c203 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ version = meta['version'] # specified here to avoid masking the more specific request requirements in # acme. See https://github.com/pypa/pip/issues/988 for more info. install_requires = [ - 'acme>=0.29.0.dev0', + 'acme>=0.29.0', # We technically need ConfigArgParse 0.10.0 for Python 2.6 support, but # saying so here causes a runtime error against our temporary fork of 0.9.3 # in which we added 2.6 support (see #2243), so we relax the requirement. From 245dbc7a95b931515b499baba81fcb4ce2d719a6 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 5 Dec 2018 10:57:45 -0800 Subject: [PATCH 075/114] Add contents to CHANGELOG.md for next version --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf83679e5..be1a8dba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). +## 0.30.0 - master + +### Added + +* + +### Changed + +* + +### Fixed + +* + +Despite us having broken lockstep, we are continuing to release new versions of +all Certbot components during releases for the time being, however, the only +package with changes other than its version number was: + +* + +More details about these changes can be found on our GitHub repo. + ## 0.29.0 - 2018-12-05 ### Added From 3edfe9206938c0e30ad912b74c6d8ba47269314e Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 5 Dec 2018 10:57:46 -0800 Subject: [PATCH 076/114] Bump version to 0.30.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/__init__.py | 2 +- letsencrypt-auto-source/letsencrypt-auto | 2 +- local-oldest-requirements.txt | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 635a98a32..53a4eda27 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages from setuptools.command.test import test as TestCommand import sys -version = '0.29.0' +version = '0.30.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 250db9a16..2562e6f3f 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index 1c2a65dc0..405f8ff73 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -4,7 +4,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 2743b9cd2..4f12e78f7 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 9bdedc418..92ed37f35 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 0de673a34..0fd52c4b0 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index a1af50d91..eec35b472 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 61da2ca29..21899f3d8 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 42e08c062..2bca63ccf 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index 93521c018..ee484e402 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index a19d4ef25..c91aabd4f 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 665108da6..9f0fe149d 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index b1fdd6dd5..4ebfeb3e1 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 3776ad518..cbd77b901 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 2d8cb2293..2ea6699df 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 1461c6d02..84ca63f00 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 59803256b..cebd48e41 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index eea680f62..970089460 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/__init__.py b/certbot/__init__.py index 464474c2a..c96f7b28e 100644 --- a/certbot/__init__.py +++ b/certbot/__init__.py @@ -1,4 +1,4 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '0.29.0' +__version__ = '0.30.0.dev0' diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 8d9528559..c6c39752c 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.29.0" +LE_AUTO_VERSION="0.30.0.dev0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates diff --git a/local-oldest-requirements.txt b/local-oldest-requirements.txt index 2346300a3..d582d5c65 100644 --- a/local-oldest-requirements.txt +++ b/local-oldest-requirements.txt @@ -1 +1 @@ --e acme[dev] +acme[dev]==0.29.0 From 11e0fa52d0f2e7d8780465f5b2202e0cb717e065 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 5 Dec 2018 14:52:58 -0800 Subject: [PATCH 077/114] Fix default directories on Linux (#6560) * fix default directories * update changelog --- CHANGELOG.md | 5 +++-- certbot/compat.py | 4 ++-- certbot/tests/cli_test.py | 10 ++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be1a8dba1..97ba2225b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,13 +14,14 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). ### Fixed -* +* The default work and log directories have been changed back to + /var/lib/letsencrypt and /var/log/letsencrypt respectively. Despite us having broken lockstep, we are continuing to release new versions of all Certbot components during releases for the time being, however, the only package with changes other than its version number was: -* +* certbot More details about these changes can be found on our GitHub repo. diff --git a/certbot/compat.py b/certbot/compat.py index 7e509206f..7d936aa9d 100644 --- a/certbot/compat.py +++ b/certbot/compat.py @@ -180,8 +180,8 @@ WINDOWS_DEFAULT_FOLDERS = { } LINUX_DEFAULT_FOLDERS = { 'config': '/etc/letsencrypt', - 'work': '/var/letsencrypt/lib', - 'logs': '/var/letsencrypt/log', + 'work': '/var/lib/letsencrypt', + 'logs': '/var/log/letsencrypt', } def get_default_folder(folder_type): diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py index 1448b86e7..e16a1bdcf 100644 --- a/certbot/tests/cli_test.py +++ b/certbot/tests/cli_test.py @@ -4,6 +4,7 @@ import unittest import os import tempfile import copy +import sys import mock import six @@ -41,6 +42,15 @@ class TestReadFile(TempDirTestCase): self.assertEqual(contents, test_contents) +class FlagDefaultTest(unittest.TestCase): + """Tests cli.flag_default""" + + def test_linux_directories(self): + if 'fcntl' in sys.modules: + self.assertEqual(cli.flag_default('config_dir'), '/etc/letsencrypt') + self.assertEqual(cli.flag_default('work_dir'), '/var/lib/letsencrypt') + self.assertEqual(cli.flag_default('logs_dir'), '/var/log/letsencrypt') + class ParseTest(unittest.TestCase): # pylint: disable=too-many-public-methods '''Test the cli args entrypoint''' From 1651bdd86b53fb4662ddfe578a513518ecdc305e Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 5 Dec 2018 15:37:06 -0800 Subject: [PATCH 078/114] Fix default directories on Linux (#6560) (#6562) * fix default directories * update changelog (cherry picked from commit 11e0fa52d0f2e7d8780465f5b2202e0cb717e065) --- CHANGELOG.md | 23 +++++++++++++++++++++++ certbot/compat.py | 4 ++-- certbot/tests/cli_test.py | 10 ++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf83679e5..d93beeecc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,29 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). +## 0.29.1 - master + +### Added + +* + +### Changed + +* + +### Fixed + +* The default work and log directories have been changed back to + /var/lib/letsencrypt and /var/log/letsencrypt respectively. + +Despite us having broken lockstep, we are continuing to release new versions of +all Certbot components during releases for the time being, however, the only +package with changes other than its version number was: + +* certbot + +More details about these changes can be found on our GitHub repo. + ## 0.29.0 - 2018-12-05 ### Added diff --git a/certbot/compat.py b/certbot/compat.py index 7e509206f..7d936aa9d 100644 --- a/certbot/compat.py +++ b/certbot/compat.py @@ -180,8 +180,8 @@ WINDOWS_DEFAULT_FOLDERS = { } LINUX_DEFAULT_FOLDERS = { 'config': '/etc/letsencrypt', - 'work': '/var/letsencrypt/lib', - 'logs': '/var/letsencrypt/log', + 'work': '/var/lib/letsencrypt', + 'logs': '/var/log/letsencrypt', } def get_default_folder(folder_type): diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py index 1448b86e7..e16a1bdcf 100644 --- a/certbot/tests/cli_test.py +++ b/certbot/tests/cli_test.py @@ -4,6 +4,7 @@ import unittest import os import tempfile import copy +import sys import mock import six @@ -41,6 +42,15 @@ class TestReadFile(TempDirTestCase): self.assertEqual(contents, test_contents) +class FlagDefaultTest(unittest.TestCase): + """Tests cli.flag_default""" + + def test_linux_directories(self): + if 'fcntl' in sys.modules: + self.assertEqual(cli.flag_default('config_dir'), '/etc/letsencrypt') + self.assertEqual(cli.flag_default('work_dir'), '/var/lib/letsencrypt') + self.assertEqual(cli.flag_default('logs_dir'), '/var/log/letsencrypt') + class ParseTest(unittest.TestCase): # pylint: disable=too-many-public-methods '''Test the cli args entrypoint''' From 87215c7fafc21febc1267540e71a2f8433d1dce3 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 5 Dec 2018 15:47:59 -0800 Subject: [PATCH 079/114] Update changelog for 0.29.1 release --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d93beeecc..d75939464 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). -## 0.29.1 - master +## 0.29.1 - 2018-12-05 ### Added From be8638dad0e934880ded0cc4a583d42a65451546 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 5 Dec 2018 16:31:07 -0800 Subject: [PATCH 080/114] Release 0.29.1 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-auto | 26 +++++++++--------- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/__init__.py | 2 +- docs/cli-help.txt | 19 +++++++------ letsencrypt-auto | 26 +++++++++--------- letsencrypt-auto-source/certbot-auto.asc | 16 +++++------ letsencrypt-auto-source/letsencrypt-auto | 26 +++++++++--------- letsencrypt-auto-source/letsencrypt-auto.sig | Bin 256 -> 256 bytes .../pieces/certbot-requirements.txt | 24 ++++++++-------- 26 files changed, 88 insertions(+), 87 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 635a98a32..f76150483 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages from setuptools.command.test import test as TestCommand import sys -version = '0.29.0' +version = '0.29.1' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 250db9a16..aa91dda7b 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-auto b/certbot-auto index 8d9528559..6003afcf4 100755 --- a/certbot-auto +++ b/certbot-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.29.0" +LE_AUTO_VERSION="0.29.1" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1230,18 +1230,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.29.0 \ - --hash=sha256:fd055f3c132f966bf72bca653a52cf5974395cea6ce4f3f727f304bd52a332e3 \ - --hash=sha256:3c9f18cc502ff3b3bc8811ee1e90b73021fcf3891e13003fbe3d499fe7384753 -acme==0.29.0 \ - --hash=sha256:d7e80231b17a8fd31d625ec4be964583b7aa08824fbfcd7e35b3185ecf342d28 \ - --hash=sha256:37a2f933ee07c0f12dcaea519e6549f6f68145788a1f5db594afaabb592a6b79 -certbot-apache==0.29.0 \ - --hash=sha256:0db527c8664a4e9cd3989e947f32dda499cc779ac0626ba6a12c1f96f9d1bbe3 \ - --hash=sha256:bd55e5d7ece13f30935d6454cc32ffcc50229a3ed39eb2a6724e5db2e53549cd -certbot-nginx==0.29.0 \ - --hash=sha256:c788ea49542959210b88c5dfb3d0e29cbf2a04bbf7f424533812ec0d47e1627b \ - --hash=sha256:675b8a9acc3945c539f6a0582d1cf9e2cd5bed183f0db262810724365812d5a5 +certbot==0.29.1 \ + --hash=sha256:2ba2c60fd1969e75d3e5048d3f7d95afd0949670b39a6a0037ba4a594e9f26a5 \ + --hash=sha256:6fc604d207c48b95dea3458bb33a11b17aa625628eb197927ffee8b458f62692 +acme==0.29.1 \ + --hash=sha256:4be3848f8813c455021f13519642d8ec2746b78d4d0bc2ae04c3dcb1d8862f60 \ + --hash=sha256:a2e203ade83cd1eaf19112004a63073830211cf7759d437f634babb08c49b47c +certbot-apache==0.29.1 \ + --hash=sha256:8d8b6b7c5f333cf5297153c6a1eacc09b4a5c73e8f93544800b3ad016d5e34d0 \ + --hash=sha256:c3af1c66c86cfeef7dac4fe9b16c7c755ebd12bc526408c27781bd34b9de8128 +certbot-nginx==0.29.1 \ + --hash=sha256:5ba3a7d93d3ce317fb8b3d0222c708fb79e96c7a9b1ba56e12e46892c2d12869 \ + --hash=sha256:0c1205ebb91eef4b7d15293c6778ffc962d09563b315120b2d226348d751e38d UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index 1c2a65dc0..fc17a4ec2 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -4,7 +4,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 2743b9cd2..0b3b1b0eb 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 9bdedc418..6c5e460e3 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 0de673a34..bc9847aae 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index a1af50d91..95c8e75b5 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 61da2ca29..62725c098 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 42e08c062..a6956b604 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index 93521c018..d540b04fb 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index a19d4ef25..aa56650f4 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 665108da6..ffc499dfc 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index b1fdd6dd5..6117bb361 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 3776ad518..329edee93 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 2d8cb2293..a7dd6d1ce 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 1461c6d02..907755a77 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 59803256b..6498365b6 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index eea680f62..ae0f63fe9 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.0' +version = '0.29.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/__init__.py b/certbot/__init__.py index 464474c2a..65144ba37 100644 --- a/certbot/__init__.py +++ b/certbot/__init__.py @@ -1,4 +1,4 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '0.29.0' +__version__ = '0.29.1' diff --git a/docs/cli-help.txt b/docs/cli-help.txt index 1dc8c5cd9..37d67cfe0 100644 --- a/docs/cli-help.txt +++ b/docs/cli-help.txt @@ -112,7 +112,7 @@ optional arguments: case, and to know when to deprecate support for past Python versions and flags. If you wish to hide this information from the Let's Encrypt server, set this to - "". (default: CertbotACMEClient/0.29.0 + "". (default: CertbotACMEClient/0.29.1 (certbot(-auto); OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). The flags encoded in the @@ -252,8 +252,8 @@ paths: None) --config-dir CONFIG_DIR Configuration directory. (default: /etc/letsencrypt) - --work-dir WORK_DIR Working directory. (default: /var/letsencrypt/lib) - --logs-dir LOGS_DIR Logs directory. (default: /var/letsencrypt/log) + --work-dir WORK_DIR Working directory. (default: /var/lib/letsencrypt) + --logs-dir LOGS_DIR Logs directory. (default: /var/log/letsencrypt) --server SERVER ACME Directory Resource URI. (default: https://acme-v02.api.letsencrypt.org/directory) @@ -480,9 +480,10 @@ apache: Apache Web Server plugin --apache-enmod APACHE_ENMOD - Path to the Apache 'a2enmod' binary (default: None) + Path to the Apache 'a2enmod' binary (default: a2enmod) --apache-dismod APACHE_DISMOD - Path to the Apache 'a2dismod' binary (default: None) + Path to the Apache 'a2dismod' binary (default: + a2dismod) --apache-le-vhost-ext APACHE_LE_VHOST_EXT SSL vhost configuration extension (default: -le- ssl.conf) @@ -496,16 +497,16 @@ apache: /var/log/apache2) --apache-challenge-location APACHE_CHALLENGE_LOCATION Directory path for challenge configuration (default: - /etc/apache2/other) + /etc/apache2) --apache-handle-modules APACHE_HANDLE_MODULES Let installer handle enabling required modules for you - (Only Ubuntu/Debian currently) (default: False) + (Only Ubuntu/Debian currently) (default: True) --apache-handle-sites APACHE_HANDLE_SITES Let installer handle enabling sites for you (Only - Ubuntu/Debian currently) (default: False) + Ubuntu/Debian currently) (default: True) --apache-ctl APACHE_CTL Full path to Apache control script (default: - apachectl) + apache2ctl) dns-cloudflare: Obtain certificates using a DNS TXT record (if you are using Cloudflare diff --git a/letsencrypt-auto b/letsencrypt-auto index 8d9528559..6003afcf4 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.29.0" +LE_AUTO_VERSION="0.29.1" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1230,18 +1230,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.29.0 \ - --hash=sha256:fd055f3c132f966bf72bca653a52cf5974395cea6ce4f3f727f304bd52a332e3 \ - --hash=sha256:3c9f18cc502ff3b3bc8811ee1e90b73021fcf3891e13003fbe3d499fe7384753 -acme==0.29.0 \ - --hash=sha256:d7e80231b17a8fd31d625ec4be964583b7aa08824fbfcd7e35b3185ecf342d28 \ - --hash=sha256:37a2f933ee07c0f12dcaea519e6549f6f68145788a1f5db594afaabb592a6b79 -certbot-apache==0.29.0 \ - --hash=sha256:0db527c8664a4e9cd3989e947f32dda499cc779ac0626ba6a12c1f96f9d1bbe3 \ - --hash=sha256:bd55e5d7ece13f30935d6454cc32ffcc50229a3ed39eb2a6724e5db2e53549cd -certbot-nginx==0.29.0 \ - --hash=sha256:c788ea49542959210b88c5dfb3d0e29cbf2a04bbf7f424533812ec0d47e1627b \ - --hash=sha256:675b8a9acc3945c539f6a0582d1cf9e2cd5bed183f0db262810724365812d5a5 +certbot==0.29.1 \ + --hash=sha256:2ba2c60fd1969e75d3e5048d3f7d95afd0949670b39a6a0037ba4a594e9f26a5 \ + --hash=sha256:6fc604d207c48b95dea3458bb33a11b17aa625628eb197927ffee8b458f62692 +acme==0.29.1 \ + --hash=sha256:4be3848f8813c455021f13519642d8ec2746b78d4d0bc2ae04c3dcb1d8862f60 \ + --hash=sha256:a2e203ade83cd1eaf19112004a63073830211cf7759d437f634babb08c49b47c +certbot-apache==0.29.1 \ + --hash=sha256:8d8b6b7c5f333cf5297153c6a1eacc09b4a5c73e8f93544800b3ad016d5e34d0 \ + --hash=sha256:c3af1c66c86cfeef7dac4fe9b16c7c755ebd12bc526408c27781bd34b9de8128 +certbot-nginx==0.29.1 \ + --hash=sha256:5ba3a7d93d3ce317fb8b3d0222c708fb79e96c7a9b1ba56e12e46892c2d12869 \ + --hash=sha256:0c1205ebb91eef4b7d15293c6778ffc962d09563b315120b2d226348d751e38d UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/certbot-auto.asc b/letsencrypt-auto-source/certbot-auto.asc index a75e1a59f..b4e520fb2 100644 --- a/letsencrypt-auto-source/certbot-auto.asc +++ b/letsencrypt-auto-source/certbot-auto.asc @@ -1,11 +1,11 @@ -----BEGIN PGP SIGNATURE----- -iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAlwIH5YACgkQTRfJlc2X -dfLonwgAt8cgnRz0rLefTJSG+Zc4SnDK+zLqtn1RjlVTtoLC+vZYpAQPqG4SVjqS -plDkyZD/9vu4tlrH9BIFCUUb2r6l4RKbfxdJMMkUfF1yYAvQbGRRtSmPDANdbVjG -9HXFMXwc7smthzHkTR4PV1GvEpNfbXRUau+h4KrPUK5pKD3Sc8PFlOZ39v9PkIxR -yyuBNYsYGxgIkmQ2zFG/877Hj/gIm18uAZtLC9ojSzra0VfmLlmegoMrs4DnuJEx -nN0Hsh979kaHV1O0yItT+oRYqONTIgvO2UG/VOqFDvpTNM53BelwnLQHLgpQkhgH -bljL/pDdu4ga+Ydz0UR0V1ExaPn/2Q== -=gc2V +iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAlwIbaAACgkQTRfJlc2X +dfLIGQf+JZr3oP89qyMREYAL3/Bx+vxsx+c01IuDaG1pBUeVwL5rdeU1kDZ1WkKb +61nCoMPbSLqLMor2IpobFj44lEFJS1WYrtfe8sgMLeSaQkWXlB3breLKI09p/IBm +X3lN7VIMPW8eLziSArGivKTpsW+cDau8Rbnn5FSMNiZojCp+bSPehOpZBmHb2OrS +2akgCBQYh2e+cadv5MmGPqta8iTDMDgMOrTzAstPKRfeHozyoOsRjeq1T9Yl65lk +XF+m0yl2r4w8VxemWzqaT53XHS+3tgCunDtB7pDXuM6zpNnWghxN1UJ8Ywle1nt4 +ecxxPwHfGAq9cAVCM7M0x4y+bxdnbw== +=8xDr -----END PGP SIGNATURE----- diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 8d9528559..6003afcf4 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.29.0" +LE_AUTO_VERSION="0.29.1" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1230,18 +1230,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.29.0 \ - --hash=sha256:fd055f3c132f966bf72bca653a52cf5974395cea6ce4f3f727f304bd52a332e3 \ - --hash=sha256:3c9f18cc502ff3b3bc8811ee1e90b73021fcf3891e13003fbe3d499fe7384753 -acme==0.29.0 \ - --hash=sha256:d7e80231b17a8fd31d625ec4be964583b7aa08824fbfcd7e35b3185ecf342d28 \ - --hash=sha256:37a2f933ee07c0f12dcaea519e6549f6f68145788a1f5db594afaabb592a6b79 -certbot-apache==0.29.0 \ - --hash=sha256:0db527c8664a4e9cd3989e947f32dda499cc779ac0626ba6a12c1f96f9d1bbe3 \ - --hash=sha256:bd55e5d7ece13f30935d6454cc32ffcc50229a3ed39eb2a6724e5db2e53549cd -certbot-nginx==0.29.0 \ - --hash=sha256:c788ea49542959210b88c5dfb3d0e29cbf2a04bbf7f424533812ec0d47e1627b \ - --hash=sha256:675b8a9acc3945c539f6a0582d1cf9e2cd5bed183f0db262810724365812d5a5 +certbot==0.29.1 \ + --hash=sha256:2ba2c60fd1969e75d3e5048d3f7d95afd0949670b39a6a0037ba4a594e9f26a5 \ + --hash=sha256:6fc604d207c48b95dea3458bb33a11b17aa625628eb197927ffee8b458f62692 +acme==0.29.1 \ + --hash=sha256:4be3848f8813c455021f13519642d8ec2746b78d4d0bc2ae04c3dcb1d8862f60 \ + --hash=sha256:a2e203ade83cd1eaf19112004a63073830211cf7759d437f634babb08c49b47c +certbot-apache==0.29.1 \ + --hash=sha256:8d8b6b7c5f333cf5297153c6a1eacc09b4a5c73e8f93544800b3ad016d5e34d0 \ + --hash=sha256:c3af1c66c86cfeef7dac4fe9b16c7c755ebd12bc526408c27781bd34b9de8128 +certbot-nginx==0.29.1 \ + --hash=sha256:5ba3a7d93d3ce317fb8b3d0222c708fb79e96c7a9b1ba56e12e46892c2d12869 \ + --hash=sha256:0c1205ebb91eef4b7d15293c6778ffc962d09563b315120b2d226348d751e38d UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/letsencrypt-auto.sig b/letsencrypt-auto-source/letsencrypt-auto.sig index fc93a7804072c78caabc97212f6ba77f84fa52a3..7b3874da00e87d2dceb20372e6079f44fdf2c6a9 100644 GIT binary patch literal 256 zcmV+b0ssC&MV4ZBp~!>0zD9eP{pH!EBXbu^4*LFC6`15?<s2Pgj|8@y%FjNX}t56=4%&hte0AGS1xZSCP?+WUH-uVvaPBwiWlaCE|BAx52f)1j#5-4sDvGoyw*QT|osS z7(iG`@e3YWpZ$J379OHLQ8iQ~K{MyXiRXaLxRU_Uu`KVrPgJU?Ev1~>h3@rj0I6X?6}bYFPUfoD%JUw!xxqUi Gz0>!iiGPRy diff --git a/letsencrypt-auto-source/pieces/certbot-requirements.txt b/letsencrypt-auto-source/pieces/certbot-requirements.txt index d8be0dc96..cfe3f6fbe 100644 --- a/letsencrypt-auto-source/pieces/certbot-requirements.txt +++ b/letsencrypt-auto-source/pieces/certbot-requirements.txt @@ -1,12 +1,12 @@ -certbot==0.29.0 \ - --hash=sha256:fd055f3c132f966bf72bca653a52cf5974395cea6ce4f3f727f304bd52a332e3 \ - --hash=sha256:3c9f18cc502ff3b3bc8811ee1e90b73021fcf3891e13003fbe3d499fe7384753 -acme==0.29.0 \ - --hash=sha256:d7e80231b17a8fd31d625ec4be964583b7aa08824fbfcd7e35b3185ecf342d28 \ - --hash=sha256:37a2f933ee07c0f12dcaea519e6549f6f68145788a1f5db594afaabb592a6b79 -certbot-apache==0.29.0 \ - --hash=sha256:0db527c8664a4e9cd3989e947f32dda499cc779ac0626ba6a12c1f96f9d1bbe3 \ - --hash=sha256:bd55e5d7ece13f30935d6454cc32ffcc50229a3ed39eb2a6724e5db2e53549cd -certbot-nginx==0.29.0 \ - --hash=sha256:c788ea49542959210b88c5dfb3d0e29cbf2a04bbf7f424533812ec0d47e1627b \ - --hash=sha256:675b8a9acc3945c539f6a0582d1cf9e2cd5bed183f0db262810724365812d5a5 +certbot==0.29.1 \ + --hash=sha256:2ba2c60fd1969e75d3e5048d3f7d95afd0949670b39a6a0037ba4a594e9f26a5 \ + --hash=sha256:6fc604d207c48b95dea3458bb33a11b17aa625628eb197927ffee8b458f62692 +acme==0.29.1 \ + --hash=sha256:4be3848f8813c455021f13519642d8ec2746b78d4d0bc2ae04c3dcb1d8862f60 \ + --hash=sha256:a2e203ade83cd1eaf19112004a63073830211cf7759d437f634babb08c49b47c +certbot-apache==0.29.1 \ + --hash=sha256:8d8b6b7c5f333cf5297153c6a1eacc09b4a5c73e8f93544800b3ad016d5e34d0 \ + --hash=sha256:c3af1c66c86cfeef7dac4fe9b16c7c755ebd12bc526408c27781bd34b9de8128 +certbot-nginx==0.29.1 \ + --hash=sha256:5ba3a7d93d3ce317fb8b3d0222c708fb79e96c7a9b1ba56e12e46892c2d12869 \ + --hash=sha256:0c1205ebb91eef4b7d15293c6778ffc962d09563b315120b2d226348d751e38d From 5ff4fa91b064e9609bf2cfd5ee0d3e9dcc160980 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 5 Dec 2018 16:31:08 -0800 Subject: [PATCH 081/114] Add contents to CHANGELOG.md for next version --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d75939464..74bc0fd98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). +## 0.30.0 - master + +### Added + +* + +### Changed + +* + +### Fixed + +* + +Despite us having broken lockstep, we are continuing to release new versions of +all Certbot components during releases for the time being, however, the only +package with changes other than its version number was: + +* + +More details about these changes can be found on our GitHub repo. + ## 0.29.1 - 2018-12-05 ### Added From 82cfff8d3519cf2ef06a091205f0c92ae783fc6e Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 5 Dec 2018 16:31:09 -0800 Subject: [PATCH 082/114] Bump version to 0.30.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/__init__.py | 2 +- letsencrypt-auto-source/letsencrypt-auto | 2 +- local-oldest-requirements.txt | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index f76150483..53a4eda27 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages from setuptools.command.test import test as TestCommand import sys -version = '0.29.1' +version = '0.30.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index aa91dda7b..2562e6f3f 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index fc17a4ec2..405f8ff73 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -4,7 +4,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 0b3b1b0eb..4f12e78f7 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 6c5e460e3..92ed37f35 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index bc9847aae..0fd52c4b0 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 95c8e75b5..eec35b472 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 62725c098..21899f3d8 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index a6956b604..2bca63ccf 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index d540b04fb..ee484e402 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index aa56650f4..c91aabd4f 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index ffc499dfc..9f0fe149d 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 6117bb361..4ebfeb3e1 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 329edee93..cbd77b901 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index a7dd6d1ce..2ea6699df 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 907755a77..84ca63f00 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 6498365b6..cebd48e41 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index ae0f63fe9..970089460 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.29.1' +version = '0.30.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/__init__.py b/certbot/__init__.py index 65144ba37..c96f7b28e 100644 --- a/certbot/__init__.py +++ b/certbot/__init__.py @@ -1,4 +1,4 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '0.29.1' +__version__ = '0.30.0.dev0' diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 6003afcf4..0ffe6c5f5 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.29.1" +LE_AUTO_VERSION="0.30.0.dev0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates diff --git a/local-oldest-requirements.txt b/local-oldest-requirements.txt index 2346300a3..302339918 100644 --- a/local-oldest-requirements.txt +++ b/local-oldest-requirements.txt @@ -1 +1 @@ --e acme[dev] +acme[dev]==0.29.1 From adedcc641644b05add3a785ddedeb771e94dd146 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Thu, 6 Dec 2018 18:33:46 +0100 Subject: [PATCH 083/114] Reduce to the minimal requirements to ensure Windows compatibility: execute tests only against lower and higher version of Python supported by Certbot on Windows. (#6565) --- appveyor.yml | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 725ecfbff..ce2b5998c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,17 +1,9 @@ +image: Visual Studio 2015 + environment: matrix: - - FYI: Python 3.4 on Windows Server 2012 R2 - TOXENV: py34 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - - FYI: Python 3.4 on Windows Server 2016 - TOXENV: py34 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - - FYI: Python 3.5 on Windows Server 2016 - TOXENV: py35 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - - FYI: Python 3.7 on Windows Server 2016 + code coverage - TOXENV: py37-cover - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - TOXENV: py35 + - TOXENV: py37-cover branches: only: @@ -23,7 +15,6 @@ install: # Use Python 3.7 by default - "SET PATH=C:\\Python37;C:\\Python37\\Scripts;%PATH%" # Check env - - "echo %APPVEYOR_BUILD_WORKER_IMAGE%" - "python --version" # Upgrade pip to avoid warnings - "python -m pip install --upgrade pip" From 353d09258575a5a8bfcfe7cb145834f787f2b7bb Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 6 Dec 2018 16:02:16 -0800 Subject: [PATCH 084/114] Remove -q/--quiet from pip invocations. (#6568) While reducing noise in test output is valuable, this flag has made a couple aspects of Certbot's development difficult: 1. We test with different sets of dependencies and running pip in quiet mode removes all output about the packages being installed which has made reviewing changes to these tests more difficult. 2. When pip fails, it provides significantly less output about the failure in quiet mode than it does normally. The output is reduced so much that in the two times I've hit this issue in the last month, I was only able to see that installing package X failed rather than what the cause of that failure was which could be seen with `--quiet` removed. Also, since running pip without `--quiet` is the tox default, I expect Python developers to be familiar with what they see here. --- tools/install_and_test.py | 4 ++-- tools/pip_install.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/install_and_test.py b/tools/install_and_test.py index 1eb81770c..79a7c2264 100755 --- a/tools/install_and_test.py +++ b/tools/install_and_test.py @@ -23,7 +23,7 @@ def call_with_print(command, cwd=None): def main(args): if os.environ.get('CERTBOT_NO_PIN') == '1': - command = [sys.executable, '-m', 'pip', '-q', '-e'] + command = [sys.executable, '-m', 'pip', '-e'] else: script_dir = os.path.dirname(os.path.abspath(__file__)) command = [sys.executable, os.path.join(script_dir, 'pip_install_editable.py')] @@ -50,7 +50,7 @@ def main(args): shutil.copy2("pytest.ini", temp_cwd) try: call_with_print(' '.join([ - sys.executable, '-m', 'pytest', '--quiet', pkg.replace('-', '_')]), cwd=temp_cwd) + sys.executable, '-m', 'pytest', pkg.replace('-', '_')]), cwd=temp_cwd) finally: shutil.rmtree(temp_cwd) diff --git a/tools/pip_install.py b/tools/pip_install.py index 8878674c9..354dce32b 100755 --- a/tools/pip_install.py +++ b/tools/pip_install.py @@ -83,10 +83,10 @@ def main(args): merge_requirements(tools_path, test_constraints, all_constraints) if requirements: - call_with_print('"{0}" -m pip install -q --constraint "{1}" --requirement "{2}"' + call_with_print('"{0}" -m pip install --constraint "{1}" --requirement "{2}"' .format(sys.executable, all_constraints, requirements)) - call_with_print('"{0}" -m pip install -q --constraint "{1}" {2}' + call_with_print('"{0}" -m pip install --constraint "{1}" {2}' .format(sys.executable, all_constraints, ' '.join(args))) finally: shutil.rmtree(working_dir) From 85f8f68263851b8f329cafdf8fee16b0f56e2d04 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Fri, 7 Dec 2018 14:18:28 -0800 Subject: [PATCH 085/114] Documentation fix-ups --- docs/challenges.rst | 18 ++++++++++++------ docs/contributing.rst | 4 ++-- docs/install.rst | 2 +- docs/using.rst | 14 +++++++------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/docs/challenges.rst b/docs/challenges.rst index 034f79956..607d5c08b 100644 --- a/docs/challenges.rst +++ b/docs/challenges.rst @@ -3,9 +3,9 @@ Challenges To receive a certificate from Let's Encrypt certificate authority (CA), you must pass a *challenge* to prove you control each of the domain names that will be listed in the certificate. A challenge is one of -three tasks that only someone who controls the domain should be able to accomplish: +a list of specified tasks that only someone who controls the domain should be able to accomplish, such as: -* Posting a specified file in a specified location on a web site (the HTTP-01 challenge) +* Posting a specified file in a specified location on a web site (the HTTP-01 challenge) * Posting a specified DNS record in the domain name system (the DNS-01 challenge) It’s possible to complete each type of challenge *automatically* (Certbot directly makes the necessary @@ -15,15 +15,21 @@ design favors performing challenges automatically, and this is the normal case f Some plugins offer an *authenticator*, meaning that they can satisfy challenges: +* Apache plugin: (HTTP-01) Tries to edit your Apache configuration files to temporarily serve files to + satisfy challenges from the certificate authority. Use the Apache plugin when you're running Certbot on a + web server with Apache listening on port 80. +* nginx plugin: (HTTP-01) Tries to edit your nginx configuration files to temporarily serve files to + satisfy challenges from the certificate authority. Use the nginx plugin when you're running Certbot on a + web server with nginx listening on port 80. * Webroot plugin: (HTTP-01) Tries to place a file where it can be served over HTTP on port 80 by a web server running on your system. Use the Webroot plugin when you're running Certbot on a web server with any server application listening on port 80 serving files from a folder on disk in response. -* Standalone plugin: (HTTP-01) Tries to run a temporary web server listening on HTTP on - port 80 (for HTTP-01). Use the Standalone plugin if no existing program - is listening to these ports. Choose HTTP-01 using the `--preferred-challenges` option. +* Standalone plugin: (HTTP-01) Tries to run a temporary web server listening on HTTP on port 80. Use the + Standalone plugin if no existing program is listening to this port. * Manual plugin: (DNS-01 or HTTP-01) Either tells you what changes to make to your configuration or updates your DNS records using an external script (for DNS-01) or your webroot (for HTTP-01). Use the Manual - plugin if you have the technical knowledge to make configuration changes yourself when asked to do so. + plugin if you have the technical knowledge to make configuration changes yourself when asked to do so, + and are prepared to repeat these steps every time the certificate needs to be renewed. Tips for Challenges ------------------- diff --git a/docs/contributing.rst b/docs/contributing.rst index f05b0fa9a..229c63841 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -187,7 +187,7 @@ Authenticators Authenticators are plugins that prove control of a domain name by solving a challenge provided by the ACME server. ACME currently defines three types of -challenges: HTTP, TLS-SNI, and DNS, represented by classes in `acme.challenges`. +challenges: HTTP, TLS-SNI (deprecated), TLS-ALPR, and DNS, represented by classes in `acme.challenges`. An authenticator plugin should implement support for at least one challenge type. An Authenticator indicates which challenges it supports by implementing @@ -215,7 +215,7 @@ support for IIS, Icecast and Plesk. Installers and Authenticators will oftentimes be the same class/object (because for instance both tasks can be performed by a webserver like nginx) though this is not always the case (the standalone plugin is an authenticator -that listens on port 443, but it cannot install certs; a postfix plugin would +that listens on port 80, but it cannot install certs; a postfix plugin would be an installer but not an authenticator). Installers and Authenticators are kept separate because diff --git a/docs/install.rst b/docs/install.rst index fc6abad7a..35b262482 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -29,7 +29,7 @@ System Requirements Certbot currently requires Python 2.7 or 3.4+ running on a UNIX-like operating system. By default, it 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 +bind to port 80 (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 diff --git a/docs/using.rst b/docs/using.rst index fd6e8e509..65c54cc8d 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -44,10 +44,13 @@ a combination_ of distinct authenticator and installer plugins. =========== ==== ==== =============================================================== ============================= Plugin Auth Inst Notes Challenge types (and port) =========== ==== ==== =============================================================== ============================= +apache_ Y Y | Automates obtaining and installing a certificate with Apache http-01_ (80) + | 2.4 on OSes with ``libaugeas0`` 1.0+. +nginx_ Y Y | Automates obtaining and installing a certificate with Nginx. http-01_ (80) webroot_ Y N | Obtains a certificate by writing to the webroot directory of http-01_ (80) | an already running webserver. -standalone_ Y N | Uses a "standalone" webserver to obtain a certificate. http-01_ (80) - | Requires port 80 to be available. This is useful on +standalone_ Y N | Uses a "standalone" webserver to obtain a certificate. http-01_ (80) + | Requires port 80 to be available. This is useful on | systems with no webserver, or when direct integration with | the local webserver is not supported or not desired. |dns_plugs| Y N | This category of plugins automates obtaining a certificate by dns-01_ (53) @@ -156,10 +159,7 @@ To obtain a certificate 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 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. - - * ``--preferred-challenges http`` to use port 80 +existing webserver. It must still be possible for your machine to accept inbound connections from the Internet on the specified port using each requested domain name. @@ -252,7 +252,7 @@ installer plugins. To do so, specify the authenticator plugin with For instance, you may want to create a certificate using the webroot_ plugin for authentication and the apache_ plugin for installation, perhaps because you -use a proxy or CDN for SSL and only want to secure the connection between them +use a proxy or CDN for HTTPS and only want to secure the connection between them and your origin server. :: From 9e1ee01547ff8d98382db7e8e5bd2b94f703caa8 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 10 Dec 2018 16:17:30 -0800 Subject: [PATCH 086/114] "Four shalt thou not count, neither count thou two" --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 229c63841..d95cbf4c0 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -186,7 +186,7 @@ Authenticators -------------- Authenticators are plugins that prove control of a domain name by solving a -challenge provided by the ACME server. ACME currently defines three types of +challenge provided by the ACME server. ACME currently defines four types of challenges: HTTP, TLS-SNI (deprecated), TLS-ALPR, and DNS, represented by classes in `acme.challenges`. An authenticator plugin should implement support for at least one challenge type. From 5a8bea458037c59c7f09f343889a722198703225 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 10 Dec 2018 16:18:57 -0800 Subject: [PATCH 087/114] Consistent capitalization for list --- docs/challenges.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/challenges.rst b/docs/challenges.rst index 607d5c08b..ee8bb8e61 100644 --- a/docs/challenges.rst +++ b/docs/challenges.rst @@ -18,7 +18,7 @@ Some plugins offer an *authenticator*, meaning that they can satisfy challenges: * Apache plugin: (HTTP-01) Tries to edit your Apache configuration files to temporarily serve files to satisfy challenges from the certificate authority. Use the Apache plugin when you're running Certbot on a web server with Apache listening on port 80. -* nginx plugin: (HTTP-01) Tries to edit your nginx configuration files to temporarily serve files to +* Nginx plugin: (HTTP-01) Tries to edit your nginx configuration files to temporarily serve files to satisfy challenges from the certificate authority. Use the nginx plugin when you're running Certbot on a web server with nginx listening on port 80. * Webroot plugin: (HTTP-01) Tries to place a file where it can be served over HTTP on port 80 by a From 6c06a10d0abb152934621ce68e82d19ba5f48515 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 10 Dec 2018 16:28:28 -0800 Subject: [PATCH 088/114] Remove motivation for combining plugins, add 2nd example --- docs/using.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 65c54cc8d..090ba49cb 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -250,15 +250,20 @@ installer plugins. To do so, specify the authenticator plugin with ``--authenticator`` or ``-a`` and the installer plugin with ``--installer`` or ``-i``. -For instance, you may want to create a certificate using the webroot_ plugin -for authentication and the apache_ plugin for installation, perhaps because you -use a proxy or CDN for HTTPS and only want to secure the connection between them -and your origin server. +For instance, you could create a certificate using the webroot_ plugin +for authentication and the apache_ plugin for installation. :: certbot run -a webroot -i apache -w /var/www/html -d example.com +Or you could create a certificate using the manual_ plugin for authentication +and the nginx_ plugin for installation. (Note that this certificate cannot +be renewed automatically.) + +:: + certbot run -a manual -i nginx -d example.com + .. _third-party-plugins: Third-party plugins From 38ae7c8f9950740cadf605186700877be0dbeb1f Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 10 Dec 2018 17:48:59 -0800 Subject: [PATCH 089/114] An unspecified number of challenges exist --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index d95cbf4c0..264db630f 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -186,7 +186,7 @@ Authenticators -------------- Authenticators are plugins that prove control of a domain name by solving a -challenge provided by the ACME server. ACME currently defines four types of +challenge provided by the ACME server. ACME currently defines several types of challenges: HTTP, TLS-SNI (deprecated), TLS-ALPR, and DNS, represented by classes in `acme.challenges`. An authenticator plugin should implement support for at least one challenge type. From 64e570d63c89f36eba8419558bf7910bdfef4762 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 10 Dec 2018 17:49:24 -0800 Subject: [PATCH 090/114] Remove spurious comma --- docs/using.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/using.rst b/docs/using.rst index 090ba49cb..5e8675418 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -67,7 +67,7 @@ manual_ Y N | Helps you obtain a certificate by giving you instruction .. |dns_plugs| replace:: :ref:`DNS plugins ` Under the hood, plugins use one of several ACME protocol challenges_ to -prove you control a domain. The options are http-01_ (which uses port 80), +prove you control a domain. The options are http-01_ (which uses port 80) and dns-01_ (requiring configuration of a DNS server on port 53, though that's often not the same machine as your webserver). A few plugins support more than one challenge type, in which case you can choose one From f137d55b31c022e9e574b1d48edc55938048ae21 Mon Sep 17 00:00:00 2001 From: dschlessman <36820111+dschlessman@users.noreply.github.com> Date: Tue, 11 Dec 2018 21:57:33 -0500 Subject: [PATCH 091/114] Issue 3816/revamp register subcommand (#6006) * address issue #3816 * formatting update * remove unused variable * address pylint trailing whitespace error * revert whitespace add * update boulder ci test for new update_registration verb * address code review comments * Issue 3816: Revert renaming '...update_regristration...' tests to '...update_account...'. Fix removing update_registration default argument value. * Issue 3816: Fix '--update-registration' not referring to 'update_registration' default as opposed to 'update_account'. * Issue 3816: delint tox output. * Issue 3816: Change @example.org domain to @domain.org in boulder test script * Issue 3816: Update CHANGELOG.md for Issue 3816 and remove extraneous space in main.py * Issue 3816: Remove extraneous default variable. --- CHANGELOG.md | 7 ++-- certbot/cli.py | 25 ++++++++----- certbot/main.py | 54 ++++++++++++++++++++-------- certbot/tests/main_test.py | 53 +++++++++++++++++++++++++-- tests/certbot-boulder-integration.sh | 6 ++++ 5 files changed, 116 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bc0fd98..a0c6f0eb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,14 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). ### Added -* +* Added the `update_account` subcommand for account management commands. ### Changed -* +* Copied account management functionality from the `register` subcommand + to the `update_account` subcommand. +* Marked usage `register --update-registration` for deprecation and + removal in a future release. ### Fixed diff --git a/certbot/cli.py b/certbot/cli.py index 8557b12c8..8e599cfda 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -101,6 +101,7 @@ manage certificates: manage your account with Let's Encrypt: register Create a Let's Encrypt ACME account + update_account Update a Let's Encrypt ACME account --agree-tos Agree to the ACME server's Subscriber Agreement -m EMAIL Email address for important account notifications """ @@ -397,9 +398,14 @@ VERB_HELP = [ }), ("register", { "short": "Register for account with Let's Encrypt / other ACME server", - "opts": "Options for account registration & modification", + "opts": "Options for account registration", "usage": "\n\n certbot register --email user@example.com [options]\n\n" }), + ("update_account", { + "short": "Update existing account with Let's Encrypt / other ACME server", + "opts": "Options for account modification", + "usage": "\n\n certbot update_account --email updated_email@example.com [options]\n\n" + }), ("unregister", { "short": "Irrevocably deactivate your account", "opts": "Options for account deactivation.", @@ -465,6 +471,7 @@ class HelpfulArgumentParser(object): "install": main.install, "plugins": main.plugins_cmd, "register": main.register, + "update_account": main.update_account, "unregister": main.unregister, "renew": main.renew, "revoke": main.revoke, @@ -993,21 +1000,21 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis "certificates. Updates to the Subscriber Agreement will still " "affect you, and will be effective 14 days after posting an " "update to the web site.") + # TODO: When `certbot register --update-registration` is fully deprecated, + # delete following helpful.add helpful.add( "register", "--update-registration", action="store_true", - default=flag_default("update_registration"), - help="With the register verb, indicates that details associated " - "with an existing registration, such as the e-mail address, " - "should be updated, rather than registering a new account.") + default=flag_default("update_registration"), dest="update_registration", + help=argparse.SUPPRESS) helpful.add( - ["register", "unregister", "automation"], "-m", "--email", + ["register", "update_account", "unregister", "automation"], "-m", "--email", default=flag_default("email"), help=config_help("email")) - helpful.add(["register", "automation"], "--eff-email", action="store_true", + helpful.add(["register", "update_account", "automation"], "--eff-email", action="store_true", default=flag_default("eff_email"), dest="eff_email", help="Share your e-mail address with EFF") - helpful.add(["register", "automation"], "--no-eff-email", action="store_false", - default=flag_default("eff_email"), dest="eff_email", + helpful.add(["register", "update_account", "automation"], "--no-eff-email", + action="store_false", default=flag_default("eff_email"), dest="eff_email", help="Don't share your e-mail address with EFF") helpful.add( ["automation", "certonly", "run"], diff --git a/certbot/main.py b/certbot/main.py index 692dafeed..b24c5c622 100644 --- a/certbot/main.py +++ b/certbot/main.py @@ -654,7 +654,45 @@ def unregister(config, unused_plugins): def register(config, unused_plugins): - """Create or modify accounts on the server. + """Create accounts on the server. + + :param config: Configuration object + :type config: interfaces.IConfig + + :param unused_plugins: List of plugins (deprecated) + :type unused_plugins: `list` of `str` + + :returns: `None` or a string indicating and error + :rtype: None or str + + """ + # TODO: When `certbot register --update-registration` is fully deprecated, + # delete the true case of if block + if config.update_registration: + msg = ("Usage 'certbot register --update-registration' is deprecated.\n" + "Please use 'cerbot update_account [options]' instead.\n") + logger.warning(msg) + return update_account(config, unused_plugins) + + # Portion of _determine_account logic to see whether accounts already + # exist or not. + account_storage = account.AccountFileStorage(config) + accounts = account_storage.find_all() + + if len(accounts) > 0: + # TODO: add a flag to register a duplicate account (this will + # also require extending _determine_account's behavior + # or else extracting the registration code from there) + return ("There is an existing account; registration of a " + "duplicate account with this command is currently " + "unsupported.") + # _determine_account will register an account + _determine_account(config) + return + + +def update_account(config, unused_plugins): + """Modify accounts on the server. :param config: Configuration object :type config: interfaces.IConfig @@ -673,20 +711,6 @@ def register(config, unused_plugins): reporter_util = zope.component.getUtility(interfaces.IReporter) add_msg = lambda m: reporter_util.add_message(m, reporter_util.MEDIUM_PRIORITY) - # registering a new account - if not config.update_registration: - if len(accounts) > 0: - # TODO: add a flag to register a duplicate account (this will - # also require extending _determine_account's behavior - # or else extracting the registration code from there) - return ("There is an existing account; registration of a " - "duplicate account with this command is currently " - "unsupported.") - # _determine_account will register an account - _determine_account(config) - return - - # --update-registration if len(accounts) == 0: return "Could not find an existing account to update." if config.email is None: diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index adfeff872..786b91a94 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -1398,7 +1398,20 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met x = self._call_no_clientmock(["register", "--email", "user@example.org"]) self.assertTrue("There is an existing account" in x[0]) - def test_update_registration_no_existing_accounts(self): + def test_update_account_no_existing_accounts(self): + # with mock.patch('certbot.main.client') as mocked_client: + with mock.patch('certbot.main.account') as mocked_account: + mocked_storage = mock.MagicMock() + mocked_account.AccountFileStorage.return_value = mocked_storage + mocked_storage.find_all.return_value = [] + x = self._call_no_clientmock( + ["update_account", "--email", + "user@example.org"]) + self.assertTrue("Could not find an existing account" in x[0]) + + # TODO: When `certbot register --update-registration` is fully deprecated, + # delete the following test + def test_update_registration_no_existing_accounts_deprecated(self): # with mock.patch('certbot.main.client') as mocked_client: with mock.patch('certbot.main.account') as mocked_account: mocked_storage = mock.MagicMock() @@ -1409,7 +1422,9 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met "user@example.org"]) self.assertTrue("Could not find an existing account" in x[0]) - def test_update_registration_unsafely(self): + # TODO: When `certbot register --update-registration` is fully deprecated, + # delete the following test + def test_update_registration_unsafely_deprecated(self): # This test will become obsolete when register --update-registration # supports removing an e-mail address from the account with mock.patch('certbot.main.account') as mocked_account: @@ -1423,7 +1438,39 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met @mock.patch('certbot.main.display_ops.get_email') @test_util.patch_get_utility() - def test_update_registration_with_email(self, mock_utility, mock_email): + def test_update_account_with_email(self, mock_utility, mock_email): + email = "user@example.com" + mock_email.return_value = email + with mock.patch('certbot.eff.handle_subscription') as mock_handle: + with mock.patch('certbot.main._determine_account') as mocked_det: + with mock.patch('certbot.main.account') as mocked_account: + with mock.patch('certbot.main.client') as mocked_client: + mocked_storage = mock.MagicMock() + mocked_account.AccountFileStorage.return_value = mocked_storage + mocked_storage.find_all.return_value = ["an account"] + mocked_det.return_value = (mock.MagicMock(), "foo") + cb_client = mock.MagicMock() + mocked_client.Client.return_value = cb_client + x = self._call_no_clientmock( + ["update_account"]) + # When registration change succeeds, the return value + # of register() is None + self.assertTrue(x[0] is None) + # and we got supposedly did update the registration from + # the server + self.assertTrue( + cb_client.acme.update_registration.called) + # and we saved the updated registration on disk + self.assertTrue(mocked_storage.save_regr.called) + self.assertTrue( + email in mock_utility().add_message.call_args[0][0]) + self.assertTrue(mock_handle.called) + + # TODO: When `certbot register --update-registration` is fully deprecated, + # delete the following test + @mock.patch('certbot.main.display_ops.get_email') + @test_util.patch_get_utility() + def test_update_registration_with_email_deprecated(self, mock_utility, mock_email): email = "user@example.com" mock_email.return_value = email with mock.patch('certbot.eff.handle_subscription') as mock_handle: diff --git a/tests/certbot-boulder-integration.sh b/tests/certbot-boulder-integration.sh index 87e3cc319..9011d8ba3 100755 --- a/tests/certbot-boulder-integration.sh +++ b/tests/certbot-boulder-integration.sh @@ -207,10 +207,16 @@ common unregister common register --email ex1@domain.org,ex2@domain.org +# TODO: When `certbot register --update-registration` is fully deprecated, delete the two following deprecated uses + common register --update-registration --email ex1@domain.org common register --update-registration --email ex1@domain.org,ex2@domain.org +common update_account --email example@domain.org + +common update_account --email ex1@domain.org,ex2@domain.org + common plugins --init --prepare | grep webroot # We start a server listening on the port for the From 6b145a480ef19309c84bfecc61465571172a4f3f Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Thu, 13 Dec 2018 20:13:39 +0100 Subject: [PATCH 092/114] Correct boulder integration tests using the latest challtestsrv version (#6600) --- tests/boulder-fetch.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/boulder-fetch.sh b/tests/boulder-fetch.sh index 31e0f6b30..f34deb74e 100755 --- a/tests/boulder-fetch.sh +++ b/tests/boulder-fetch.sh @@ -11,7 +11,6 @@ if [ ! -d ${BOULDERPATH} ]; then fi cd ${BOULDERPATH} -sed -i "s/FAKE_DNS: .*/FAKE_DNS: 10.77.77.1/" docker-compose.yml docker-compose up -d boulder @@ -28,3 +27,6 @@ if ! curl http://localhost:4000/directory 2>/dev/null; then echo "timed out waiting for boulder to start" exit 1 fi + +# Setup the DNS resolution used by boulder instance to docker host +curl -X POST -d '{"ip":"10.77.77.1"}' http://localhost:8055/set-default-ipv4 From 346a4246398b72d27b74b537142ee05073e71cd0 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 13 Dec 2018 15:54:38 -0800 Subject: [PATCH 093/114] Update pinned urllib3 (#6601) GitHub notified us about a security vulnerability in our pinned version of `urllib3` earlier this week. It doesn't affect us, but we might as well upgrade anyway. I checked: * There are no backwards incompatible features we care about listed at https://github.com/urllib3/urllib3/blob/master/CHANGES.rst. * urllib3's dependencies don't also need to be updated according to https://github.com/urllib3/urllib3/blob/1.24.1/setup.py. * The hashes match when obtained from different network vantage points. --- letsencrypt-auto-source/letsencrypt-auto | 6 +++--- letsencrypt-auto-source/pieces/dependency-requirements.txt | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 0ffe6c5f5..9703b3506 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -1212,9 +1212,9 @@ requests-toolbelt==0.8.0 \ chardet==3.0.2 \ --hash=sha256:4f7832e7c583348a9eddd927ee8514b3bf717c061f57b21dbe7697211454d9bb \ --hash=sha256:6ebf56457934fdce01fb5ada5582762a84eed94cad43ed877964aebbdd8174c0 -urllib3==1.21.1 \ - --hash=sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1 \ - --hash=sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5 +urllib3==1.24.1 \ + --hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \ + --hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22 certifi==2017.4.17 \ --hash=sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010 \ --hash=sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a diff --git a/letsencrypt-auto-source/pieces/dependency-requirements.txt b/letsencrypt-auto-source/pieces/dependency-requirements.txt index 983d2bb95..eb297bc6e 100644 --- a/letsencrypt-auto-source/pieces/dependency-requirements.txt +++ b/letsencrypt-auto-source/pieces/dependency-requirements.txt @@ -188,9 +188,9 @@ requests-toolbelt==0.8.0 \ chardet==3.0.2 \ --hash=sha256:4f7832e7c583348a9eddd927ee8514b3bf717c061f57b21dbe7697211454d9bb \ --hash=sha256:6ebf56457934fdce01fb5ada5582762a84eed94cad43ed877964aebbdd8174c0 -urllib3==1.21.1 \ - --hash=sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1 \ - --hash=sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5 +urllib3==1.24.1 \ + --hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \ + --hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22 certifi==2017.4.17 \ --hash=sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010 \ --hash=sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a From e3cb782e5992ba306de59ba96dfb6f125720cd06 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 17 Dec 2018 13:23:57 -0800 Subject: [PATCH 094/114] Allow josepy to be accessed through acme.jose. (#6592) When working on an update to our packages in Ubuntu Xenial, @NCommander noticed that importing code through acme.jose no longer works since josepy became a separate package and remembers having to fix up some code that was using acme.jose himself. This PR should fix that problem by making all of josepy accessible through acme.jose. This is primarily beneficial to our OS package maintainers who want to avoid subtle API changes when updating packages in stable repositories. They will likely backport this change, but I figure we might as well add it ourselves to minimize divergences in our OS packages in the future and avoid problems on the off chance someone hasn't upgraded acme and was relying on this feature. --- CHANGELOG.md | 8 ++++++-- acme/acme/__init__.py | 15 +++++++++++++++ acme/acme/jose_test.py | 43 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 acme/acme/jose_test.py diff --git a/CHANGELOG.md b/CHANGELOG.md index a0c6f0eb2..c6fac76fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,13 +17,17 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). ### Fixed -* +* Older modules in the josepy library can now be accessed through acme.jose + like it could in previous versions of acme. This is only done to preserve + backwards compatibility and support for doing this with new modules in josepy + will not be added. Users of the acme library should switch to using josepy + directly if they haven't done so already. Despite us having broken lockstep, we are continuing to release new versions of all Certbot components during releases for the time being, however, the only package with changes other than its version number was: -* +* acme More details about these changes can be found on our GitHub repo. diff --git a/acme/acme/__init__.py b/acme/acme/__init__.py index e8a0b16a8..d2cb1ee06 100644 --- a/acme/acme/__init__.py +++ b/acme/acme/__init__.py @@ -10,3 +10,18 @@ supported version: `draft-ietf-acme-01`_. https://github.com/ietf-wg-acme/acme/tree/draft-ietf-acme-acme-01 """ +import sys + +import josepy + +# This code exists to keep backwards compatibility with people using acme.jose +# before it became the standalone josepy package. +# +# It is based on +# https://github.com/requests/requests/blob/1278ecdf71a312dc2268f3bfc0aabfab3c006dcf/requests/packages.py + +for mod in list(sys.modules): + # This traversal is apparently necessary such that the identities are + # preserved (acme.jose.* is josepy.*) + if mod == 'josepy' or mod.startswith('josepy.'): + sys.modules['acme.' + mod.replace('josepy', 'jose', 1)] = sys.modules[mod] diff --git a/acme/acme/jose_test.py b/acme/acme/jose_test.py new file mode 100644 index 000000000..ecd483662 --- /dev/null +++ b/acme/acme/jose_test.py @@ -0,0 +1,43 @@ +"""Tests for acme.jose shim.""" +import importlib +import unittest + +class JoseTest(unittest.TestCase): + """Tests for acme.jose shim.""" + + def _test_it(self, submodule, attribute): + if submodule: + acme_jose_path = 'acme.jose.' + submodule + josepy_path = 'josepy.' + submodule + else: + acme_jose_path = 'acme.jose' + josepy_path = 'josepy' + acme_jose = importlib.import_module(acme_jose_path) + josepy = importlib.import_module(josepy_path) + + self.assertIs(acme_jose, josepy) + self.assertIs(getattr(acme_jose, attribute), getattr(josepy, attribute)) + + def test_top_level(self): + self._test_it('', 'RS512') + + def test_submodules(self): + # This test ensures that the modules in josepy that were + # available at the time it was moved into its own package are + # available under acme.jose. Backwards compatibility with new + # modules or testing code is not maintained. + mods_and_attrs = [('b64', 'b64decode',), + ('errors', 'Error',), + ('interfaces', 'JSONDeSerializable',), + ('json_util', 'Field',), + ('jwa', 'HS256',), + ('jwk', 'JWK',), + ('jws', 'JWS',), + ('util', 'ImmutableMap',),] + + for mod, attr in mods_and_attrs: + self._test_it(mod, attr) + + +if __name__ == '__main__': + unittest.main() # pragma: no cover From 62cb67ec670f70dc22a7c7ad2e738c8235164b33 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 17 Dec 2018 15:38:28 -0800 Subject: [PATCH 095/114] default to any py3 test (#6609) --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 61cee8eff..b672286ac 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ [tox] skipsdist = true -envlist = modification,py{34,35,36},py27-cover,lint +envlist = modification,py3,py27-cover,lint [base] # pip installs the requested packages in editable mode From f90561012241171ed8e0dd9996c703c384357eba Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 17 Dec 2018 16:22:03 -0800 Subject: [PATCH 096/114] add mypy to envlist (#6610) --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index b672286ac..021c23949 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ [tox] skipsdist = true -envlist = modification,py3,py27-cover,lint +envlist = modification,py3,py27-cover,lint,mypy [base] # pip installs the requested packages in editable mode From 856bfe354427203136161e037fad92cdb1fa03b3 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Wed, 19 Dec 2018 01:17:54 +0100 Subject: [PATCH 097/114] Tag to disable random sleep upon a renew task (#6599) * Extraction from #6541 to add flag to disable shuffle sleep on renew action * Move the logic of random sleep to execute it only if there is effectively a certificate to renew. * Add comments * Correct lint * Suspend lint rule * Revert code cleaning * Hide the flag * Ignore lint * Update cli.py --- certbot/cli.py | 4 ++++ certbot/constants.py | 1 + certbot/main.py | 12 ------------ certbot/renewal.py | 22 +++++++++++++++++++++- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/certbot/cli.py b/certbot/cli.py index 8e599cfda..ff1827cb1 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -1215,6 +1215,10 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis " one will be run.") helpful.add("renew", "--renew-hook", action=_RenewHookAction, help=argparse.SUPPRESS) + helpful.add( + "renew", "--no-random-sleep-on-renew", action="store_false", + default=flag_default("random_sleep_on_renew"), dest="random_sleep_on_renew", + help=argparse.SUPPRESS) helpful.add( "renew", "--deploy-hook", action=_DeployHookAction, help='Command to be run in a shell once for each successfully' diff --git a/certbot/constants.py b/certbot/constants.py index eb4105f82..7d0e0c879 100644 --- a/certbot/constants.py +++ b/certbot/constants.py @@ -68,6 +68,7 @@ CLI_DEFAULTS = dict( directory_hooks=True, reuse_key=False, disable_renew_updates=False, + random_sleep_on_renew=True, eab_hmac_key=None, eab_kid=None, diff --git a/certbot/main.py b/certbot/main.py index b24c5c622..ac639bc80 100644 --- a/certbot/main.py +++ b/certbot/main.py @@ -4,9 +4,7 @@ from __future__ import print_function import functools import logging.handlers import os -import random import sys -import time import configobj import josepy as jose @@ -1269,16 +1267,6 @@ def renew(config, unused_plugins): :rtype: None """ - if not sys.stdin.isatty(): - # Noninteractive renewals include a random delay in order to spread - # out the load on the certificate authority servers, even if many - # users all pick the same time for renewals. This delay precedes - # running any hooks, so that side effects of the hooks (such as - # shutting down a web service) aren't prolonged unnecessarily. - sleep_time = random.randint(1, 60*8) - logger.info("Non-interactive renewal: random delay of %s seconds", sleep_time) - time.sleep(sleep_time) - try: renewal.handle_renewal_request(config) finally: diff --git a/certbot/renewal.py b/certbot/renewal.py index 5b2e00740..4c592b27f 100644 --- a/certbot/renewal.py +++ b/certbot/renewal.py @@ -5,6 +5,9 @@ import itertools import logging import os import traceback +import sys +import time +import random import six import zope.component @@ -372,7 +375,7 @@ def _renew_describe_results(config, renew_successes, renew_failures, disp.notification("\n".join(out), wrap=False) -def handle_renewal_request(config): +def handle_renewal_request(config): # pylint: disable=too-many-locals,too-many-branches,too-many-statements """Examine each lineage; renew if due and report results""" # This is trivially False if config.domains is empty @@ -396,6 +399,14 @@ def handle_renewal_request(config): renew_failures = [] renew_skipped = [] parse_failures = [] + + # Noninteractive renewals include a random delay in order to spread + # out the load on the certificate authority servers, even if many + # users all pick the same time for renewals. This delay precedes + # running any hooks, so that side effects of the hooks (such as + # shutting down a web service) aren't prolonged unnecessarily. + apply_random_sleep = not sys.stdin.isatty() and config.random_sleep_on_renew + for renewal_file in conf_files: disp = zope.component.getUtility(interfaces.IDisplay) disp.notification("Processing " + renewal_file, pause=False) @@ -424,6 +435,15 @@ def handle_renewal_request(config): from certbot import main plugins = plugins_disco.PluginsRegistry.find_all() if should_renew(lineage_config, renewal_candidate): + # Apply random sleep upon first renewal if needed + if apply_random_sleep: + sleep_time = random.randint(1, 60 * 8) + logger.info("Non-interactive renewal: random delay of %s seconds", + sleep_time) + time.sleep(sleep_time) + # We will sleep only once this day, folks. + apply_random_sleep = False + # domains have been restored into lineage_config by reconstitute # but they're unnecessary anyway because renew_cert here # will just grab them from the certificate From 1cdcc15e64ba8b4f01ca96cc170e26b7d1cac183 Mon Sep 17 00:00:00 2001 From: ohemorange Date: Wed, 2 Jan 2019 10:08:08 -0800 Subject: [PATCH 098/114] Pin all dependency installation in the release script (#6584) (#6602) Fixes #6584. * Pin all dependency installation in the release script * also use pip_install.py to install pytest --- tools/_release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/_release.sh b/tools/_release.sh index 90c176b0e..ec2deda22 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -143,7 +143,7 @@ pip install -U pip # (or our dependencies) have conditional dependencies implemented with if # statements in setup.py and we have cached wheels lying around that would # cause those ifs to not be evaluated. -pip install \ +python ../tools/pip_install.py \ --no-cache-dir \ --extra-index-url http://localhost:$PORT \ $SUBPKGS @@ -166,7 +166,7 @@ fi mkdir kgs kgs="kgs/$version" pip freeze | tee $kgs -pip install pytest +python ../tools/pip_install.py pytest for module in $subpkgs_modules ; do echo testing $module # use an empty configuration file rather than the one in the repo root From ba358f9d07f76ae5f5540e1c8f3d6e622731a6ca Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 2 Jan 2019 12:01:39 -0800 Subject: [PATCH 099/114] Update changelog for 0.30.0 release --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6fac76fe..182f6db32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). -## 0.30.0 - master +## 0.30.0 - 2019-01-02 ### Added From 3971573d7a9426fdd7394e11c5dc41b3b8624134 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 2 Jan 2019 12:33:19 -0800 Subject: [PATCH 100/114] Release 0.30.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-auto | 32 +++++++++--------- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/__init__.py | 2 +- docs/cli-help.txt | 13 ++++--- letsencrypt-auto | 32 +++++++++--------- letsencrypt-auto-source/certbot-auto.asc | 16 ++++----- letsencrypt-auto-source/letsencrypt-auto | 26 +++++++------- letsencrypt-auto-source/letsencrypt-auto.sig | Bin 256 -> 256 bytes .../pieces/certbot-requirements.txt | 24 ++++++------- 26 files changed, 90 insertions(+), 91 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 53a4eda27..7ddcf0f06 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages from setuptools.command.test import test as TestCommand import sys -version = '0.30.0.dev0' +version = '0.30.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 2562e6f3f..42a88b7b4 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-auto b/certbot-auto index 6003afcf4..be2c3679b 100755 --- a/certbot-auto +++ b/certbot-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.29.1" +LE_AUTO_VERSION="0.30.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1212,9 +1212,9 @@ requests-toolbelt==0.8.0 \ chardet==3.0.2 \ --hash=sha256:4f7832e7c583348a9eddd927ee8514b3bf717c061f57b21dbe7697211454d9bb \ --hash=sha256:6ebf56457934fdce01fb5ada5582762a84eed94cad43ed877964aebbdd8174c0 -urllib3==1.21.1 \ - --hash=sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1 \ - --hash=sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5 +urllib3==1.24.1 \ + --hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \ + --hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22 certifi==2017.4.17 \ --hash=sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010 \ --hash=sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a @@ -1230,18 +1230,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.29.1 \ - --hash=sha256:2ba2c60fd1969e75d3e5048d3f7d95afd0949670b39a6a0037ba4a594e9f26a5 \ - --hash=sha256:6fc604d207c48b95dea3458bb33a11b17aa625628eb197927ffee8b458f62692 -acme==0.29.1 \ - --hash=sha256:4be3848f8813c455021f13519642d8ec2746b78d4d0bc2ae04c3dcb1d8862f60 \ - --hash=sha256:a2e203ade83cd1eaf19112004a63073830211cf7759d437f634babb08c49b47c -certbot-apache==0.29.1 \ - --hash=sha256:8d8b6b7c5f333cf5297153c6a1eacc09b4a5c73e8f93544800b3ad016d5e34d0 \ - --hash=sha256:c3af1c66c86cfeef7dac4fe9b16c7c755ebd12bc526408c27781bd34b9de8128 -certbot-nginx==0.29.1 \ - --hash=sha256:5ba3a7d93d3ce317fb8b3d0222c708fb79e96c7a9b1ba56e12e46892c2d12869 \ - --hash=sha256:0c1205ebb91eef4b7d15293c6778ffc962d09563b315120b2d226348d751e38d +certbot==0.30.0 \ + --hash=sha256:b3468e128e74d2295598f6d3fbf9d0edfb67fe5abaca3b985a9e858395bd027f \ + --hash=sha256:d631fe6c75700ce9b2fdae194ff8b53c7518545d87dd451a1704f7572dcd49e8 +acme==0.30.0 \ + --hash=sha256:eed9389f802ebf4988c9e43c28ad3d5c2734237371d78e97450a1d61189a15aa \ + --hash=sha256:984b6d00bec73dcfa616636a760e80ca14bd246fb908710a656547f542f09445 +certbot-apache==0.30.0 \ + --hash=sha256:d38c70fc6930db298ea992a3145362eebdce460d3d2651f86a8f2f43d838c6d0 \ + --hash=sha256:1d4bc207d53a3e5d37e5d9ebd05f26089aa21d1fbf384113ed9d1829b4d1e9bf +certbot-nginx==0.30.0 \ + --hash=sha256:6163c7d0080f59b4ebe510afcc6af2d2eebf15469275c3835866690db4d465d6 \ + --hash=sha256:e39a3f3d77cd4c653949cf066fb2211039fd2032665697c27b6e8501c7c2dd92 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index 405f8ff73..e64c7bba1 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -4,7 +4,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 4f12e78f7..47888bec1 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 92ed37f35..66420e354 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 0fd52c4b0..0260d5011 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index eec35b472..5f5e939c2 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 21899f3d8..5d5874459 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 2bca63ccf..5ba4ece27 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index ee484e402..bc04d3ff1 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index c91aabd4f..4db08c575 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 9f0fe149d..f07b08024 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 4ebfeb3e1..0467da1f0 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index cbd77b901..3959e0b84 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 2ea6699df..811d8aec1 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 84ca63f00..5a99c4ffa 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index cebd48e41..8225e47de 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 970089460..c19fd862d 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0.dev0' +version = '0.30.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/__init__.py b/certbot/__init__.py index c96f7b28e..768efc2b5 100644 --- a/certbot/__init__.py +++ b/certbot/__init__.py @@ -1,4 +1,4 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '0.30.0.dev0' +__version__ = '0.30.0' diff --git a/docs/cli-help.txt b/docs/cli-help.txt index 37d67cfe0..bad6275e7 100644 --- a/docs/cli-help.txt +++ b/docs/cli-help.txt @@ -29,6 +29,7 @@ manage certificates: manage your account with Let's Encrypt: register Create a Let's Encrypt ACME account + update_account Update a Let's Encrypt ACME account --agree-tos Agree to the ACME server's Subscriber Agreement -m EMAIL Email address for important account notifications @@ -112,7 +113,7 @@ optional arguments: case, and to know when to deprecate support for past Python versions and flags. If you wish to hide this information from the Let's Encrypt server, set this to - "". (default: CertbotACMEClient/0.29.1 + "". (default: CertbotACMEClient/0.30.0 (certbot(-auto); OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). The flags encoded in the @@ -359,7 +360,7 @@ revoke: certificates. (default: None) register: - Options for account registration & modification + Options for account registration --register-unsafely-without-email Specifying this flag enables registering an account @@ -371,11 +372,6 @@ register: to the Subscriber Agreement will still affect you, and will be effective 14 days after posting an update to the web site. (default: False) - --update-registration - With the register verb, indicates that details - associated with an existing registration, such as the - e-mail address, should be updated, rather than - registering a new account. (default: False) -m EMAIL, --email EMAIL Email used for registration and recovery contact. Use comma to register multiple emails, ex: @@ -384,6 +380,9 @@ register: --no-eff-email Don't share your e-mail address with EFF (default: None) +update_account: + Options for account modification + unregister: Options for account deactivation. diff --git a/letsencrypt-auto b/letsencrypt-auto index 6003afcf4..be2c3679b 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.29.1" +LE_AUTO_VERSION="0.30.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1212,9 +1212,9 @@ requests-toolbelt==0.8.0 \ chardet==3.0.2 \ --hash=sha256:4f7832e7c583348a9eddd927ee8514b3bf717c061f57b21dbe7697211454d9bb \ --hash=sha256:6ebf56457934fdce01fb5ada5582762a84eed94cad43ed877964aebbdd8174c0 -urllib3==1.21.1 \ - --hash=sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1 \ - --hash=sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5 +urllib3==1.24.1 \ + --hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \ + --hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22 certifi==2017.4.17 \ --hash=sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010 \ --hash=sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a @@ -1230,18 +1230,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.29.1 \ - --hash=sha256:2ba2c60fd1969e75d3e5048d3f7d95afd0949670b39a6a0037ba4a594e9f26a5 \ - --hash=sha256:6fc604d207c48b95dea3458bb33a11b17aa625628eb197927ffee8b458f62692 -acme==0.29.1 \ - --hash=sha256:4be3848f8813c455021f13519642d8ec2746b78d4d0bc2ae04c3dcb1d8862f60 \ - --hash=sha256:a2e203ade83cd1eaf19112004a63073830211cf7759d437f634babb08c49b47c -certbot-apache==0.29.1 \ - --hash=sha256:8d8b6b7c5f333cf5297153c6a1eacc09b4a5c73e8f93544800b3ad016d5e34d0 \ - --hash=sha256:c3af1c66c86cfeef7dac4fe9b16c7c755ebd12bc526408c27781bd34b9de8128 -certbot-nginx==0.29.1 \ - --hash=sha256:5ba3a7d93d3ce317fb8b3d0222c708fb79e96c7a9b1ba56e12e46892c2d12869 \ - --hash=sha256:0c1205ebb91eef4b7d15293c6778ffc962d09563b315120b2d226348d751e38d +certbot==0.30.0 \ + --hash=sha256:b3468e128e74d2295598f6d3fbf9d0edfb67fe5abaca3b985a9e858395bd027f \ + --hash=sha256:d631fe6c75700ce9b2fdae194ff8b53c7518545d87dd451a1704f7572dcd49e8 +acme==0.30.0 \ + --hash=sha256:eed9389f802ebf4988c9e43c28ad3d5c2734237371d78e97450a1d61189a15aa \ + --hash=sha256:984b6d00bec73dcfa616636a760e80ca14bd246fb908710a656547f542f09445 +certbot-apache==0.30.0 \ + --hash=sha256:d38c70fc6930db298ea992a3145362eebdce460d3d2651f86a8f2f43d838c6d0 \ + --hash=sha256:1d4bc207d53a3e5d37e5d9ebd05f26089aa21d1fbf384113ed9d1829b4d1e9bf +certbot-nginx==0.30.0 \ + --hash=sha256:6163c7d0080f59b4ebe510afcc6af2d2eebf15469275c3835866690db4d465d6 \ + --hash=sha256:e39a3f3d77cd4c653949cf066fb2211039fd2032665697c27b6e8501c7c2dd92 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/certbot-auto.asc b/letsencrypt-auto-source/certbot-auto.asc index b4e520fb2..4e2a700e5 100644 --- a/letsencrypt-auto-source/certbot-auto.asc +++ b/letsencrypt-auto-source/certbot-auto.asc @@ -1,11 +1,11 @@ -----BEGIN PGP SIGNATURE----- -iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAlwIbaAACgkQTRfJlc2X -dfLIGQf+JZr3oP89qyMREYAL3/Bx+vxsx+c01IuDaG1pBUeVwL5rdeU1kDZ1WkKb -61nCoMPbSLqLMor2IpobFj44lEFJS1WYrtfe8sgMLeSaQkWXlB3breLKI09p/IBm -X3lN7VIMPW8eLziSArGivKTpsW+cDau8Rbnn5FSMNiZojCp+bSPehOpZBmHb2OrS -2akgCBQYh2e+cadv5MmGPqta8iTDMDgMOrTzAstPKRfeHozyoOsRjeq1T9Yl65lk -XF+m0yl2r4w8VxemWzqaT53XHS+3tgCunDtB7pDXuM6zpNnWghxN1UJ8Ywle1nt4 -ecxxPwHfGAq9cAVCM7M0x4y+bxdnbw== -=8xDr +iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAlwtH9cACgkQTRfJlc2X +dfIqUwf/RXLZAeFF/59PjTAzcV+eEISlvEmFcV0zL3vv23PsY3S5Iuuwcd6rTm5M +UWNtmUTmFVo0xmxAj6Eqfpnt0P+JPpPcnbLNIGKFekBWIshgH84RRFWPJjNh/hu1 +pyzkkcWaOB86egdVfjvuRJ0j7AGd0ih6ur2rlgfHVjTYR+0EdWszFDEFBlq8cpct +9d1gCgH7VWKSIQMhzGLMsmdMxNoDl4hiqVPU0FP5/mn2xGF7FgeKNW3+NiTouKuB +mZOeEl3f3uOze/suHPyfOu+49jk+TWWE05Xfqfowjf486nKPg6/uSA2izW/MwIKN +HuIuY3bBf+lx5yUVIraoZhH2MxODDQ== +=BZqz -----END PGP SIGNATURE----- diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 9703b3506..be2c3679b 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.30.0.dev0" +LE_AUTO_VERSION="0.30.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -1230,18 +1230,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==0.29.1 \ - --hash=sha256:2ba2c60fd1969e75d3e5048d3f7d95afd0949670b39a6a0037ba4a594e9f26a5 \ - --hash=sha256:6fc604d207c48b95dea3458bb33a11b17aa625628eb197927ffee8b458f62692 -acme==0.29.1 \ - --hash=sha256:4be3848f8813c455021f13519642d8ec2746b78d4d0bc2ae04c3dcb1d8862f60 \ - --hash=sha256:a2e203ade83cd1eaf19112004a63073830211cf7759d437f634babb08c49b47c -certbot-apache==0.29.1 \ - --hash=sha256:8d8b6b7c5f333cf5297153c6a1eacc09b4a5c73e8f93544800b3ad016d5e34d0 \ - --hash=sha256:c3af1c66c86cfeef7dac4fe9b16c7c755ebd12bc526408c27781bd34b9de8128 -certbot-nginx==0.29.1 \ - --hash=sha256:5ba3a7d93d3ce317fb8b3d0222c708fb79e96c7a9b1ba56e12e46892c2d12869 \ - --hash=sha256:0c1205ebb91eef4b7d15293c6778ffc962d09563b315120b2d226348d751e38d +certbot==0.30.0 \ + --hash=sha256:b3468e128e74d2295598f6d3fbf9d0edfb67fe5abaca3b985a9e858395bd027f \ + --hash=sha256:d631fe6c75700ce9b2fdae194ff8b53c7518545d87dd451a1704f7572dcd49e8 +acme==0.30.0 \ + --hash=sha256:eed9389f802ebf4988c9e43c28ad3d5c2734237371d78e97450a1d61189a15aa \ + --hash=sha256:984b6d00bec73dcfa616636a760e80ca14bd246fb908710a656547f542f09445 +certbot-apache==0.30.0 \ + --hash=sha256:d38c70fc6930db298ea992a3145362eebdce460d3d2651f86a8f2f43d838c6d0 \ + --hash=sha256:1d4bc207d53a3e5d37e5d9ebd05f26089aa21d1fbf384113ed9d1829b4d1e9bf +certbot-nginx==0.30.0 \ + --hash=sha256:6163c7d0080f59b4ebe510afcc6af2d2eebf15469275c3835866690db4d465d6 \ + --hash=sha256:e39a3f3d77cd4c653949cf066fb2211039fd2032665697c27b6e8501c7c2dd92 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/letsencrypt-auto-source/letsencrypt-auto.sig b/letsencrypt-auto-source/letsencrypt-auto.sig index 7b3874da00e87d2dceb20372e6079f44fdf2c6a9..e4902c0ee7241e37491b8a941e25744b837cb7f8 100644 GIT binary patch literal 256 zcmV+b0ssDv4s4Tx!Gpv36M!K{^ zade@s@$}@HWNXZloBGk`1V%UIbVc*QUSk|U~K*`EpZhpmOER`)Vh~vtkxoSl**~O#gMxciG8{xI~ zBjQkiW9*%R^8`&dakxvsB>SH8_YUxTWg^fH-(kERXdaGN%kJjgKStmdpmEs%4pGXQ zEz^kZX>73#HrgfHH^KzS6(C0T%A&Lv6bMbMN>!BFV}3U0NOGuT;#))Lwb_f~H7)4W GuwXBg?}bPJ literal 256 zcmV+b0ssC&MV4ZBp~!>0zD9eP{pH!EBXbu^4*LFC6`15?<s2Pgj|8@y%FjNX}t56=4%&hte0AGS1xZSCP?+WUH-uVvaPBwiWl Date: Wed, 2 Jan 2019 12:33:31 -0800 Subject: [PATCH 101/114] Add contents to CHANGELOG.md for next version --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 182f6db32..73e6d13b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). +## 0.31.0 - master + +### Added + +* + +### Changed + +* + +### Fixed + +* + +Despite us having broken lockstep, we are continuing to release new versions of +all Certbot components during releases for the time being, however, the only +package with changes other than its version number was: + +* + +More details about these changes can be found on our GitHub repo. + ## 0.30.0 - 2019-01-02 ### Added From c25e6a8adf41d8a8551fb153aca16143c5dbc495 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Wed, 2 Jan 2019 12:33:31 -0800 Subject: [PATCH 102/114] Bump version to 0.31.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/__init__.py | 2 +- letsencrypt-auto-source/letsencrypt-auto | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 7ddcf0f06..77ff7bae8 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages from setuptools.command.test import test as TestCommand import sys -version = '0.30.0' +version = '0.31.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 42a88b7b4..14d6cacb6 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index e64c7bba1..f519ed422 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -4,7 +4,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 47888bec1..ff33293fe 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 66420e354..5c8709445 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 0260d5011..2f7fa37d6 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 5f5e939c2..3bb43cf5d 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 5d5874459..599cec486 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 5ba4ece27..894d809ac 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index bc04d3ff1..c99ad38aa 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 4db08c575..588b6a40a 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index f07b08024..b09a09762 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 0467da1f0..e48428191 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 3959e0b84..8b6d73d33 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 811d8aec1..edf7b6ba6 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 5a99c4ffa..69c2c7ed3 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -1,7 +1,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 8225e47de..05843d2ed 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index c19fd862d..70e11f62b 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -2,7 +2,7 @@ from setuptools import setup from setuptools import find_packages -version = '0.30.0' +version = '0.31.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/__init__.py b/certbot/__init__.py index 768efc2b5..bf68034c8 100644 --- a/certbot/__init__.py +++ b/certbot/__init__.py @@ -1,4 +1,4 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '0.30.0' +__version__ = '0.31.0.dev0' diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index be2c3679b..c08a08160 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="0.30.0" +LE_AUTO_VERSION="0.31.0.dev0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates From bb0f3566109e6d1265454619f70e22a500b03f16 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 2 Jan 2019 16:15:25 -0800 Subject: [PATCH 103/114] Tell people to update changed package list. (#6633) --- pull_request_template.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pull_request_template.md b/pull_request_template.md index c071d4135..60fd6da7e 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1 +1,3 @@ -Be sure to edit the `master` section of `CHANGELOG.md` with a line describing this PR before it gets merged. +Be sure to edit the `master` section of `CHANGELOG.md`. This includes a +description of the change and ensuring the modified package(s) are listed as +having been changed. From 3cb6d6c25bb57410e6a66b9b92a7f0848a826cd1 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 3 Jan 2019 11:26:15 -0800 Subject: [PATCH 104/114] Don't sleep in integration tests (#6636) Fixes #6635. * Don't sleep in integration tests. * add backslash --- tests/integration/_common.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/_common.sh b/tests/integration/_common.sh index 1e444fa26..8a1c07e3c 100755 --- a/tests/integration/_common.sh +++ b/tests/integration/_common.sh @@ -43,5 +43,6 @@ certbot_test_no_force_renew () { --register-unsafely-without-email \ --debug \ -vv \ + --no-random-sleep-on-renew \ "$@" } From ec297ccf72e95961586ec2382c3e3225ce578aa4 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 3 Jan 2019 12:46:25 -0800 Subject: [PATCH 105/114] Add missing acme.jose attribute. (#6637) Fixes the problem at https://github.com/certbot/certbot/pull/6592#discussion_r245106383. The tests use `eval` which neither myself or `pylint` like very much. I started to change this by splitting the path we wanted to test and repeatedly calling `getattr`, but it didn't seem worth the effort to me. * Add missing acme.jose attribute. * update changelog --- CHANGELOG.md | 5 +++-- acme/acme/__init__.py | 4 ++-- acme/acme/jose_test.py | 18 ++++++++++++++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73e6d13b5..501070baf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,13 +14,14 @@ Certbot adheres to [Semantic Versioning](http://semver.org/). ### Fixed -* +* Fixed accessing josepy contents through acme.jose when the full acme.jose + path is used. Despite us having broken lockstep, we are continuing to release new versions of all Certbot components during releases for the time being, however, the only package with changes other than its version number was: -* +* acme More details about these changes can be found on our GitHub repo. diff --git a/acme/acme/__init__.py b/acme/acme/__init__.py index d2cb1ee06..bab5b40ce 100644 --- a/acme/acme/__init__.py +++ b/acme/acme/__init__.py @@ -12,14 +12,14 @@ supported version: `draft-ietf-acme-01`_. """ import sys -import josepy - # This code exists to keep backwards compatibility with people using acme.jose # before it became the standalone josepy package. # # It is based on # https://github.com/requests/requests/blob/1278ecdf71a312dc2268f3bfc0aabfab3c006dcf/requests/packages.py +import josepy as jose + for mod in list(sys.modules): # This traversal is apparently necessary such that the identities are # preserved (acme.jose.* is josepy.*) diff --git a/acme/acme/jose_test.py b/acme/acme/jose_test.py index ecd483662..340624a4f 100644 --- a/acme/acme/jose_test.py +++ b/acme/acme/jose_test.py @@ -12,11 +12,21 @@ class JoseTest(unittest.TestCase): else: acme_jose_path = 'acme.jose' josepy_path = 'josepy' - acme_jose = importlib.import_module(acme_jose_path) - josepy = importlib.import_module(josepy_path) + acme_jose_mod = importlib.import_module(acme_jose_path) + josepy_mod = importlib.import_module(josepy_path) - self.assertIs(acme_jose, josepy) - self.assertIs(getattr(acme_jose, attribute), getattr(josepy, attribute)) + self.assertIs(acme_jose_mod, josepy_mod) + self.assertIs(getattr(acme_jose_mod, attribute), getattr(josepy_mod, attribute)) + + # We use the imports below with eval, but pylint doesn't + # understand that. + # pylint: disable=eval-used,unused-variable + import acme + import josepy + acme_jose_mod = eval(acme_jose_path) + josepy_mod = eval(josepy_path) + self.assertIs(acme_jose_mod, josepy_mod) + self.assertIs(getattr(acme_jose_mod, attribute), getattr(josepy_mod, attribute)) def test_top_level(self): self._test_it('', 'RS512') From 59bbda51abf641483b4f760bb732f6e0646d0d39 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Thu, 3 Jan 2019 17:48:09 -0800 Subject: [PATCH 106/114] Compatibility with more traditional versions of awk --- tests/certbot-boulder-integration.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/certbot-boulder-integration.sh b/tests/certbot-boulder-integration.sh index 9011d8ba3..630571148 100755 --- a/tests/certbot-boulder-integration.sh +++ b/tests/certbot-boulder-integration.sh @@ -174,7 +174,7 @@ CheckRenewHook() { TotalAndDistinctLines() { total=$1 distinct=$2 - awk '{a[$1] = 1}; END {exit(NR !='$total' || length(a) !='$distinct')}' + awk '{a[$1] = 1}; END {n = 0; for (i in a) { n++ }; exit(NR !='$total' || n !='$distinct')}' } # Cleanup coverage data From fd023cc3ea13c41e4f0612029ae2d657891d7675 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 4 Jan 2019 09:27:45 -0800 Subject: [PATCH 107/114] Use HTTPS link to semver. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 501070baf..724820356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Certbot change log -Certbot adheres to [Semantic Versioning](http://semver.org/). +Certbot adheres to [Semantic Versioning](https://semver.org/). ## 0.31.0 - master From 233cfe52075d96fa928099c402c5d1e8e3c28ddd Mon Sep 17 00:00:00 2001 From: Trinopoty Biswas Date: Sat, 5 Jan 2019 00:44:12 +0530 Subject: [PATCH 108/114] Added sorting to renewal_conf_files() --- certbot/storage.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/certbot/storage.py b/certbot/storage.py index eb17e1d38..7472df975 100644 --- a/certbot/storage.py +++ b/certbot/storage.py @@ -41,7 +41,9 @@ def renewal_conf_files(config): :rtype: `list` of `str` """ - return glob.glob(os.path.join(config.renewal_configs_dir, "*.conf")) + result = glob.glob(os.path.join(config.renewal_configs_dir, "*.conf")) + result.sort() + return result def renewal_file_for_certname(config, certname): """Return /path/to/certname.conf in the renewal conf directory""" From 33090ab77a51a15e2aff46ee925ab7cb16a2b20b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 4 Jan 2019 12:44:31 -0800 Subject: [PATCH 109/114] Fix oldest nginx integration tests (#6642) #6636 broke [test-everything tests](https://travis-ci.org/certbot/certbot/builds/475173804) because `_common.sh` is a common file shared between Certbot and Nginx integration tests and `--no-random-sleep-on-renew` isn't defined for the version of Certbot used in the "oldest" integration tests. This PR adds code to `_common.sh` to check the Certbot version and if it's new enough, add `--no-random-sleep-on-renew` to the command line. I repurposed `$store_flags` and stopped exporting it because it's not used anywhere outside of this file. Other approaches I considered and decided against were: 1. Adding this flag in `certbot-boulder-integration.sh`. I decided against it because it's setting us up for the same problem in the future if the oldest version of Certbot is upgraded in the Nginx tests and we call `certbot renew`. 2. Just upgrading the oldest version of Certbot required by Nginx to avoid these issues. While this would work (with perhaps some unnecessary burden for our packagers), I think it's avoiding the real problem here which should now be able to addressed easily with the addition of `$other_flags` and `version_at_least`. * Add version_at_least(). * Conditionally disable sleep. * Consolidate store_flags and other_flags. * update comments --- tests/integration/_common.sh | 38 ++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/tests/integration/_common.sh b/tests/integration/_common.sh index 8a1c07e3c..83aa91a9e 100755 --- a/tests/integration/_common.sh +++ b/tests/integration/_common.sh @@ -3,12 +3,15 @@ root=${root:-$(mktemp -d -t leitXXXX)} echo "Root integration tests directory: $root" config_dir="$root/conf" -store_flags="--config-dir $config_dir --work-dir $root/work" -store_flags="$store_flags --logs-dir $root/logs" tls_sni_01_port=5001 http_01_port=5002 sources="acme/,$(ls -dm certbot*/ | tr -d ' \n')" -export root config_dir store_flags tls_sni_01_port http_01_port sources +export root config_dir tls_sni_01_port http_01_port sources +certbot_path="$(command -v certbot)" +# Flags that are added here will be added to Certbot calls within +# certbot_test_no_force_renew. +other_flags="--config-dir $config_dir --work-dir $root/work" +other_flags="$other_flags --logs-dir $root/logs" certbot_test () { certbot_test_no_force_renew \ @@ -16,11 +19,35 @@ certbot_test () { "$@" } +# Succeeds if Certbot version is at least the given version number and fails +# otherwise. This is useful for making sure Certbot has certain features +# available. The patch version is currently ignored. +# +# Arguments: +# First argument is the minimum major version +# Second argument is the minimum minor version +version_at_least () { + # Certbot major and minor version (e.g. 0.30) + major_minor=$("$certbot_path" --version 2>&1 | cut -d' ' -f2 | cut -d. -f1,2) + major=$(echo "$major_minor" | cut -d. -f1) + minor=$(echo "$major_minor" | cut -d. -f2) + # Test that either the major version is greater or major version is equal + # and minor version is greater than or equal to. + [ \( "$major" -gt "$1" \) -o \( "$major" -eq "$1" -a "$minor" -ge "$2" \) ] +} + # Use local ACMEv2 endpoint if requested and SERVER isn't already set. if [ "${BOULDER_INTEGRATION:-v1}" = "v2" -a -z "${SERVER:+x}" ]; then SERVER="http://localhost:4001/directory" fi +# --no-random-sleep-on-renew was added in +# https://github.com/certbot/certbot/pull/6599 and first released in Certbot +# 0.30.0. +if version_at_least 0 30; then + other_flags="$other_flags --no-random-sleep-on-renew" +fi + certbot_test_no_force_renew () { omit_patterns="*/*.egg-info/*,*/dns_common*,*/setup.py,*/test_*,*/tests/*" omit_patterns="$omit_patterns,*_test.py,*_test_*,certbot-apache/*" @@ -30,19 +57,18 @@ certbot_test_no_force_renew () { --append \ --source $sources \ --omit $omit_patterns \ - $(command -v certbot) \ + "$certbot_path" \ --server "${SERVER:-http://localhost:4000/directory}" \ --no-verify-ssl \ --tls-sni-01-port $tls_sni_01_port \ --http-01-port $http_01_port \ --manual-public-ip-logging-ok \ - $store_flags \ + $other_flags \ --non-interactive \ --no-redirect \ --agree-tos \ --register-unsafely-without-email \ --debug \ -vv \ - --no-random-sleep-on-renew \ "$@" } From efaaf48f909923562c127398d317ca1065327bbe Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Mon, 7 Jan 2019 21:00:01 +0100 Subject: [PATCH 110/114] [Windows|Unix] Use double quote compatible both for windows and linux (#6553) File _venv_common.py uses single quotes to ask pip to install setuptools>=30.3. Using single quotes to enclose a string is not supported on Windows shell (Batch). This PR replaces theses single quotes by double quotes supported both on Windows and Linux. --- tools/_venv_common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/_venv_common.py b/tools/_venv_common.py index ecd438f94..540842773 100755 --- a/tools/_venv_common.py +++ b/tools/_venv_common.py @@ -156,7 +156,7 @@ def main(venv_name, venv_args, args): new_environ['PATH'] = os.pathsep.join([get_venv_bin_path(venv_name), new_environ['PATH']]) subprocess_with_print('python {0}'.format('./letsencrypt-auto-source/pieces/pipstrap.py'), env=new_environ, shell=True) - subprocess_with_print("python -m pip install --upgrade 'setuptools>=30.3'", + subprocess_with_print('python -m pip install --upgrade "setuptools>=30.3"', env=new_environ, shell=True) subprocess_with_print('python {0} {1}'.format('./tools/pip_install.py', ' '.join(args)), env=new_environ, shell=True) From 5130e9ba1e958225d951a5ce0e0eb714be317cd1 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Wed, 9 Jan 2019 04:44:25 +0100 Subject: [PATCH 111/114] Correct the oldest requirements environment (#6569) I observed that the current set of oldest requirements do not correspond to any environment, except the specific Xenial image in Travis CI (and standard Xenial containers will also fail). It is because the requirements make cryptography and requests fail against standard libraries available in the typical Linux distributions that are targeted by the oldest requirements approach (Centos 6, Centos 7, Xenial, Jessie). This PR fixes that, by aligning the minimal version requirements of cryptography and requests to the maximal versions that are available on Centos 6. Centos 7, Jessie and Xenial stay unusable with oldest requirements for other reasons, but at least one old and supported Linux distribution is able to run the tests with oldest requirements out of the box. A test is also corrected to match the expected error message that old versions of urllib3 will raise. --- acme/acme/client_test.py | 6 +++--- acme/setup.py | 6 +++--- setup.py | 2 +- tools/oldest_constraints.txt | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 33ae3886b..b3d0f1921 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -707,6 +707,7 @@ class ClientTest(ClientTestBase): self.certr, self.rsn) + class ClientV2Test(ClientTestBase): """Tests for acme.client.ClientV2.""" @@ -950,7 +951,6 @@ class ClientNetworkTest(unittest.TestCase): self.assertEqual(jws.signature.combined.kid, u'acct-uri') self.assertEqual(jws.signature.combined.url, u'url') - def test_check_response_not_ok_jobj_no_error(self): self.response.ok = False self.response.json.return_value = {} @@ -1113,8 +1113,8 @@ class ClientNetworkTest(unittest.TestCase): # Requests Library Exceptions except requests.exceptions.ConnectionError as z: #pragma: no cover - self.assertTrue("('Connection aborted.', error(111, 'Connection refused'))" - == str(z) or "[WinError 10061]" in str(z)) + self.assertTrue("'Connection aborted.'" in str(z) or "[WinError 10061]" in str(z)) + class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" diff --git a/acme/setup.py b/acme/setup.py index 77ff7bae8..eac3974fa 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -9,15 +9,15 @@ version = '0.31.0.dev0' install_requires = [ # load_pem_private/public_key (>=0.6) # rsa_recover_prime_factors (>=0.8) - 'cryptography>=0.8', + 'cryptography>=1.2.3', # formerly known as acme.jose: 'josepy>=1.0.0', # Connection.set_tlsext_host_name (>=0.13) 'mock', - 'PyOpenSSL>=0.13', + 'PyOpenSSL>=0.13.1', 'pyrfc3339', 'pytz', - 'requests[security]>=2.4.1', # security extras added in 2.4.1 + 'requests[security]>=2.6.0', # security extras added in 2.4.1 'requests-toolbelt>=0.3.0', 'setuptools', 'six>=1.9.0', # needed for python_2_unicode_compatible diff --git a/setup.py b/setup.py index 2a9b2c203..9e6af2d4f 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ install_requires = [ # in which we added 2.6 support (see #2243), so we relax the requirement. 'ConfigArgParse>=0.9.3', 'configobj', - 'cryptography>=1.2', # load_pem_x509_certificate + 'cryptography>=1.2.3', # load_pem_x509_certificate 'josepy', 'mock', 'parsedatetime>=1.3', # Calendar.parseDT diff --git a/tools/oldest_constraints.txt b/tools/oldest_constraints.txt index 80fce8b33..20fa0672a 100644 --- a/tools/oldest_constraints.txt +++ b/tools/oldest_constraints.txt @@ -37,13 +37,13 @@ pytz==2012rc0 # Our setup.py constraints cloudflare==1.5.1 -cryptography==1.2.0 +cryptography==1.2.3 google-api-python-client==1.5 oauth2client==2.0 parsedatetime==1.3 pyparsing==1.5.5 python-digitalocean==1.11 -requests[security]==2.4.1 +requests[security]==2.6.0 # Ubuntu Xenial constraints ConfigArgParse==0.10.0 From b52cbc0fb706d2837b01b90c4bfb38ad160da2ad Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Wed, 9 Jan 2019 05:45:16 +0100 Subject: [PATCH 112/114] Reduce build log verbosity on Travis (#6597) PR #6568 removed the --quiet option in pip invocations, because this option deletes a lot of extremely useful logs when something goes wrong. However, when everything goes right, or at least when pip install is correctly executed, theses logs add hundreds of lines that are only noise, making hard to debug errors that can be in only one or two lines. We can have best of both worlds. Travis allows to fold large blocks of logs, that can be expanded directly from the UI if needed. It only requires to print in the console some specific code, that this PR implements in the pip_install.py script when the build is run in Travis (known by the existence of TRAVIS environment variable). I also take the occasion to clean up a little tox.ini. Note that AppVeyor does not have this fold capability, but it can be emulated using a proper capture of stdout/stderr delivered only when an error is detected. * Fold pip install log on travis * Global test env * Export env variable --- .travis.yml | 1 + appveyor.yml | 1 + tools/pip_install.py | 7 +++++++ tox.ini | 7 ------- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2b8eafc13..89885d08e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ before_install: before_script: - 'if [ $TRAVIS_OS_NAME = osx ] ; then ulimit -n 1024 ; fi' + - export TOX_TESTENV_PASSENV=TRAVIS matrix: include: diff --git a/appveyor.yml b/appveyor.yml index ce2b5998c..2b6b82747 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,6 +24,7 @@ install: build: off test_script: + - set TOX_TESTENV_PASSENV=APPVEYOR # Test env is set by TOXENV env variable - tox diff --git a/tools/pip_install.py b/tools/pip_install.py index 354dce32b..4466729e0 100755 --- a/tools/pip_install.py +++ b/tools/pip_install.py @@ -71,6 +71,11 @@ def main(args): tools_path = find_tools_path() working_dir = tempfile.mkdtemp() + if os.environ.get('TRAVIS'): + # When this script is executed on Travis, the following print will make the log + # be folded until the end command is printed (see finally section). + print('travis_fold:start:install_certbot_deps') + try: test_constraints = os.path.join(working_dir, 'test_constraints.txt') all_constraints = os.path.join(working_dir, 'all_constraints.txt') @@ -89,6 +94,8 @@ def main(args): call_with_print('"{0}" -m pip install --constraint "{1}" {2}' .format(sys.executable, all_constraints, ' '.join(args))) finally: + if os.environ.get('TRAVIS'): + print('travis_fold:end:install_certbot_deps') shutil.rmtree(working_dir) diff --git a/tox.ini b/tox.ini index 021c23949..71491c34a 100644 --- a/tox.ini +++ b/tox.ini @@ -64,9 +64,6 @@ source_paths = tests/lock_test.py [testenv] -passenv = - TRAVIS - APPVEYOR commands = {[base]install_and_test} {[base]all_packages} python tests/lock_test.py @@ -176,7 +173,6 @@ whitelist_externals = docker passenv = DOCKER_* - TRAVIS [testenv:nginx_compat] commands = @@ -187,7 +183,6 @@ whitelist_externals = docker passenv = DOCKER_* - TRAVIS [testenv:le_auto_precise] # At the moment, this tests under Python 2.7 only, as only that version is @@ -199,7 +194,6 @@ whitelist_externals = docker passenv = DOCKER_* - TRAVIS [testenv:le_auto_trusty] # At the moment, this tests under Python 2.7 only, as only that version is @@ -212,7 +206,6 @@ whitelist_externals = docker passenv = DOCKER_* - TRAVIS TRAVIS_BRANCH [testenv:le_auto_wheezy] From 95557fa9b49fa2615774ed6ef734817dcd11b819 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 9 Jan 2019 12:37:45 -0800 Subject: [PATCH 113/114] Stop using staging in apacheconftests (#6647) Fixes #6585. I wrote up three suggestions for fixing this at https://github.com/certbot/certbot/issues/6585#issuecomment-448054502. I took the middle approach of requiring the user to provide an ACME server to use. I like this better than the other approaches which were: > Resolve #5938 instead of this issue. There is value in these tests as is over the compatibility tests in that they don't use Docker and run on different OSes. > Spin up a local Python server to return the directory object. Trying to set up a dummy ACME server seemed hacky and error prone. Other notes about this PR are: * I put the Pebble setup in `tox.ini` rather than `.travis.yml` as this seems much cleaner and more natural. * I created a new `tox` environment called `apacheconftest-with-pebble` that reuses the code from `testenv:apacheconftest` so `apacheconftest` can continue to be used with servers other than Pebble like is done in our test farm tests. * I chose the environment variable `SERVER` for consistency with our integration tests. I chose to not give this environment variable a default but to fail fast when it is not set. * I ran test farm tests on this PR and they passed. --- .travis.yml | 3 ++- .../tests/apache-conf-files/apache-conf-test | 10 +++++++++- tests/letstest/scripts/test_apache2.sh | 1 + tox.ini | 14 ++++++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 89885d08e..a35d43b63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,8 +58,9 @@ matrix: before_install: addons: - python: "2.7" - env: TOXENV=apacheconftest + env: TOXENV=apacheconftest-with-pebble sudo: required + services: docker - python: "2.7" env: TOXENV=nginxroundtrip diff --git a/certbot-apache/certbot_apache/tests/apache-conf-files/apache-conf-test b/certbot-apache/certbot_apache/tests/apache-conf-files/apache-conf-test index dcbba9d3e..4838a6eee 100755 --- a/certbot-apache/certbot_apache/tests/apache-conf-files/apache-conf-test +++ b/certbot-apache/certbot_apache/tests/apache-conf-files/apache-conf-test @@ -3,6 +3,11 @@ # A hackish script to see if the client is behaving as expected # with each of the "passing" conf files. +if [ -z "$SERVER" ]; then + echo "Please set SERVER to the ACME server's directory URL." + exit 1 +fi + export EA=/etc/apache2/ TESTDIR="`dirname $0`" cd $TESTDIR/passing @@ -56,13 +61,16 @@ if [ "$1" = --debian-modules ] ; then done fi +CERTBOT_CMD="sudo $(command -v certbot) --server $SERVER -vvvv" +CERTBOT_CMD="$CERTBOT_CMD --debug --apache --register-unsafely-without-email" +CERTBOT_CMD="$CERTBOT_CMD --agree-tos certonly -t --no-verify-ssl" FAILS=0 trap CleanupExit INT for f in *.conf ; do echo -n testing "$f"... Setup - RESULT=`echo c | sudo $(command -v certbot) -vvvv --debug --staging --apache --register-unsafely-without-email --agree-tos certonly -t 2>&1` + RESULT=`echo c | $CERTBOT_CMD 2>&1` if echo $RESULT | grep -Eq \("Which names would you like"\|"mod_macro is not yet"\) ; then echo passed else diff --git a/tests/letstest/scripts/test_apache2.sh b/tests/letstest/scripts/test_apache2.sh index 4036e6efa..d24de2458 100755 --- a/tests/letstest/scripts/test_apache2.sh +++ b/tests/letstest/scripts/test_apache2.sh @@ -54,6 +54,7 @@ if [ $? -ne 0 ] ; then fi if [ "$OS_TYPE" = "ubuntu" ] ; then + export SERVER="$BOULDER_URL" venv/bin/tox -e apacheconftest else echo Not running hackish apache tests on $OS_TYPE diff --git a/tox.ini b/tox.ini index 71491c34a..95b2f2c64 100644 --- a/tox.ini +++ b/tox.ini @@ -152,6 +152,20 @@ commands = commands = {[base]pip_install} acme . certbot-apache certbot-compatibility-test {toxinidir}/certbot-apache/certbot_apache/tests/apache-conf-files/apache-conf-test --debian-modules +passenv = + SERVER + +[testenv:apacheconftest-with-pebble] +commands = + {toxinidir}/tests/pebble-fetch.sh + {[testenv:apacheconftest]commands} +passenv = + HOME + GOPATH + PEBBLEPATH + PEBBLE_STRICT +setenv = + SERVER=https://localhost:14000/dir [testenv:nginxroundtrip] commands = From 52c42b6927645292994c87bb35be13bdfc0c13a8 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 9 Jan 2019 15:08:47 -0800 Subject: [PATCH 114/114] Install homebrew packages through .travis.yml. --- .travis.yml | 11 ++++++++++- tests/travis-macos-setup.sh | 17 ----------------- 2 files changed, 10 insertions(+), 18 deletions(-) delete mode 100755 tests/travis-macos-setup.sh diff --git a/.travis.yml b/.travis.yml index 98193a779..5af8908c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,6 @@ before_install: - cp .travis.yml /tmp/travis.yml - git pull origin master --strategy=recursive --strategy-option=theirs --no-edit - if ! git diff .travis.yml /tmp/travis.yml ; then echo "Please merge master into test-everything"; exit 1; fi - - '[ "$TRAVIS_OS_NAME" != osx ] || tests/travis-macos-setup.sh' before_script: - 'if [ $TRAVIS_OS_NAME = osx ] ; then ulimit -n 1024 ; fi' @@ -122,9 +121,19 @@ matrix: - language: generic env: TOXENV=py27 os: osx + addons: + homebrew: + packages: + - augeas + - python2 - language: generic env: TOXENV=py3 os: osx + addons: + homebrew: + packages: + - augeas + - python3 # Only build pushes to the master branch, PRs, and branches beginning with diff --git a/tests/travis-macos-setup.sh b/tests/travis-macos-setup.sh deleted file mode 100755 index bf72f26a5..000000000 --- a/tests/travis-macos-setup.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -e -# -# Set up the test environment for macOS on Travis. - -# Install the given package with brew if it's not already installed. -brew_install() { - if ! brew list "$1" > /dev/null 2>&1; then - brew install "$1" - fi -} - -brew_install augeas -brew_install python -brew_install python3 - -# Ensure we use python from brew. -brew link python