From 55ca1b484fc18626e89b111ff5e960a4081694c1 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Fri, 1 Jan 2016 20:55:52 -0500 Subject: [PATCH 001/126] Initial verison of DNS-01 implementation --- acme/acme/challenges.py | 79 ++++++++++++++++++++++++++++++ acme/acme/challenges_test.py | 93 ++++++++++++++++++++++++++++++++++++ acme/setup.py | 1 + 3 files changed, 173 insertions(+) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 1e456d325..f48c20443 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -1,5 +1,8 @@ """ACME Identifier Validation Challenges.""" import abc +import base64 +import dns.resolver +import dns.exception import functools import hashlib import logging @@ -215,6 +218,82 @@ class KeyAuthorizationChallenge(_TokenDVChallenge): self.validation(account_key, *args, **kwargs)) +@ChallengeResponse.register +class DNS01Response(KeyAuthorizationChallengeResponse): + """ACME "dns-01" challenge response.""" + typ = "dns-01" + + def simple_verify(self, chall, domain, account_public_key): + """Simple verify. + + :param challenges.DNS01 chall: Corresponding challenge. + :param unicode domain: Domain name being verified. + :param account_public_key: Public key for the key pair + being authorized. If ``None`` key verification is not + performed! + :param JWK account_public_key: + + :returns: ``True`` iff validation is successful, ``False`` + otherwise. + :rtype: bool + + """ + if not self.verify(chall, account_public_key): + logger.debug("Verification of key authorization in response failed") + return False + + validation_name = chall.validation_domain_name(domain) + validation = chall.validation(account_public_key) + logger.debug("Verifying %s at %s...", chall.typ, validation_name) + txt_records = [] + try: + dns_response = dns.resolver.query(validation_name, 'TXT') + for rdata in dns_response: + for txt_record in rdata.strings: + txt_records.append(txt_record) + except dns.exception.DNSException as error: + logger.error("Unable to resolve %s: %s", validation_name, error) + return False + + for txt_record in txt_records: + if txt_record == validation: + return True + + logger.debug("Key authorization from response (%r) doesn't match any " + "DNS response in %r", self.key_authorization, txt_records) + return False + +@Challenge.register # pylint: disable=too-many-ancestors +class DNS01(KeyAuthorizationChallenge): + """ACME "dns-01" challenge.""" + + response_cls = DNS01Response + typ = response_cls.typ + + LABEL = "_acme-challenge" + """Label clients prepend to the domain name being validated.""" + + def validation(self, account_key, **unused_kwargs): + """Generate validation. + + :param JWK account_key: + :rtype: unicode + + """ + key_authorization = self.key_authorization(account_key) + # FIXME Once boulder response according to the spec this needs to be fixed + # return base64.b64encode(hashlib.sha256(key_authorization).digest()) + return hashlib.sha256(key_authorization).hexdigest() + + def validation_domain_name(self, name): + """Domain name for TXT validation record. + + :param unicode name: Domain name being validated. + + """ + return "{0}.{1}".format(self.LABEL, name) + + @ChallengeResponse.register class HTTP01Response(KeyAuthorizationChallengeResponse): """ACME http-01 challenge response.""" diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index a4e78ebe9..a587d3f61 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -1,6 +1,7 @@ """Tests for acme.challenges.""" import unittest +import dns.rrset import mock import OpenSSL import requests @@ -76,6 +77,98 @@ class KeyAuthorizationChallengeResponseTest(unittest.TestCase): key_authorization='.foo.oKGqedy-b-acd5eoybm2f-NVFxvyOoET5CNy3xnv8WY') self.assertFalse(response.verify(self.chall, KEY.public_key())) +class DNS01ResponseTest(unittest.TestCase): + # pylint: disable=too-many-instance-attributes + + def setUp(self): + from acme.challenges import DNS01Response + self.msg = DNS01Response(key_authorization=u'foo') + self.jmsg = { + 'resource': 'challenge', + 'type': 'dns-01', + 'keyAuthorization': u'foo', + } + + from acme.challenges import DNS01 + self.chall = DNS01(token=(b'x' * 16)) + self.response = self.chall.response(KEY) + + # This takes advantage of the fact that an answer object mostly behaves like + # an RRset + def create_txt_response(self, name, txt_record): + return dns.rrset.from_text(name, 60, "IN", "TXT", txt_record) + + def test_to_partial_json(self): + self.assertEqual(self.jmsg, self.msg.to_partial_json()) + + def test_from_json(self): + from acme.challenges import DNS01Response + self.assertEqual( + self.msg, DNS01Response.from_json(self.jmsg)) + + def test_from_json_hashable(self): + from acme.challenges import DNS01Response + hash(DNS01Response.from_json(self.jmsg)) + + def test_simple_verify_bad_key_authorization(self): + key2 = jose.JWKRSA.load(test_util.load_vector('rsa256_key.pem')) + self.response.simple_verify(self.chall, "local", key2.public_key()) + + @mock.patch("acme.challenges.dns.resolver.query") + def test_simple_verify_good_validation(self, mock_dns): + mock_dns.return_value = self.create_txt_response( + self.chall.validation_domain_name("local"), + self.chall.validation(KEY.public_key())) + self.assertTrue(self.response.simple_verify( + self.chall, "local", KEY.public_key())) + mock_dns.assert_called_once_with( + self.chall.validation_domain_name("local"), "TXT") + + @mock.patch("acme.challenges.dns.resolver.query") + def test_simple_verify_bad_validation(self, mock_dns): + mock_dns.return_value = self.create_txt_response( + self.chall.validation_domain_name("local"), "!") + self.assertFalse(self.response.simple_verify( + self.chall, "local", KEY.public_key())) + + @mock.patch("acme.challenges.dns.resolver.query") + def test_simple_verify_connection_error(self, mock_dns): + mock_dns.side_effect = dns.exception.DNSException + self.assertFalse(self.response.simple_verify( + self.chall, "local", KEY.public_key())) + +class DNS01Test(unittest.TestCase): + + def setUp(self): + from acme.challenges import DNS01 + self.msg = DNS01( + token=jose.decode_b64jose( + 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA')) + self.jmsg = { + 'type': 'dns-01', + 'token': 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA', + } + + def test_validation_domain_name(self): + self.assertEqual('_acme-challenge.www.example.com', + self.msg.validation_domain_name('www.example.com')) + + def test_validation(self): + self.assertEqual( + "ac06bb8888382b6cbaddfbd48427f2f1d3f55e5ef0121990ab4a02853704dd99", + self.msg.validation(KEY)) + + def test_to_partial_json(self): + self.assertEqual(self.jmsg, self.msg.to_partial_json()) + + def test_from_json(self): + from acme.challenges import DNS01 + self.assertEqual(self.msg, DNS01.from_json(self.jmsg)) + + def test_from_json_hashable(self): + from acme.challenges import DNS01 + hash(DNS01.from_json(self.jmsg)) + class HTTP01ResponseTest(unittest.TestCase): # pylint: disable=too-many-instance-attributes diff --git a/acme/setup.py b/acme/setup.py index ba2c88394..dd2bce5d9 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -12,6 +12,7 @@ install_requires = [ 'cryptography>=0.8', # Connection.set_tlsext_host_name (>=0.13), X509Req.get_extensions (>=0.15) 'PyOpenSSL>=0.15', + 'dnspython', 'pyrfc3339', 'pytz', 'requests', From ffc2b1ee7864a848c0f2a22ca873ac970bb911bf Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sat, 2 Jan 2016 01:42:47 -0500 Subject: [PATCH 002/126] - Lint fixes - Add test for multiple TXT records returned - Add extra parameter in DNS01.validation to select hexdigit vs. bas64 encoded validation --- acme/acme/challenges.py | 23 +++++++++++------------ acme/acme/challenges_test.py | 36 +++++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index f48c20443..6c13ec906 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -242,17 +242,15 @@ class DNS01Response(KeyAuthorizationChallengeResponse): logger.debug("Verification of key authorization in response failed") return False - validation_name = chall.validation_domain_name(domain) + validation_domain_name = chall.validation_domain_name(domain) validation = chall.validation(account_public_key) - logger.debug("Verifying %s at %s...", chall.typ, validation_name) - txt_records = [] + logger.debug("Verifying %s at %s...", chall.typ, validation_domain_name) try: - dns_response = dns.resolver.query(validation_name, 'TXT') - for rdata in dns_response: - for txt_record in rdata.strings: - txt_records.append(txt_record) + dns_response = dns.resolver.query(validation_domain_name, 'TXT') + txt_records = sum([rdata.strings for rdata in dns_response], []) except dns.exception.DNSException as error: - logger.error("Unable to resolve %s: %s", validation_name, error) + logger.error("Unable to resolve %s: %s", validation_domain_name, + error) return False for txt_record in txt_records: @@ -273,7 +271,8 @@ class DNS01(KeyAuthorizationChallenge): LABEL = "_acme-challenge" """Label clients prepend to the domain name being validated.""" - def validation(self, account_key, **unused_kwargs): + # FIXME: Remove extra parameter once #2052 is integrated + def validation(self, account_key, dns01_hexdigit_response=True, **unused_kwargs): """Generate validation. :param JWK account_key: @@ -281,9 +280,9 @@ class DNS01(KeyAuthorizationChallenge): """ key_authorization = self.key_authorization(account_key) - # FIXME Once boulder response according to the spec this needs to be fixed - # return base64.b64encode(hashlib.sha256(key_authorization).digest()) - return hashlib.sha256(key_authorization).hexdigest() + if dns01_hexdigit_response: + return hashlib.sha256(key_authorization).hexdigest() + return base64.urlsafe_b64encode(hashlib.sha256(key_authorization).digest()) def validation_domain_name(self, name): """Domain name for TXT validation record. diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index a587d3f61..c2a629bb3 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -93,10 +93,15 @@ class DNS01ResponseTest(unittest.TestCase): self.chall = DNS01(token=(b'x' * 16)) self.response = self.chall.response(KEY) - # This takes advantage of the fact that an answer object mostly behaves like - # an RRset - def create_txt_response(self, name, txt_record): - return dns.rrset.from_text(name, 60, "IN", "TXT", txt_record) + def create_txt_response(self, name, txt_records): + """ + Returns an RRSet containing the 'txt_records' as the result of a DNS + query for 'name'. + + This takes advantage of the fact that an Answer object mostly behaves + like an RRset. + """ + return dns.rrset.from_text_list(name, 60, "IN", "TXT", txt_records) def test_to_partial_json(self): self.assertEqual(self.jmsg, self.msg.to_partial_json()) @@ -118,7 +123,17 @@ class DNS01ResponseTest(unittest.TestCase): def test_simple_verify_good_validation(self, mock_dns): mock_dns.return_value = self.create_txt_response( self.chall.validation_domain_name("local"), - self.chall.validation(KEY.public_key())) + [self.chall.validation(KEY.public_key())]) + self.assertTrue(self.response.simple_verify( + self.chall, "local", KEY.public_key())) + mock_dns.assert_called_once_with( + self.chall.validation_domain_name("local"), "TXT") + + @mock.patch("acme.challenges.dns.resolver.query") + def test_simple_verify_good_validation_multiple_txts(self, mock_dns): + mock_dns.return_value = self.create_txt_response( + self.chall.validation_domain_name("local"), + ["!", self.chall.validation(KEY.public_key())]) self.assertTrue(self.response.simple_verify( self.chall, "local", KEY.public_key())) mock_dns.assert_called_once_with( @@ -127,7 +142,7 @@ class DNS01ResponseTest(unittest.TestCase): @mock.patch("acme.challenges.dns.resolver.query") def test_simple_verify_bad_validation(self, mock_dns): mock_dns.return_value = self.create_txt_response( - self.chall.validation_domain_name("local"), "!") + self.chall.validation_domain_name("local"), ["!"]) self.assertFalse(self.response.simple_verify( self.chall, "local", KEY.public_key())) @@ -153,10 +168,17 @@ class DNS01Test(unittest.TestCase): self.assertEqual('_acme-challenge.www.example.com', self.msg.validation_domain_name('www.example.com')) + # FIXME: Remove extra parameter once #2052 is integrated def test_validation(self): + self.assertEqual( + "rAa7iIg4K2y63fvUhCfy8dP1Xl7wEhmQq0oChTcE3Zk=", + self.msg.validation(KEY, dns01_hexdigit_response=False)) + + # FIXME: Remove this once #2052 is integrated + def test_validation_for_server_with_hexdigit_response(self): self.assertEqual( "ac06bb8888382b6cbaddfbd48427f2f1d3f55e5ef0121990ab4a02853704dd99", - self.msg.validation(KEY)) + self.msg.validation(KEY, dns01_hexdigit_response=True)) def test_to_partial_json(self): self.assertEqual(self.jmsg, self.msg.to_partial_json()) From 7e2a1532ef5a3c48e3d1cf9c382a13da0ed62097 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sat, 2 Jan 2016 12:53:47 -0500 Subject: [PATCH 003/126] Move dns record retrieval into a separate method. --- acme/acme/challenges.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 6c13ec906..cc938dd31 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -223,6 +223,22 @@ class DNS01Response(KeyAuthorizationChallengeResponse): """ACME "dns-01" challenge response.""" typ = "dns-01" + def txt_records_for_name(self, name): + """Resolve the name and return the TXT records. + + :param unicode name: Domain name being verified. + + :returns: A list of txt records, or None if the name could not be resolved + :rtype: list of unicode + + """ + try: + dns_response = dns.resolver.query(name, 'TXT') + except dns.exception.DNSException as error: + logger.error("Unable to resolve %s: %s", name, error) + return None + return sum([rdata.strings for rdata in dns_response], []) + def simple_verify(self, chall, domain, account_public_key): """Simple verify. @@ -245,15 +261,7 @@ class DNS01Response(KeyAuthorizationChallengeResponse): validation_domain_name = chall.validation_domain_name(domain) validation = chall.validation(account_public_key) logger.debug("Verifying %s at %s...", chall.typ, validation_domain_name) - try: - dns_response = dns.resolver.query(validation_domain_name, 'TXT') - txt_records = sum([rdata.strings for rdata in dns_response], []) - except dns.exception.DNSException as error: - logger.error("Unable to resolve %s: %s", validation_domain_name, - error) - return False - - for txt_record in txt_records: + for txt_record in self.txt_records_for_domain(validation_domain_name): if txt_record == validation: return True From 64f3f53467b33d97359d0ba6f9795d5757d3f4a7 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sat, 2 Jan 2016 13:51:37 -0500 Subject: [PATCH 004/126] Fix --- acme/acme/challenges.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index cc938dd31..5c3c8e8aa 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -261,7 +261,11 @@ class DNS01Response(KeyAuthorizationChallengeResponse): validation_domain_name = chall.validation_domain_name(domain) validation = chall.validation(account_public_key) logger.debug("Verifying %s at %s...", chall.typ, validation_domain_name) - for txt_record in self.txt_records_for_domain(validation_domain_name): + txt_records = self.txt_records_for_name(validation_domain_name) + if txt_records == None: + return False + + for txt_record in txt_records: if txt_record == validation: return True From 97fb1a03f99cd219cffe7e77ab6c616c03b9afec Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 3 Jan 2016 13:19:32 -0500 Subject: [PATCH 005/126] Documentation fixes. --- acme/acme/challenges.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 5c3c8e8aa..6ca36d482 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -249,8 +249,8 @@ class DNS01Response(KeyAuthorizationChallengeResponse): performed! :param JWK account_public_key: - :returns: ``True`` iff validation is successful, ``False`` - otherwise. + :returns: ``True`` iff validation with the TXT records resolved from a + DNS server is successful. :rtype: bool """ @@ -332,8 +332,8 @@ class HTTP01Response(KeyAuthorizationChallengeResponse): :param JWK account_public_key: :param int port: Port used in the validation. - :returns: ``True`` iff validation is successful, ``False`` - otherwise. + :returns: ``True`` iff validation of the files currently server by the + HTTP server is successful. :rtype: bool """ @@ -504,7 +504,7 @@ class TLSSNI01Response(KeyAuthorizationChallengeResponse): :returns: ``True`` iff client's control of the domain has been - verified, ``False`` otherwise. + verified. :rtype: bool """ From 74a9703269a320a0180e8360218e6f8de599d0ba Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Mon, 4 Jan 2016 16:16:42 -0500 Subject: [PATCH 006/126] Style fix --- acme/acme/challenges.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 6ca36d482..b783eee9c 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -262,7 +262,7 @@ class DNS01Response(KeyAuthorizationChallengeResponse): validation = chall.validation(account_public_key) logger.debug("Verifying %s at %s...", chall.typ, validation_domain_name) txt_records = self.txt_records_for_name(validation_domain_name) - if txt_records == None: + if txt_records is None: return False for txt_record in txt_records: From 7747dc8488f2ea67b21ad53ffe9e31cd8e7d1232 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Mon, 4 Jan 2016 19:46:28 -0500 Subject: [PATCH 007/126] Remove non-compliant hexdigit encoding for dns-01 challenges (#2052 is now merged). --- acme/acme/challenges.py | 8 ++------ acme/acme/challenges_test.py | 11 ++--------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 6ca36d482..77ca2e214 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -1,6 +1,5 @@ """ACME Identifier Validation Challenges.""" import abc -import base64 import dns.resolver import dns.exception import functools @@ -283,8 +282,7 @@ class DNS01(KeyAuthorizationChallenge): LABEL = "_acme-challenge" """Label clients prepend to the domain name being validated.""" - # FIXME: Remove extra parameter once #2052 is integrated - def validation(self, account_key, dns01_hexdigit_response=True, **unused_kwargs): + def validation(self, account_key, **unused_kwargs): """Generate validation. :param JWK account_key: @@ -292,9 +290,7 @@ class DNS01(KeyAuthorizationChallenge): """ key_authorization = self.key_authorization(account_key) - if dns01_hexdigit_response: - return hashlib.sha256(key_authorization).hexdigest() - return base64.urlsafe_b64encode(hashlib.sha256(key_authorization).digest()) + return jose.b64encode(hashlib.sha256(key_authorization).digest()) def validation_domain_name(self, name): """Domain name for TXT validation record. diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index c2a629bb3..b6c771d1b 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -168,17 +168,10 @@ class DNS01Test(unittest.TestCase): self.assertEqual('_acme-challenge.www.example.com', self.msg.validation_domain_name('www.example.com')) - # FIXME: Remove extra parameter once #2052 is integrated def test_validation(self): self.assertEqual( - "rAa7iIg4K2y63fvUhCfy8dP1Xl7wEhmQq0oChTcE3Zk=", - self.msg.validation(KEY, dns01_hexdigit_response=False)) - - # FIXME: Remove this once #2052 is integrated - def test_validation_for_server_with_hexdigit_response(self): - self.assertEqual( - "ac06bb8888382b6cbaddfbd48427f2f1d3f55e5ef0121990ab4a02853704dd99", - self.msg.validation(KEY, dns01_hexdigit_response=True)) + "rAa7iIg4K2y63fvUhCfy8dP1Xl7wEhmQq0oChTcE3Zk", + self.msg.validation(KEY)) def test_to_partial_json(self): self.assertEqual(self.jmsg, self.msg.to_partial_json()) From b5bb90628c080d7719546438d73b01534c7db25a Mon Sep 17 00:00:00 2001 From: wteiken Date: Tue, 5 Jan 2016 20:33:30 -0500 Subject: [PATCH 008/126] Style changes. --- acme/acme/challenges.py | 30 ++++++++++++------------------ acme/acme/challenges_test.py | 4 ++-- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 77ca2e214..cb8873984 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -1,13 +1,13 @@ """ACME Identifier Validation Challenges.""" import abc -import dns.resolver -import dns.exception import functools import hashlib import logging import socket from cryptography.hazmat.primitives import hashes +import dns.resolver +import dns.exception import OpenSSL import requests @@ -217,17 +217,16 @@ class KeyAuthorizationChallenge(_TokenDVChallenge): self.validation(account_key, *args, **kwargs)) -@ChallengeResponse.register class DNS01Response(KeyAuthorizationChallengeResponse): """ACME "dns-01" challenge response.""" typ = "dns-01" - def txt_records_for_name(self, name): + def txt_records_for_name(name): """Resolve the name and return the TXT records. :param unicode name: Domain name being verified. - :returns: A list of txt records, or None if the name could not be resolved + :returns: A list of txt records, if empty the name could not be resolved :rtype: list of unicode """ @@ -235,17 +234,17 @@ class DNS01Response(KeyAuthorizationChallengeResponse): dns_response = dns.resolver.query(name, 'TXT') except dns.exception.DNSException as error: logger.error("Unable to resolve %s: %s", name, error) - return None - return sum([rdata.strings for rdata in dns_response], []) + return [] + return [txt_rec in dns_response for txt_rec in rdata.strings] +@ChallengeResponse.register def simple_verify(self, chall, domain, account_public_key): """Simple verify. :param challenges.DNS01 chall: Corresponding challenge. :param unicode domain: Domain name being verified. :param account_public_key: Public key for the key pair - being authorized. If ``None`` key verification is not - performed! + being authorized. :param JWK account_public_key: :returns: ``True`` iff validation with the TXT records resolved from a @@ -260,14 +259,9 @@ class DNS01Response(KeyAuthorizationChallengeResponse): validation_domain_name = chall.validation_domain_name(domain) validation = chall.validation(account_public_key) logger.debug("Verifying %s at %s...", chall.typ, validation_domain_name) - txt_records = self.txt_records_for_name(validation_domain_name) - if txt_records == None: - return False - - for txt_record in txt_records: - if txt_record == validation: - return True + if validation in txt_records_for_name(validation_domain_name): + return True logger.debug("Key authorization from response (%r) doesn't match any " "DNS response in %r", self.key_authorization, txt_records) return False @@ -289,8 +283,8 @@ class DNS01(KeyAuthorizationChallenge): :rtype: unicode """ - key_authorization = self.key_authorization(account_key) - return jose.b64encode(hashlib.sha256(key_authorization).digest()) + return jose.b64encode(hashlib.sha256( + self.key_authorization(account_key)).digest()) def validation_domain_name(self, name): """Domain name for TXT validation record. diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index b6c771d1b..b744de024 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -77,6 +77,7 @@ class KeyAuthorizationChallengeResponseTest(unittest.TestCase): key_authorization='.foo.oKGqedy-b-acd5eoybm2f-NVFxvyOoET5CNy3xnv8WY') self.assertFalse(response.verify(self.chall, KEY.public_key())) + class DNS01ResponseTest(unittest.TestCase): # pylint: disable=too-many-instance-attributes @@ -108,8 +109,7 @@ class DNS01ResponseTest(unittest.TestCase): def test_from_json(self): from acme.challenges import DNS01Response - self.assertEqual( - self.msg, DNS01Response.from_json(self.jmsg)) + self.assertEqual(self.msg, DNS01Response.from_json(self.jmsg)) def test_from_json_hashable(self): from acme.challenges import DNS01Response From 4403a78e52e684d5b94b8982f5b86609fc1fc20f Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Tue, 5 Jan 2016 22:25:24 -0500 Subject: [PATCH 009/126] Move txt_records_for_name out of class. --- acme/acme/challenges.py | 49 +++++++++++++++++++----------------- acme/acme/challenges_test.py | 1 + 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index cb8873984..e235a087e 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -217,27 +217,11 @@ class KeyAuthorizationChallenge(_TokenDVChallenge): self.validation(account_key, *args, **kwargs)) +@ChallengeResponse.register class DNS01Response(KeyAuthorizationChallengeResponse): """ACME "dns-01" challenge response.""" typ = "dns-01" - def txt_records_for_name(name): - """Resolve the name and return the TXT records. - - :param unicode name: Domain name being verified. - - :returns: A list of txt records, if empty the name could not be resolved - :rtype: list of unicode - - """ - try: - dns_response = dns.resolver.query(name, 'TXT') - except dns.exception.DNSException as error: - logger.error("Unable to resolve %s: %s", name, error) - return [] - return [txt_rec in dns_response for txt_rec in rdata.strings] - -@ChallengeResponse.register def simple_verify(self, chall, domain, account_public_key): """Simple verify. @@ -260,16 +244,18 @@ class DNS01Response(KeyAuthorizationChallengeResponse): validation = chall.validation(account_public_key) logger.debug("Verifying %s at %s...", chall.typ, validation_domain_name) - if validation in txt_records_for_name(validation_domain_name): - return True - logger.debug("Key authorization from response (%r) doesn't match any " - "DNS response in %r", self.key_authorization, txt_records) - return False + txt_records = txt_records_for_name(validation_domain_name) + exists = validation in txt_records + if not exists: + logger.debug("Key authorization from response (%r) doesn't match " + "any DNS response in %r", self.key_authorization, + txt_records) + return exists + @Challenge.register # pylint: disable=too-many-ancestors class DNS01(KeyAuthorizationChallenge): """ACME "dns-01" challenge.""" - response_cls = DNS01Response typ = response_cls.typ @@ -716,3 +702,20 @@ class DNSResponse(ChallengeResponse): """ return chall.check_validation(self.validation, account_public_key) + + +def txt_records_for_name(name): + """Resolve the name and return the TXT records. + + :param unicode name: Domain name being verified. + + :returns: A list of txt records, if empty the name could not be resolved + :rtype: list of unicode + + """ + try: + dns_response = dns.resolver.query(name, 'TXT') + except dns.exception.DNSException as error: + logger.error("Unable to resolve %s: %s", name, error) + return [] + return [txt_rec for rdata in dns_response for txt_rec in rdata.strings] diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index b744de024..79a928456 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -152,6 +152,7 @@ class DNS01ResponseTest(unittest.TestCase): self.assertFalse(self.response.simple_verify( self.chall, "local", KEY.public_key())) + class DNS01Test(unittest.TestCase): def setUp(self): From fd2709a6fa2c2cc764aa2b1a50178ad62e71a1c5 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Tue, 5 Jan 2016 23:58:23 -0500 Subject: [PATCH 010/126] Move dnspython dependency to tests only and only import the dns.resolver when actually resolving the client. That way user code that does not call 'simple_verify' for DNS01 challenges does not depend on dnspython. --- acme/acme/challenges.py | 10 ++++++---- acme/setup.py | 3 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index e235a087e..aa7b20689 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -6,8 +6,6 @@ import logging import socket from cryptography.hazmat.primitives import hashes -import dns.resolver -import dns.exception import OpenSSL import requests @@ -714,8 +712,12 @@ def txt_records_for_name(name): """ try: + import dns.resolver dns_response = dns.resolver.query(name, 'TXT') - except dns.exception.DNSException as error: - logger.error("Unable to resolve %s: %s", name, error) + except ImportError as error: + raise ImportError("Local validation for 'dns-01' challenges requires " + "'dnspython'"); + except Exception as error: + logger.error("Unable to resolve %s: %s", name, str(error)) return [] return [txt_rec for rdata in dns_response for txt_rec in rdata.strings] diff --git a/acme/setup.py b/acme/setup.py index dd2bce5d9..76a2c1b72 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -12,7 +12,6 @@ install_requires = [ 'cryptography>=0.8', # Connection.set_tlsext_host_name (>=0.13), X509Req.get_extensions (>=0.15) 'PyOpenSSL>=0.15', - 'dnspython', 'pyrfc3339', 'pytz', 'requests', @@ -76,7 +75,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, - 'testing': testing_extras, + 'testing': testing_extras + 'dnspython', }, entry_points={ 'console_scripts': [ From 57c265c7f36087bb3de0f96a25cfcd8ae62538ab Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 00:27:07 -0500 Subject: [PATCH 011/126] Setup.py and style fixes --- acme/acme/challenges.py | 5 +++-- acme/setup.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index aa7b20689..f4eb115c4 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -713,11 +713,12 @@ def txt_records_for_name(name): """ try: import dns.resolver + import dns.exception dns_response = dns.resolver.query(name, 'TXT') except ImportError as error: raise ImportError("Local validation for 'dns-01' challenges requires " - "'dnspython'"); - except Exception as error: + "'dnspython'") + except dns.exception.DNSException as error: logger.error("Unable to resolve %s: %s", name, str(error)) return [] return [txt_rec for rdata in dns_response for txt_rec in rdata.strings] diff --git a/acme/setup.py b/acme/setup.py index 76a2c1b72..e00476117 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -75,7 +75,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, - 'testing': testing_extras + 'dnspython', + 'testing': testing_extras + ['dnspython'], }, entry_points={ 'console_scripts': [ From dc743fb57cc9c3c7fb805ece50681f1388440f9c Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 01:11:24 -0500 Subject: [PATCH 012/126] Move DNS resolver to separate module to decouple dependencies and testing. --- acme/acme/challenges.py | 30 ++++++---------------- acme/acme/challenges_test.py | 46 +++++++++------------------------- acme/acme/dns_resolver.py | 28 +++++++++++++++++++++ acme/acme/dns_resolver_test.py | 37 +++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 57 deletions(-) create mode 100644 acme/acme/dns_resolver.py create mode 100644 acme/acme/dns_resolver_test.py diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index f4eb115c4..221eb406c 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -15,7 +15,6 @@ from acme import fields from acme import jose from acme import other - logger = logging.getLogger(__name__) @@ -242,7 +241,13 @@ class DNS01Response(KeyAuthorizationChallengeResponse): validation = chall.validation(account_public_key) logger.debug("Verifying %s at %s...", chall.typ, validation_domain_name) - txt_records = txt_records_for_name(validation_domain_name) + try: + from acme import dns_resolver + txt_records = dns_resolver.txt_records_for_name( + validation_domain_name) + except ImportError as error: + raise ImportError("Local validation for 'dns-01' challenges " + "requires 'dnspython'") exists = validation in txt_records if not exists: logger.debug("Key authorization from response (%r) doesn't match " @@ -701,24 +706,3 @@ class DNSResponse(ChallengeResponse): """ return chall.check_validation(self.validation, account_public_key) - -def txt_records_for_name(name): - """Resolve the name and return the TXT records. - - :param unicode name: Domain name being verified. - - :returns: A list of txt records, if empty the name could not be resolved - :rtype: list of unicode - - """ - try: - import dns.resolver - import dns.exception - dns_response = dns.resolver.query(name, 'TXT') - except ImportError as error: - raise ImportError("Local validation for 'dns-01' challenges requires " - "'dnspython'") - except dns.exception.DNSException as error: - logger.error("Unable to resolve %s: %s", name, str(error)) - return [] - return [txt_rec for rdata in dns_response for txt_rec in rdata.strings] diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index 79a928456..0fc8fcef7 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -1,7 +1,6 @@ """Tests for acme.challenges.""" import unittest -import dns.rrset import mock import OpenSSL import requests @@ -94,16 +93,6 @@ class DNS01ResponseTest(unittest.TestCase): self.chall = DNS01(token=(b'x' * 16)) self.response = self.chall.response(KEY) - def create_txt_response(self, name, txt_records): - """ - Returns an RRSet containing the 'txt_records' as the result of a DNS - query for 'name'. - - This takes advantage of the fact that an Answer object mostly behaves - like an RRset. - """ - return dns.rrset.from_text_list(name, 60, "IN", "TXT", txt_records) - def test_to_partial_json(self): self.assertEqual(self.jmsg, self.msg.to_partial_json()) @@ -119,36 +108,25 @@ class DNS01ResponseTest(unittest.TestCase): key2 = jose.JWKRSA.load(test_util.load_vector('rsa256_key.pem')) self.response.simple_verify(self.chall, "local", key2.public_key()) - @mock.patch("acme.challenges.dns.resolver.query") - def test_simple_verify_good_validation(self, mock_dns): - mock_dns.return_value = self.create_txt_response( - self.chall.validation_domain_name("local"), - [self.chall.validation(KEY.public_key())]) + @mock.patch("acme.dns_resolver.txt_records_for_name") + def test_simple_verify_good_validation(self, mock_resolver): + mock_resolver.return_value = [self.chall.validation(KEY.public_key())] self.assertTrue(self.response.simple_verify( self.chall, "local", KEY.public_key())) - mock_dns.assert_called_once_with( - self.chall.validation_domain_name("local"), "TXT") + mock_resolver.assert_called_once_with( + self.chall.validation_domain_name("local")) - @mock.patch("acme.challenges.dns.resolver.query") - def test_simple_verify_good_validation_multiple_txts(self, mock_dns): - mock_dns.return_value = self.create_txt_response( - self.chall.validation_domain_name("local"), - ["!", self.chall.validation(KEY.public_key())]) + @mock.patch("acme.dns_resolver.txt_records_for_name") + def test_simple_verify_good_validation_multiple_txts(self, mock_resolver): + mock_resolver.return_value = ["!", self.chall.validation(KEY.public_key())] self.assertTrue(self.response.simple_verify( self.chall, "local", KEY.public_key())) - mock_dns.assert_called_once_with( - self.chall.validation_domain_name("local"), "TXT") + mock_resolver.assert_called_once_with( + self.chall.validation_domain_name("local")) - @mock.patch("acme.challenges.dns.resolver.query") + @mock.patch("acme.dns_resolver.txt_records_for_name") def test_simple_verify_bad_validation(self, mock_dns): - mock_dns.return_value = self.create_txt_response( - self.chall.validation_domain_name("local"), ["!"]) - self.assertFalse(self.response.simple_verify( - self.chall, "local", KEY.public_key())) - - @mock.patch("acme.challenges.dns.resolver.query") - def test_simple_verify_connection_error(self, mock_dns): - mock_dns.side_effect = dns.exception.DNSException + mock_dns.return_value = ["!"] self.assertFalse(self.response.simple_verify( self.chall, "local", KEY.public_key())) diff --git a/acme/acme/dns_resolver.py b/acme/acme/dns_resolver.py new file mode 100644 index 000000000..04e52224e --- /dev/null +++ b/acme/acme/dns_resolver.py @@ -0,0 +1,28 @@ +"""DNS Resolver for ACME client. +Required only for local validation of 'dns-01' challenges. +""" +import logging + +import dns.resolver +import dns.exception + +logger = logging.getLogger(__name__) + +def txt_records_for_name(name): + """Resolve the name and return the TXT records. + + :param unicode name: Domain name being verified. + + :returns: A list of txt records, if empty the name could not be resolved + :rtype: list of unicode + + """ + try: + dns_response = dns.resolver.query(name, 'TXT') + except ImportError as error: + raise ImportError("Local validation for 'dns-01' challenges requires " + "'dnspython'") + except dns.exception.DNSException as error: + logger.error("Unable to resolve %s: %s", name, str(error)) + return [] + return [txt_rec for rdata in dns_response for txt_rec in rdata.strings] diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py new file mode 100644 index 000000000..d1daa2d37 --- /dev/null +++ b/acme/acme/dns_resolver_test.py @@ -0,0 +1,37 @@ +"""Tests for acme.dns_resolver.""" +import unittest + +import dns +import mock + +from acme import dns_resolver + +class TxtRecordsForNameTest(unittest.TestCase): + + def create_txt_response(self, name, txt_records): + """ + Returns an RRSet containing the 'txt_records' as the result of a DNS + query for 'name'. + + This takes advantage of the fact that an Answer object mostly behaves + like an RRset. + """ + return dns.rrset.from_text_list(name, 60, "IN", "TXT", txt_records) + + @mock.patch("acme.dns_resolver.dns.resolver.query") + def test_txt_records_for_name_test_with_single_response(self, mock_dns): + mock_dns.return_value = self.create_txt_response('name', ['response']) + self.assertEqual(['response'], + dns_resolver.txt_records_for_name('name')) + + @mock.patch("acme.dns_resolver.dns.resolver.query") + def test_txt_records_for_name_with_multiple_responses(self, mock_dns): + mock_dns.return_value = self.create_txt_response( + 'name', ['response1', 'response2']) + self.assertEqual(['response1', 'response2'], + dns_resolver.txt_records_for_name('name')) + + @mock.patch("acme.dns_resolver.dns.resolver.query") + def test_txt_records_for_name_domain_not_found(self, mock_dns): + mock_dns.side_effect = dns.exception.DNSException + self.assertEquals([], dns_resolver.txt_records_for_name('name')) From a9a5e60bc59a65fb8d02f60f88946f1bafcc655c Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 01:26:32 -0500 Subject: [PATCH 013/126] Added requirements for coverage and lint. --- acme/acme/challenges.py | 2 +- acme/acme/dns_resolver_test.py | 2 +- acme/setup.py | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 221eb406c..22bda6445 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -245,7 +245,7 @@ class DNS01Response(KeyAuthorizationChallengeResponse): from acme import dns_resolver txt_records = dns_resolver.txt_records_for_name( validation_domain_name) - except ImportError as error: + except ImportError: raise ImportError("Local validation for 'dns-01' challenges " "requires 'dnspython'") exists = validation in txt_records diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index d1daa2d37..2202ce4e8 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -23,7 +23,7 @@ class TxtRecordsForNameTest(unittest.TestCase): mock_dns.return_value = self.create_txt_response('name', ['response']) self.assertEqual(['response'], dns_resolver.txt_records_for_name('name')) - + @mock.patch("acme.dns_resolver.dns.resolver.query") def test_txt_records_for_name_with_multiple_responses(self, mock_dns): mock_dns.return_value = self.create_txt_response( diff --git a/acme/setup.py b/acme/setup.py index e00476117..269d9e1fd 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -74,7 +74,9 @@ setup( include_package_data=True, install_requires=install_requires, extras_require={ + 'coverage': ['dnspython'], 'docs': docs_extras, + 'lint': ['dnspython'], 'testing': testing_extras + ['dnspython'], }, entry_points={ From d2ced2de6aa31d6fe2aab4b68a7feb89aad307d1 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 01:48:12 -0500 Subject: [PATCH 014/126] Dep fixes for lint/coverage. --- acme/setup.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 269d9e1fd..e4a525605 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -35,6 +35,10 @@ if sys.version_info < (2, 7, 9): install_requires.append('ndg-httpsclient') install_requires.append('pyasn1') +dev_extras = [ + 'dnspython', +] + docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -42,6 +46,7 @@ docs_extras = [ ] testing_extras = [ + 'dnspython', 'nose', 'tox', ] @@ -74,10 +79,9 @@ setup( include_package_data=True, install_requires=install_requires, extras_require={ - 'coverage': ['dnspython'], + 'dev': dev_extras, 'docs': docs_extras, - 'lint': ['dnspython'], - 'testing': testing_extras + ['dnspython'], + 'testing': testing_extras, }, entry_points={ 'console_scripts': [ From 52c487f462067ca810f3f3b840876306dfd1e9b1 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 02:44:19 -0500 Subject: [PATCH 015/126] Add new 'test' extras and update tox.ini accordingly. --- acme/acme/challenges_test.py | 5 ++--- acme/setup.py | 5 ++--- tox.ini | 10 +++++----- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index 0fc8fcef7..ac94619b5 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -135,9 +135,8 @@ class DNS01Test(unittest.TestCase): def setUp(self): from acme.challenges import DNS01 - self.msg = DNS01( - token=jose.decode_b64jose( - 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA')) + self.msg = DNS01(token=jose.decode_b64jose( + 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA')) self.jmsg = { 'type': 'dns-01', 'token': 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA', diff --git a/acme/setup.py b/acme/setup.py index e4a525605..3cb69ce9e 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -35,7 +35,7 @@ if sys.version_info < (2, 7, 9): install_requires.append('ndg-httpsclient') install_requires.append('pyasn1') -dev_extras = [ +dns_extras = [ 'dnspython', ] @@ -46,7 +46,6 @@ docs_extras = [ ] testing_extras = [ - 'dnspython', 'nose', 'tox', ] @@ -79,7 +78,7 @@ setup( include_package_data=True, install_requires=install_requires, extras_require={ - 'dev': dev_extras, + 'dns': dns_extras, 'docs': docs_extras, 'testing': testing_extras, }, diff --git a/tox.ini b/tox.ini index 1abe1cf39..98e185cfa 100644 --- a/tox.ini +++ b/tox.ini @@ -33,23 +33,23 @@ setenv = [testenv:py33] commands = - pip install -e acme[testing] + pip install -e acme[dev,testing] nosetests -v acme [testenv:py34] commands = - pip install -e acme[testing] + pip install -e acme[dev,testing] nosetests -v acme [testenv:py35] commands = - pip install -e acme[testing] + pip install -e acme[dev,testing] nosetests -v acme [testenv:cover] basepython = python2.7 commands = - pip install -e acme -e .[testing] -e letsencrypt-apache -e letsencrypt-nginx -e letshelp-letsencrypt + pip install -e acme[dns] -e .[testing] -e letsencrypt-apache -e letsencrypt-nginx -e letshelp-letsencrypt ./tox.cover.sh [testenv:lint] @@ -59,7 +59,7 @@ basepython = python2.7 # duplicate code checking; if one of the commands fails, others will # continue, but tox return code will reflect previous error commands = - pip install -e acme -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt + pip install -e acme -e .[dns,dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt ./pep8.travis.sh pylint --rcfile=.pylintrc letsencrypt pylint --rcfile=.pylintrc acme/acme From cead22f4a7d46ff921a66bd049317c78733c596b Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 02:45:20 -0500 Subject: [PATCH 016/126] Add dns env to lint/cover --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 98e185cfa..a1ed23cf7 100644 --- a/tox.ini +++ b/tox.ini @@ -59,7 +59,7 @@ basepython = python2.7 # duplicate code checking; if one of the commands fails, others will # continue, but tox return code will reflect previous error commands = - pip install -e acme -e .[dns,dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt + pip install -e acme[dns] -e .[dns,dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt ./pep8.travis.sh pylint --rcfile=.pylintrc letsencrypt pylint --rcfile=.pylintrc acme/acme From e61e83f7e26803b556c7e6620cd014779d1f5e36 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 02:46:29 -0500 Subject: [PATCH 017/126] tox.ini fix --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index a1ed23cf7..cdc2c2396 100644 --- a/tox.ini +++ b/tox.ini @@ -59,7 +59,7 @@ basepython = python2.7 # duplicate code checking; if one of the commands fails, others will # continue, but tox return code will reflect previous error commands = - pip install -e acme[dns] -e .[dns,dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt + pip install -e acme[dns] -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt ./pep8.travis.sh pylint --rcfile=.pylintrc letsencrypt pylint --rcfile=.pylintrc acme/acme From b8a9c2597c4ba6a02ed9b530c1286a1c24b7ccac Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 02:57:53 -0500 Subject: [PATCH 018/126] add dns environment to pyXX --- tox.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tox.ini b/tox.ini index cdc2c2396..4a7aea0d0 100644 --- a/tox.ini +++ b/tox.ini @@ -33,17 +33,17 @@ setenv = [testenv:py33] commands = - pip install -e acme[dev,testing] + pip install -e acme[dns,testing] nosetests -v acme [testenv:py34] commands = - pip install -e acme[dev,testing] + pip install -e acme[dns,testing] nosetests -v acme [testenv:py35] commands = - pip install -e acme[dev,testing] + pip install -e acme[dns,testing] nosetests -v acme [testenv:cover] From b73b410729e90bf0c6c1882130f6c0759675d7c3 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 02:59:25 -0500 Subject: [PATCH 019/126] Exclude import error case from coverage in dns_resolver --- acme/acme/dns_resolver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/dns_resolver.py b/acme/acme/dns_resolver.py index 04e52224e..e28f132f1 100644 --- a/acme/acme/dns_resolver.py +++ b/acme/acme/dns_resolver.py @@ -19,7 +19,7 @@ def txt_records_for_name(name): """ try: dns_response = dns.resolver.query(name, 'TXT') - except ImportError as error: + except ImportError as error: # pragma: no cover raise ImportError("Local validation for 'dns-01' challenges requires " "'dnspython'") except dns.exception.DNSException as error: From 6bc3060fbb6a3d248654b6f97c004ce682e1e52f Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 03:11:09 -0500 Subject: [PATCH 020/126] More fixes for travis tests --- acme/acme/challenges.py | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 22bda6445..08d847627 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -245,7 +245,7 @@ class DNS01Response(KeyAuthorizationChallengeResponse): from acme import dns_resolver txt_records = dns_resolver.txt_records_for_name( validation_domain_name) - except ImportError: + except ImportError: # pragma: no cover raise ImportError("Local validation for 'dns-01' challenges " "requires 'dnspython'") exists = validation in txt_records diff --git a/tox.ini b/tox.ini index 4a7aea0d0..c0a819b5e 100644 --- a/tox.ini +++ b/tox.ini @@ -15,7 +15,7 @@ envlist = py26,py27,py33,py34,py35,cover,lint # packages installed separately to ensure that dowstream deps problems # are detected, c.f. #1002 commands = - pip install -e acme[testing] + pip install -e acme[dns,testing] nosetests -v acme pip install -e .[testing] nosetests -v letsencrypt From 02a493011ef039ca6ec1d52d9c87d4317afe0d12 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Wed, 6 Jan 2016 22:56:59 -0500 Subject: [PATCH 021/126] Remove superfluous except: and change Exception returned if dnspython is not available. --- acme/acme/challenges.py | 4 ++-- acme/acme/dns_resolver.py | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 08d847627..3a78e403a 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -246,8 +246,8 @@ class DNS01Response(KeyAuthorizationChallengeResponse): txt_records = dns_resolver.txt_records_for_name( validation_domain_name) except ImportError: # pragma: no cover - raise ImportError("Local validation for 'dns-01' challenges " - "requires 'dnspython'") + raise errors.Error("Local validation for 'dns-01' challenges " + "requires 'dnspython'") exists = validation in txt_records if not exists: logger.debug("Key authorization from response (%r) doesn't match " diff --git a/acme/acme/dns_resolver.py b/acme/acme/dns_resolver.py index e28f132f1..3572ee277 100644 --- a/acme/acme/dns_resolver.py +++ b/acme/acme/dns_resolver.py @@ -19,9 +19,6 @@ def txt_records_for_name(name): """ try: dns_response = dns.resolver.query(name, 'TXT') - except ImportError as error: # pragma: no cover - raise ImportError("Local validation for 'dns-01' challenges requires " - "'dnspython'") except dns.exception.DNSException as error: logger.error("Unable to resolve %s: %s", name, str(error)) return [] From 446994e8ef11a860ac94a52751bc51a9fded6b04 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sat, 9 Jan 2016 14:58:19 -0500 Subject: [PATCH 022/126] Limit length of try block. --- acme/acme/challenges.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 3a78e403a..493d230d8 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -243,11 +243,10 @@ class DNS01Response(KeyAuthorizationChallengeResponse): try: from acme import dns_resolver - txt_records = dns_resolver.txt_records_for_name( - validation_domain_name) except ImportError: # pragma: no cover raise errors.Error("Local validation for 'dns-01' challenges " "requires 'dnspython'") + txt_records = dns_resolver.txt_records_for_name(validation_domain_name) exists = validation in txt_records if not exists: logger.debug("Key authorization from response (%r) doesn't match " From 56154f1301725dff575e22011a81ca18d5729307 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sat, 9 Jan 2016 16:43:43 -0500 Subject: [PATCH 023/126] - Use dnspython3 fir py3X environments. - Fix encoding for simple_verify. --- acme/acme/challenges.py | 4 ++-- acme/setup.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 493d230d8..3fa259b13 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -271,8 +271,8 @@ class DNS01(KeyAuthorizationChallenge): :rtype: unicode """ - return jose.b64encode(hashlib.sha256( - self.key_authorization(account_key)).digest()) + return jose.b64encode(hashlib.sha256(self.key_authorization( + account_key).encode("utf-8")).digest()).decode() def validation_domain_name(self, name): """Domain name for TXT validation record. diff --git a/acme/setup.py b/acme/setup.py index c54dc42e6..df5cfba0e 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -35,9 +35,14 @@ if sys.version_info < (2, 7, 9): install_requires.append('ndg-httpsclient') install_requires.append('pyasn1') -dns_extras = [ - 'dnspython', -] +if sys.version_info < (3, 0): + dns_extras = [ + 'dnspython', + ] +else: + dns_extras = [ + 'dnspython3', + ] docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags From d842f268e5414f418e69913f6ac4fadffb327fb1 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sat, 9 Jan 2016 17:07:20 -0500 Subject: [PATCH 024/126] - Use dnspython3 fir py3X environments. - Fix encoding for simple_verify. --- acme/acme/challenges.py | 4 ++-- acme/setup.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 493d230d8..3fa259b13 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -271,8 +271,8 @@ class DNS01(KeyAuthorizationChallenge): :rtype: unicode """ - return jose.b64encode(hashlib.sha256( - self.key_authorization(account_key)).digest()) + return jose.b64encode(hashlib.sha256(self.key_authorization( + account_key).encode("utf-8")).digest()).decode() def validation_domain_name(self, name): """Domain name for TXT validation record. diff --git a/acme/setup.py b/acme/setup.py index c54dc42e6..df5cfba0e 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -35,9 +35,14 @@ if sys.version_info < (2, 7, 9): install_requires.append('ndg-httpsclient') install_requires.append('pyasn1') -dns_extras = [ - 'dnspython', -] +if sys.version_info < (3, 0): + dns_extras = [ + 'dnspython', + ] +else: + dns_extras = [ + 'dnspython3', + ] docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags From f2b52bd830457200474e98394b8aff0315e9d51f Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 10 Jan 2016 12:58:29 -0500 Subject: [PATCH 025/126] Fix dcumentation --- acme/acme/challenges.py | 1 - 1 file changed, 1 deletion(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 3fa259b13..a5b142c5b 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -226,7 +226,6 @@ class DNS01Response(KeyAuthorizationChallengeResponse): :param unicode domain: Domain name being verified. :param account_public_key: Public key for the key pair being authorized. - :param JWK account_public_key: :returns: ``True`` iff validation with the TXT records resolved from a DNS server is successful. From 49c40e7a584d1d8faeac4436c6c7787e44a12b6d Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 10 Jan 2016 13:00:38 -0500 Subject: [PATCH 026/126] Skip dns_resolver tests if dnspython is not available. --- acme/acme/dns_resolver_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index 2202ce4e8..0d5cc2543 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -1,11 +1,17 @@ """Tests for acme.dns_resolver.""" import unittest -import dns import mock +try: + import dns +except ImportError: + dns = None + from acme import dns_resolver +@unittest.skipIf(dns is None, + "dnspython is not available, skipping dns_resolver tests") class TxtRecordsForNameTest(unittest.TestCase): def create_txt_response(self, name, txt_records): From cfe56cbd925a4c90a051355f4f891ee8f15308d0 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 10 Jan 2016 17:00:14 -0500 Subject: [PATCH 027/126] 2.6 compatible skipping of tests. --- acme/acme/dns_resolver_test.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index 0d5cc2543..54f074a92 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -1,17 +1,15 @@ """Tests for acme.dns_resolver.""" import unittest - import mock -try: - import dns -except ImportError: - dns = None - from acme import dns_resolver -@unittest.skipIf(dns is None, - "dnspython is not available, skipping dns_resolver tests") +try: + import dns +except ImportError: # pragma: no cover + dns = None + + class TxtRecordsForNameTest(unittest.TestCase): def create_txt_response(self, name, txt_records): @@ -41,3 +39,9 @@ class TxtRecordsForNameTest(unittest.TestCase): def test_txt_records_for_name_domain_not_found(self, mock_dns): mock_dns.side_effect = dns.exception.DNSException self.assertEquals([], dns_resolver.txt_records_for_name('name')) + + def run(self, result=None): + if dns is None: + print self, "... SKIPPING, no dnspython available" + return + super(TxtRecordsForNameTest, self).run(result) From 0010610a4a038fd592c0544d02fd0f36a8ff3495 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 10 Jan 2016 17:06:03 -0500 Subject: [PATCH 028/126] py3X fix --- acme/acme/dns_resolver_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index 54f074a92..8e92cd4a3 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -42,6 +42,6 @@ class TxtRecordsForNameTest(unittest.TestCase): def run(self, result=None): if dns is None: - print self, "... SKIPPING, no dnspython available" + print(self, "... SKIPPING, no dnspython available") return super(TxtRecordsForNameTest, self).run(result) From 2d8de74f4abd659cad518ec5d74d8613fe9830ac Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 10 Jan 2016 17:13:25 -0500 Subject: [PATCH 029/126] pcoverage fix --- acme/acme/dns_resolver_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index 8e92cd4a3..770a95a77 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -7,7 +7,7 @@ from acme import dns_resolver try: import dns except ImportError: # pragma: no cover - dns = None + dns = Nones class TxtRecordsForNameTest(unittest.TestCase): @@ -41,7 +41,7 @@ class TxtRecordsForNameTest(unittest.TestCase): self.assertEquals([], dns_resolver.txt_records_for_name('name')) def run(self, result=None): - if dns is None: + if dns is None: # pragma: no cover print(self, "... SKIPPING, no dnspython available") return super(TxtRecordsForNameTest, self).run(result) From 1ff121b616c8d599549be19a07bd45fb8429fc49 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 10 Jan 2016 18:08:16 -0500 Subject: [PATCH 030/126] pcoverage fix --- acme/acme/dns_resolver_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index 770a95a77..5d160fc07 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -7,7 +7,7 @@ from acme import dns_resolver try: import dns except ImportError: # pragma: no cover - dns = Nones + dns = None class TxtRecordsForNameTest(unittest.TestCase): From 9179276cb982945f6d6083b26d7a55d0112894e9 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 10 Jan 2016 20:59:11 -0500 Subject: [PATCH 031/126] Modify dns_resolver_test to skip tests if dnspython is not available. --- acme/acme/dns_resolver_test.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index 2202ce4e8..5d160fc07 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -1,11 +1,15 @@ """Tests for acme.dns_resolver.""" import unittest - -import dns import mock from acme import dns_resolver +try: + import dns +except ImportError: # pragma: no cover + dns = None + + class TxtRecordsForNameTest(unittest.TestCase): def create_txt_response(self, name, txt_records): @@ -35,3 +39,9 @@ class TxtRecordsForNameTest(unittest.TestCase): def test_txt_records_for_name_domain_not_found(self, mock_dns): mock_dns.side_effect = dns.exception.DNSException self.assertEquals([], dns_resolver.txt_records_for_name('name')) + + def run(self, result=None): + if dns is None: # pragma: no cover + print(self, "... SKIPPING, no dnspython available") + return + super(TxtRecordsForNameTest, self).run(result) From 05a61c181b277d4a3f94abe038da0fda549faeda Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 10 Jan 2016 21:42:20 -0500 Subject: [PATCH 032/126] Lint fixes. --- acme/acme/challenges_test.py | 2 +- acme/acme/dns_resolver_test.py | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index ac94619b5..b32bebed0 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -114,7 +114,7 @@ class DNS01ResponseTest(unittest.TestCase): self.assertTrue(self.response.simple_verify( self.chall, "local", KEY.public_key())) mock_resolver.assert_called_once_with( - self.chall.validation_domain_name("local")) + self.chall.validation_domain_name("local")) @mock.patch("acme.dns_resolver.txt_records_for_name") def test_simple_verify_good_validation_multiple_txts(self, mock_resolver): diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index 5d160fc07..39645c492 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -9,28 +9,28 @@ try: except ImportError: # pragma: no cover dns = None +def create_txt_response(name, txt_records): + """ + Returns an RRSet containing the 'txt_records' as the result of a DNS + query for 'name'. + + This takes advantage of the fact that an Answer object mostly behaves + like an RRset. + """ + return dns.rrset.from_text_list(name, 60, "IN", "TXT", txt_records) + class TxtRecordsForNameTest(unittest.TestCase): - def create_txt_response(self, name, txt_records): - """ - Returns an RRSet containing the 'txt_records' as the result of a DNS - query for 'name'. - - This takes advantage of the fact that an Answer object mostly behaves - like an RRset. - """ - return dns.rrset.from_text_list(name, 60, "IN", "TXT", txt_records) - @mock.patch("acme.dns_resolver.dns.resolver.query") - def test_txt_records_for_name_test_with_single_response(self, mock_dns): - mock_dns.return_value = self.create_txt_response('name', ['response']) + def test_txt_records_for_name_with_single_response(self, mock_dns): + mock_dns.return_value = create_txt_response('name', ['response']) self.assertEqual(['response'], dns_resolver.txt_records_for_name('name')) @mock.patch("acme.dns_resolver.dns.resolver.query") def test_txt_records_for_name_with_multiple_responses(self, mock_dns): - mock_dns.return_value = self.create_txt_response( + mock_dns.return_value = create_txt_response( 'name', ['response1', 'response2']) self.assertEqual(['response1', 'response2'], dns_resolver.txt_records_for_name('name')) From c15581bcfd4b9ffe8d1e1ceb03e316c337691524 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Thu, 14 Jan 2016 23:37:05 -0500 Subject: [PATCH 033/126] Fix lint problems. --- acme/acme/challenges_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index 39f7449f2..af4b81f80 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -119,7 +119,8 @@ class DNS01ResponseTest(unittest.TestCase): @mock.patch("acme.dns_resolver.txt_records_for_name") def test_simple_verify_good_validation_multiple_txts(self, mock_resolver): - mock_resolver.return_value = ["!", self.chall.validation(KEY.public_key())] + mock_resolver.return_value = [ + "!", self.chall.validation(KEY.public_key())] self.assertTrue(self.response.simple_verify( self.chall, "local", KEY.public_key())) mock_resolver.assert_called_once_with( From 7c3271545fe48de9c67b2781ab1fd58328e4e095 Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sat, 13 Feb 2016 01:05:35 -0500 Subject: [PATCH 034/126] Do not log an error when getting NXDOMAIN. --- acme/acme/dns_resolver.py | 4 +++- acme/acme/dns_resolver_test.py | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/acme/acme/dns_resolver.py b/acme/acme/dns_resolver.py index 3572ee277..badbf486a 100644 --- a/acme/acme/dns_resolver.py +++ b/acme/acme/dns_resolver.py @@ -19,7 +19,9 @@ def txt_records_for_name(name): """ try: dns_response = dns.resolver.query(name, 'TXT') + except dns.resolver.NXDOMAIN as error: + return [] except dns.exception.DNSException as error: - logger.error("Unable to resolve %s: %s", name, str(error)) + logger.error("Error resolving %s: %s", name, str(error)) return [] return [txt_rec for rdata in dns_response for txt_rec in rdata.strings] diff --git a/acme/acme/dns_resolver_test.py b/acme/acme/dns_resolver_test.py index 80481343d..53fc0cc77 100644 --- a/acme/acme/dns_resolver_test.py +++ b/acme/acme/dns_resolver_test.py @@ -38,6 +38,11 @@ class TxtRecordsForNameTest(unittest.TestCase): @mock.patch("acme.dns_resolver.dns.resolver.query") def test_txt_records_for_name_domain_not_found(self, mock_dns): + mock_dns.side_effect = dns.resolver.NXDOMAIN + self.assertEquals([], dns_resolver.txt_records_for_name('name')) + + @mock.patch("acme.dns_resolver.dns.resolver.query") + def test_txt_records_for_name_domain_other_error(self, mock_dns): mock_dns.side_effect = dns.exception.DNSException self.assertEquals([], dns_resolver.txt_records_for_name('name')) From 9396e92a966cbc07c0a69b7148f760b4337823dd Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Mon, 25 Apr 2016 00:46:45 -0400 Subject: [PATCH 035/126] Fix lint issues. --- acme/acme/challenges.py | 1 - acme/acme/dns_resolver.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index d27719449..f611578dd 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -599,4 +599,3 @@ class DNSResponse(ChallengeResponse): """ return chall.check_validation(self.validation, account_public_key) - diff --git a/acme/acme/dns_resolver.py b/acme/acme/dns_resolver.py index badbf486a..15638e5d0 100644 --- a/acme/acme/dns_resolver.py +++ b/acme/acme/dns_resolver.py @@ -8,6 +8,7 @@ import dns.exception logger = logging.getLogger(__name__) + def txt_records_for_name(name): """Resolve the name and return the TXT records. From ecbff9e60d7913be893f1931ccd5e19fe3ab00f9 Mon Sep 17 00:00:00 2001 From: Noah Swartz Date: Mon, 9 May 2016 14:40:03 -0700 Subject: [PATCH 036/126] migrate packaging info --- docs/packaging.rst | 77 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/docs/packaging.rst b/docs/packaging.rst index 5f09b65fa..c0baf6232 100644 --- a/docs/packaging.rst +++ b/docs/packaging.rst @@ -2,5 +2,78 @@ Packaging Guide =============== -Documentation can be found at -https://github.com/letsencrypt/letsencrypt/wiki/Packaging. +## Releases + +We release packages and upload them to PyPI (wheels and source tarballs). + +- https://pypi.python.org/pypi/acme +- https://pypi.python.org/pypi/letsencrypt +- https://pypi.python.org/pypi/letsencrypt-apache +- https://pypi.python.org/pypi/letsencrypt-nginx +- https://pypi.python.org/pypi/letshelp-letsencrypt + +The following scripts are used in the process: + +- https://github.com/letsencrypt/letsencrypt/blob/master/tools/release.sh +- https://gist.github.com/kuba/b9a3a2ca3bd35b8368ef + +We currently version as `0.0.0.devYYYYMMDD`, and will change at GA time to the following scheme: +- `0.1.0` +- `0.2.0dev` for developement in `master` +- `0.2.0` (only temporarily in `master`) +- ... + +Tracking issue for non-dev release scripts: https://github.com/letsencrypt/letsencrypt/issues/1185 + +## Notes for package maintainers + +0. Please use our releases, not `master`! + +1. Do not package `letsencrypt-compatibility-test` - it's only used internally. + +2. `letsencrypt-renewer` should be added to crontab... but it currently doesn't work well + +3. `letsencrypt.client` provides developer API so it should be possible to `import letsencrypt.client` when the package is installed (`letsencrypt` vs `python-letsencrypt` debate for Debian). + +4. `jws` is an internal script for `acme` module and it doesn't have to be packaged - it's mostly for debugging: you can use it as `echo foo | jws sign | jws verify`. + +5. Do get in touch with us. We are happy to make any changes that will make packaging easier. If you need to apply some patches don't do it downstream - make a PR here. + +## Already ongoing efforts + + + +### Arch + +From PyPI: +- https://www.archlinux.org/packages/community/any/python2-acme +- https://www.archlinux.org/packages/community/any/letsencrypt +- https://www.archlinux.org/packages/community/any/letsencrypt-apache +- https://www.archlinux.org/packages/community/any/letsencrypt-nginx +- https://www.archlinux.org/packages/community/any/letshelp-letsencrypt + +From `master`: https://aur.archlinux.org/packages/letsencrypt-git + +### Debian (and its derivatives, including Ubuntu) + +https://alioth.debian.org/projects/letsencrypt/ + +### Fedora +In Fedora 23+. + +- https://admin.fedoraproject.org/pkgdb/package/letsencrypt/ +- https://admin.fedoraproject.org/pkgdb/package/python-acme/ +- https://bugzilla.redhat.com/show_bug.cgi?id=1287193 (review request, closed) + +### FreeBSD + +https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=203405 + +### GNU Guix +- https://www.gnu.org/software/guix/package-list.html#letsencrypt + +### OpenBSD + +- http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/security/letsencrypt/ +- https://github.com/letsencrypt/letsencrypt/pull/1175 +- https://github.com/letsencrypt/letsencrypt/issues/1174 From 05131da32e6f88101c300aebfb7e4f3e7eec4263 Mon Sep 17 00:00:00 2001 From: Noah Swartz Date: Mon, 9 May 2016 14:44:26 -0700 Subject: [PATCH 037/126] make code blocks code blocks --- docs/packaging.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/packaging.rst b/docs/packaging.rst index c0baf6232..8ec7d7fca 100644 --- a/docs/packaging.rst +++ b/docs/packaging.rst @@ -2,7 +2,8 @@ Packaging Guide =============== -## Releases +Releases +======== We release packages and upload them to PyPI (wheels and source tarballs). @@ -17,25 +18,25 @@ The following scripts are used in the process: - https://github.com/letsencrypt/letsencrypt/blob/master/tools/release.sh - https://gist.github.com/kuba/b9a3a2ca3bd35b8368ef -We currently version as `0.0.0.devYYYYMMDD`, and will change at GA time to the following scheme: -- `0.1.0` -- `0.2.0dev` for developement in `master` -- `0.2.0` (only temporarily in `master`) +We currently version as ``0.0.0.devYYYYMMDD``, and will change at GA time to the following scheme: +- ``0.1.0`` +- ``0.2.0dev`` for developement in ``master`` +- ``0.2.0`` (only temporarily in ``master``) - ... Tracking issue for non-dev release scripts: https://github.com/letsencrypt/letsencrypt/issues/1185 ## Notes for package maintainers -0. Please use our releases, not `master`! +0. Please use our releases, not ``master``! -1. Do not package `letsencrypt-compatibility-test` - it's only used internally. +1. Do not package ``letsencrypt-compatibility-test`` - it's only used internally. -2. `letsencrypt-renewer` should be added to crontab... but it currently doesn't work well +2. ``letsencrypt-renewer`` should be added to crontab... but it currently doesn't work well -3. `letsencrypt.client` provides developer API so it should be possible to `import letsencrypt.client` when the package is installed (`letsencrypt` vs `python-letsencrypt` debate for Debian). +3. ``letsencrypt.client`` provides developer API so it should be possible to ``import letsencrypt.client`` when the package is installed (``letsencrypt`` vs ``python-letsencrypt`` debate for Debian). -4. `jws` is an internal script for `acme` module and it doesn't have to be packaged - it's mostly for debugging: you can use it as `echo foo | jws sign | jws verify`. +4. ``jws`` is an internal script for ``acme`` module and it doesn't have to be packaged - it's mostly for debugging: you can use it as ``echo foo | jws sign | jws verify``. 5. Do get in touch with us. We are happy to make any changes that will make packaging easier. If you need to apply some patches don't do it downstream - make a PR here. @@ -52,7 +53,7 @@ From PyPI: - https://www.archlinux.org/packages/community/any/letsencrypt-nginx - https://www.archlinux.org/packages/community/any/letshelp-letsencrypt -From `master`: https://aur.archlinux.org/packages/letsencrypt-git +From ``master``: https://aur.archlinux.org/packages/letsencrypt-git ### Debian (and its derivatives, including Ubuntu) From 505b8854f67b95e84217a7833c02a92ee79191d2 Mon Sep 17 00:00:00 2001 From: Noah Swartz Date: Mon, 9 May 2016 14:46:37 -0700 Subject: [PATCH 038/126] break sections correctly --- docs/packaging.rst | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/docs/packaging.rst b/docs/packaging.rst index 8ec7d7fca..0113fbbe6 100644 --- a/docs/packaging.rst +++ b/docs/packaging.rst @@ -19,6 +19,7 @@ The following scripts are used in the process: - https://gist.github.com/kuba/b9a3a2ca3bd35b8368ef We currently version as ``0.0.0.devYYYYMMDD``, and will change at GA time to the following scheme: + - ``0.1.0`` - ``0.2.0dev`` for developement in ``master`` - ``0.2.0`` (only temporarily in ``master``) @@ -26,7 +27,8 @@ We currently version as ``0.0.0.devYYYYMMDD``, and will change at GA time to the Tracking issue for non-dev release scripts: https://github.com/letsencrypt/letsencrypt/issues/1185 -## Notes for package maintainers +Notes for package maintainers +============================= 0. Please use our releases, not ``master``! @@ -40,11 +42,12 @@ Tracking issue for non-dev release scripts: https://github.com/letsencrypt/letse 5. Do get in touch with us. We are happy to make any changes that will make packaging easier. If you need to apply some patches don't do it downstream - make a PR here. -## Already ongoing efforts +Already ongoing efforts +----------------------- - -### Arch +Arch +==== From PyPI: - https://www.archlinux.org/packages/community/any/python2-acme @@ -55,25 +58,32 @@ From PyPI: From ``master``: https://aur.archlinux.org/packages/letsencrypt-git -### Debian (and its derivatives, including Ubuntu) +Debian (and its derivatives, including Ubuntu) +====== https://alioth.debian.org/projects/letsencrypt/ -### Fedora +Fedora +====== + In Fedora 23+. - https://admin.fedoraproject.org/pkgdb/package/letsencrypt/ - https://admin.fedoraproject.org/pkgdb/package/python-acme/ - https://bugzilla.redhat.com/show_bug.cgi?id=1287193 (review request, closed) -### FreeBSD +FreeBSD +======= https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=203405 -### GNU Guix +GNU Guix +======== + - https://www.gnu.org/software/guix/package-list.html#letsencrypt -### OpenBSD +OpenBSD +======= - http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/security/letsencrypt/ - https://github.com/letsencrypt/letsencrypt/pull/1175 From c4c1fa3a26b8291532d936f194b89a4ffea45081 Mon Sep 17 00:00:00 2001 From: Noah Swartz Date: Mon, 9 May 2016 14:48:28 -0700 Subject: [PATCH 039/126] switch size of subheadings --- docs/packaging.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/packaging.rst b/docs/packaging.rst index 0113fbbe6..6bf359bf2 100644 --- a/docs/packaging.rst +++ b/docs/packaging.rst @@ -43,11 +43,11 @@ Notes for package maintainers 5. Do get in touch with us. We are happy to make any changes that will make packaging easier. If you need to apply some patches don't do it downstream - make a PR here. Already ongoing efforts ------------------------ +======================= Arch -==== +---- From PyPI: - https://www.archlinux.org/packages/community/any/python2-acme @@ -59,12 +59,12 @@ From PyPI: From ``master``: https://aur.archlinux.org/packages/letsencrypt-git Debian (and its derivatives, including Ubuntu) -====== +------ https://alioth.debian.org/projects/letsencrypt/ Fedora -====== +------ In Fedora 23+. @@ -73,17 +73,17 @@ In Fedora 23+. - https://bugzilla.redhat.com/show_bug.cgi?id=1287193 (review request, closed) FreeBSD -======= +------- https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=203405 GNU Guix -======== +-------- - https://www.gnu.org/software/guix/package-list.html#letsencrypt OpenBSD -======= +------- - http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/security/letsencrypt/ - https://github.com/letsencrypt/letsencrypt/pull/1175 From e11e42f98e37fdaed8eb15fe33ef8d83f1c3bcc8 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Tue, 12 Jul 2016 15:09:31 +0300 Subject: [PATCH 040/126] Added simple socket bind check for populated ports if psutil is not available --- certbot/plugins/util.py | 64 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/certbot/plugins/util.py b/certbot/plugins/util.py index 5fc98dff6..0ee2b1587 100644 --- a/certbot/plugins/util.py +++ b/certbot/plugins/util.py @@ -2,14 +2,25 @@ import logging import socket -import psutil import zope.component from certbot import interfaces +try: + import psutil + USE_PSUTIL = True +except ImportError: + USE_PSUTIL = False logger = logging.getLogger(__name__) +RENEWER_EXTRA_MSG = ( + " For automated renewal, you may want to use a script that stops" + " and starts your webserver. You can find an example at" + " https://letsencrypt.org/howitworks/#writing-your-own-renewal-script" + ". Alternatively you can use the webroot plugin to renew without" + " needing to stop and start your webserver.") + def already_listening(port, renewer=False): """Check if a process is already listening on the port. @@ -23,6 +34,50 @@ def already_listening(port, renewer=False): :param int port: The TCP port in question. :returns: True or False. + """ + + if USE_PSUTIL: + return already_listening_psutil(port, renewer=renewer) + else: + logger.debug("Psutil not found, using simple socket check.") + return already_listening_socket(port, renewer=renewer) + + +def already_listening_socket(port, renewer=False): + """Simple socket based check to find out if port is already in use + + :param int port: The TCP port in question. + :returns: True or False + """ + + try: + testsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + try: + testsocket.bind(("", port)) + except socket.error: + display = zope.component.getUtility(interfaces.IDisplay) + extra = "" + if renewer: + extra = RENEWER_EXTRA_MSG + display.notification( + "Port {0} is already in use by another process. This will " + "prevent us from binding to that port. Please stop the " + "process that is populating the port in question and try " + "again. {1}".format(port, extra), height=13) + return True + finally: + testsocket.close() + except socket.error: + pass + return False + + +def already_listening_psutil(port, renewer=False): + """Psutil variant of the open port check + + :param int port: The TCP port in question. + :returns: True or False. + """ try: net_connections = psutil.net_connections() @@ -51,12 +106,7 @@ def already_listening(port, renewer=False): display = zope.component.getUtility(interfaces.IDisplay) extra = "" if renewer: - extra = ( - " For automated renewal, you may want to use a script that stops" - " and starts your webserver. You can find an example at" - " https://letsencrypt.org/howitworks/#writing-your-own-renewal-script" - ". Alternatively you can use the webroot plugin to renew without" - " needing to stop and start your webserver.") + extra = RENEWER_EXTRA_MSG display.notification( "The program {0} (process ID {1}) is already listening " "on TCP port {2}. This will prevent us from binding to " From b7cf9288524cd9ec717f6c88d2b26226d8d04bf0 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 13 Jul 2016 17:17:45 -0700 Subject: [PATCH 041/126] Parse charset_map correctly (though we still don't emit it correctly...) --- .../chive/chive-nginx-master/win-utf | 1 + certbot-nginx/certbot_nginx/nginxparser.py | 27 ++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/certbot-compatibility-test/nginx/nginx-roundtrip-testdata/chive/chive-nginx-master/win-utf b/certbot-compatibility-test/nginx/nginx-roundtrip-testdata/chive/chive-nginx-master/win-utf index ed8bc007a..e4b1e8360 100644 --- a/certbot-compatibility-test/nginx/nginx-roundtrip-testdata/chive/chive-nginx-master/win-utf +++ b/certbot-compatibility-test/nginx/nginx-roundtrip-testdata/chive/chive-nginx-master/win-utf @@ -2,6 +2,7 @@ # This map is not a full windows-1251 <> utf8 map: it does not # contain Serbian and Macedonian letters. If you need a full map, # use contrib/unicode2nginx/win-utf map instead. +# charset_map windows-1251 utf-8 { diff --git a/certbot-nginx/certbot_nginx/nginxparser.py b/certbot-nginx/certbot_nginx/nginxparser.py index 1859777d8..10a26ecb2 100644 --- a/certbot-nginx/certbot_nginx/nginxparser.py +++ b/certbot-nginx/certbot_nginx/nginxparser.py @@ -40,6 +40,7 @@ class RawNginxParser(object): assignment = space + key + Optional(space + value, default=None) + semicolon location_statement = space + Optional(modifier) + Optional(space + location + space) if_statement = space + Literal("if") + space + condition + space + charset_map_statement = space + Literal("charset_map") + space + value + space + value map_statement = space + Literal("map") + space + nonspace + space + dollar_var + space # This is NOT an accurate way to parse nginx map entries; it's almost @@ -52,28 +53,36 @@ class RawNginxParser(object): map_pattern = Regex(r'".*"') | Regex(r"'.*'") | nonspace map_entry = space + map_pattern + space + value + space + semicolon map_block = Group( - # key could for instance be "server" or "http", or "location" (in which case - # location_statement needs to have a non-empty location) Group(map_statement).leaveWhitespace() + left_bracket + Group(ZeroOrMore(Group(comment | map_entry)) + space).leaveWhitespace() + right_bracket) block = Forward() - block << Group( - # key could for instance be "server" or "http", or "location" (in which case - # location_statement needs to have a non-empty location) - (Group(space + key + location_statement) ^ Group(if_statement)).leaveWhitespace() + - left_bracket + - Group(ZeroOrMore(Group(comment | assignment) | block | map_block) + space).leaveWhitespace() - + right_bracket) + + # key could for instance be "server" or "http", or "location" (in which case + # location_statement needs to have a non-empty location) + + block_begin = (Group(space + key + location_statement) ^ + Group(if_statement) ^ + Group(charset_map_statement)).leaveWhitespace() + + block_innards = Group(ZeroOrMore(Group(comment | assignment) | block | map_block) + + space).leaveWhitespace() + + block << Group(block_begin + left_bracket + block_innards + right_bracket) script = OneOrMore(Group(comment | assignment) ^ block ^ map_block) + space + stringEnd script.parseWithTabs() + testLine = OneOrMore(Group(space + key + location_statement)).leaveWhitespace() + testTwo = OneOrMore(block) def __init__(self, source): self.source = source + def test(self): + return self.testLine.parseString(self.source) + def parse(self): """Returns the parsed tree.""" return self.script.parseString(self.source) From 7b3144c168199e6e0cf93935eb36e165727bac51 Mon Sep 17 00:00:00 2001 From: Noah Swartz Date: Thu, 14 Jul 2016 11:53:36 -0700 Subject: [PATCH 042/126] brads comments --- docs/packaging.rst | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/docs/packaging.rst b/docs/packaging.rst index 6bf359bf2..6463e777d 100644 --- a/docs/packaging.rst +++ b/docs/packaging.rst @@ -8,39 +8,33 @@ Releases We release packages and upload them to PyPI (wheels and source tarballs). - https://pypi.python.org/pypi/acme -- https://pypi.python.org/pypi/letsencrypt -- https://pypi.python.org/pypi/letsencrypt-apache -- https://pypi.python.org/pypi/letsencrypt-nginx -- https://pypi.python.org/pypi/letshelp-letsencrypt +- https://pypi.python.org/pypi/certbot +- https://pypi.python.org/pypi/certbot-apache +- https://pypi.python.org/pypi/certbot-nginx The following scripts are used in the process: - https://github.com/letsencrypt/letsencrypt/blob/master/tools/release.sh -- https://gist.github.com/kuba/b9a3a2ca3bd35b8368ef -We currently version as ``0.0.0.devYYYYMMDD``, and will change at GA time to the following scheme: +We currently version with the following scheme: - ``0.1.0`` - ``0.2.0dev`` for developement in ``master`` - ``0.2.0`` (only temporarily in ``master``) - ... -Tracking issue for non-dev release scripts: https://github.com/letsencrypt/letsencrypt/issues/1185 - Notes for package maintainers ============================= 0. Please use our releases, not ``master``! -1. Do not package ``letsencrypt-compatibility-test`` - it's only used internally. +1. Do not package ``certbot-compatibility-test`` or ``letshelp-certbot`` - it's only used internally. -2. ``letsencrypt-renewer`` should be added to crontab... but it currently doesn't work well +2. If you'd like to include automated renewal in your package ``certbot renew -q`` should be added to crontab. -3. ``letsencrypt.client`` provides developer API so it should be possible to ``import letsencrypt.client`` when the package is installed (``letsencrypt`` vs ``python-letsencrypt`` debate for Debian). +3. ``jws`` is an internal script for ``acme`` module and it doesn't have to be packaged - it's mostly for debugging: you can use it as ``echo foo | jws sign | jws verify``. -4. ``jws`` is an internal script for ``acme`` module and it doesn't have to be packaged - it's mostly for debugging: you can use it as ``echo foo | jws sign | jws verify``. - -5. Do get in touch with us. We are happy to make any changes that will make packaging easier. If you need to apply some patches don't do it downstream - make a PR here. +4. Do get in touch with us. We are happy to make any changes that will make packaging easier. If you need to apply some patches don't do it downstream - make a PR here. Already ongoing efforts ======================= @@ -51,17 +45,20 @@ Arch From PyPI: - https://www.archlinux.org/packages/community/any/python2-acme -- https://www.archlinux.org/packages/community/any/letsencrypt -- https://www.archlinux.org/packages/community/any/letsencrypt-apache -- https://www.archlinux.org/packages/community/any/letsencrypt-nginx -- https://www.archlinux.org/packages/community/any/letshelp-letsencrypt +- https://www.archlinux.org/packages/community/any/certbot +- https://www.archlinux.org/packages/community/any/certbot-apache +- https://www.archlinux.org/packages/community/any/certbot-nginx +- https://www.archlinux.org/packages/community/any/letshelp-certbot -From ``master``: https://aur.archlinux.org/packages/letsencrypt-git +From ``master``: https://aur.archlinux.org/packages/certbot-git Debian (and its derivatives, including Ubuntu) ------ https://alioth.debian.org/projects/letsencrypt/ +https://packages.debian.org/sid/certbot +https://packages.debian.org/sid/python-certbot +https://packages.debian.org/sid/python-certbot-apache Fedora ------ @@ -69,8 +66,8 @@ Fedora In Fedora 23+. - https://admin.fedoraproject.org/pkgdb/package/letsencrypt/ +- https://admin.fedoraproject.org/pkgdb/package/certbot/ - https://admin.fedoraproject.org/pkgdb/package/python-acme/ -- https://bugzilla.redhat.com/show_bug.cgi?id=1287193 (review request, closed) FreeBSD ------- From 9fe6836c014428b2d7781a050d9d9312306e0d6d Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 14 Jul 2016 15:05:41 -0700 Subject: [PATCH 043/126] remove coupling between README and docs introduction --- README.rst | 195 +----------------------------------------- docs/intro.rst | 4 +- docs/intro_common.rst | 192 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 196 deletions(-) create mode 100644 docs/intro_common.rst diff --git a/README.rst b/README.rst index c71079f9a..06cb3f8bc 100644 --- a/README.rst +++ b/README.rst @@ -1,194 +1 @@ -.. notice for github users - -Disclaimer -========== - -Certbot (previously, the Let's Encrypt client) is **BETA SOFTWARE**. It -contains plenty of bugs and rough edges, and should be tested thoroughly in -staging environments before use on production systems. - -For more information regarding the status of the project, please see -https://letsencrypt.org. Be sure to checkout the -`Frequently Asked Questions (FAQ) `_. - -About Certbot -============================== - -Certbot is a fully-featured, extensible client for the Let's -Encrypt CA (or any other CA that speaks the `ACME -`_ -protocol) that can automate the tasks of obtaining certificates and -configuring webservers to use them. This client runs on Unix-based operating -systems. - -Until May 2016, Certbot was named simply ``letsencrypt`` or ``letsencrypt-auto``, -depending on install method. Instructions on the Internet, and some pieces of the -software, may still refer to this older name. - -Contributing ------------- - -If you'd like to contribute to this project please read `Developer Guide -`_. - -.. _installation: - -Installation ------------- - -If ``certbot`` (or ``letsencrypt``) is packaged for your Unix OS (visit -certbot.eff.org_ to find out), you can install it -from there, and run it by typing ``certbot`` (or ``letsencrypt``). Because -not all operating systems have packages yet, we provide a temporary solution -via the ``certbot-auto`` wrapper script, which obtains some dependencies from -your OS and puts others in a python virtual environment:: - - user@webserver:~$ wget https://dl.eff.org/certbot-auto - user@webserver:~$ chmod a+x ./certbot-auto - user@webserver:~$ ./certbot-auto --help - -.. hint:: The certbot-auto download is protected by HTTPS, which is pretty good, but if you'd like to - double check the integrity of the ``certbot-auto`` script, you can use these steps for verification before running it:: - - user@server:~$ wget -N https://dl.eff.org/certbot-auto.asc - user@server:~$ gpg2 --recv-key A2CFB51FA275A7286234E7B24D17C995CD9775F2 - user@server:~$ gpg2 --trusted-key 4D17C995CD9775F2 --verify certbot-auto.asc certbot-auto - -And for full command line help, you can type:: - - ./certbot-auto --help all - -``certbot-auto`` updates to the latest client release automatically. And -since ``certbot-auto`` is a wrapper to ``certbot``, it accepts exactly -the same command line flags and arguments. More details about this script and -other installation methods can be found `in the User Guide -`_. - -How to run the client ---------------------- - -In many cases, you can just run ``certbot-auto`` or ``certbot``, and the -client will guide you through the process of obtaining and installing certs -interactively. - -You can also tell it exactly what you want it to do from the command line. -For instance, if you want to obtain a cert for ``example.com``, -``www.example.com``, and ``other.example.net``, using the Apache plugin to both -obtain and install the certs, you could do this:: - - ./certbot-auto --apache -d example.com -d www.example.com -d other.example.net - -(The first time you run the command, it will make an account, and ask for an -email and agreement to the Let's Encrypt Subscriber Agreement; you can -automate those with ``--email`` and ``--agree-tos``) - -If you want to use a webserver that doesn't have full plugin support yet, you -can still use "standalone" or "webroot" plugins to obtain a certificate:: - - ./certbot-auto certonly --standalone --email admin@example.com -d example.com -d www.example.com -d other.example.net - - -Understanding the client in more depth --------------------------------------- - -To understand what the client is doing in detail, it's important to -understand the way it uses plugins. Please see the `explanation of -plugins `_ in -the User Guide. - -Links -===== - -Documentation: https://certbot.eff.org/docs - -Software project: https://github.com/certbot/certbot - -Notes for developers: https://certbot.eff.org/docs/contributing.html - -Main Website: https://letsencrypt.org/ - -IRC Channel: #letsencrypt on `Freenode`_ or #certbot on `OFTC`_ - -Community: https://community.letsencrypt.org - -ACME spec: http://ietf-wg-acme.github.io/acme/ - -ACME working area in github: https://github.com/ietf-wg-acme/acme - - -Mailing list: `client-dev`_ (to subscribe without a Google account, send an -email to client-dev+subscribe@letsencrypt.org) - -|build-status| |coverage| |docs| |container| - - - -.. |build-status| image:: https://travis-ci.org/certbot/certbot.svg?branch=master - :target: https://travis-ci.org/certbot/certbot - :alt: Travis CI status - -.. |coverage| image:: https://coveralls.io/repos/certbot/certbot/badge.svg?branch=master - :target: https://coveralls.io/r/certbot/certbot - :alt: Coverage status - -.. |docs| image:: https://readthedocs.org/projects/letsencrypt/badge/ - :target: https://readthedocs.org/projects/letsencrypt/ - :alt: Documentation status - -.. |container| image:: https://quay.io/repository/letsencrypt/letsencrypt/status - :target: https://quay.io/repository/letsencrypt/letsencrypt - :alt: Docker Repository on Quay.io - -.. _`installation instructions`: - https://letsencrypt.readthedocs.org/en/latest/using.html - -.. _watch demo video: https://www.youtube.com/watch?v=Gas_sSB-5SU - -System Requirements -=================== - -The Let's Encrypt Client presently only runs on Unix-ish OSes that include -Python 2.6 or 2.7; Python 3.x support will hopefully be added in the future. The -client requires root access in order to write to ``/etc/letsencrypt``, -``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443 -(if you use the ``standalone`` plugin) and to read and modify webserver -configurations (if you use the ``apache`` or ``nginx`` plugins). If none of -these apply to you, it is theoretically possible to run without root privileges, -but for most users who want to avoid running an ACME client as root, either -`letsencrypt-nosudo `_ or -`simp_le `_ are more appropriate choices. - -The Apache plugin currently requires a Debian-based OS with augeas version -1.0; this includes Ubuntu 12.04+ and Debian 7+. - - -Current Features -================ - -* Supports multiple web servers: - - - apache/2.x (working on Debian 8+ and Ubuntu 12.04+) - - standalone (runs its own simple webserver to prove you control a domain) - - webroot (adds files to webroot directories in order to prove control of - domains and obtain certs) - - nginx/0.8.48+ (highly experimental, not included in certbot-auto) - -* The private key is generated locally on your system. -* Can talk to the Let's Encrypt CA or optionally to other ACME - compliant services. -* Can get domain-validated (DV) certificates. -* Can revoke certificates. -* Adjustable RSA key bit-length (2048 (default), 4096, ...). -* Can optionally install a http -> https redirect, so your site effectively - runs https only (Apache only) -* Fully automated. -* Configuration changes are logged and can be reverted. -* Supports ncurses and text (-t) UI, or can be driven entirely from the - command line. -* Free and Open Source Software, made with Python. - - -.. _Freenode: https://webchat.freenode.net?channels=%23letsencrypt -.. _OFTC: https://webchat.oftc.net?channels=%23certbot -.. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev -.. _certbot.eff.org: https://certbot.eff.org/ +.. include:: docs/intro_common.rst diff --git a/docs/intro.rst b/docs/intro.rst index 2fffbec68..b841aece9 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -1,6 +1,6 @@ ===================== -README / Introduction +Introduction ===================== -.. include:: ../README.rst +.. include:: intro_common.rst .. include:: ../CHANGES.rst diff --git a/docs/intro_common.rst b/docs/intro_common.rst new file mode 100644 index 000000000..30da17fa1 --- /dev/null +++ b/docs/intro_common.rst @@ -0,0 +1,192 @@ +Disclaimer +========== + +Certbot (previously, the Let's Encrypt client) is **BETA SOFTWARE**. It +contains plenty of bugs and rough edges, and should be tested thoroughly in +staging environments before use on production systems. + +For more information regarding the status of the project, please see +https://letsencrypt.org. Be sure to checkout the +`Frequently Asked Questions (FAQ) `_. + +About Certbot +============================== + +Certbot is a fully-featured, extensible client for the Let's +Encrypt CA (or any other CA that speaks the `ACME +`_ +protocol) that can automate the tasks of obtaining certificates and +configuring webservers to use them. This client runs on Unix-based operating +systems. + +Until May 2016, Certbot was named simply ``letsencrypt`` or ``letsencrypt-auto``, +depending on install method. Instructions on the Internet, and some pieces of the +software, may still refer to this older name. + +Contributing +------------ + +If you'd like to contribute to this project please read `Developer Guide +`_. + +.. _installation: + +Installation +------------ + +If ``certbot`` (or ``letsencrypt``) is packaged for your Unix OS (visit +certbot.eff.org_ to find out), you can install it +from there, and run it by typing ``certbot`` (or ``letsencrypt``). Because +not all operating systems have packages yet, we provide a temporary solution +via the ``certbot-auto`` wrapper script, which obtains some dependencies from +your OS and puts others in a python virtual environment:: + + user@webserver:~$ wget https://dl.eff.org/certbot-auto + user@webserver:~$ chmod a+x ./certbot-auto + user@webserver:~$ ./certbot-auto --help + +.. hint:: The certbot-auto download is protected by HTTPS, which is pretty good, but if you'd like to + double check the integrity of the ``certbot-auto`` script, you can use these steps for verification before running it:: + + user@server:~$ wget -N https://dl.eff.org/certbot-auto.asc + user@server:~$ gpg2 --recv-key A2CFB51FA275A7286234E7B24D17C995CD9775F2 + user@server:~$ gpg2 --trusted-key 4D17C995CD9775F2 --verify certbot-auto.asc certbot-auto + +And for full command line help, you can type:: + + ./certbot-auto --help all + +``certbot-auto`` updates to the latest client release automatically. And +since ``certbot-auto`` is a wrapper to ``certbot``, it accepts exactly +the same command line flags and arguments. More details about this script and +other installation methods can be found `in the User Guide +`_. + +How to run the client +--------------------- + +In many cases, you can just run ``certbot-auto`` or ``certbot``, and the +client will guide you through the process of obtaining and installing certs +interactively. + +You can also tell it exactly what you want it to do from the command line. +For instance, if you want to obtain a cert for ``example.com``, +``www.example.com``, and ``other.example.net``, using the Apache plugin to both +obtain and install the certs, you could do this:: + + ./certbot-auto --apache -d example.com -d www.example.com -d other.example.net + +(The first time you run the command, it will make an account, and ask for an +email and agreement to the Let's Encrypt Subscriber Agreement; you can +automate those with ``--email`` and ``--agree-tos``) + +If you want to use a webserver that doesn't have full plugin support yet, you +can still use "standalone" or "webroot" plugins to obtain a certificate:: + + ./certbot-auto certonly --standalone --email admin@example.com -d example.com -d www.example.com -d other.example.net + + +Understanding the client in more depth +-------------------------------------- + +To understand what the client is doing in detail, it's important to +understand the way it uses plugins. Please see the `explanation of +plugins `_ in +the User Guide. + +Links +===== + +Documentation: https://certbot.eff.org/docs + +Software project: https://github.com/certbot/certbot + +Notes for developers: https://certbot.eff.org/docs/contributing.html + +Main Website: https://letsencrypt.org/ + +IRC Channel: #letsencrypt on `Freenode`_ or #certbot on `OFTC`_ + +Community: https://community.letsencrypt.org + +ACME spec: http://ietf-wg-acme.github.io/acme/ + +ACME working area in github: https://github.com/ietf-wg-acme/acme + + +Mailing list: `client-dev`_ (to subscribe without a Google account, send an +email to client-dev+subscribe@letsencrypt.org) + +|build-status| |coverage| |docs| |container| + + + +.. |build-status| image:: https://travis-ci.org/certbot/certbot.svg?branch=master + :target: https://travis-ci.org/certbot/certbot + :alt: Travis CI status + +.. |coverage| image:: https://coveralls.io/repos/certbot/certbot/badge.svg?branch=master + :target: https://coveralls.io/r/certbot/certbot + :alt: Coverage status + +.. |docs| image:: https://readthedocs.org/projects/letsencrypt/badge/ + :target: https://readthedocs.org/projects/letsencrypt/ + :alt: Documentation status + +.. |container| image:: https://quay.io/repository/letsencrypt/letsencrypt/status + :target: https://quay.io/repository/letsencrypt/letsencrypt + :alt: Docker Repository on Quay.io + +.. _`installation instructions`: + https://letsencrypt.readthedocs.org/en/latest/using.html + +.. _watch demo video: https://www.youtube.com/watch?v=Gas_sSB-5SU + +System Requirements +=================== + +The Let's Encrypt Client presently only runs on Unix-ish OSes that include +Python 2.6 or 2.7; Python 3.x support will hopefully be added in the future. The +client requires root access in order to write to ``/etc/letsencrypt``, +``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443 +(if you use the ``standalone`` plugin) and to read and modify webserver +configurations (if you use the ``apache`` or ``nginx`` plugins). If none of +these apply to you, it is theoretically possible to run without root privileges, +but for most users who want to avoid running an ACME client as root, either +`letsencrypt-nosudo `_ or +`simp_le `_ are more appropriate choices. + +The Apache plugin currently requires a Debian-based OS with augeas version +1.0; this includes Ubuntu 12.04+ and Debian 7+. + + +Current Features +================ + +* Supports multiple web servers: + + - apache/2.x (working on Debian 8+ and Ubuntu 12.04+) + - standalone (runs its own simple webserver to prove you control a domain) + - webroot (adds files to webroot directories in order to prove control of + domains and obtain certs) + - nginx/0.8.48+ (highly experimental, not included in certbot-auto) + +* The private key is generated locally on your system. +* Can talk to the Let's Encrypt CA or optionally to other ACME + compliant services. +* Can get domain-validated (DV) certificates. +* Can revoke certificates. +* Adjustable RSA key bit-length (2048 (default), 4096, ...). +* Can optionally install a http -> https redirect, so your site effectively + runs https only (Apache only) +* Fully automated. +* Configuration changes are logged and can be reverted. +* Supports ncurses and text (-t) UI, or can be driven entirely from the + command line. +* Free and Open Source Software, made with Python. + + +.. _Freenode: https://webchat.freenode.net?channels=%23letsencrypt +.. _OFTC: https://webchat.oftc.net?channels=%23certbot +.. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev +.. _certbot.eff.org: https://certbot.eff.org/ From 26ac17a4a1fa2718719f5e1ecd50207ef6e6dba0 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 14 Jul 2016 15:07:32 -0700 Subject: [PATCH 044/126] Add quick install page --- docs/index.rst | 1 + docs/install.rst | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 docs/install.rst diff --git a/docs/index.rst b/docs/index.rst index b541e376e..dab1f6201 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,6 +5,7 @@ Welcome to the Certbot documentation! :maxdepth: 2 intro + install using contributing packaging diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 000000000..d21ddaf44 --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,3 @@ +===================== +Quick Installation +===================== From 129f78a7f5e7d5370f153cb1ec4ee5e3ca269fd9 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 14 Jul 2016 15:11:39 -0700 Subject: [PATCH 045/126] Add resources page --- docs/index.rst | 1 + docs/resources.rst | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 docs/resources.rst diff --git a/docs/index.rst b/docs/index.rst index dab1f6201..746080864 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,6 +9,7 @@ Welcome to the Certbot documentation! using contributing packaging + resources .. toctree:: :maxdepth: 1 diff --git a/docs/resources.rst b/docs/resources.rst new file mode 100644 index 000000000..7f9fb93b6 --- /dev/null +++ b/docs/resources.rst @@ -0,0 +1,3 @@ +===================== +Resources +===================== From 6367641992e0813ffd7074c41d60fa681a420123 Mon Sep 17 00:00:00 2001 From: Noah Swartz Date: Thu, 14 Jul 2016 15:28:18 -0700 Subject: [PATCH 046/126] add other files, brads comments --- docs/ciphersuite.rst | 113 +++++++++++++++++++++++++++++++++ docs/packaging.rst | 13 ++-- docs/webhosting.rst | 144 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 262 insertions(+), 8 deletions(-) create mode 100644 docs/ciphersuite.rst create mode 100644 docs/webhosting.rst diff --git a/docs/ciphersuite.rst b/docs/ciphersuite.rst new file mode 100644 index 000000000..4141c96b8 --- /dev/null +++ b/docs/ciphersuite.rst @@ -0,0 +1,113 @@ +This page aims to track suggestions and references that people have offered or identified to improve the ciphersuites that Let's Encrypt enables when configuring TLS on servers. + +Because of the Chatham House Rule applicable to some of the discussions, people are *not* individually credited for their suggestions, but most suggestions here were made or found by other people, and I thank them for their contributions. + +Some people provided rationale information mostly having to do with compatibility of particular user-agents (especially UAs that don't support ECC, or that don't support DH groups > 1024 bits). Some ciphersuite configurations have been chosen to try to increase compatibility with older UAs while allowing newer UAs to negotiate stronger crypto. For example, some configurations forego forward secrecy entirely for connections from old UAs, like by offering ECDHE and RSA key exchange, but no DHE at all. (There are UAs that can fail the negotiation completely if a DHE ciphersuite with prime > 1024 bits is offered.) + +## References ## + +### RFC 7575 ### + +IETF has published a BCP document, RFC 7525, "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" + +https://datatracker.ietf.org/doc/rfc7525/ + +### BetterCrypto.org ### + +BetterCrypto.org, a collaboration of mostly European IT security experts, has published a draft paper, "Applied Crypto Hardening" + +https://bettercrypto.org/static/applied-crypto-hardening.pdf + +### FF-DHE Internet-Draft ### + +Gillmor's Internet-Draft "Negotiated Discrete Log Diffie-Hellman Ephemeral Parameters for TLS" is being developed at the IETF TLS WG. It advocates using *standardized* DH groups in all cases, not individually-chosen ones (mostly because of the Triple Handshake attack which can involve maliciously choosing invalid DH groups). The draft provides a list of recommended groups, with primes beginning at 2048 bits and going up from there. It also has a new protocol mechanism for agreeing to use these groups, with the possibility of backwards compatibility (and use of weaker DH groups) for older clients and servers that don't know about this mechanism. + +https://tools.ietf.org/html/draft-ietf-tls-negotiated-ff-dhe-10 + +### Mozilla ### + +Mozilla's general server configuration guidance is available at https://wiki.mozilla.org/Security/Server_Side_TLS + +Mozilla has also produced a configuration generator: https://mozilla.github.io/server-side-tls/ssl-config-generator/ + +### Dutch National Cyber Security Centre ### + +The Dutch National Cyber Security Centre has published guidance on "ICT-beveiligingsrichtlijnen voor Transport Layer Security (TLS)" ("IT Security Guidelines for Transport Layer Security (TLS)"). These are available only in Dutch at + +https://www.ncsc.nl/dienstverlening/expertise-advies/kennisdeling/whitepapers/ict-beveiligingsrichtlijnen-voor-transport-layer-security-tls.html + +I have access to an English-language summary of the recommendations. + +### Keylength.com ### + +Damien Giry collects recommendations by academic researchers and standards organizations about keylengths for particular cryptoperiods, years, or security levels. The keylength recommendations of the various sources are summarized in a chart. This site has been updated over time and includes expert guidance from eight sources published between 2000 and 2015. + +http://www.keylength.com/ + +### NIST ### + +NISA published its "NIST Special Publication 800-52 Revision 1: Guidelines for the Selection, Configuration, and Use of Transport Layer Security (TLS) Implementations" + +http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r1.pdf + +and its "NIST Special Publication 800-57: Recommendation for Key Management – Part 1: General (Revision 3)" + +http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf + +### ENISA ### + +ENISA published its "Algorithms, Key Sizes and Parameters Report - 2013" + +https://www.enisa.europa.eu/activities/identity-and-trust/library/deliverables/algorithms-key-sizes-and-parameters-report + +## WeakDH/Logjam ## + +The WeakDH/Logjam research has thrown into question the safety of some existing practice using DH ciphersuites, especially the use of standardized groups with a prime ≤ 1024 bits. The authors provided detailed guidance, including ciphersuite lists, at + +https://weakdh.org/sysadmin.html + +These lists may have been derived from Mozilla's recommendations. + +One of the authors clarified his view of the priorities for various changes as a result of the research at + +https://www.ietf.org/mail-archive/web/tls/current/msg16496.html + +In particular, he supports ECDHE and also supports the use of the standardized groups in the FF-DHE Internet-Draft mentioned above (which isn't clear from the group's original recommendations). + +## Particular sites' opinions or configurations ## + +### Amazon ELB ### + +Amazon ELB explains its current ciphersuite choices at + +https://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-security-policy-table.html + +### U.S. Government 18F ### + +The 18F site (https://18f.gsa.gov/) is using + +`ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';` + +### Duraconf ### + +The Duraconf project collects particular configuration files, with an apparent focus on avoiding the use of obsolete symmetric ciphers and hash functions, and favoring forward secrecy while not requiring it. + +https://github.com/ioerror/duraconf + +## Site scanning or rating tools ## + +### Qualys SSL Labs ### + +Qualys offers the best-known TLS security scanner, maintained by Ivan Ristić. + +https://www.ssllabs.com/ + +### Dutch NCSC ### + +The Dutch NCSC, mentioned above, has also made available its own site security scanner which indicates how well sites comply with the recommendations. + +https://en.internet.nl/ + +## Java compatibility issue ## + +A lot of backward-compatibility concerns have to do with Java hard-coding DHE primes to a 1024-bit limit, accepting DHE ciphersuites in negotiation, and then aborting the connection entirely if a prime > 1024 bits is presented. The simple summary is that servers offering a Java-compatible DHE ciphersuite in preference to other Java-compatible ciphersuites, and then presenting a DH group with a prime > 1024 bits, will be completely incompatible with clients running some versions of Java. (This may also be the case with very old MSIE versions...?) There are various strategies for dealing with this, and maybe we can document the options here. diff --git a/docs/packaging.rst b/docs/packaging.rst index 6463e777d..1a1b83f50 100644 --- a/docs/packaging.rst +++ b/docs/packaging.rst @@ -30,7 +30,7 @@ Notes for package maintainers 1. Do not package ``certbot-compatibility-test`` or ``letshelp-certbot`` - it's only used internally. -2. If you'd like to include automated renewal in your package ``certbot renew -q`` should be added to crontab. +2. If you'd like to include automated renewal in your package ``certbot renew -q`` should be added to crontab or systemd timer. 3. ``jws`` is an internal script for ``acme`` module and it doesn't have to be packaged - it's mostly for debugging: you can use it as ``echo foo | jws sign | jws verify``. @@ -43,7 +43,7 @@ Already ongoing efforts Arch ---- -From PyPI: +From our official releases: - https://www.archlinux.org/packages/community/any/python2-acme - https://www.archlinux.org/packages/community/any/certbot - https://www.archlinux.org/packages/community/any/certbot-apache @@ -55,7 +55,6 @@ From ``master``: https://aur.archlinux.org/packages/certbot-git Debian (and its derivatives, including Ubuntu) ------ -https://alioth.debian.org/projects/letsencrypt/ https://packages.debian.org/sid/certbot https://packages.debian.org/sid/python-certbot https://packages.debian.org/sid/python-certbot-apache @@ -72,16 +71,14 @@ In Fedora 23+. FreeBSD ------- -https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=203405 +https://svnweb.freebsd.org/ports/head/security/py-certbot/ GNU Guix -------- -- https://www.gnu.org/software/guix/package-list.html#letsencrypt +- https://www.gnu.org/software/guix/package-list.html#certbot OpenBSD ------- -- http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/security/letsencrypt/ -- https://github.com/letsencrypt/letsencrypt/pull/1175 -- https://github.com/letsencrypt/letsencrypt/issues/1174 +- http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/security/letsencrypt/client/ diff --git a/docs/webhosting.rst b/docs/webhosting.rst new file mode 100644 index 000000000..0aab50874 --- /dev/null +++ b/docs/webhosting.rst @@ -0,0 +1,144 @@ +# Web Hosting Providers Let's Encrypt Support Status + +_This is a community maintained list and does not guarantee implementation._ + +## Web Hosting Providers with Let's Encrypt Support + +* [34SP.com](https://www.34SP.com) ([Source](https://www.34sp.com/hosting-news/blog/lets-encrypt-free-ssl-certificates/)) +* [a2hosting.com](https://a2hosting.com) ([Source](https://www.a2hosting.com/kb/security/ssl/securing-your-site-with-a-lets-encrypt-ssl-certificate)) +* [Active24.co.uk](https://www.active24.co.uk) ([Source](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fblog.active24.cz%2F2016%2F06%2Fduveryhodne-certifikaty-lets-encrypt-zdarma-ke-kazdemu-linux-hostingu-od-active-24%2F)) +* [Active24.cz](https://www.active24.cz) ([Source](https://blog.active24.cz/2016/06/duveryhodne-certifikaty-lets-encrypt-zdarma-ke-kazdemu-linux-hostingu-od-active-24/)) +* [all-inkl.com](http://all-inkl.com) ([Source](http://kasserver.com/news.php#111), [more detailed instructions](https://www.ra-networks.at/2015/12/07/lets-encrypt-mit-all-inkl-com-nutzen/#comment-279)) (*both in German*) +* [Apis Networks](https://apisnetworks.com/)([Source](http://updates.apisnetworks.com/2016/02/lets-encrypt-is-here/)) +* [blueboard.cz](https://blueboard.cz) ([Source](https://blog.blueboard.cz/ssl-certifikaty-pro-vsechny-klienty-zdarma/)) +* [Brontobytes](https://www.brontobytes.com/) ([Source](https://www.brontobytes.com/announcements/39/Free-SSL-Certificate-for-everyone.html)) +* [Brownrice Internet](https://hosting.brownrice.com) ([Source](http://blog.brownrice.com/2016/server-stuff/letsencrypt-automated-fee-ssl/)) +* [Buyshared.net](http://buyshared.net/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/57)) +* [Certified Hosting](http://certifiedhosting.com/) ([Source](http://certifiedhosting.com/blog/tech-news/free-ssl-for-everyone/)) +* [checkdomain](https://www.checkdomain.de/) ([Source](https://www.checkdomain.de/ssl/zertifikat/ssl-free/)) +* [Cloudways](https://www.cloudways.com/) ([Source](http://www.cloudways.com/blog/lets-encrypt-free-ssl-on-cloud/)) +* [Configbox](https://www.configbox.com/) ([Source](http://www.cloudways.com/blog/lets-encrypt-free-ssl-on-cloud/)) +* [Cyon.ch](https://www.cyon.ch/) ([Source](https://www.cyon.ch/blog/Lets-Encrypt-ist-da-Kostenlose-SSL-Zertifikate-fuer-alle)) +* [Deep.ch](http://deep.ch/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/51)) +* [Digital Ocean](http://www.digitalocean.com/) ([Source](https://www.digitalocean.com/community/tutorials/how-to-set-up-let-s-encrypt-certificates-for-multiple-apache-virtual-hosts-on-ubuntu-14-04)) +* [Domain & Webspace Tremmel](https://www.domain-and-webspace.com/) ([Source](https://www.domain-and-webspace.com/en/webspace/2gb)) +* [Dreamhost.com](https://www.dreamhost.com/) ([Source](https://www.dreamhost.com/blog/2016/01/20/free-ssltls-certificates-at-dreamhost-with-lets-encrypt/)) +* [Dwe Gruppe](https://www.dwe-gruppe.eu) ([Source *in German*](https://www.dwe-gruppe.eu/news/18/news_single.html)) +* [EDIS.AT, Austria](http://www.edis.at/) ([Source](http://www.edis.at/de/hosting/letsencrypt-ssl-tls-zertifikate/)) +* [Eidolonhost.com](https://eidolonhost.com) ([Source](https://eidolonhost.com/forums/index.php/topic,2.0.html)) +* [ElbiaHosting.sk](http://www.elbiahosting.sk/) ([Source](https://www.facebook.com/elbiahosting/photos/a.591086047574269.148637.556646721018202/1221680761181458/)) +* [Espace2001.com](https://www.espace2001.com) ([Source](http://cp.espace2001.com/announcements.php?id=8)) +* [EvenNode.com](http://www.evennode.com) ([Source](http://blog.evennode.com/lets-encrypt-ssl-certificates-support/)) +* [FlockHosting](http://flockhosting.com/) ([Source](http://blog.flockhosting.com/tags/free-ssl/)) +* [fortrabbit](https://www.fortrabbit.com) ([Source](https://blog.fortrabbit.com/tls-free-launched)) +* [Funio.com](https://www.funio.com) ([Source](https://kb.funio.com/view/id/98912157/)) +* [Gandi](https://www.gandi.net) ([Source](https://www.gandi.net/news/en/2016-01-12/6677-free_tlsssl_certificates_with_lets_encrypt_and_gandi/)) +* [GeekGhost](http://geekghost.net) ([Source](http://geekghost.net/1479-2/)) +* [GoDaddy](https://www.godaddy.com/) ([Source](https://www.godaddy.com/help/install-a-lets-encrypt-ssl-apache-20245)) Limited on shared hosting +* [Host4Geeks](https://host4geeks.com) ([Source](https://host4geeks.com/lets-encrypt-free-ssl-certificates/)) +* [Hosting4Real](http://hosting4real.net/) +* [Hosting90 Systems](https://www.hosting90.cz/) ([Source](https://twitter.com/hosting90/status/711898647806533633)) +* [HostM.com](https://www.hostm.com) ([Source](https://www.hostm.com/free-ssl-certificates)) +* [hostNET.de](https://www.hostnet.de) ([Source](https://www.hostnet.de/faq/wie-kann-ich-letsencrypt-nutzen.html)) +* [Inertia Networks](https://inertianetworks.com) ([Source](https://secure.inertianetworks.com/inetsrv5/plugin/support_manager/knowledgebase/view/7/issuing-let-s-encrypt-ssl-certificates/2/)) +* [Infomaniak](https://infomaniak.com/) ([Source](https://news.infomaniak.com/en/certificats-ssl-gratuits-chez-infomaniak/)) +* [KeyCDN](https://www.keycdn.com) ([Source](https://www.keycdn.com/blog/free-ssl-certificates/)) +* [KingHost](http://www.kinghost.com.br/) ([Source in portuguese](http://www.kinghost.com.br/certificado-ssl)) +* [KLE-Hosting](https://www.kle-hosting.de) ([Source in Germany](https://www.kle-hosting.de/webhosting/)) +* [Krystal Hosting](https://krystal.co.uk/)([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/86)) +* [Level27](https://level27.be) ([Source](https://level27.be/blog/lets-encrypt)) +* [madRooster.com](http://www.madrooster.com/) ([Source](https://twitter.com/madRooster/status/721742100757393410)) +* [manitu](https://www.manitu.de) ([Source](https://www.manitu.de/webhosting/)) +* [MilesWeb](https://www.milesweb.com) ([Source](https://twitter.com/chinmaydingore/status/691988956565495808)) +* [MonsterMegs](https://www.monstermegs.com) ([Source](https://blog.monstermegs.com/free-lets-encrypt-ssl-certificates/)) +* [Mydevil.net](https://www.mydevil.net/) ([Source](https://wiki.mydevil.net/Let's_Encrypt)) +* [Mythic Beasts](https://www.mythic-beasts.com/) ([Source](http://blog.mythic-beasts.com/2016/01/29/free-ssl-certificates-for-hosting-accounts/)) +* [Neostrada.nl](https://www.neostrada.nl/) ([Source](https://www.neostrada.nl/letsencrypt-hosting.html)) (*both in Dutch*) +* [Netcup.de] (https://www.netcup.de/) ([Source](http://www.netcup-news.de/2016/02/04/lets-encrypt-internetprovider-netcup-integriert-kostenlose-ssl-zertifikate-in-webhosting-angebote-2/)) +* [NewHostServers.net](http://newhostservers.com/)([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/85)) +* [Ngage Hosting](https://www.ngagehosting.uk/) ([Source](https://clients.ngagehosting.uk/knowledgebase.php?action=displayarticle&id=1)) +* [Novatrend.ch](https://www.novatrend.ch/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-letsencrypt-org/6920/18)) +* [Ntechit.de](https://ntechit.de/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/35)) +* [Nucleus.be](https://www.nucleus.be) ([Source](https://www.nucleus.be/en/blog/free-ssl-certificates-for-all-customers/)) +* [Online.net](https://www.online.net/) ([Source](https://community.letsencrypt.org/t/shared-hosting/384/11)) +* [Openminds.be](https://www.openminds.be/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-letsencrypt-org/6920/22)) +* [OVH.com](https://www.ovh.com) ([Source](https://www.ovh.com/fr/hebergement-web/ssl_mutualise.xml)) +* [Planethoster.net](https://www.planethoster.net/) ([Source](https://forums.planethoster.net/threads/exclusive-free-ssl-to-all-our-customers.4731/#post-17876)) +* [Pressjitsu.com](https://pressjitsu.com/) ([Source](https://pressjitsu.com/blog/ssl-wordpress-letsencrypt/)) +* [Progreso.pl](https://progreso.pl/) ([Source](https://progreso.pl/o_nas/newsroom/#news_78)) +* [PulseHeberg.com](http://pulseheberg.com/) ([Source](https://community.letsencrypt.org/t/shared-hosting/384/16)) +* [ResellerChoice](https://www.resellerchoice.com) +* [Schokokeks.org](https://schokokeks.org/) ([Source](https://schokokeks.org/blog/https-f-r-alle-mit-lets-encrypt)) +* [Sensson](https://www.sensson.net) ([Source](https://www.sensson.net/2016/02/21/webhosting-met-ssl-certificaten-van-letsencrypt/)) +* [ServerPilot](https://serverpilot.io/) ([Source](https://serverpilot.io/blog/2016/03/09/free-ssl-certificates-from-lets-encrypt.html)) +* [Serversaurus](https://www.serversaurus.com.au/) ([Source](https://blog.serversaurus.com.au/free-ssl-with-lets-encrypt/)) +* [SiteGround.com](https://www.siteground.com/) ([Source](https://www.siteground.com/blog/lets-encrypt/)) +* [Squidix](https://squidix.com/) ([Source](https://squidix.com/blog/squidix-is-now-support-lets-encrypt-on-all-sharedresellersemi-plans/)) +* [Strony-Domeny.pl](https://strony-domeny.pl/) ([Source](https://strony-domeny.pl/blogtech/9/Lets-encrypt-darmowy-certyfikat-SSL.html)) +* [TD Web Services](https://tdwebservices.com/) +* [Thisistap](https://thisistap.com/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/52)) +* [Tiger Technologies](https://www.tigertech.net/) ([Source](https://blog.tigertech.net/posts/lets-encrypt/)) +* [Top Host](https://www.tophost.gr/) ([Source](https://support.tophost.gr/kb/article.php?id=1410)) -- Greek +* [TrafficPlanet Hosting](https://trafficplanethosting.com/) ([Source](https://trafficplanethosting.com/page/free-ssl-certificates/)) +* [Uberspace.de](https://uberspace.de/) ([Source](https://blog.uberspace.de/lets-encrypt-rollt-an/)) +* [UnoEuro](https://en.unoeuro.com/) ([Source](https://blog.unoeuro.com/2016/04/ny-feature-lets-encrypt-certifikater/) *– in Danish*) +* [UnoEuro](https://www.unoeuro.com) ([Source *in Danish*](https://blog.unoeuro.com/2016/ny-feature-lets-encrypt-certifikater/)) +* [VentraIP Australia](https://ventraip.com.au/) ([Source](https://ventraip.com.au/blog/announcements/lets-encrypt-free-ssl-certificates-now-available/)) +* [Webfaction](https://webfaction.com/) ([some support](https://community.webfaction.com/questions/19722/is-the-letsencrypt-certificate-service-supported/19723) including [a third-party open-source utility to automate the process](https://github.com/will-in-wi/letsencrypt-webfaction), and [wider support depends on formal release of Let's Encrypt](https://community.webfaction.com/questions/18989/using-lets-encrypt-to-get-ssl-certificates/18990) +* [webgo](https://www.webgo.de/) ([Source](https://www.webgo.de/blog/webgo-webhosting-jetzt-kostenlos-ssl-verschluesselung-nutzen-mit-lets-encrypt/)) +* [WebhostOne](https://www.webhostone.de/) ([Source](https://www.webhostone.de/lets-encrypt.html)) +* [Websupport.sk](https://websupport.sk/) ([Source *in Slovak*](https://www.websupport.sk/blog/2016/02/lets-encrypt-ssl-certifikat-zadarmo-pre-kazdeho/)) +* [Wetopi](https://wetopi.com/) ([Source](https://wetopi.com/wordpress-ssl)) +* [WordPress.com](https://wordpress.com/) ([Source](https://en.blog.wordpress.com/2016/04/08/https-everywhere-encryption-for-all-wordpress-com-sites/)) +* [World4You Internet Services GmbH](https://www.world4you.com/) ([Source *in German*] (https://www.world4you.at/de/webhosting/ssl.html/)) +* [wp-webhosting.de](https://www.wp-webhosting.de/) ([Source *in German*](https://www.internetwerk.de/blog/webhosting/2015/12/04/kostenlose-ssl-zertifikate-fuer-alle/)) +* [XiNiX](http://www.xinix.co/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/66)) +* [Zuver](https://zuver.net.au/) ([Source](https://forums.whirlpool.net.au/archive/2467065#r50573142)) + +*** + +## Planned: +* [Kinsta](https://kinsta.com/) +* [Pagely](https://pagely.com/) +* [pair Networks](https://www.pair.com/) Ability to automate certificate installation is in long-term plans. (via support email) +* [RAIDBOXES.de](https://raidboxes.de/) / [RAIDBOXES.eu](https://raidboxes.eu/) + +*** + +## Waiting/Delayed + +* [Hostgator] (https://www.hostgator.com/) Implementation of Let's Encrypt has been relayed internally for further consideration. ([Source](https://twitter.com/hgsupport/status/694292490485133313)) +* [Strato.de] (https://www.strato.de/) Waiting for Let's Encrypt beta to end to evaluate possible adoption for all customers. ([Source *in German*](https://blog.strato.de/verschluesselte-website-bald-standard/)) +* [Tsohost] (https://www.tsohost.com/) Not supported, but the team are looking into it. ([Source](https://twitter.com/tsohost/status/722448514228318208)) + +*** + +## Unconfirmed: + +* [spolehlive-servery.cz](https://www.spolehlive-servery.cz) & [cesky-hosting.cz](https://www.cesky-hosting.cz) (information via support ticket; planned to ~ autumn 2016) + +## Dedicated Hosting: + +* All Dedicated hosting supports installation. This is not a link directory page. + +## No Planned Support: + +* 1and1.com ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/77)) +* 247-host.com (maybe anytime in the future, via support chat) +* Amazili-communication (Not a hosting company) +* df.eu (DomainFactory - no plans to support LE, [Source *in German*](https://www.df.eu/forum/threads/76119-Unterst%C3%BCtzung-von-Let-s-encrypt-Langfristiges-SSL-Konzept-von-Domainfactory/page3?p=499684#post499684)) +* Greengeeks.com (tech support said 'no plans and you can buy our SSL') +* HostEurope.de (via email reply from customer support; LE can be installed manually) +* Hostinger.com (no plans to support LE) +* HostMonster.com ('no plans', via live chat) +* Hostpapa.ca (tech support said 'no plans') +* Hostripples.com (no plans, via live chat) +* Inmotionhosting.com ([Source](https://twitter.com/inmotionhosting/status/678085107891240960)) +* Linode (doesn't offer shared hosting) +* Namecheap.com ([Source](https://gist.github.com/stopspazzing/c871f935771f14933c63)) +* Netsons.com (no plans to support LE) +* Site5.com (no plans to support at all, except unmanaged vps - via support chat) + +## Remarks + +Moved from [forums](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/). From 7b029afb10192954805ea2c7104131e6a0152e5a Mon Sep 17 00:00:00 2001 From: Jason Grinblat Date: Thu, 14 Jul 2016 16:11:01 -0700 Subject: [PATCH 047/126] Adds new introduction and refactors the old introduction --- docs/current_features.rst | 25 +++++ docs/install.rst | 28 ++++++ docs/intro.rst | 3 + docs/intro_common.rst | 192 +------------------------------------- docs/resources.rst | 47 ++++++++++ docs/using.rst | 24 ++++- 6 files changed, 130 insertions(+), 189 deletions(-) create mode 100644 docs/current_features.rst diff --git a/docs/current_features.rst b/docs/current_features.rst new file mode 100644 index 000000000..5bb037756 --- /dev/null +++ b/docs/current_features.rst @@ -0,0 +1,25 @@ +===================== +Current Features +===================== + +* Supports multiple web servers: + + - apache/2.x (working on Debian 8+ and Ubuntu 12.04+) + - standalone (runs its own simple webserver to prove you control a domain) + - webroot (adds files to webroot directories in order to prove control of + domains and obtain certs) + - nginx/0.8.48+ (highly experimental, not included in certbot-auto) + +* The private key is generated locally on your system. +* Can talk to the Let's Encrypt CA or optionally to other ACME + compliant services. +* Can get domain-validated (DV) certificates. +* Can revoke certificates. +* Adjustable RSA key bit-length (2048 (default), 4096, ...). +* Can optionally install a http -> https redirect, so your site effectively + runs https only (Apache only) +* Fully automated. +* Configuration changes are logged and can be reverted. +* Supports ncurses and text (-t) UI, or can be driven entirely from the + command line. +* Free and Open Source Software, made with Python. \ No newline at end of file diff --git a/docs/install.rst b/docs/install.rst index d21ddaf44..1bccdad0c 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -1,3 +1,31 @@ ===================== Quick Installation ===================== + +If ``certbot`` (or ``letsencrypt``) is packaged for your Unix OS (visit +certbot.eff.org_ to find out), you can install it +from there, and run it by typing ``certbot`` (or ``letsencrypt``). Because +not all operating systems have packages yet, we provide a temporary solution +via the ``certbot-auto`` wrapper script, which obtains some dependencies from +your OS and puts others in a python virtual environment:: + + user@webserver:~$ wget https://dl.eff.org/certbot-auto + user@webserver:~$ chmod a+x ./certbot-auto + user@webserver:~$ ./certbot-auto --help + +.. hint:: The certbot-auto download is protected by HTTPS, which is pretty good, but if you'd like to + double check the integrity of the ``certbot-auto`` script, you can use these steps for verification before running it:: + + user@server:~$ wget -N https://dl.eff.org/certbot-auto.asc + user@server:~$ gpg2 --recv-key A2CFB51FA275A7286234E7B24D17C995CD9775F2 + user@server:~$ gpg2 --trusted-key 4D17C995CD9775F2 --verify certbot-auto.asc certbot-auto + +And for full command line help, you can type:: + + ./certbot-auto --help all + +``certbot-auto`` updates to the latest client release automatically. And +since ``certbot-auto`` is a wrapper to ``certbot``, it accepts exactly +the same command line flags and arguments. More details about this script and +other installation methods can be found `in the User Guide +`_. \ No newline at end of file diff --git a/docs/intro.rst b/docs/intro.rst index b841aece9..5122487bf 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -3,4 +3,7 @@ Introduction ===================== .. include:: intro_common.rst +.. include:: current_features.rst .. include:: ../CHANGES.rst + +For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. \ No newline at end of file diff --git a/docs/intro_common.rst b/docs/intro_common.rst index 30da17fa1..4ca286f07 100644 --- a/docs/intro_common.rst +++ b/docs/intro_common.rst @@ -1,192 +1,8 @@ -Disclaimer -========== -Certbot (previously, the Let's Encrypt client) is **BETA SOFTWARE**. It -contains plenty of bugs and rough edges, and should be tested thoroughly in -staging environments before use on production systems. +Certbot is part of EFF’s effort to encrypt the entire Internet. Secure communication over the Web relies on HTTPS, which requires the use of a digital certificate that lets browsers verify the identify of web servers (e.g., is that really google.com?). Web servers obtain their certificates from trusted third parties called certificate authorities (CAs). Certbot is an easy-to-use client that fetches a certificate from Let’s Encrypt—an open certificate authority launched by the EFF, Mozilla, and others—and deploys it to a web server. -For more information regarding the status of the project, please see -https://letsencrypt.org. Be sure to checkout the -`Frequently Asked Questions (FAQ) `_. +Anyone who has gone through the trouble of setting up a secure website knows what a hassle getting and maintaining a certificate is. Certbot and Let’s Encrypt can automate away the pain and let you turn on and manage HTTPS with simple commands. Using Certbot and Let's Encrypt is free, so there’s no need to arrange payment. -About Certbot -============================== +How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide`_. It generates instructions based on your configuration settings. You’ll need root or administrator access to your web server to run Certbot. -Certbot is a fully-featured, extensible client for the Let's -Encrypt CA (or any other CA that speaks the `ACME -`_ -protocol) that can automate the tasks of obtaining certificates and -configuring webservers to use them. This client runs on Unix-based operating -systems. - -Until May 2016, Certbot was named simply ``letsencrypt`` or ``letsencrypt-auto``, -depending on install method. Instructions on the Internet, and some pieces of the -software, may still refer to this older name. - -Contributing ------------- - -If you'd like to contribute to this project please read `Developer Guide -`_. - -.. _installation: - -Installation ------------- - -If ``certbot`` (or ``letsencrypt``) is packaged for your Unix OS (visit -certbot.eff.org_ to find out), you can install it -from there, and run it by typing ``certbot`` (or ``letsencrypt``). Because -not all operating systems have packages yet, we provide a temporary solution -via the ``certbot-auto`` wrapper script, which obtains some dependencies from -your OS and puts others in a python virtual environment:: - - user@webserver:~$ wget https://dl.eff.org/certbot-auto - user@webserver:~$ chmod a+x ./certbot-auto - user@webserver:~$ ./certbot-auto --help - -.. hint:: The certbot-auto download is protected by HTTPS, which is pretty good, but if you'd like to - double check the integrity of the ``certbot-auto`` script, you can use these steps for verification before running it:: - - user@server:~$ wget -N https://dl.eff.org/certbot-auto.asc - user@server:~$ gpg2 --recv-key A2CFB51FA275A7286234E7B24D17C995CD9775F2 - user@server:~$ gpg2 --trusted-key 4D17C995CD9775F2 --verify certbot-auto.asc certbot-auto - -And for full command line help, you can type:: - - ./certbot-auto --help all - -``certbot-auto`` updates to the latest client release automatically. And -since ``certbot-auto`` is a wrapper to ``certbot``, it accepts exactly -the same command line flags and arguments. More details about this script and -other installation methods can be found `in the User Guide -`_. - -How to run the client ---------------------- - -In many cases, you can just run ``certbot-auto`` or ``certbot``, and the -client will guide you through the process of obtaining and installing certs -interactively. - -You can also tell it exactly what you want it to do from the command line. -For instance, if you want to obtain a cert for ``example.com``, -``www.example.com``, and ``other.example.net``, using the Apache plugin to both -obtain and install the certs, you could do this:: - - ./certbot-auto --apache -d example.com -d www.example.com -d other.example.net - -(The first time you run the command, it will make an account, and ask for an -email and agreement to the Let's Encrypt Subscriber Agreement; you can -automate those with ``--email`` and ``--agree-tos``) - -If you want to use a webserver that doesn't have full plugin support yet, you -can still use "standalone" or "webroot" plugins to obtain a certificate:: - - ./certbot-auto certonly --standalone --email admin@example.com -d example.com -d www.example.com -d other.example.net - - -Understanding the client in more depth --------------------------------------- - -To understand what the client is doing in detail, it's important to -understand the way it uses plugins. Please see the `explanation of -plugins `_ in -the User Guide. - -Links -===== - -Documentation: https://certbot.eff.org/docs - -Software project: https://github.com/certbot/certbot - -Notes for developers: https://certbot.eff.org/docs/contributing.html - -Main Website: https://letsencrypt.org/ - -IRC Channel: #letsencrypt on `Freenode`_ or #certbot on `OFTC`_ - -Community: https://community.letsencrypt.org - -ACME spec: http://ietf-wg-acme.github.io/acme/ - -ACME working area in github: https://github.com/ietf-wg-acme/acme - - -Mailing list: `client-dev`_ (to subscribe without a Google account, send an -email to client-dev+subscribe@letsencrypt.org) - -|build-status| |coverage| |docs| |container| - - - -.. |build-status| image:: https://travis-ci.org/certbot/certbot.svg?branch=master - :target: https://travis-ci.org/certbot/certbot - :alt: Travis CI status - -.. |coverage| image:: https://coveralls.io/repos/certbot/certbot/badge.svg?branch=master - :target: https://coveralls.io/r/certbot/certbot - :alt: Coverage status - -.. |docs| image:: https://readthedocs.org/projects/letsencrypt/badge/ - :target: https://readthedocs.org/projects/letsencrypt/ - :alt: Documentation status - -.. |container| image:: https://quay.io/repository/letsencrypt/letsencrypt/status - :target: https://quay.io/repository/letsencrypt/letsencrypt - :alt: Docker Repository on Quay.io - -.. _`installation instructions`: - https://letsencrypt.readthedocs.org/en/latest/using.html - -.. _watch demo video: https://www.youtube.com/watch?v=Gas_sSB-5SU - -System Requirements -=================== - -The Let's Encrypt Client presently only runs on Unix-ish OSes that include -Python 2.6 or 2.7; Python 3.x support will hopefully be added in the future. The -client requires root access in order to write to ``/etc/letsencrypt``, -``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443 -(if you use the ``standalone`` plugin) and to read and modify webserver -configurations (if you use the ``apache`` or ``nginx`` plugins). If none of -these apply to you, it is theoretically possible to run without root privileges, -but for most users who want to avoid running an ACME client as root, either -`letsencrypt-nosudo `_ or -`simp_le `_ are more appropriate choices. - -The Apache plugin currently requires a Debian-based OS with augeas version -1.0; this includes Ubuntu 12.04+ and Debian 7+. - - -Current Features -================ - -* Supports multiple web servers: - - - apache/2.x (working on Debian 8+ and Ubuntu 12.04+) - - standalone (runs its own simple webserver to prove you control a domain) - - webroot (adds files to webroot directories in order to prove control of - domains and obtain certs) - - nginx/0.8.48+ (highly experimental, not included in certbot-auto) - -* The private key is generated locally on your system. -* Can talk to the Let's Encrypt CA or optionally to other ACME - compliant services. -* Can get domain-validated (DV) certificates. -* Can revoke certificates. -* Adjustable RSA key bit-length (2048 (default), 4096, ...). -* Can optionally install a http -> https redirect, so your site effectively - runs https only (Apache only) -* Fully automated. -* Configuration changes are logged and can be reverted. -* Supports ncurses and text (-t) UI, or can be driven entirely from the - command line. -* Free and Open Source Software, made with Python. - - -.. _Freenode: https://webchat.freenode.net?channels=%23letsencrypt -.. _OFTC: https://webchat.oftc.net?channels=%23certbot -.. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev -.. _certbot.eff.org: https://certbot.eff.org/ +If you’re using a hosted service and don’t have direct access to your web server, you might not be able to use Certbot. Check with your hosting provider for documentation about uploading certificates or using certificates issues by Let’s Encrypt. \ No newline at end of file diff --git a/docs/resources.rst b/docs/resources.rst index 7f9fb93b6..94b5a9d58 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -1,3 +1,50 @@ ===================== Resources ===================== + +Documentation: https://certbot.eff.org/docs + +Software project: https://github.com/certbot/certbot + +Notes for developers: https://certbot.eff.org/docs/contributing.html + +Main Website: https://letsencrypt.org/ + +Let's Encrypt FAQ: https://community.letsencrypt.org/t/frequently-asked-questions-faq/26#topic-title + +IRC Channel: #letsencrypt on `Freenode`_ or #certbot on `OFTC`_ + +Community: https://community.letsencrypt.org + +ACME spec: http://ietf-wg-acme.github.io/acme/ + +ACME working area in github: https://github.com/ietf-wg-acme/acme + + +Mailing list: `client-dev`_ (to subscribe without a Google account, send an +email to client-dev+subscribe@letsencrypt.org) + +|build-status| |coverage| |docs| |container| + + + +.. |build-status| image:: https://travis-ci.org/certbot/certbot.svg?branch=master + :target: https://travis-ci.org/certbot/certbot + :alt: Travis CI status + +.. |coverage| image:: https://coveralls.io/repos/certbot/certbot/badge.svg?branch=master + :target: https://coveralls.io/r/certbot/certbot + :alt: Coverage status + +.. |docs| image:: https://readthedocs.org/projects/letsencrypt/badge/ + :target: https://readthedocs.org/projects/letsencrypt/ + :alt: Documentation status + +.. |container| image:: https://quay.io/repository/letsencrypt/letsencrypt/status + :target: https://quay.io/repository/letsencrypt/letsencrypt + :alt: Docker Repository on Quay.io + +.. _`installation instructions`: + https://letsencrypt.readthedocs.org/en/latest/using.html + +.. _watch demo video: https://www.youtube.com/watch?v=Gas_sSB-5SU diff --git a/docs/using.rst b/docs/using.rst index 806dfb340..6620c2575 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -5,12 +5,31 @@ User Guide .. contents:: Table of Contents :local: + +System Requirements +=================== + +The Let's Encrypt Client presently only runs on Unix-ish OSes that include +Python 2.6 or 2.7; Python 3.x support will hopefully be added in the future. The +client requires root access in order to write to ``/etc/letsencrypt``, +``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443 +(if you use the ``standalone`` plugin) and to read and modify webserver +configurations (if you use the ``apache`` or ``nginx`` plugins). If none of +these apply to you, it is theoretically possible to run without root privileges, +but for most users who want to avoid running an ACME client as root, either +`letsencrypt-nosudo `_ or +`simp_le `_ are more appropriate choices. + +The Apache plugin currently requires a Debian-based OS with augeas version +1.0; this includes Ubuntu 12.04+ and Debian 7+. + + Getting Certbot =============== To get specific instructions for installing Certbot on your OS, we recommend visiting certbot.eff.org_. If you're offline, you can find some general -instructions `in the README / Introduction `__ +instructions `Quick Installation `__ __ installation_ .. _certbot.eff.org: https://certbot.eff.org @@ -552,3 +571,6 @@ Beyond the methods discussed here, other methods may be possible, such as installing Certbot directly with pip from PyPI or downloading a ZIP archive from GitHub may be technically possible but are not presently recommended or supported. + +.. include:: current_features.rst +.. include:: ../CHANGES.rst From fd308f8ce1d51ab30af42f8b40914a28cf3a2480 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 15 Jul 2016 09:34:12 -0700 Subject: [PATCH 048/126] Make current features a subsection --- docs/current_features.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/current_features.rst b/docs/current_features.rst index 5bb037756..16c26af01 100644 --- a/docs/current_features.rst +++ b/docs/current_features.rst @@ -1,4 +1,3 @@ -===================== Current Features ===================== @@ -22,4 +21,4 @@ Current Features * Configuration changes are logged and can be reverted. * Supports ncurses and text (-t) UI, or can be driven entirely from the command line. -* Free and Open Source Software, made with Python. \ No newline at end of file +* Free and Open Source Software, made with Python. From 8be5849a9e9f7497e19fd71e5a42861434fca7b2 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 15 Jul 2016 09:35:42 -0700 Subject: [PATCH 049/126] Flip README and intro --- README.rst | 4 ++++ docs/intro.rst | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 06cb3f8bc..e7bac2fde 100644 --- a/README.rst +++ b/README.rst @@ -1 +1,5 @@ .. include:: docs/intro_common.rst +.. include:: docs/current_features.rst +.. include:: CHANGES.rst + +For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. diff --git a/docs/intro.rst b/docs/intro.rst index 5122487bf..65c862f69 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -3,7 +3,3 @@ Introduction ===================== .. include:: intro_common.rst -.. include:: current_features.rst -.. include:: ../CHANGES.rst - -For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. \ No newline at end of file From 37c8abf1e5a8045f869de06b9e851b76dbe919a4 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 15 Jul 2016 09:36:44 -0700 Subject: [PATCH 050/126] Fix interactive guide link --- docs/intro_common.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/intro_common.rst b/docs/intro_common.rst index 4ca286f07..630e07b51 100644 --- a/docs/intro_common.rst +++ b/docs/intro_common.rst @@ -3,6 +3,6 @@ Certbot is part of EFF’s effort to encrypt the entire Internet. Secure communi Anyone who has gone through the trouble of setting up a secure website knows what a hassle getting and maintaining a certificate is. Certbot and Let’s Encrypt can automate away the pain and let you turn on and manage HTTPS with simple commands. Using Certbot and Let's Encrypt is free, so there’s no need to arrange payment. -How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide`_. It generates instructions based on your configuration settings. You’ll need root or administrator access to your web server to run Certbot. +How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide `_. It generates instructions based on your configuration settings. You’ll need root or administrator access to your web server to run Certbot. -If you’re using a hosted service and don’t have direct access to your web server, you might not be able to use Certbot. Check with your hosting provider for documentation about uploading certificates or using certificates issues by Let’s Encrypt. \ No newline at end of file +If you’re using a hosted service and don’t have direct access to your web server, you might not be able to use Certbot. Check with your hosting provider for documentation about uploading certificates or using certificates issues by Let’s Encrypt. From de3010d99b4e6358024cf5bdd63282cfd25f4db8 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Fri, 15 Jul 2016 23:19:00 +0300 Subject: [PATCH 051/126] Tests for non-psutil socket bind check --- certbot/plugins/util_test.py | 61 ++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/certbot/plugins/util_test.py b/certbot/plugins/util_test.py index fa8b364d9..ffabadab7 100644 --- a/certbot/plugins/util_test.py +++ b/certbot/plugins/util_test.py @@ -1,9 +1,21 @@ """Tests for certbot.plugins.util.""" import os import unittest +import sys import mock -import psutil + +try: + # Python 3.5+ + from importlib import reload +except ImportError: + try: + # Python 2-3.4 + from imp import reload + except ImportError: + # The rest + pass + class PathSurgeryTest(unittest.TestCase): """Tests for certbot.plugins.path_surgery.""" @@ -29,7 +41,50 @@ class PathSurgeryTest(unittest.TestCase): self.assertTrue("/usr/local/bin" in os.environ["PATH"]) self.assertTrue("/tmp" in os.environ["PATH"]) -class AlreadyListeningTest(unittest.TestCase): + +class AlreadyListeningTestNoPsutil(unittest.TestCase): + """Tests for certbot.plugins.already_listening when + psutil is not available""" + def setUp(self): + import certbot.plugins.util + # Ensure we get importerror + if "psutil" in sys.modules: + self.psutil = sys.modules['psutil'] + else: + self.psutil = None + sys.modules['psutil'] = None + # Reload hackery to ensure getting non-psutil version + # loaded to memory + reload(certbot.plugins.util) + + def tearDown(self): + # Need to reload the module to ensure + # getting back to normal + import certbot.plugins.util + sys.modules["psutil"] = self.psutil + reload(certbot.plugins.util) + + @mock.patch("certbot.plugins.util.zope.component.getUtility") + def test_ports_available(self, mock_getutil): + import certbot.plugins.util as plugins_util + # Ensure we don't get error + with mock.patch("socket._socketobject.bind"): + self.assertFalse(plugins_util.already_listening(80)) + self.assertFalse(plugins_util.already_listening(80, True)) + + @mock.patch("certbot.plugins.util.zope.component.getUtility") + def test_ports_blocked(self, mock_getutil): + sys.modules["psutil"] = None + import certbot.plugins.util as plugins_util + import socket + with mock.patch("socket._socketobject.bind", side_effect=socket.error): + self.assertTrue(plugins_util.already_listening(80)) + self.assertTrue(plugins_util.already_listening(80, True)) + with mock.patch("socket.socket", side_effect=socket.error): + self.assertFalse(plugins_util.already_listening(80)) + + +class AlreadyListeningTestPsutil(unittest.TestCase): """Tests for certbot.plugins.already_listening.""" def _call(self, *args, **kwargs): from certbot.plugins.util import already_listening @@ -42,6 +97,7 @@ class AlreadyListeningTest(unittest.TestCase): # This tests a race condition, or permission problem, or OS # incompatibility in which, for some reason, no process name can be # found to match the identified listening PID. + import psutil from psutil._common import sconn conns = [ sconn(fd=-1, family=2, type=1, laddr=("0.0.0.0", 30), @@ -124,6 +180,7 @@ class AlreadyListeningTest(unittest.TestCase): @mock.patch("certbot.plugins.util.psutil.net_connections") def test_access_denied_exception(self, mock_net): + import psutil mock_net.side_effect = psutil.AccessDenied("") self.assertFalse(self._call(12345)) From e39b3214b4b1994a63117aae7a0004fd610c787d Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Fri, 15 Jul 2016 23:42:27 +0300 Subject: [PATCH 052/126] Test fixes --- certbot/plugins/util_test.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/certbot/plugins/util_test.py b/certbot/plugins/util_test.py index ffabadab7..31b1496de 100644 --- a/certbot/plugins/util_test.py +++ b/certbot/plugins/util_test.py @@ -7,14 +7,14 @@ import mock try: # Python 3.5+ - from importlib import reload + from importlib import reload as refresh # pylint: disable=no-name-in-module except ImportError: try: # Python 2-3.4 - from imp import reload + from imp import reload as refresh except ImportError: # The rest - pass + from __builtin__ import reload as refresh class PathSurgeryTest(unittest.TestCase): @@ -55,14 +55,14 @@ class AlreadyListeningTestNoPsutil(unittest.TestCase): sys.modules['psutil'] = None # Reload hackery to ensure getting non-psutil version # loaded to memory - reload(certbot.plugins.util) + refresh(certbot.plugins.util) def tearDown(self): # Need to reload the module to ensure # getting back to normal import certbot.plugins.util sys.modules["psutil"] = self.psutil - reload(certbot.plugins.util) + refresh(certbot.plugins.util) @mock.patch("certbot.plugins.util.zope.component.getUtility") def test_ports_available(self, mock_getutil): @@ -71,6 +71,7 @@ class AlreadyListeningTestNoPsutil(unittest.TestCase): with mock.patch("socket._socketobject.bind"): self.assertFalse(plugins_util.already_listening(80)) self.assertFalse(plugins_util.already_listening(80, True)) + self.assertEqual(mock_getutil.call_count, 0) @mock.patch("certbot.plugins.util.zope.component.getUtility") def test_ports_blocked(self, mock_getutil): @@ -82,6 +83,7 @@ class AlreadyListeningTestNoPsutil(unittest.TestCase): self.assertTrue(plugins_util.already_listening(80, True)) with mock.patch("socket.socket", side_effect=socket.error): self.assertFalse(plugins_util.already_listening(80)) + self.assertEqual(mock_getutil.call_count, 2) class AlreadyListeningTestPsutil(unittest.TestCase): From 7183896ed76ac5b44d895303c8a7f6c08726b5f7 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 13 Jul 2016 17:24:05 -0700 Subject: [PATCH 053/126] Preserve spaces before comments at the beginning of a file --- .../chive/chive-nginx-master/win-utf | 1 - certbot-nginx/certbot_nginx/nginxparser.py | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/certbot-compatibility-test/nginx/nginx-roundtrip-testdata/chive/chive-nginx-master/win-utf b/certbot-compatibility-test/nginx/nginx-roundtrip-testdata/chive/chive-nginx-master/win-utf index e4b1e8360..ed8bc007a 100644 --- a/certbot-compatibility-test/nginx/nginx-roundtrip-testdata/chive/chive-nginx-master/win-utf +++ b/certbot-compatibility-test/nginx/nginx-roundtrip-testdata/chive/chive-nginx-master/win-utf @@ -2,7 +2,6 @@ # This map is not a full windows-1251 <> utf8 map: it does not # contain Serbian and Macedonian letters. If you need a full map, # use contrib/unicode2nginx/win-utf map instead. -# charset_map windows-1251 utf-8 { diff --git a/certbot-nginx/certbot_nginx/nginxparser.py b/certbot-nginx/certbot_nginx/nginxparser.py index 10a26ecb2..d02687d2f 100644 --- a/certbot-nginx/certbot_nginx/nginxparser.py +++ b/certbot-nginx/certbot_nginx/nginxparser.py @@ -73,16 +73,11 @@ class RawNginxParser(object): block << Group(block_begin + left_bracket + block_innards + right_bracket) script = OneOrMore(Group(comment | assignment) ^ block ^ map_block) + space + stringEnd - script.parseWithTabs() - testLine = OneOrMore(Group(space + key + location_statement)).leaveWhitespace() - testTwo = OneOrMore(block) + script.parseWithTabs().leaveWhitespace() def __init__(self, source): self.source = source - def test(self): - return self.testLine.parseString(self.source) - def parse(self): """Returns the parsed tree.""" return self.script.parseString(self.source) From b6966fc05e568bcc1381524bcfff676ab8e89bf2 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 13 Jul 2016 18:47:05 -0700 Subject: [PATCH 054/126] lint --- certbot-nginx/certbot_nginx/nginxparser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot-nginx/certbot_nginx/nginxparser.py b/certbot-nginx/certbot_nginx/nginxparser.py index d02687d2f..372ecef6a 100644 --- a/certbot-nginx/certbot_nginx/nginxparser.py +++ b/certbot-nginx/certbot_nginx/nginxparser.py @@ -63,11 +63,11 @@ class RawNginxParser(object): # key could for instance be "server" or "http", or "location" (in which case # location_statement needs to have a non-empty location) - block_begin = (Group(space + key + location_statement) ^ + block_begin = (Group(space + key + location_statement) ^ Group(if_statement) ^ Group(charset_map_statement)).leaveWhitespace() - block_innards = Group(ZeroOrMore(Group(comment | assignment) | block | map_block) + block_innards = Group(ZeroOrMore(Group(comment | assignment) | block | map_block) + space).leaveWhitespace() block << Group(block_begin + left_bracket + block_innards + right_bracket) From e3ab49a93bfda1c7dbe7c46567671e63411eeeba Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Fri, 15 Jul 2016 16:57:10 -0700 Subject: [PATCH 055/126] Rework "value" parser: - Now handles any${VAR_SUBSTITUTION}inthemiddle/of/values - Don't use a single giant janky Regex; use small ones and have PyParsing combine them --- certbot-nginx/certbot_nginx/nginxparser.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/certbot-nginx/certbot_nginx/nginxparser.py b/certbot-nginx/certbot_nginx/nginxparser.py index 372ecef6a..c7a9f0c75 100644 --- a/certbot-nginx/certbot_nginx/nginxparser.py +++ b/certbot-nginx/certbot_nginx/nginxparser.py @@ -25,11 +25,19 @@ class RawNginxParser(object): key = Word(alphanums + "_/+-.") dollar_var = Combine(Literal('$') + Regex(r"[^\{\};,\s]+")) condition = Regex(r"\(.+\)") - # Matches anything that is not a special character AND any chars in single - # or double quotes + # Matches anything that is not a special character, and ${SHELL_VARS}, AND + # any chars in single or double quotes # All of these COULD be upgraded to something like # https://stackoverflow.com/a/16130746 - value = Regex(r"((\".*\")?(\'.*\')?[^\{\};,]?)+") + dquoted = Regex(r'(\".*\")') + squoted = Regex(r"(\'.*\')") + nonspecial = Regex(r"[^\{\};,]") + varsub = Regex(r"(\$\{\w+\})") + # nonspecial nibbles one character at a time, but the other objects take + # precedence. We use ZeroOrMore to allow entries like "break ;" to be + # parsed as assignments + value = Combine(ZeroOrMore(dquoted | squoted | varsub | nonspecial)) + location = CharsNotIn("{};," + string.whitespace) # modifier for location uri [ = | ~ | ~* | ^~ ] modifier = Literal("=") | Literal("~*") | Literal("~") | Literal("^~") From 3b4fb2401d7c95e937de5ac1fe38fa4f1f6dd867 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Sat, 16 Jul 2016 10:02:13 +0300 Subject: [PATCH 056/126] Coverage fixes, and unused fallback removal --- certbot/plugins/util_test.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/certbot/plugins/util_test.py b/certbot/plugins/util_test.py index 31b1496de..663dac4d3 100644 --- a/certbot/plugins/util_test.py +++ b/certbot/plugins/util_test.py @@ -9,12 +9,8 @@ try: # Python 3.5+ from importlib import reload as refresh # pylint: disable=no-name-in-module except ImportError: - try: - # Python 2-3.4 - from imp import reload as refresh - except ImportError: - # The rest - from __builtin__ import reload as refresh + # Python 2-3.4 + from imp import reload as refresh class PathSurgeryTest(unittest.TestCase): @@ -48,10 +44,9 @@ class AlreadyListeningTestNoPsutil(unittest.TestCase): def setUp(self): import certbot.plugins.util # Ensure we get importerror + self.psutil = None if "psutil" in sys.modules: self.psutil = sys.modules['psutil'] - else: - self.psutil = None sys.modules['psutil'] = None # Reload hackery to ensure getting non-psutil version # loaded to memory @@ -152,7 +147,7 @@ class AlreadyListeningTestPsutil(unittest.TestCase): raddr=(), status="LISTEN", pid=4416)] mock_net.return_value = conns mock_process.name.return_value = "inetd" - result = self._call(17) + result = self._call(17, True) self.assertTrue(result) self.assertEqual(mock_get_utility.call_count, 1) mock_process.assert_called_once_with(4416) From 9fb235850731a6c7a6eadd2650108b3564da9d22 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 20 Jul 2016 14:59:42 -0700 Subject: [PATCH 057/126] Move text back into README --- README.rst | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index e7bac2fde..9be732c3b 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,42 @@ -.. include:: docs/intro_common.rst -.. include:: docs/current_features.rst -.. include:: CHANGES.rst +.. This file contains of a series of comments that are used to include sections of this README in other files. Do not modify these comments unless you know what you are doing. tag:intro-begin + +Certbot is part of EFF’s effort to encrypt the entire Internet. Secure communication over the Web relies on HTTPS, which requires the use of a digital certificate that lets browsers verify the identify of web servers (e.g., is that really google.com?). Web servers obtain their certificates from trusted third parties called certificate authorities (CAs). Certbot is an easy-to-use client that fetches a certificate from Let’s Encrypt—an open certificate authority launched by the EFF, Mozilla, and others—and deploys it to a web server. + +Anyone who has gone through the trouble of setting up a secure website knows what a hassle getting and maintaining a certificate is. Certbot and Let’s Encrypt can automate away the pain and let you turn on and manage HTTPS with simple commands. Using Certbot and Let's Encrypt is free, so there’s no need to arrange payment. + +How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide `_. It generates instructions based on your configuration settings. You’ll need root or administrator access to your web server to run Certbot. + +If you’re using a hosted service and don’t have direct access to your web server, you might not be able to use Certbot. Check with your hosting provider for documentation about uploading certificates or using certificates issues by Let’s Encrypt. + +.. Do not modify this comment unless you know what you're doing. tag:intro-end + +.. Do not modify this comment unless you know what you're doing. tag:features-begin + +Current Features +===================== + +* Supports multiple web servers: + + - apache/2.x (working on Debian 8+ and Ubuntu 12.04+) + - standalone (runs its own simple webserver to prove you control a domain) + - webroot (adds files to webroot directories in order to prove control of + domains and obtain certs) + - nginx/0.8.48+ (highly experimental, not included in certbot-auto) + +* The private key is generated locally on your system. +* Can talk to the Let's Encrypt CA or optionally to other ACME + compliant services. +* Can get domain-validated (DV) certificates. +* Can revoke certificates. +* Adjustable RSA key bit-length (2048 (default), 4096, ...). +* Can optionally install a http -> https redirect, so your site effectively + runs https only (Apache only) +* Fully automated. +* Configuration changes are logged and can be reverted. +* Supports ncurses and text (-t) UI, or can be driven entirely from the + command line. +* Free and Open Source Software, made with Python. + +.. Do not modify this comment unless you know what you're doing. tag:features-end For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. From e67144434471a5c07db6e1c624c7d3f6d182de6f Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 20 Jul 2016 14:59:50 -0700 Subject: [PATCH 058/126] Make intro.rst include README --- docs/intro.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/intro.rst b/docs/intro.rst index 65c862f69..90c3761ec 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -2,4 +2,6 @@ Introduction ===================== -.. include:: intro_common.rst +.. include:: ../README.rst + :start-after: tag:intro-begin + :end-before: tag:intro-end From 642d67b3eb880aa036ab3644a0e777082b987d6a Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 20 Jul 2016 15:00:33 -0700 Subject: [PATCH 059/126] Remove intro_common.rst --- docs/intro_common.rst | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 docs/intro_common.rst diff --git a/docs/intro_common.rst b/docs/intro_common.rst deleted file mode 100644 index 630e07b51..000000000 --- a/docs/intro_common.rst +++ /dev/null @@ -1,8 +0,0 @@ - -Certbot is part of EFF’s effort to encrypt the entire Internet. Secure communication over the Web relies on HTTPS, which requires the use of a digital certificate that lets browsers verify the identify of web servers (e.g., is that really google.com?). Web servers obtain their certificates from trusted third parties called certificate authorities (CAs). Certbot is an easy-to-use client that fetches a certificate from Let’s Encrypt—an open certificate authority launched by the EFF, Mozilla, and others—and deploys it to a web server. - -Anyone who has gone through the trouble of setting up a secure website knows what a hassle getting and maintaining a certificate is. Certbot and Let’s Encrypt can automate away the pain and let you turn on and manage HTTPS with simple commands. Using Certbot and Let's Encrypt is free, so there’s no need to arrange payment. - -How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide `_. It generates instructions based on your configuration settings. You’ll need root or administrator access to your web server to run Certbot. - -If you’re using a hosted service and don’t have direct access to your web server, you might not be able to use Certbot. Check with your hosting provider for documentation about uploading certificates or using certificates issues by Let’s Encrypt. From b9198591811217b406edb479e8c0d5fb3ba1614f Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 20 Jul 2016 15:01:55 -0700 Subject: [PATCH 060/126] Include README for current_features in using.rst. --- docs/using.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/using.rst b/docs/using.rst index 6620c2575..ac0ce3bcd 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -572,5 +572,7 @@ installing Certbot directly with pip from PyPI or downloading a ZIP archive from GitHub may be technically possible but are not presently recommended or supported. -.. include:: current_features.rst +.. include:: ../README.rst + :start-after: tag:features-begin + :end-before: tag:features-end .. include:: ../CHANGES.rst From 4eb9ea7b720d70bc941355d98c126aa0a0f7eceb Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 20 Jul 2016 15:02:10 -0700 Subject: [PATCH 061/126] Remove current_features.rst --- docs/current_features.rst | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 docs/current_features.rst diff --git a/docs/current_features.rst b/docs/current_features.rst deleted file mode 100644 index 16c26af01..000000000 --- a/docs/current_features.rst +++ /dev/null @@ -1,24 +0,0 @@ -Current Features -===================== - -* Supports multiple web servers: - - - apache/2.x (working on Debian 8+ and Ubuntu 12.04+) - - standalone (runs its own simple webserver to prove you control a domain) - - webroot (adds files to webroot directories in order to prove control of - domains and obtain certs) - - nginx/0.8.48+ (highly experimental, not included in certbot-auto) - -* The private key is generated locally on your system. -* Can talk to the Let's Encrypt CA or optionally to other ACME - compliant services. -* Can get domain-validated (DV) certificates. -* Can revoke certificates. -* Adjustable RSA key bit-length (2048 (default), 4096, ...). -* Can optionally install a http -> https redirect, so your site effectively - runs https only (Apache only) -* Fully automated. -* Configuration changes are logged and can be reverted. -* Supports ncurses and text (-t) UI, or can be driven entirely from the - command line. -* Free and Open Source Software, made with Python. From 0c68a8cd6e6ee9ee4e84c3b878cd0bf2f4a6f87c Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 20 Jul 2016 15:19:21 -0700 Subject: [PATCH 062/126] Fix broken links --- docs/install.rst | 4 +++- docs/resources.rst | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/install.rst b/docs/install.rst index 1bccdad0c..e79a3b596 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -28,4 +28,6 @@ And for full command line help, you can type:: since ``certbot-auto`` is a wrapper to ``certbot``, it accepts exactly the same command line flags and arguments. More details about this script and other installation methods can be found `in the User Guide -`_. \ No newline at end of file +`_. + +.. _certbot.eff.org: https://certbot.eff.org/ diff --git a/docs/resources.rst b/docs/resources.rst index 94b5a9d58..a284f4a3d 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -48,3 +48,7 @@ email to client-dev+subscribe@letsencrypt.org) https://letsencrypt.readthedocs.org/en/latest/using.html .. _watch demo video: https://www.youtube.com/watch?v=Gas_sSB-5SU + +.. _Freenode: https://webchat.freenode.net?channels=%23letsencrypt +.. _OFTC: https://webchat.oftc.net?channels=%23certbot +.. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev From 54eafcf8da527d5028fecb86deb9c092ee7c3f65 Mon Sep 17 00:00:00 2001 From: shodan Date: Thu, 21 Jul 2016 14:50:12 +0200 Subject: [PATCH 063/126] Change fatal warning to a fatal message --- letsencrypt-auto-source/letsencrypt-auto | 2 +- letsencrypt-auto-source/letsencrypt-auto.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index cf2de34ed..27b11c656 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -126,7 +126,7 @@ ExperimentalBootstrap() { $2 fi else - echo "WARNING: $1 support is very experimental at present..." + echo "FATAL: $1 support is very experimental at present..." echo "if you would like to work on improving it, please ensure you have backups" echo "and then run this script again with the --debug flag!" exit 1 diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index d049e9df8..991d9dd76 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -126,7 +126,7 @@ ExperimentalBootstrap() { $2 fi else - echo "WARNING: $1 support is very experimental at present..." + echo "FATAL: $1 support is very experimental at present..." echo "if you would like to work on improving it, please ensure you have backups" echo "and then run this script again with the --debug flag!" exit 1 From 4a7a9b7d5dc44367efdec701e197c1c5d590a024 Mon Sep 17 00:00:00 2001 From: Noah Swartz Date: Thu, 21 Jul 2016 08:53:10 -0700 Subject: [PATCH 064/126] remove webhosting, fold ciphersuite --- docs/ciphers.rst | 114 ++++++++++++++++++++++++++++++++++ docs/ciphersuite.rst | 113 --------------------------------- docs/webhosting.rst | 144 ------------------------------------------- 3 files changed, 114 insertions(+), 257 deletions(-) delete mode 100644 docs/ciphersuite.rst delete mode 100644 docs/webhosting.rst diff --git a/docs/ciphers.rst b/docs/ciphers.rst index 8996dd9ef..dd05aef68 100644 --- a/docs/ciphers.rst +++ b/docs/ciphers.rst @@ -205,3 +205,117 @@ so far is redirecting HTTP requests to HTTPS in web servers, the "redirect" enhancement). The changes here would probably be either a new "ciphersuite" enhancement in each plugin that provides an installer, or a family of enhancements, one per selectable ciphersuite configuration. + +Feedback +---- +We recieve lots of feedback on the type of ciphersuites that Let's Encrypt supports and list some coallated feedback below. This section aims to track suggestions and references that people have offered or identified to improve the ciphersuites that Let's Encrypt enables when configuring TLS on servers. + +Because of the Chatham House Rule applicable to some of the discussions, people are *not* individually credited for their suggestions, but most suggestions here were made or found by other people, and I thank them for their contributions. + +Some people provided rationale information mostly having to do with compatibility of particular user-agents (especially UAs that don't support ECC, or that don't support DH groups > 1024 bits). Some ciphersuite configurations have been chosen to try to increase compatibility with older UAs while allowing newer UAs to negotiate stronger crypto. For example, some configurations forego forward secrecy entirely for connections from old UAs, like by offering ECDHE and RSA key exchange, but no DHE at all. (There are UAs that can fail the negotiation completely if a DHE ciphersuite with prime > 1024 bits is offered.) + +## References ## + +### RFC 7575 ### + +IETF has published a BCP document, RFC 7525, "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" + +https://datatracker.ietf.org/doc/rfc7525/ + +### BetterCrypto.org ### + +BetterCrypto.org, a collaboration of mostly European IT security experts, has published a draft paper, "Applied Crypto Hardening" + +https://bettercrypto.org/static/applied-crypto-hardening.pdf + +### FF-DHE Internet-Draft ### + +Gillmor's Internet-Draft "Negotiated Discrete Log Diffie-Hellman Ephemeral Parameters for TLS" is being developed at the IETF TLS WG. It advocates using *standardized* DH groups in all cases, not individually-chosen ones (mostly because of the Triple Handshake attack which can involve maliciously choosing invalid DH groups). The draft provides a list of recommended groups, with primes beginning at 2048 bits and going up from there. It also has a new protocol mechanism for agreeing to use these groups, with the possibility of backwards compatibility (and use of weaker DH groups) for older clients and servers that don't know about this mechanism. + +https://tools.ietf.org/html/draft-ietf-tls-negotiated-ff-dhe-10 + +### Mozilla ### + +Mozilla's general server configuration guidance is available at https://wiki.mozilla.org/Security/Server_Side_TLS + +Mozilla has also produced a configuration generator: https://mozilla.github.io/server-side-tls/ssl-config-generator/ + +### Dutch National Cyber Security Centre ### + +The Dutch National Cyber Security Centre has published guidance on "ICT-beveiligingsrichtlijnen voor Transport Layer Security (TLS)" ("IT Security Guidelines for Transport Layer Security (TLS)"). These are available only in Dutch at + +https://www.ncsc.nl/dienstverlening/expertise-advies/kennisdeling/whitepapers/ict-beveiligingsrichtlijnen-voor-transport-layer-security-tls.html + +I have access to an English-language summary of the recommendations. + +### Keylength.com ### + +Damien Giry collects recommendations by academic researchers and standards organizations about keylengths for particular cryptoperiods, years, or security levels. The keylength recommendations of the various sources are summarized in a chart. This site has been updated over time and includes expert guidance from eight sources published between 2000 and 2015. + +http://www.keylength.com/ + +### NIST ### +NISA published its "NIST Special Publication 800-52 Revision 1: Guidelines for the Selection, Configuration, and Use of Transport Layer Security (TLS) Implementations" + +http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r1.pdf + +and its "NIST Special Publication 800-57: Recommendation for Key Management – Part 1: General (Revision 3)" + +http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf + +### ENISA ### + +ENISA published its "Algorithms, Key Sizes and Parameters Report - 2013" + +https://www.enisa.europa.eu/activities/identity-and-trust/library/deliverables/algorithms-key-sizes-and-parameters-report + +## WeakDH/Logjam ## + +The WeakDH/Logjam research has thrown into question the safety of some existing practice using DH ciphersuites, especially the use of standardized groups with a prime ≤ 1024 bits. The authors provided detailed guidance, including ciphersuite lists, at + +https://weakdh.org/sysadmin.html + +These lists may have been derived from Mozilla's recommendations. +One of the authors clarified his view of the priorities for various changes as a result of the research at + +https://www.ietf.org/mail-archive/web/tls/current/msg16496.html + +In particular, he supports ECDHE and also supports the use of the standardized groups in the FF-DHE Internet-Draft mentioned above (which isn't clear from the group's original recommendations). + +## Particular sites' opinions or configurations ## + +### Amazon ELB ### + +Amazon ELB explains its current ciphersuite choices at + +https://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-security-policy-table.html + +### U.S. Government 18F ### + +The 18F site (https://18f.gsa.gov/) is using + +`ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';` + +### Duraconf ### + +The Duraconf project collects particular configuration files, with an apparent focus on avoiding the use of obsolete symmetric ciphers and hash functions, and favoring forward secrecy while not requiring it. + +https://github.com/ioerror/duraconf + +## Site scanning or rating tools ## + +### Qualys SSL Labs ### + +Qualys offers the best-known TLS security scanner, maintained by Ivan Ristić. + +https://www.ssllabs.com/ + +### Dutch NCSC ### + +The Dutch NCSC, mentioned above, has also made available its own site security scanner which indicates how well sites comply with the recommendations. + +https://en.internet.nl/ + +## Java compatibility issue ## + +A lot of backward-compatibility concerns have to do with Java hard-coding DHE primes to a 1024-bit limit, accepting DHE ciphersuites in negotiation, and then aborting the connection entirely if a prime > 1024 bits is presented. The simple summary is that servers offering a Java-compatible DHE ciphersuite in preference to other Java-compatible ciphersuites, and then presenting a DH group with a prime > 1024 bits, will be completely incompatible with clients running some versions of Java. (This may also be the case with very old MSIE versions...?) There are various strategies for dealing with this, and maybe we can document the options here. diff --git a/docs/ciphersuite.rst b/docs/ciphersuite.rst deleted file mode 100644 index 4141c96b8..000000000 --- a/docs/ciphersuite.rst +++ /dev/null @@ -1,113 +0,0 @@ -This page aims to track suggestions and references that people have offered or identified to improve the ciphersuites that Let's Encrypt enables when configuring TLS on servers. - -Because of the Chatham House Rule applicable to some of the discussions, people are *not* individually credited for their suggestions, but most suggestions here were made or found by other people, and I thank them for their contributions. - -Some people provided rationale information mostly having to do with compatibility of particular user-agents (especially UAs that don't support ECC, or that don't support DH groups > 1024 bits). Some ciphersuite configurations have been chosen to try to increase compatibility with older UAs while allowing newer UAs to negotiate stronger crypto. For example, some configurations forego forward secrecy entirely for connections from old UAs, like by offering ECDHE and RSA key exchange, but no DHE at all. (There are UAs that can fail the negotiation completely if a DHE ciphersuite with prime > 1024 bits is offered.) - -## References ## - -### RFC 7575 ### - -IETF has published a BCP document, RFC 7525, "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" - -https://datatracker.ietf.org/doc/rfc7525/ - -### BetterCrypto.org ### - -BetterCrypto.org, a collaboration of mostly European IT security experts, has published a draft paper, "Applied Crypto Hardening" - -https://bettercrypto.org/static/applied-crypto-hardening.pdf - -### FF-DHE Internet-Draft ### - -Gillmor's Internet-Draft "Negotiated Discrete Log Diffie-Hellman Ephemeral Parameters for TLS" is being developed at the IETF TLS WG. It advocates using *standardized* DH groups in all cases, not individually-chosen ones (mostly because of the Triple Handshake attack which can involve maliciously choosing invalid DH groups). The draft provides a list of recommended groups, with primes beginning at 2048 bits and going up from there. It also has a new protocol mechanism for agreeing to use these groups, with the possibility of backwards compatibility (and use of weaker DH groups) for older clients and servers that don't know about this mechanism. - -https://tools.ietf.org/html/draft-ietf-tls-negotiated-ff-dhe-10 - -### Mozilla ### - -Mozilla's general server configuration guidance is available at https://wiki.mozilla.org/Security/Server_Side_TLS - -Mozilla has also produced a configuration generator: https://mozilla.github.io/server-side-tls/ssl-config-generator/ - -### Dutch National Cyber Security Centre ### - -The Dutch National Cyber Security Centre has published guidance on "ICT-beveiligingsrichtlijnen voor Transport Layer Security (TLS)" ("IT Security Guidelines for Transport Layer Security (TLS)"). These are available only in Dutch at - -https://www.ncsc.nl/dienstverlening/expertise-advies/kennisdeling/whitepapers/ict-beveiligingsrichtlijnen-voor-transport-layer-security-tls.html - -I have access to an English-language summary of the recommendations. - -### Keylength.com ### - -Damien Giry collects recommendations by academic researchers and standards organizations about keylengths for particular cryptoperiods, years, or security levels. The keylength recommendations of the various sources are summarized in a chart. This site has been updated over time and includes expert guidance from eight sources published between 2000 and 2015. - -http://www.keylength.com/ - -### NIST ### - -NISA published its "NIST Special Publication 800-52 Revision 1: Guidelines for the Selection, Configuration, and Use of Transport Layer Security (TLS) Implementations" - -http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r1.pdf - -and its "NIST Special Publication 800-57: Recommendation for Key Management – Part 1: General (Revision 3)" - -http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf - -### ENISA ### - -ENISA published its "Algorithms, Key Sizes and Parameters Report - 2013" - -https://www.enisa.europa.eu/activities/identity-and-trust/library/deliverables/algorithms-key-sizes-and-parameters-report - -## WeakDH/Logjam ## - -The WeakDH/Logjam research has thrown into question the safety of some existing practice using DH ciphersuites, especially the use of standardized groups with a prime ≤ 1024 bits. The authors provided detailed guidance, including ciphersuite lists, at - -https://weakdh.org/sysadmin.html - -These lists may have been derived from Mozilla's recommendations. - -One of the authors clarified his view of the priorities for various changes as a result of the research at - -https://www.ietf.org/mail-archive/web/tls/current/msg16496.html - -In particular, he supports ECDHE and also supports the use of the standardized groups in the FF-DHE Internet-Draft mentioned above (which isn't clear from the group's original recommendations). - -## Particular sites' opinions or configurations ## - -### Amazon ELB ### - -Amazon ELB explains its current ciphersuite choices at - -https://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-security-policy-table.html - -### U.S. Government 18F ### - -The 18F site (https://18f.gsa.gov/) is using - -`ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';` - -### Duraconf ### - -The Duraconf project collects particular configuration files, with an apparent focus on avoiding the use of obsolete symmetric ciphers and hash functions, and favoring forward secrecy while not requiring it. - -https://github.com/ioerror/duraconf - -## Site scanning or rating tools ## - -### Qualys SSL Labs ### - -Qualys offers the best-known TLS security scanner, maintained by Ivan Ristić. - -https://www.ssllabs.com/ - -### Dutch NCSC ### - -The Dutch NCSC, mentioned above, has also made available its own site security scanner which indicates how well sites comply with the recommendations. - -https://en.internet.nl/ - -## Java compatibility issue ## - -A lot of backward-compatibility concerns have to do with Java hard-coding DHE primes to a 1024-bit limit, accepting DHE ciphersuites in negotiation, and then aborting the connection entirely if a prime > 1024 bits is presented. The simple summary is that servers offering a Java-compatible DHE ciphersuite in preference to other Java-compatible ciphersuites, and then presenting a DH group with a prime > 1024 bits, will be completely incompatible with clients running some versions of Java. (This may also be the case with very old MSIE versions...?) There are various strategies for dealing with this, and maybe we can document the options here. diff --git a/docs/webhosting.rst b/docs/webhosting.rst deleted file mode 100644 index 0aab50874..000000000 --- a/docs/webhosting.rst +++ /dev/null @@ -1,144 +0,0 @@ -# Web Hosting Providers Let's Encrypt Support Status - -_This is a community maintained list and does not guarantee implementation._ - -## Web Hosting Providers with Let's Encrypt Support - -* [34SP.com](https://www.34SP.com) ([Source](https://www.34sp.com/hosting-news/blog/lets-encrypt-free-ssl-certificates/)) -* [a2hosting.com](https://a2hosting.com) ([Source](https://www.a2hosting.com/kb/security/ssl/securing-your-site-with-a-lets-encrypt-ssl-certificate)) -* [Active24.co.uk](https://www.active24.co.uk) ([Source](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fblog.active24.cz%2F2016%2F06%2Fduveryhodne-certifikaty-lets-encrypt-zdarma-ke-kazdemu-linux-hostingu-od-active-24%2F)) -* [Active24.cz](https://www.active24.cz) ([Source](https://blog.active24.cz/2016/06/duveryhodne-certifikaty-lets-encrypt-zdarma-ke-kazdemu-linux-hostingu-od-active-24/)) -* [all-inkl.com](http://all-inkl.com) ([Source](http://kasserver.com/news.php#111), [more detailed instructions](https://www.ra-networks.at/2015/12/07/lets-encrypt-mit-all-inkl-com-nutzen/#comment-279)) (*both in German*) -* [Apis Networks](https://apisnetworks.com/)([Source](http://updates.apisnetworks.com/2016/02/lets-encrypt-is-here/)) -* [blueboard.cz](https://blueboard.cz) ([Source](https://blog.blueboard.cz/ssl-certifikaty-pro-vsechny-klienty-zdarma/)) -* [Brontobytes](https://www.brontobytes.com/) ([Source](https://www.brontobytes.com/announcements/39/Free-SSL-Certificate-for-everyone.html)) -* [Brownrice Internet](https://hosting.brownrice.com) ([Source](http://blog.brownrice.com/2016/server-stuff/letsencrypt-automated-fee-ssl/)) -* [Buyshared.net](http://buyshared.net/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/57)) -* [Certified Hosting](http://certifiedhosting.com/) ([Source](http://certifiedhosting.com/blog/tech-news/free-ssl-for-everyone/)) -* [checkdomain](https://www.checkdomain.de/) ([Source](https://www.checkdomain.de/ssl/zertifikat/ssl-free/)) -* [Cloudways](https://www.cloudways.com/) ([Source](http://www.cloudways.com/blog/lets-encrypt-free-ssl-on-cloud/)) -* [Configbox](https://www.configbox.com/) ([Source](http://www.cloudways.com/blog/lets-encrypt-free-ssl-on-cloud/)) -* [Cyon.ch](https://www.cyon.ch/) ([Source](https://www.cyon.ch/blog/Lets-Encrypt-ist-da-Kostenlose-SSL-Zertifikate-fuer-alle)) -* [Deep.ch](http://deep.ch/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/51)) -* [Digital Ocean](http://www.digitalocean.com/) ([Source](https://www.digitalocean.com/community/tutorials/how-to-set-up-let-s-encrypt-certificates-for-multiple-apache-virtual-hosts-on-ubuntu-14-04)) -* [Domain & Webspace Tremmel](https://www.domain-and-webspace.com/) ([Source](https://www.domain-and-webspace.com/en/webspace/2gb)) -* [Dreamhost.com](https://www.dreamhost.com/) ([Source](https://www.dreamhost.com/blog/2016/01/20/free-ssltls-certificates-at-dreamhost-with-lets-encrypt/)) -* [Dwe Gruppe](https://www.dwe-gruppe.eu) ([Source *in German*](https://www.dwe-gruppe.eu/news/18/news_single.html)) -* [EDIS.AT, Austria](http://www.edis.at/) ([Source](http://www.edis.at/de/hosting/letsencrypt-ssl-tls-zertifikate/)) -* [Eidolonhost.com](https://eidolonhost.com) ([Source](https://eidolonhost.com/forums/index.php/topic,2.0.html)) -* [ElbiaHosting.sk](http://www.elbiahosting.sk/) ([Source](https://www.facebook.com/elbiahosting/photos/a.591086047574269.148637.556646721018202/1221680761181458/)) -* [Espace2001.com](https://www.espace2001.com) ([Source](http://cp.espace2001.com/announcements.php?id=8)) -* [EvenNode.com](http://www.evennode.com) ([Source](http://blog.evennode.com/lets-encrypt-ssl-certificates-support/)) -* [FlockHosting](http://flockhosting.com/) ([Source](http://blog.flockhosting.com/tags/free-ssl/)) -* [fortrabbit](https://www.fortrabbit.com) ([Source](https://blog.fortrabbit.com/tls-free-launched)) -* [Funio.com](https://www.funio.com) ([Source](https://kb.funio.com/view/id/98912157/)) -* [Gandi](https://www.gandi.net) ([Source](https://www.gandi.net/news/en/2016-01-12/6677-free_tlsssl_certificates_with_lets_encrypt_and_gandi/)) -* [GeekGhost](http://geekghost.net) ([Source](http://geekghost.net/1479-2/)) -* [GoDaddy](https://www.godaddy.com/) ([Source](https://www.godaddy.com/help/install-a-lets-encrypt-ssl-apache-20245)) Limited on shared hosting -* [Host4Geeks](https://host4geeks.com) ([Source](https://host4geeks.com/lets-encrypt-free-ssl-certificates/)) -* [Hosting4Real](http://hosting4real.net/) -* [Hosting90 Systems](https://www.hosting90.cz/) ([Source](https://twitter.com/hosting90/status/711898647806533633)) -* [HostM.com](https://www.hostm.com) ([Source](https://www.hostm.com/free-ssl-certificates)) -* [hostNET.de](https://www.hostnet.de) ([Source](https://www.hostnet.de/faq/wie-kann-ich-letsencrypt-nutzen.html)) -* [Inertia Networks](https://inertianetworks.com) ([Source](https://secure.inertianetworks.com/inetsrv5/plugin/support_manager/knowledgebase/view/7/issuing-let-s-encrypt-ssl-certificates/2/)) -* [Infomaniak](https://infomaniak.com/) ([Source](https://news.infomaniak.com/en/certificats-ssl-gratuits-chez-infomaniak/)) -* [KeyCDN](https://www.keycdn.com) ([Source](https://www.keycdn.com/blog/free-ssl-certificates/)) -* [KingHost](http://www.kinghost.com.br/) ([Source in portuguese](http://www.kinghost.com.br/certificado-ssl)) -* [KLE-Hosting](https://www.kle-hosting.de) ([Source in Germany](https://www.kle-hosting.de/webhosting/)) -* [Krystal Hosting](https://krystal.co.uk/)([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/86)) -* [Level27](https://level27.be) ([Source](https://level27.be/blog/lets-encrypt)) -* [madRooster.com](http://www.madrooster.com/) ([Source](https://twitter.com/madRooster/status/721742100757393410)) -* [manitu](https://www.manitu.de) ([Source](https://www.manitu.de/webhosting/)) -* [MilesWeb](https://www.milesweb.com) ([Source](https://twitter.com/chinmaydingore/status/691988956565495808)) -* [MonsterMegs](https://www.monstermegs.com) ([Source](https://blog.monstermegs.com/free-lets-encrypt-ssl-certificates/)) -* [Mydevil.net](https://www.mydevil.net/) ([Source](https://wiki.mydevil.net/Let's_Encrypt)) -* [Mythic Beasts](https://www.mythic-beasts.com/) ([Source](http://blog.mythic-beasts.com/2016/01/29/free-ssl-certificates-for-hosting-accounts/)) -* [Neostrada.nl](https://www.neostrada.nl/) ([Source](https://www.neostrada.nl/letsencrypt-hosting.html)) (*both in Dutch*) -* [Netcup.de] (https://www.netcup.de/) ([Source](http://www.netcup-news.de/2016/02/04/lets-encrypt-internetprovider-netcup-integriert-kostenlose-ssl-zertifikate-in-webhosting-angebote-2/)) -* [NewHostServers.net](http://newhostservers.com/)([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/85)) -* [Ngage Hosting](https://www.ngagehosting.uk/) ([Source](https://clients.ngagehosting.uk/knowledgebase.php?action=displayarticle&id=1)) -* [Novatrend.ch](https://www.novatrend.ch/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-letsencrypt-org/6920/18)) -* [Ntechit.de](https://ntechit.de/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/35)) -* [Nucleus.be](https://www.nucleus.be) ([Source](https://www.nucleus.be/en/blog/free-ssl-certificates-for-all-customers/)) -* [Online.net](https://www.online.net/) ([Source](https://community.letsencrypt.org/t/shared-hosting/384/11)) -* [Openminds.be](https://www.openminds.be/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-letsencrypt-org/6920/22)) -* [OVH.com](https://www.ovh.com) ([Source](https://www.ovh.com/fr/hebergement-web/ssl_mutualise.xml)) -* [Planethoster.net](https://www.planethoster.net/) ([Source](https://forums.planethoster.net/threads/exclusive-free-ssl-to-all-our-customers.4731/#post-17876)) -* [Pressjitsu.com](https://pressjitsu.com/) ([Source](https://pressjitsu.com/blog/ssl-wordpress-letsencrypt/)) -* [Progreso.pl](https://progreso.pl/) ([Source](https://progreso.pl/o_nas/newsroom/#news_78)) -* [PulseHeberg.com](http://pulseheberg.com/) ([Source](https://community.letsencrypt.org/t/shared-hosting/384/16)) -* [ResellerChoice](https://www.resellerchoice.com) -* [Schokokeks.org](https://schokokeks.org/) ([Source](https://schokokeks.org/blog/https-f-r-alle-mit-lets-encrypt)) -* [Sensson](https://www.sensson.net) ([Source](https://www.sensson.net/2016/02/21/webhosting-met-ssl-certificaten-van-letsencrypt/)) -* [ServerPilot](https://serverpilot.io/) ([Source](https://serverpilot.io/blog/2016/03/09/free-ssl-certificates-from-lets-encrypt.html)) -* [Serversaurus](https://www.serversaurus.com.au/) ([Source](https://blog.serversaurus.com.au/free-ssl-with-lets-encrypt/)) -* [SiteGround.com](https://www.siteground.com/) ([Source](https://www.siteground.com/blog/lets-encrypt/)) -* [Squidix](https://squidix.com/) ([Source](https://squidix.com/blog/squidix-is-now-support-lets-encrypt-on-all-sharedresellersemi-plans/)) -* [Strony-Domeny.pl](https://strony-domeny.pl/) ([Source](https://strony-domeny.pl/blogtech/9/Lets-encrypt-darmowy-certyfikat-SSL.html)) -* [TD Web Services](https://tdwebservices.com/) -* [Thisistap](https://thisistap.com/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/52)) -* [Tiger Technologies](https://www.tigertech.net/) ([Source](https://blog.tigertech.net/posts/lets-encrypt/)) -* [Top Host](https://www.tophost.gr/) ([Source](https://support.tophost.gr/kb/article.php?id=1410)) -- Greek -* [TrafficPlanet Hosting](https://trafficplanethosting.com/) ([Source](https://trafficplanethosting.com/page/free-ssl-certificates/)) -* [Uberspace.de](https://uberspace.de/) ([Source](https://blog.uberspace.de/lets-encrypt-rollt-an/)) -* [UnoEuro](https://en.unoeuro.com/) ([Source](https://blog.unoeuro.com/2016/04/ny-feature-lets-encrypt-certifikater/) *– in Danish*) -* [UnoEuro](https://www.unoeuro.com) ([Source *in Danish*](https://blog.unoeuro.com/2016/ny-feature-lets-encrypt-certifikater/)) -* [VentraIP Australia](https://ventraip.com.au/) ([Source](https://ventraip.com.au/blog/announcements/lets-encrypt-free-ssl-certificates-now-available/)) -* [Webfaction](https://webfaction.com/) ([some support](https://community.webfaction.com/questions/19722/is-the-letsencrypt-certificate-service-supported/19723) including [a third-party open-source utility to automate the process](https://github.com/will-in-wi/letsencrypt-webfaction), and [wider support depends on formal release of Let's Encrypt](https://community.webfaction.com/questions/18989/using-lets-encrypt-to-get-ssl-certificates/18990) -* [webgo](https://www.webgo.de/) ([Source](https://www.webgo.de/blog/webgo-webhosting-jetzt-kostenlos-ssl-verschluesselung-nutzen-mit-lets-encrypt/)) -* [WebhostOne](https://www.webhostone.de/) ([Source](https://www.webhostone.de/lets-encrypt.html)) -* [Websupport.sk](https://websupport.sk/) ([Source *in Slovak*](https://www.websupport.sk/blog/2016/02/lets-encrypt-ssl-certifikat-zadarmo-pre-kazdeho/)) -* [Wetopi](https://wetopi.com/) ([Source](https://wetopi.com/wordpress-ssl)) -* [WordPress.com](https://wordpress.com/) ([Source](https://en.blog.wordpress.com/2016/04/08/https-everywhere-encryption-for-all-wordpress-com-sites/)) -* [World4You Internet Services GmbH](https://www.world4you.com/) ([Source *in German*] (https://www.world4you.at/de/webhosting/ssl.html/)) -* [wp-webhosting.de](https://www.wp-webhosting.de/) ([Source *in German*](https://www.internetwerk.de/blog/webhosting/2015/12/04/kostenlose-ssl-zertifikate-fuer-alle/)) -* [XiNiX](http://www.xinix.co/) ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/66)) -* [Zuver](https://zuver.net.au/) ([Source](https://forums.whirlpool.net.au/archive/2467065#r50573142)) - -*** - -## Planned: -* [Kinsta](https://kinsta.com/) -* [Pagely](https://pagely.com/) -* [pair Networks](https://www.pair.com/) Ability to automate certificate installation is in long-term plans. (via support email) -* [RAIDBOXES.de](https://raidboxes.de/) / [RAIDBOXES.eu](https://raidboxes.eu/) - -*** - -## Waiting/Delayed - -* [Hostgator] (https://www.hostgator.com/) Implementation of Let's Encrypt has been relayed internally for further consideration. ([Source](https://twitter.com/hgsupport/status/694292490485133313)) -* [Strato.de] (https://www.strato.de/) Waiting for Let's Encrypt beta to end to evaluate possible adoption for all customers. ([Source *in German*](https://blog.strato.de/verschluesselte-website-bald-standard/)) -* [Tsohost] (https://www.tsohost.com/) Not supported, but the team are looking into it. ([Source](https://twitter.com/tsohost/status/722448514228318208)) - -*** - -## Unconfirmed: - -* [spolehlive-servery.cz](https://www.spolehlive-servery.cz) & [cesky-hosting.cz](https://www.cesky-hosting.cz) (information via support ticket; planned to ~ autumn 2016) - -## Dedicated Hosting: - -* All Dedicated hosting supports installation. This is not a link directory page. - -## No Planned Support: - -* 1and1.com ([Source](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/77)) -* 247-host.com (maybe anytime in the future, via support chat) -* Amazili-communication (Not a hosting company) -* df.eu (DomainFactory - no plans to support LE, [Source *in German*](https://www.df.eu/forum/threads/76119-Unterst%C3%BCtzung-von-Let-s-encrypt-Langfristiges-SSL-Konzept-von-Domainfactory/page3?p=499684#post499684)) -* Greengeeks.com (tech support said 'no plans and you can buy our SSL') -* HostEurope.de (via email reply from customer support; LE can be installed manually) -* Hostinger.com (no plans to support LE) -* HostMonster.com ('no plans', via live chat) -* Hostpapa.ca (tech support said 'no plans') -* Hostripples.com (no plans, via live chat) -* Inmotionhosting.com ([Source](https://twitter.com/inmotionhosting/status/678085107891240960)) -* Linode (doesn't offer shared hosting) -* Namecheap.com ([Source](https://gist.github.com/stopspazzing/c871f935771f14933c63)) -* Netsons.com (no plans to support LE) -* Site5.com (no plans to support at all, except unmanaged vps - via support chat) - -## Remarks - -Moved from [forums](https://community.letsencrypt.org/t/web-hosting-who-support-lets-encrypt/6920/). From 86b287b338dd18cb49da9852ee90ef41b04dfbed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Tue, 19 Jul 2016 20:12:47 +0300 Subject: [PATCH 065/126] Use assertEqual instead of deprecated assertEquals --- .../certbot_apache/tests/configurator_test.py | 6 +++--- .../certbot_nginx/tests/configurator_test.py | 6 +++--- .../certbot_nginx/tests/nginxparser_test.py | 6 +++--- certbot-nginx/certbot_nginx/tests/parser_test.py | 4 ++-- certbot/plugins/util_test.py | 12 ++++++------ 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/certbot-apache/certbot_apache/tests/configurator_test.py b/certbot-apache/certbot_apache/tests/configurator_test.py index 0bbdac1aa..ac692ae54 100644 --- a/certbot-apache/certbot_apache/tests/configurator_test.py +++ b/certbot-apache/certbot_apache/tests/configurator_test.py @@ -56,7 +56,7 @@ class MultipleVhostsTest(util.ApacheTest): mock_surgery.return_value = False with mock.patch.dict('os.environ', silly_path): self.assertRaises(errors.NoInstallationError, self.config.prepare) - self.assertEquals(mock_surgery.call_count, 1) + self.assertEqual(mock_surgery.call_count, 1) @mock.patch("certbot_apache.augeas_configurator.AugeasConfigurator.init_augeas") def test_prepare_no_augeas(self, mock_init_augeas): @@ -1242,8 +1242,8 @@ class MultipleVhostsTest(util.ApacheTest): mock_match = mock.Mock(return_value=["something"]) self.config.aug.match = mock_match # pylint: disable=protected-access - self.assertEquals(self.config._check_aug_version(), - ["something"]) + self.assertEqual(self.config._check_aug_version(), + ["something"]) self.config.aug.match.side_effect = RuntimeError self.assertFalse(self.config._check_aug_version()) diff --git a/certbot-nginx/certbot_nginx/tests/configurator_test.py b/certbot-nginx/certbot_nginx/tests/configurator_test.py index 7529bc10b..fa130fc4e 100644 --- a/certbot-nginx/certbot_nginx/tests/configurator_test.py +++ b/certbot-nginx/certbot_nginx/tests/configurator_test.py @@ -37,8 +37,8 @@ class NginxConfiguratorTest(util.NginxTest): errors.NoInstallationError, self.config.prepare) def test_prepare(self): - self.assertEquals((1, 6, 2), self.config.version) - self.assertEquals(5, len(self.config.parser.parsed)) + self.assertEqual((1, 6, 2), self.config.version) + self.assertEqual(5, len(self.config.parser.parsed)) @mock.patch("certbot_nginx.configurator.util.exe_exists") @mock.patch("certbot_nginx.configurator.subprocess.Popen") @@ -56,7 +56,7 @@ class NginxConfiguratorTest(util.NginxTest): self.config.version = None self.config.config_test = mock.Mock() self.config.prepare() - self.assertEquals((1, 6, 2), self.config.version) + self.assertEqual((1, 6, 2), self.config.version) @mock.patch("certbot_nginx.configurator.socket.gethostbyaddr") def test_get_all_names(self, mock_gethostbyaddr): diff --git a/certbot-nginx/certbot_nginx/tests/nginxparser_test.py b/certbot-nginx/certbot_nginx/tests/nginxparser_test.py index a0a0736a5..5fa9a7d1e 100644 --- a/certbot-nginx/certbot_nginx/tests/nginxparser_test.py +++ b/certbot-nginx/certbot_nginx/tests/nginxparser_test.py @@ -134,8 +134,8 @@ class TestRawNginxParser(unittest.TestCase): parsed_new = load(handle) try: self.maxDiff = None - self.assertEquals(parsed[0], parsed_new[0]) - self.assertEquals(parsed[1:], parsed_new[1:]) + self.assertEqual(parsed[0], parsed_new[0]) + self.assertEqual(parsed[1:], parsed_new[1:]) finally: os.unlink(util.get_data_filename('nginx.new.conf')) @@ -150,7 +150,7 @@ class TestRawNginxParser(unittest.TestCase): parsed_new = load(handle) try: - self.assertEquals(parsed, parsed_new) + self.assertEqual(parsed, parsed_new) self.assertEqual(parsed_new, [ ['#', " Use bar.conf when it's a full moon!"], diff --git a/certbot-nginx/certbot_nginx/tests/parser_test.py b/certbot-nginx/certbot_nginx/tests/parser_test.py index 464d717ed..77b4a877a 100644 --- a/certbot-nginx/certbot_nginx/tests/parser_test.py +++ b/certbot-nginx/certbot_nginx/tests/parser_test.py @@ -117,9 +117,9 @@ class NginxParserTest(util.NginxTest): fooconf = [x for x in vhosts if 'foo.conf' in x.filep][0] self.assertEqual(vhost5, fooconf) localhost = [x for x in vhosts if 'localhost' in x.names][0] - self.assertEquals(vhost1, localhost) + self.assertEqual(vhost1, localhost) somename = [x for x in vhosts if 'somename' in x.names][0] - self.assertEquals(vhost2, somename) + self.assertEqual(vhost2, somename) def test_add_server_directives(self): nparser = parser.NginxParser(self.config_path, self.ssl_options) diff --git a/certbot/plugins/util_test.py b/certbot/plugins/util_test.py index fa8b364d9..6f6e14571 100644 --- a/certbot/plugins/util_test.py +++ b/certbot/plugins/util_test.py @@ -16,15 +16,15 @@ class PathSurgeryTest(unittest.TestCase): with mock.patch.dict('os.environ', all_path): with mock.patch('certbot.util.exe_exists') as mock_exists: mock_exists.return_value = True - self.assertEquals(path_surgery("eg"), True) - self.assertEquals(mock_debug.call_count, 0) - self.assertEquals(mock_warn.call_count, 0) - self.assertEquals(os.environ["PATH"], all_path["PATH"]) + self.assertEqual(path_surgery("eg"), True) + self.assertEqual(mock_debug.call_count, 0) + self.assertEqual(mock_warn.call_count, 0) + self.assertEqual(os.environ["PATH"], all_path["PATH"]) no_path = {"PATH": "/tmp/"} with mock.patch.dict('os.environ', no_path): path_surgery("thingy") - self.assertEquals(mock_debug.call_count, 1) - self.assertEquals(mock_warn.call_count, 1) + self.assertEqual(mock_debug.call_count, 1) + self.assertEqual(mock_warn.call_count, 1) self.assertTrue("Failed to find" in mock_warn.call_args[0][0]) self.assertTrue("/usr/local/bin" in os.environ["PATH"]) self.assertTrue("/tmp" in os.environ["PATH"]) From c7b89c334b6c8086fb3b49b58f3d676c31438f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Tue, 19 Jul 2016 20:13:50 +0300 Subject: [PATCH 066/126] Use logger.warning instead of deprecated warn --- acme/acme/fields.py | 2 +- certbot-apache/certbot_apache/configurator.py | 12 ++++++------ certbot-apache/certbot_apache/display_ops.py | 2 +- certbot-apache/certbot_apache/parser.py | 2 +- certbot-apache/certbot_apache/tls_sni_01.py | 2 +- .../certbot_compatibility_test/test_driver.py | 4 ++-- certbot-nginx/certbot_nginx/configurator.py | 4 ++-- certbot-nginx/certbot_nginx/parser.py | 2 +- certbot/cli.py | 2 +- certbot/client.py | 8 ++++---- certbot/hooks.py | 2 +- certbot/main.py | 2 +- certbot/plugins/selection.py | 2 +- certbot/plugins/util.py | 2 +- certbot/plugins/util_test.py | 2 +- certbot/reverter.py | 2 +- certbot/tests/client_test.py | 2 +- certbot/util.py | 2 +- 18 files changed, 28 insertions(+), 28 deletions(-) diff --git a/acme/acme/fields.py b/acme/acme/fields.py index 002240b23..12d09acf4 100644 --- a/acme/acme/fields.py +++ b/acme/acme/fields.py @@ -24,7 +24,7 @@ class Fixed(jose.Field): def encode(self, value): if value != self.value: - logger.warn( + logger.warning( 'Overriding fixed field (%s) with %r', self.json_name, value) return value diff --git a/certbot-apache/certbot_apache/configurator.py b/certbot-apache/certbot_apache/configurator.py index e61a9f2e6..238255133 100644 --- a/certbot-apache/certbot_apache/configurator.py +++ b/certbot-apache/certbot_apache/configurator.py @@ -244,7 +244,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): if not path["cert_path"] or not path["cert_key"]: # Throw some can't find all of the directives error" - logger.warn( + logger.warning( "Cannot find a cert or key directive in %s. " "VirtualHost was not modified", vhost.path) # Presumably break here so that the virtualhost is not modified @@ -522,7 +522,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): try: args = self.aug.match(path + "/arg") except RuntimeError: - logger.warn("Encountered a problem while parsing file: %s, skipping", path) + logger.warning("Encountered a problem while parsing file: %s, skipping", path) return None for arg in args: addrs.add(obj.Addr.fromstring(self.parser.get_arg(arg))) @@ -1089,7 +1089,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): try: func(self.choose_vhost(domain), options) except errors.PluginError: - logger.warn("Failed %s for %s", enhancement, domain) + logger.warning("Failed %s for %s", enhancement, domain) raise def _enable_ocsp_stapling(self, ssl_vhost, unused_options): @@ -1276,9 +1276,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): # but redirect loops are possible in very obscure cases; see #1620 # for reasoning. if self._is_rewrite_exists(general_vh): - logger.warn("Added an HTTP->HTTPS rewrite in addition to " - "other RewriteRules; you may wish to check for " - "overall consistency.") + logger.warning("Added an HTTP->HTTPS rewrite in addition to " + "other RewriteRules; you may wish to check for " + "overall consistency.") # Add directives to server # Note: These are not immediately searchable in sites-enabled diff --git a/certbot-apache/certbot_apache/display_ops.py b/certbot-apache/certbot_apache/display_ops.py index 24aabaed4..d7b76f83d 100644 --- a/certbot-apache/certbot_apache/display_ops.py +++ b/certbot-apache/certbot_apache/display_ops.py @@ -91,7 +91,7 @@ def _vhost_menu(domain, vhosts): "non-interactive mode. Currently Certbot needs each vhost to be " "in its own conf file, and may need vhosts to be explicitly " "labelled with ServerName or ServerAlias directories.") - logger.warn(msg) + logger.warning(msg) raise errors.MissingCommandlineFlag(msg) return code, tag diff --git a/certbot-apache/certbot_apache/parser.py b/certbot-apache/certbot_apache/parser.py index 321546eb3..6bb6ff170 100644 --- a/certbot-apache/certbot_apache/parser.py +++ b/certbot-apache/certbot_apache/parser.py @@ -146,7 +146,7 @@ class ApacheParser(object): constants.os_constant("define_cmd")) # Small errors that do not impede if proc.returncode != 0: - logger.warn("Error in checking parameter list: %s", stderr) + logger.warning("Error in checking parameter list: %s", stderr) raise errors.MisconfigurationError( "Apache is unable to check whether or not the module is " "loaded because Apache is misconfigured.") diff --git a/certbot-apache/certbot_apache/tls_sni_01.py b/certbot-apache/certbot_apache/tls_sni_01.py index 06d9e9ebd..18179d080 100644 --- a/certbot-apache/certbot_apache/tls_sni_01.py +++ b/certbot-apache/certbot_apache/tls_sni_01.py @@ -129,7 +129,7 @@ class ApacheTlsSni01(common.TLSSNI01): # because it's a new vhost that's not configured yet (GH #677), # or perhaps because there were multiple sections # in the config file (GH #1042). See also GH #2600. - logger.warn("Falling back to default vhost %s...", default_addr) + logger.warning("Falling back to default vhost %s...", default_addr) addrs.add(default_addr) return addrs diff --git a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py index 38abffb18..2c78eea1f 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py +++ b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py @@ -369,10 +369,10 @@ def main(): plugin.cleanup_from_tests() if overall_success: - logger.warn("All compatibility tests succeeded") + logger.warning("All compatibility tests succeeded") sys.exit(0) else: - logger.warn("One or more compatibility tests failed") + logger.warning("One or more compatibility tests failed") sys.exit(1) diff --git a/certbot-nginx/certbot_nginx/configurator.py b/certbot-nginx/certbot_nginx/configurator.py index d11b6bb14..8157e48f1 100644 --- a/certbot-nginx/certbot_nginx/configurator.py +++ b/certbot-nginx/certbot_nginx/configurator.py @@ -179,7 +179,7 @@ class NginxConfigurator(common.Plugin): vhost.filep, vhost.names) except errors.MisconfigurationError as error: logger.debug(error) - logger.warn( + logger.warning( "Cannot find a cert or key directive in %s for %s. " "VirtualHost was not modified.", vhost.filep, vhost.names) # Presumably break here so that the virtualhost is not modified @@ -385,7 +385,7 @@ class NginxConfigurator(common.Plugin): raise errors.PluginError( "Unsupported enhancement: {0}".format(enhancement)) except errors.PluginError: - logger.warn("Failed %s for %s", enhancement, domain) + logger.warning("Failed %s for %s", enhancement, domain) def _enable_redirect(self, vhost, unused_options): """Redirect all equivalent HTTP traffic to ssl_vhost. diff --git a/certbot-nginx/certbot_nginx/parser.py b/certbot-nginx/certbot_nginx/parser.py index e7992810a..aae6ce122 100644 --- a/certbot-nginx/certbot_nginx/parser.py +++ b/certbot-nginx/certbot_nginx/parser.py @@ -168,7 +168,7 @@ class NginxParser(object): self.parsed[item] = parsed trees.append(parsed) except IOError: - logger.warn("Could not open file: %s", item) + logger.warning("Could not open file: %s", item) except pyparsing.ParseException: logger.debug("Could not parse file: %s", item) return trees diff --git a/certbot/cli.py b/certbot/cli.py index d353f5402..5813af730 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -158,7 +158,7 @@ def possible_deprecation_warning(config): # need warnings return if "CERTBOT_AUTO" not in os.environ: - logger.warn("You are running with an old copy of letsencrypt-auto that does " + 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.") diff --git a/certbot/client.py b/certbot/client.py index 81b7ccdc6..0f414b474 100644 --- a/certbot/client.py +++ b/certbot/client.py @@ -104,10 +104,10 @@ def register(config, account_storage, tos_cb=None): if not config.register_unsafely_without_email: msg = ("No email was provided and " "--register-unsafely-without-email was not present.") - logger.warn(msg) + logger.warning(msg) raise errors.Error(msg) if not config.dry_run: - logger.warn("Registering without email!") + logger.warning("Registering without email!") # Each new registration shall use a fresh new key key = jose.JWKRSA(key=jose.ComparableRSAKey( @@ -453,10 +453,10 @@ class Client(object): try: self.installer.enhance(dom, enhancement, options) except errors.PluginEnhancementAlreadyPresent: - logger.warn("Enhancement %s was already set.", + logger.warning("Enhancement %s was already set.", enhancement) except errors.PluginError: - logger.warn("Unable to set enhancement %s for %s", + logger.warning("Unable to set enhancement %s for %s", enhancement, dom) raise diff --git a/certbot/hooks.py b/certbot/hooks.py index 1a3e4a98e..f37f81c6e 100644 --- a/certbot/hooks.py +++ b/certbot/hooks.py @@ -53,7 +53,7 @@ def post_hook(config, final=False): if not pre_hook.already: logger.info("No renewals attempted, so not running post-hook") if config.verb != "renew": - logger.warn("Sanity failure in renewal hooks") + logger.warning("Sanity failure in renewal hooks") return if final or config.verb != "renew": logger.info("Running post-hook command: %s", config.post_hook) diff --git a/certbot/main.py b/certbot/main.py index 8bccc524d..511046df0 100644 --- a/certbot/main.py +++ b/certbot/main.py @@ -773,5 +773,5 @@ def main(cli_args=sys.argv[1:]): if __name__ == "__main__": err_string = main() if err_string: - logger.warn("Exiting with message %s", err_string) + logger.warning("Exiting with message %s", err_string) sys.exit(err_string) # pragma: no cover diff --git a/certbot/plugins/selection.py b/certbot/plugins/selection.py index 1d7fa323f..21ebe9029 100644 --- a/certbot/plugins/selection.py +++ b/certbot/plugins/selection.py @@ -174,7 +174,7 @@ def choose_configurator_plugins(config, plugins, verb): if verb == "install": need_inst = True if config.authenticator: - logger.warn("Specifying an authenticator doesn't make sense in install mode") + logger.warning("Specifying an authenticator doesn't make sense in install mode") # Try to meet the user's request and/or ask them to pick plugins authenticator = installer = None diff --git a/certbot/plugins/util.py b/certbot/plugins/util.py index cdba88a87..76372154c 100644 --- a/certbot/plugins/util.py +++ b/certbot/plugins/util.py @@ -38,7 +38,7 @@ def path_surgery(restart_cmd): return True else: expanded = " expanded" if any(added) else "" - logger.warn("Failed to find %s in%s PATH: %s", restart_cmd, expanded, path) + logger.warning("Failed to find %s in%s PATH: %s", restart_cmd, expanded, path) return False def already_listening(port, renewer=False): diff --git a/certbot/plugins/util_test.py b/certbot/plugins/util_test.py index 6f6e14571..6ba5e8bcf 100644 --- a/certbot/plugins/util_test.py +++ b/certbot/plugins/util_test.py @@ -8,7 +8,7 @@ import psutil class PathSurgeryTest(unittest.TestCase): """Tests for certbot.plugins.path_surgery.""" - @mock.patch("certbot.plugins.util.logger.warn") + @mock.patch("certbot.plugins.util.logger.warning") @mock.patch("certbot.plugins.util.logger.debug") def test_path_surgery(self, mock_debug, mock_warn): from certbot.plugins.util import path_surgery diff --git a/certbot/reverter.py b/certbot/reverter.py index 6dde05077..1c404e29b 100644 --- a/certbot/reverter.py +++ b/certbot/reverter.py @@ -552,7 +552,7 @@ class Reverter(object): others.sort() if others[-1] != timestamp: timetravel = str(float(others[-1]) + 1) - logger.warn("Current timestamp %s does not correspond to newest reverter " + logger.warning("Current timestamp %s does not correspond to newest reverter " "checkpoint; your clock probably jumped. Time travelling to %s", timestamp, timetravel) timestamp = timetravel diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index 9156277a9..e7ae6bbd1 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -82,7 +82,7 @@ class RegisterTest(unittest.TestCase): self.config.register_unsafely_without_email = True self.config.dry_run = False self._call() - mock_logger.warn.assert_called_once_with(mock.ANY) + mock_logger.warning.assert_called_once_with(mock.ANY) def test_unsupported_error(self): from acme import messages diff --git a/certbot/util.py b/certbot/util.py index 2b40a0f2c..65aae59e2 100644 --- a/certbot/util.py +++ b/certbot/util.py @@ -349,7 +349,7 @@ def safe_email(email): if EMAIL_REGEX.match(email) is not None: return not email.startswith(".") and ".." not in email else: - logger.warn("Invalid email address: %s.", email) + logger.warning("Invalid email address: %s.", email) return False From 0fb0a662e329b609beba52a8f6ddc0d7d3333af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Fri, 22 Jul 2016 09:49:56 +0300 Subject: [PATCH 067/126] Zero mock warning call count after setting three checkpoints _setup_three_checkpoints may generate warnings that are not being tested in test_rollback_too_many; just the ones directly from rollback_checkpoints are. --- certbot/tests/reverter_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/tests/reverter_test.py b/certbot/tests/reverter_test.py index 58cc68dce..450cecacf 100644 --- a/certbot/tests/reverter_test.py +++ b/certbot/tests/reverter_test.py @@ -362,8 +362,8 @@ class TestFullCheckpointsReverter(unittest.TestCase): self.assertEqual(mock_logger.warning.call_count, 1) # Test Generic warning - mock_logger.warning.call_count = 0 self._setup_three_checkpoints() + mock_logger.warning.call_count = 0 self.reverter.rollback_checkpoints(4) self.assertEqual(mock_logger.warning.call_count, 1) From 774e9870aeb2cc66cd6ee376070dba76299ee218 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Mon, 25 Jul 2016 10:23:40 +0300 Subject: [PATCH 068/126] Fixed the renew URL --- certbot/plugins/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot/plugins/util.py b/certbot/plugins/util.py index 36f4b0ff4..1a4379ba4 100644 --- a/certbot/plugins/util.py +++ b/certbot/plugins/util.py @@ -19,8 +19,8 @@ logger = logging.getLogger(__name__) RENEWER_EXTRA_MSG = ( " For automated renewal, you may want to use a script that stops" " and starts your webserver. You can find an example at" - " https://letsencrypt.org/howitworks/#writing-your-own-renewal-script" - ". Alternatively you can use the webroot plugin to renew without" + " https://certbot.eff.org/docs/using.html#renewal ." + " Alternatively you can use the webroot plugin to renew without" " needing to stop and start your webserver.") From 9bd361b28d62a9c81695f0e2e4c7211fb70e5d66 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Mon, 25 Jul 2016 11:13:16 +0300 Subject: [PATCH 069/126] Remove psutil dependency --- certbot-auto | 22 ---------------------- letsencrypt-auto | 22 ---------------------- letsencrypt-auto-source/letsencrypt-auto | 22 ---------------------- setup.py | 2 +- 4 files changed, 1 insertion(+), 67 deletions(-) diff --git a/certbot-auto b/certbot-auto index 80f39cf59..3b5734914 100755 --- a/certbot-auto +++ b/certbot-auto @@ -645,28 +645,6 @@ parsedatetime==2.1 \ pbr==1.8.1 \ --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \ --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649 -psutil==3.3.0 \ - --hash=sha256:584f0b29fcc5d523b433cb8918b2fc74d67e30ee0b44a95baf031528f424619f \ - --hash=sha256:28ca0b6e9d99aa8dc286e8747a4471362b69812a25291de29b6a8d70a1545a0d \ - --hash=sha256:167ad5fff52a672c4ddc1c1a0b25146d6813ebb08a9aab0a3ac45f8a5b669c3b \ - --hash=sha256:e6dea6173a988727bb223d3497349ad5cdef5c0b282eff2d83e5f9065c53f85f \ - --hash=sha256:2af5e0a4aad66049955d0734aa4e3dc8caa17a9eaf8b4c1a27a5f1ee6e40f6fc \ - --hash=sha256:d9884dc0dc2e55e2448e495778dc9899c1c8bf37aeb2f434c1bea74af93c2683 \ - --hash=sha256:e27c2fe6dfcc8738be3d2c5a022f785eb72971057e1a9e1e34fba73bce8a71a6 \ - --hash=sha256:65afd6fecc8f3aed09ee4be63583bc8eb472f06ceaa4fe24c4d1d5a1a3c0e13f \ - --hash=sha256:ba1c558fbfcdf94515c2394b1155c1dc56e2bc2a9c17d30349827c9ed8a67e46 \ - --hash=sha256:ba95ea0022dcb64d36f0c1335c0605fae35bdf3e0fea8d92f5d0f6456a35e55b \ - --hash=sha256:421b6591d16b509aaa8d8c15821d66bb94cb4a8dc4385cad5c51b85d4a096d85 \ - --hash=sha256:326b305cbdb6f94dafbfe2c26b11da88b0ab07b8a07f8188ab9d75ff0c6e841a \ - --hash=sha256:9aede5b2b6fe46b3748ea8e5214443890d1634027bef3d33b7dad16556830278 \ - --hash=sha256:73bed1db894d1aa9c3c7e611d302cdeab7ae8a0dc0eeaf76727878db1ac5cd87 \ - --hash=sha256:935b5dd6d558af512f42501a7c08f41d7aff139af1bb3959daa3abb859234d6c \ - --hash=sha256:4ca0111cf157dcc0f2f69a323c5b5478718d68d45fc9435d84be0ec0f186215b \ - --hash=sha256:b6f13c95398a3fcf0226c4dcfa448560ba5865259cd96ec2810658651e932189 \ - --hash=sha256:ee6be30d1635bbdea4c4325d507dc8a0dbbde7e1c198bd62ddb9f43198b9e214 \ - --hash=sha256:dfa786858c268d7fbbe1b6175e001ec02738d7cfae0a7ce77bf9b651af676729 \ - --hash=sha256:aa77f9de72af9c16cc288cd4a24cf58824388f57d7a81e400c4616457629870e \ - --hash=sha256:f500093357d04da8140d87932cac2e54ef592a54ca8a743abb2850f60c2c22eb pyasn1==0.1.9 \ --hash=sha256:61f9d99e3cef65feb1bfe3a2eef7a93eb93819d345bf54bcd42f4e63d5204dae \ --hash=sha256:1802a6dd32045e472a419db1441aecab469d33e0d2749e192abdec52101724af \ diff --git a/letsencrypt-auto b/letsencrypt-auto index 80f39cf59..3b5734914 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -645,28 +645,6 @@ parsedatetime==2.1 \ pbr==1.8.1 \ --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \ --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649 -psutil==3.3.0 \ - --hash=sha256:584f0b29fcc5d523b433cb8918b2fc74d67e30ee0b44a95baf031528f424619f \ - --hash=sha256:28ca0b6e9d99aa8dc286e8747a4471362b69812a25291de29b6a8d70a1545a0d \ - --hash=sha256:167ad5fff52a672c4ddc1c1a0b25146d6813ebb08a9aab0a3ac45f8a5b669c3b \ - --hash=sha256:e6dea6173a988727bb223d3497349ad5cdef5c0b282eff2d83e5f9065c53f85f \ - --hash=sha256:2af5e0a4aad66049955d0734aa4e3dc8caa17a9eaf8b4c1a27a5f1ee6e40f6fc \ - --hash=sha256:d9884dc0dc2e55e2448e495778dc9899c1c8bf37aeb2f434c1bea74af93c2683 \ - --hash=sha256:e27c2fe6dfcc8738be3d2c5a022f785eb72971057e1a9e1e34fba73bce8a71a6 \ - --hash=sha256:65afd6fecc8f3aed09ee4be63583bc8eb472f06ceaa4fe24c4d1d5a1a3c0e13f \ - --hash=sha256:ba1c558fbfcdf94515c2394b1155c1dc56e2bc2a9c17d30349827c9ed8a67e46 \ - --hash=sha256:ba95ea0022dcb64d36f0c1335c0605fae35bdf3e0fea8d92f5d0f6456a35e55b \ - --hash=sha256:421b6591d16b509aaa8d8c15821d66bb94cb4a8dc4385cad5c51b85d4a096d85 \ - --hash=sha256:326b305cbdb6f94dafbfe2c26b11da88b0ab07b8a07f8188ab9d75ff0c6e841a \ - --hash=sha256:9aede5b2b6fe46b3748ea8e5214443890d1634027bef3d33b7dad16556830278 \ - --hash=sha256:73bed1db894d1aa9c3c7e611d302cdeab7ae8a0dc0eeaf76727878db1ac5cd87 \ - --hash=sha256:935b5dd6d558af512f42501a7c08f41d7aff139af1bb3959daa3abb859234d6c \ - --hash=sha256:4ca0111cf157dcc0f2f69a323c5b5478718d68d45fc9435d84be0ec0f186215b \ - --hash=sha256:b6f13c95398a3fcf0226c4dcfa448560ba5865259cd96ec2810658651e932189 \ - --hash=sha256:ee6be30d1635bbdea4c4325d507dc8a0dbbde7e1c198bd62ddb9f43198b9e214 \ - --hash=sha256:dfa786858c268d7fbbe1b6175e001ec02738d7cfae0a7ce77bf9b651af676729 \ - --hash=sha256:aa77f9de72af9c16cc288cd4a24cf58824388f57d7a81e400c4616457629870e \ - --hash=sha256:f500093357d04da8140d87932cac2e54ef592a54ca8a743abb2850f60c2c22eb pyasn1==0.1.9 \ --hash=sha256:61f9d99e3cef65feb1bfe3a2eef7a93eb93819d345bf54bcd42f4e63d5204dae \ --hash=sha256:1802a6dd32045e472a419db1441aecab469d33e0d2749e192abdec52101724af \ diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 22c914ed8..22963edcb 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -651,28 +651,6 @@ parsedatetime==2.1 \ pbr==1.8.1 \ --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \ --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649 -psutil==3.3.0 \ - --hash=sha256:584f0b29fcc5d523b433cb8918b2fc74d67e30ee0b44a95baf031528f424619f \ - --hash=sha256:28ca0b6e9d99aa8dc286e8747a4471362b69812a25291de29b6a8d70a1545a0d \ - --hash=sha256:167ad5fff52a672c4ddc1c1a0b25146d6813ebb08a9aab0a3ac45f8a5b669c3b \ - --hash=sha256:e6dea6173a988727bb223d3497349ad5cdef5c0b282eff2d83e5f9065c53f85f \ - --hash=sha256:2af5e0a4aad66049955d0734aa4e3dc8caa17a9eaf8b4c1a27a5f1ee6e40f6fc \ - --hash=sha256:d9884dc0dc2e55e2448e495778dc9899c1c8bf37aeb2f434c1bea74af93c2683 \ - --hash=sha256:e27c2fe6dfcc8738be3d2c5a022f785eb72971057e1a9e1e34fba73bce8a71a6 \ - --hash=sha256:65afd6fecc8f3aed09ee4be63583bc8eb472f06ceaa4fe24c4d1d5a1a3c0e13f \ - --hash=sha256:ba1c558fbfcdf94515c2394b1155c1dc56e2bc2a9c17d30349827c9ed8a67e46 \ - --hash=sha256:ba95ea0022dcb64d36f0c1335c0605fae35bdf3e0fea8d92f5d0f6456a35e55b \ - --hash=sha256:421b6591d16b509aaa8d8c15821d66bb94cb4a8dc4385cad5c51b85d4a096d85 \ - --hash=sha256:326b305cbdb6f94dafbfe2c26b11da88b0ab07b8a07f8188ab9d75ff0c6e841a \ - --hash=sha256:9aede5b2b6fe46b3748ea8e5214443890d1634027bef3d33b7dad16556830278 \ - --hash=sha256:73bed1db894d1aa9c3c7e611d302cdeab7ae8a0dc0eeaf76727878db1ac5cd87 \ - --hash=sha256:935b5dd6d558af512f42501a7c08f41d7aff139af1bb3959daa3abb859234d6c \ - --hash=sha256:4ca0111cf157dcc0f2f69a323c5b5478718d68d45fc9435d84be0ec0f186215b \ - --hash=sha256:b6f13c95398a3fcf0226c4dcfa448560ba5865259cd96ec2810658651e932189 \ - --hash=sha256:ee6be30d1635bbdea4c4325d507dc8a0dbbde7e1c198bd62ddb9f43198b9e214 \ - --hash=sha256:dfa786858c268d7fbbe1b6175e001ec02738d7cfae0a7ce77bf9b651af676729 \ - --hash=sha256:aa77f9de72af9c16cc288cd4a24cf58824388f57d7a81e400c4616457629870e \ - --hash=sha256:f500093357d04da8140d87932cac2e54ef592a54ca8a743abb2850f60c2c22eb pyasn1==0.1.9 \ --hash=sha256:61f9d99e3cef65feb1bfe3a2eef7a93eb93819d345bf54bcd42f4e63d5204dae \ --hash=sha256:1802a6dd32045e472a419db1441aecab469d33e0d2749e192abdec52101724af \ diff --git a/setup.py b/setup.py index 21cda901a..548314ad8 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,6 @@ install_requires = [ 'configobj', 'cryptography>=0.7', # load_pem_x509_certificate 'parsedatetime>=1.3', # Calendar.parseDT - 'psutil>=2.2.1', # 2.1.0 for net_connections and 2.2.1 resolves #1080 'PyOpenSSL', 'pyrfc3339', 'python2-pythondialog>=3.2.2rc1', # Debian squeeze support, cf. #280 @@ -70,6 +69,7 @@ dev_extras = [ 'coverage', 'nose', 'pep8', + 'psutil>=2.2.1', # for tests, optional 'pylint==1.4.2', # upstream #248 'tox', 'twine', From f4f80b339f0cf51220878a1515f04cc9729d9598 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Mon, 25 Jul 2016 11:36:42 +0300 Subject: [PATCH 070/126] Fixed merge error --- certbot/plugins/util.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/certbot/plugins/util.py b/certbot/plugins/util.py index e04123b94..b97ca1afd 100644 --- a/certbot/plugins/util.py +++ b/certbot/plugins/util.py @@ -50,9 +50,8 @@ def path_surgery(restart_cmd): return True else: expanded = " expanded" if any(added) else "" - logger.warning("Failed to find %s in%s PATH: %s", restart_cmd, expanded, path) - return False - + logger.warning("Failed to find %s in%s PATH: %s", restart_cmd, + expanded, path) return False From fb399a844b2b388ceda9943b181fd205173c9c7a Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 25 Jul 2016 12:51:33 -0700 Subject: [PATCH 071/126] Fix Feedback link --- docs/ciphers.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/ciphers.rst b/docs/ciphers.rst index dd05aef68..59d6971ca 100644 --- a/docs/ciphers.rst +++ b/docs/ciphers.rst @@ -151,9 +151,7 @@ Resources for recommendations In the course of considering how to handle this issue, we received recommendations with sources of expert guidance on ciphersuites and other cryptographic parameters. We're grateful to everyone who contributed -suggestions. The recommendations we received are available at - -https://github.com/certbot/certbot/wiki/Ciphersuite-guidance +suggestions. The recommendations we received are available under Feedback_. Certbot users are welcome to review these authorities to better inform their own cryptographic parameter choices. We also From 7a0d4d48a06b712ee756322c9d59c0a49d040fa4 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 25 Jul 2016 12:54:14 -0700 Subject: [PATCH 072/126] Remove broken known issues link --- docs/contributing.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index bdda0e2e6..f1eec04df 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -323,11 +323,7 @@ Steps: should run the integration tests, see `integration`_. See `Known Issues`_ for some common failures that have nothing to do with your code. 7. Submit the PR. -8. Did your tests pass on Travis? If they didn't, it might not be your fault! - See `Known Issues`_. If it's not a known issue, fix any errors. - -.. _Known Issues: - https://github.com/certbot/certbot/wiki/Known-issues +8. Did your tests pass on Travis? If they didn't, fix any errors. Updating the documentation ========================== From 6830bb01f85834f267a93b774ff45cff4fe0e8cf Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 25 Jul 2016 13:01:47 -0700 Subject: [PATCH 073/126] Change ciphersuite link from wiki to rst file --- docs/using.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/using.rst b/docs/using.rst index ccd1d8f97..0945f4faf 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -406,7 +406,7 @@ good reason to do so. You should definitely read the :ref:`where-certs` section, in order to know how to manage the certs -manually. https://github.com/certbot/certbot/wiki/Ciphersuite-guidance +manually. `Our ciphersuites page `__ provides some information about recommended ciphersuites. If none of these make much sense to you, you should definitely use the certbot-auto_ method, which enables you to use installer plugins From a0efc2c27cf7f5c9d73f7551c28ea66f68de090a Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 25 Jul 2016 13:13:54 -0700 Subject: [PATCH 074/126] Convert ciphers.rst markdown to rst --- docs/ciphers.rst | 60 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/docs/ciphers.rst b/docs/ciphers.rst index 59d6971ca..c429c185d 100644 --- a/docs/ciphers.rst +++ b/docs/ciphers.rst @@ -205,40 +205,46 @@ so far is redirecting HTTP requests to HTTPS in web servers, the or a family of enhancements, one per selectable ciphersuite configuration. Feedback ----- +======== We recieve lots of feedback on the type of ciphersuites that Let's Encrypt supports and list some coallated feedback below. This section aims to track suggestions and references that people have offered or identified to improve the ciphersuites that Let's Encrypt enables when configuring TLS on servers. Because of the Chatham House Rule applicable to some of the discussions, people are *not* individually credited for their suggestions, but most suggestions here were made or found by other people, and I thank them for their contributions. Some people provided rationale information mostly having to do with compatibility of particular user-agents (especially UAs that don't support ECC, or that don't support DH groups > 1024 bits). Some ciphersuite configurations have been chosen to try to increase compatibility with older UAs while allowing newer UAs to negotiate stronger crypto. For example, some configurations forego forward secrecy entirely for connections from old UAs, like by offering ECDHE and RSA key exchange, but no DHE at all. (There are UAs that can fail the negotiation completely if a DHE ciphersuite with prime > 1024 bits is offered.) -## References ## +References +---------- -### RFC 7575 ### +RFC 7575 +~~~~~~~~ IETF has published a BCP document, RFC 7525, "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" https://datatracker.ietf.org/doc/rfc7525/ -### BetterCrypto.org ### +BetterCrypto.org +~~~~~~~~~~~~~~~~ BetterCrypto.org, a collaboration of mostly European IT security experts, has published a draft paper, "Applied Crypto Hardening" https://bettercrypto.org/static/applied-crypto-hardening.pdf -### FF-DHE Internet-Draft ### +FF-DHE Internet-Draft +~~~~~~~~~~~~~~~~~~~~~ Gillmor's Internet-Draft "Negotiated Discrete Log Diffie-Hellman Ephemeral Parameters for TLS" is being developed at the IETF TLS WG. It advocates using *standardized* DH groups in all cases, not individually-chosen ones (mostly because of the Triple Handshake attack which can involve maliciously choosing invalid DH groups). The draft provides a list of recommended groups, with primes beginning at 2048 bits and going up from there. It also has a new protocol mechanism for agreeing to use these groups, with the possibility of backwards compatibility (and use of weaker DH groups) for older clients and servers that don't know about this mechanism. https://tools.ietf.org/html/draft-ietf-tls-negotiated-ff-dhe-10 -### Mozilla ### +Mozilla +~~~~~~~ Mozilla's general server configuration guidance is available at https://wiki.mozilla.org/Security/Server_Side_TLS Mozilla has also produced a configuration generator: https://mozilla.github.io/server-side-tls/ssl-config-generator/ -### Dutch National Cyber Security Centre ### +Dutch National Cyber Security Centre +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Dutch National Cyber Security Centre has published guidance on "ICT-beveiligingsrichtlijnen voor Transport Layer Security (TLS)" ("IT Security Guidelines for Transport Layer Security (TLS)"). These are available only in Dutch at @@ -246,13 +252,15 @@ https://www.ncsc.nl/dienstverlening/expertise-advies/kennisdeling/whitepapers/ic I have access to an English-language summary of the recommendations. -### Keylength.com ### +Keylength.com +~~~~~~~~~~~~~ Damien Giry collects recommendations by academic researchers and standards organizations about keylengths for particular cryptoperiods, years, or security levels. The keylength recommendations of the various sources are summarized in a chart. This site has been updated over time and includes expert guidance from eight sources published between 2000 and 2015. http://www.keylength.com/ -### NIST ### +NIST +~~~~ NISA published its "NIST Special Publication 800-52 Revision 1: Guidelines for the Selection, Configuration, and Use of Transport Layer Security (TLS) Implementations" http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r1.pdf @@ -261,13 +269,15 @@ and its "NIST Special Publication 800-57: Recommendation for Key Management – http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf -### ENISA ### +ENISA +~~~~~ ENISA published its "Algorithms, Key Sizes and Parameters Report - 2013" https://www.enisa.europa.eu/activities/identity-and-trust/library/deliverables/algorithms-key-sizes-and-parameters-report -## WeakDH/Logjam ## +WeakDH/Logjam +------------- The WeakDH/Logjam research has thrown into question the safety of some existing practice using DH ciphersuites, especially the use of standardized groups with a prime ≤ 1024 bits. The authors provided detailed guidance, including ciphersuite lists, at @@ -280,40 +290,50 @@ https://www.ietf.org/mail-archive/web/tls/current/msg16496.html In particular, he supports ECDHE and also supports the use of the standardized groups in the FF-DHE Internet-Draft mentioned above (which isn't clear from the group's original recommendations). -## Particular sites' opinions or configurations ## +Particular sites' opinions or configurations +-------------------------------------------- -### Amazon ELB ### +Amazon ELB +~~~~~~~~~~ Amazon ELB explains its current ciphersuite choices at https://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-security-policy-table.html -### U.S. Government 18F ### +U.S. Government 18F +~~~~~~~~~~~~~~~~~~~ The 18F site (https://18f.gsa.gov/) is using -`ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';` +:: -### Duraconf ### + ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED'; + +Duraconf +~~~~~~~~ The Duraconf project collects particular configuration files, with an apparent focus on avoiding the use of obsolete symmetric ciphers and hash functions, and favoring forward secrecy while not requiring it. https://github.com/ioerror/duraconf -## Site scanning or rating tools ## +Site scanning or rating tools +----------------------------- -### Qualys SSL Labs ### +Qualys SSL Labs +~~~~~~~~~~~~~~~ Qualys offers the best-known TLS security scanner, maintained by Ivan Ristić. https://www.ssllabs.com/ -### Dutch NCSC ### +Dutch NCSC +~~~~~~~~~~ The Dutch NCSC, mentioned above, has also made available its own site security scanner which indicates how well sites comply with the recommendations. https://en.internet.nl/ -## Java compatibility issue ## +Java compatibility issue +------------------------ A lot of backward-compatibility concerns have to do with Java hard-coding DHE primes to a 1024-bit limit, accepting DHE ciphersuites in negotiation, and then aborting the connection entirely if a prime > 1024 bits is presented. The simple summary is that servers offering a Java-compatible DHE ciphersuite in preference to other Java-compatible ciphersuites, and then presenting a DH group with a prime > 1024 bits, will be completely incompatible with clients running some versions of Java. (This may also be the case with very old MSIE versions...?) There are various strategies for dealing with this, and maybe we can document the options here. From ade8403310b247efe968b86fa2f1e35b1011410e Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 27 Jul 2016 15:36:12 +0300 Subject: [PATCH 075/126] Revert "Remove psutil dependency" This reverts commit 9bd361b28d62a9c81695f0e2e4c7211fb70e5d66. --- certbot-auto | 22 ++++++++++++++++++++++ letsencrypt-auto | 22 ++++++++++++++++++++++ letsencrypt-auto-source/letsencrypt-auto | 22 ++++++++++++++++++++++ setup.py | 2 +- 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/certbot-auto b/certbot-auto index 3b5734914..80f39cf59 100755 --- a/certbot-auto +++ b/certbot-auto @@ -645,6 +645,28 @@ parsedatetime==2.1 \ pbr==1.8.1 \ --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \ --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649 +psutil==3.3.0 \ + --hash=sha256:584f0b29fcc5d523b433cb8918b2fc74d67e30ee0b44a95baf031528f424619f \ + --hash=sha256:28ca0b6e9d99aa8dc286e8747a4471362b69812a25291de29b6a8d70a1545a0d \ + --hash=sha256:167ad5fff52a672c4ddc1c1a0b25146d6813ebb08a9aab0a3ac45f8a5b669c3b \ + --hash=sha256:e6dea6173a988727bb223d3497349ad5cdef5c0b282eff2d83e5f9065c53f85f \ + --hash=sha256:2af5e0a4aad66049955d0734aa4e3dc8caa17a9eaf8b4c1a27a5f1ee6e40f6fc \ + --hash=sha256:d9884dc0dc2e55e2448e495778dc9899c1c8bf37aeb2f434c1bea74af93c2683 \ + --hash=sha256:e27c2fe6dfcc8738be3d2c5a022f785eb72971057e1a9e1e34fba73bce8a71a6 \ + --hash=sha256:65afd6fecc8f3aed09ee4be63583bc8eb472f06ceaa4fe24c4d1d5a1a3c0e13f \ + --hash=sha256:ba1c558fbfcdf94515c2394b1155c1dc56e2bc2a9c17d30349827c9ed8a67e46 \ + --hash=sha256:ba95ea0022dcb64d36f0c1335c0605fae35bdf3e0fea8d92f5d0f6456a35e55b \ + --hash=sha256:421b6591d16b509aaa8d8c15821d66bb94cb4a8dc4385cad5c51b85d4a096d85 \ + --hash=sha256:326b305cbdb6f94dafbfe2c26b11da88b0ab07b8a07f8188ab9d75ff0c6e841a \ + --hash=sha256:9aede5b2b6fe46b3748ea8e5214443890d1634027bef3d33b7dad16556830278 \ + --hash=sha256:73bed1db894d1aa9c3c7e611d302cdeab7ae8a0dc0eeaf76727878db1ac5cd87 \ + --hash=sha256:935b5dd6d558af512f42501a7c08f41d7aff139af1bb3959daa3abb859234d6c \ + --hash=sha256:4ca0111cf157dcc0f2f69a323c5b5478718d68d45fc9435d84be0ec0f186215b \ + --hash=sha256:b6f13c95398a3fcf0226c4dcfa448560ba5865259cd96ec2810658651e932189 \ + --hash=sha256:ee6be30d1635bbdea4c4325d507dc8a0dbbde7e1c198bd62ddb9f43198b9e214 \ + --hash=sha256:dfa786858c268d7fbbe1b6175e001ec02738d7cfae0a7ce77bf9b651af676729 \ + --hash=sha256:aa77f9de72af9c16cc288cd4a24cf58824388f57d7a81e400c4616457629870e \ + --hash=sha256:f500093357d04da8140d87932cac2e54ef592a54ca8a743abb2850f60c2c22eb pyasn1==0.1.9 \ --hash=sha256:61f9d99e3cef65feb1bfe3a2eef7a93eb93819d345bf54bcd42f4e63d5204dae \ --hash=sha256:1802a6dd32045e472a419db1441aecab469d33e0d2749e192abdec52101724af \ diff --git a/letsencrypt-auto b/letsencrypt-auto index 3b5734914..80f39cf59 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -645,6 +645,28 @@ parsedatetime==2.1 \ pbr==1.8.1 \ --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \ --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649 +psutil==3.3.0 \ + --hash=sha256:584f0b29fcc5d523b433cb8918b2fc74d67e30ee0b44a95baf031528f424619f \ + --hash=sha256:28ca0b6e9d99aa8dc286e8747a4471362b69812a25291de29b6a8d70a1545a0d \ + --hash=sha256:167ad5fff52a672c4ddc1c1a0b25146d6813ebb08a9aab0a3ac45f8a5b669c3b \ + --hash=sha256:e6dea6173a988727bb223d3497349ad5cdef5c0b282eff2d83e5f9065c53f85f \ + --hash=sha256:2af5e0a4aad66049955d0734aa4e3dc8caa17a9eaf8b4c1a27a5f1ee6e40f6fc \ + --hash=sha256:d9884dc0dc2e55e2448e495778dc9899c1c8bf37aeb2f434c1bea74af93c2683 \ + --hash=sha256:e27c2fe6dfcc8738be3d2c5a022f785eb72971057e1a9e1e34fba73bce8a71a6 \ + --hash=sha256:65afd6fecc8f3aed09ee4be63583bc8eb472f06ceaa4fe24c4d1d5a1a3c0e13f \ + --hash=sha256:ba1c558fbfcdf94515c2394b1155c1dc56e2bc2a9c17d30349827c9ed8a67e46 \ + --hash=sha256:ba95ea0022dcb64d36f0c1335c0605fae35bdf3e0fea8d92f5d0f6456a35e55b \ + --hash=sha256:421b6591d16b509aaa8d8c15821d66bb94cb4a8dc4385cad5c51b85d4a096d85 \ + --hash=sha256:326b305cbdb6f94dafbfe2c26b11da88b0ab07b8a07f8188ab9d75ff0c6e841a \ + --hash=sha256:9aede5b2b6fe46b3748ea8e5214443890d1634027bef3d33b7dad16556830278 \ + --hash=sha256:73bed1db894d1aa9c3c7e611d302cdeab7ae8a0dc0eeaf76727878db1ac5cd87 \ + --hash=sha256:935b5dd6d558af512f42501a7c08f41d7aff139af1bb3959daa3abb859234d6c \ + --hash=sha256:4ca0111cf157dcc0f2f69a323c5b5478718d68d45fc9435d84be0ec0f186215b \ + --hash=sha256:b6f13c95398a3fcf0226c4dcfa448560ba5865259cd96ec2810658651e932189 \ + --hash=sha256:ee6be30d1635bbdea4c4325d507dc8a0dbbde7e1c198bd62ddb9f43198b9e214 \ + --hash=sha256:dfa786858c268d7fbbe1b6175e001ec02738d7cfae0a7ce77bf9b651af676729 \ + --hash=sha256:aa77f9de72af9c16cc288cd4a24cf58824388f57d7a81e400c4616457629870e \ + --hash=sha256:f500093357d04da8140d87932cac2e54ef592a54ca8a743abb2850f60c2c22eb pyasn1==0.1.9 \ --hash=sha256:61f9d99e3cef65feb1bfe3a2eef7a93eb93819d345bf54bcd42f4e63d5204dae \ --hash=sha256:1802a6dd32045e472a419db1441aecab469d33e0d2749e192abdec52101724af \ diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index d13abb30e..27b11c656 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -651,6 +651,28 @@ parsedatetime==2.1 \ pbr==1.8.1 \ --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \ --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649 +psutil==3.3.0 \ + --hash=sha256:584f0b29fcc5d523b433cb8918b2fc74d67e30ee0b44a95baf031528f424619f \ + --hash=sha256:28ca0b6e9d99aa8dc286e8747a4471362b69812a25291de29b6a8d70a1545a0d \ + --hash=sha256:167ad5fff52a672c4ddc1c1a0b25146d6813ebb08a9aab0a3ac45f8a5b669c3b \ + --hash=sha256:e6dea6173a988727bb223d3497349ad5cdef5c0b282eff2d83e5f9065c53f85f \ + --hash=sha256:2af5e0a4aad66049955d0734aa4e3dc8caa17a9eaf8b4c1a27a5f1ee6e40f6fc \ + --hash=sha256:d9884dc0dc2e55e2448e495778dc9899c1c8bf37aeb2f434c1bea74af93c2683 \ + --hash=sha256:e27c2fe6dfcc8738be3d2c5a022f785eb72971057e1a9e1e34fba73bce8a71a6 \ + --hash=sha256:65afd6fecc8f3aed09ee4be63583bc8eb472f06ceaa4fe24c4d1d5a1a3c0e13f \ + --hash=sha256:ba1c558fbfcdf94515c2394b1155c1dc56e2bc2a9c17d30349827c9ed8a67e46 \ + --hash=sha256:ba95ea0022dcb64d36f0c1335c0605fae35bdf3e0fea8d92f5d0f6456a35e55b \ + --hash=sha256:421b6591d16b509aaa8d8c15821d66bb94cb4a8dc4385cad5c51b85d4a096d85 \ + --hash=sha256:326b305cbdb6f94dafbfe2c26b11da88b0ab07b8a07f8188ab9d75ff0c6e841a \ + --hash=sha256:9aede5b2b6fe46b3748ea8e5214443890d1634027bef3d33b7dad16556830278 \ + --hash=sha256:73bed1db894d1aa9c3c7e611d302cdeab7ae8a0dc0eeaf76727878db1ac5cd87 \ + --hash=sha256:935b5dd6d558af512f42501a7c08f41d7aff139af1bb3959daa3abb859234d6c \ + --hash=sha256:4ca0111cf157dcc0f2f69a323c5b5478718d68d45fc9435d84be0ec0f186215b \ + --hash=sha256:b6f13c95398a3fcf0226c4dcfa448560ba5865259cd96ec2810658651e932189 \ + --hash=sha256:ee6be30d1635bbdea4c4325d507dc8a0dbbde7e1c198bd62ddb9f43198b9e214 \ + --hash=sha256:dfa786858c268d7fbbe1b6175e001ec02738d7cfae0a7ce77bf9b651af676729 \ + --hash=sha256:aa77f9de72af9c16cc288cd4a24cf58824388f57d7a81e400c4616457629870e \ + --hash=sha256:f500093357d04da8140d87932cac2e54ef592a54ca8a743abb2850f60c2c22eb pyasn1==0.1.9 \ --hash=sha256:61f9d99e3cef65feb1bfe3a2eef7a93eb93819d345bf54bcd42f4e63d5204dae \ --hash=sha256:1802a6dd32045e472a419db1441aecab469d33e0d2749e192abdec52101724af \ diff --git a/setup.py b/setup.py index 548314ad8..21cda901a 100644 --- a/setup.py +++ b/setup.py @@ -40,6 +40,7 @@ install_requires = [ 'configobj', 'cryptography>=0.7', # load_pem_x509_certificate 'parsedatetime>=1.3', # Calendar.parseDT + 'psutil>=2.2.1', # 2.1.0 for net_connections and 2.2.1 resolves #1080 'PyOpenSSL', 'pyrfc3339', 'python2-pythondialog>=3.2.2rc1', # Debian squeeze support, cf. #280 @@ -69,7 +70,6 @@ dev_extras = [ 'coverage', 'nose', 'pep8', - 'psutil>=2.2.1', # for tests, optional 'pylint==1.4.2', # upstream #248 'tox', 'twine', From 702e218f147de27c100a2278b8931a0d0419b22b Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 27 Jul 2016 15:40:47 +0300 Subject: [PATCH 076/126] Re-remove the psutil dependency from setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 21cda901a..548314ad8 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,6 @@ install_requires = [ 'configobj', 'cryptography>=0.7', # load_pem_x509_certificate 'parsedatetime>=1.3', # Calendar.parseDT - 'psutil>=2.2.1', # 2.1.0 for net_connections and 2.2.1 resolves #1080 'PyOpenSSL', 'pyrfc3339', 'python2-pythondialog>=3.2.2rc1', # Debian squeeze support, cf. #280 @@ -70,6 +69,7 @@ dev_extras = [ 'coverage', 'nose', 'pep8', + 'psutil>=2.2.1', # for tests, optional 'pylint==1.4.2', # upstream #248 'tox', 'twine', From 2feeb50109c25295ec383afdff16af75da114aba Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 27 Jul 2016 16:00:43 -0700 Subject: [PATCH 077/126] Fix spacing of nginx redirect blocks --- certbot-nginx/certbot_nginx/configurator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot-nginx/certbot_nginx/configurator.py b/certbot-nginx/certbot_nginx/configurator.py index 8157e48f1..b2d39b388 100644 --- a/certbot-nginx/certbot_nginx/configurator.py +++ b/certbot-nginx/certbot_nginx/configurator.py @@ -401,8 +401,8 @@ class NginxConfigurator(common.Plugin): :type unused_options: Not Available """ redirect_block = [[ - ['if', '($scheme != "https")'], - [['return', '301 https://$host$request_uri']] + ['\n', 'if', ' ', '($scheme != "https")'], + [['\n ', 'return', ' ', '301 https://$host$request_uri']] ]] self.parser.add_server_directives( vhost.filep, vhost.names, redirect_block, replace=False) From d55580025f99a3225dbffb0c0dfacad8b681102d Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 27 Jul 2016 16:07:07 -0700 Subject: [PATCH 078/126] Extra newlines & spacing --- certbot-nginx/certbot_nginx/configurator.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/certbot-nginx/certbot_nginx/configurator.py b/certbot-nginx/certbot_nginx/configurator.py index b2d39b388..a1c24b5c8 100644 --- a/certbot-nginx/certbot_nginx/configurator.py +++ b/certbot-nginx/certbot_nginx/configurator.py @@ -160,9 +160,9 @@ class NginxConfigurator(common.Plugin): stapling_directives = [] if self.version >= (1, 3, 7): stapling_directives = [ - ['\n', 'ssl_trusted_certificate', ' ', chain_path], - ['\n', 'ssl_stapling', ' ', 'on'], - ['\n', 'ssl_stapling_verify', ' ', 'on'], ['\n']] + ['\n ', 'ssl_trusted_certificate', ' ', chain_path], + ['\n ', 'ssl_stapling', ' ', 'on'], + ['\n ', 'ssl_stapling_verify', ' ', 'on'], ['\n']] if len(stapling_directives) != 0 and not chain_path: raise errors.PluginError( @@ -337,10 +337,10 @@ class NginxConfigurator(common.Plugin): """ snakeoil_cert, snakeoil_key = self._get_snakeoil_paths() - ssl_block = [['\n', 'listen', ' ', '{0} ssl'.format(self.config.tls_sni_01_port)], - ['\n', 'ssl_certificate', ' ', snakeoil_cert], - ['\n', 'ssl_certificate_key', ' ', snakeoil_key], - ['\n', 'include', ' ', self.parser.loc["ssl_options"]]] + ssl_block = [['\n ', 'listen', ' ', '{0} ssl'.format(self.config.tls_sni_01_port)], + ['\n ', 'ssl_certificate', ' ', snakeoil_cert], + ['\n ', 'ssl_certificate_key', ' ', snakeoil_key], + ['\n ', 'include', ' ', self.parser.loc["ssl_options"]]] self.parser.add_server_directives( vhost.filep, vhost.names, ssl_block, replace=False) vhost.ssl = True @@ -401,9 +401,10 @@ class NginxConfigurator(common.Plugin): :type unused_options: Not Available """ redirect_block = [[ - ['\n', 'if', ' ', '($scheme != "https")'], - [['\n ', 'return', ' ', '301 https://$host$request_uri']] - ]] + ['\n ', 'if', ' ', '($scheme != "https") '], + [['\n ', 'return', ' ', '301 https://$host$request_uri'], + '\n '] + ], ['\n']] self.parser.add_server_directives( vhost.filep, vhost.names, redirect_block, replace=False) logger.info("Redirecting all traffic to ssl in %s", vhost.filep) From 9e9c4dfcf5c574ad66864bec5f40f80834501f91 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 27 Jul 2016 16:54:17 -0700 Subject: [PATCH 079/126] fix test --- certbot-nginx/certbot_nginx/tests/configurator_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-nginx/certbot_nginx/tests/configurator_test.py b/certbot-nginx/certbot_nginx/tests/configurator_test.py index fa130fc4e..fede3bc08 100644 --- a/certbot-nginx/certbot_nginx/tests/configurator_test.py +++ b/certbot-nginx/certbot_nginx/tests/configurator_test.py @@ -415,7 +415,7 @@ class NginxConfiguratorTest(util.NginxTest): def test_redirect_enhance(self): expected = [ - ['if', '($scheme != "https")'], + ['if', '($scheme != "https") '], [['return', '301 https://$host$request_uri']] ] From 07eaa4a61b603889cb9b9a8dd01840ccc235758e Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 28 Jul 2016 17:11:07 -0700 Subject: [PATCH 080/126] Clarify need for root privileges --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 9be732c3b..f2f1b1191 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ Certbot is part of EFF’s effort to encrypt the entire Internet. Secure communi Anyone who has gone through the trouble of setting up a secure website knows what a hassle getting and maintaining a certificate is. Certbot and Let’s Encrypt can automate away the pain and let you turn on and manage HTTPS with simple commands. Using Certbot and Let's Encrypt is free, so there’s no need to arrange payment. -How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide `_. It generates instructions based on your configuration settings. You’ll need root or administrator access to your web server to run Certbot. +How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide `_. It generates instructions based on your configuration settings. In most cases, you’ll need root or administrator access to your web server to run Certbot. More information about the privileges Certbot requires can be found in our `FAQ `_. If you’re using a hosted service and don’t have direct access to your web server, you might not be able to use Certbot. Check with your hosting provider for documentation about uploading certificates or using certificates issues by Let’s Encrypt. From eeb0948a96423f194150e2c675c7a1af79342a3d Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 28 Jul 2016 17:14:04 -0700 Subject: [PATCH 081/126] point devs specifically at developer guide --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index f2f1b1191..bea900889 100644 --- a/README.rst +++ b/README.rst @@ -39,4 +39,4 @@ Current Features .. Do not modify this comment unless you know what you're doing. tag:features-end -For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. +For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. If you would like to contribute to the project, you should read our `developer guide `. From fbf8a2715765931bdd68dbaa57778e886c804c29 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Thu, 28 Jul 2016 19:05:08 -0700 Subject: [PATCH 082/126] Slight tweaks --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index bea900889..fe66f8af2 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ Certbot is part of EFF’s effort to encrypt the entire Internet. Secure communi Anyone who has gone through the trouble of setting up a secure website knows what a hassle getting and maintaining a certificate is. Certbot and Let’s Encrypt can automate away the pain and let you turn on and manage HTTPS with simple commands. Using Certbot and Let's Encrypt is free, so there’s no need to arrange payment. -How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide `_. It generates instructions based on your configuration settings. In most cases, you’ll need root or administrator access to your web server to run Certbot. More information about the privileges Certbot requires can be found in our `FAQ `_. +How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide `_. It generates instructions based on your configuration settings. In most cases, you’ll need `root or administrator access `_ to your web server to run Certbot. If you’re using a hosted service and don’t have direct access to your web server, you might not be able to use Certbot. Check with your hosting provider for documentation about uploading certificates or using certificates issues by Let’s Encrypt. @@ -39,4 +39,4 @@ Current Features .. Do not modify this comment unless you know what you're doing. tag:features-end -For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. If you would like to contribute to the project, you should read our `developer guide `. +For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. If you would like to contribute to the project or run the latest code from git, you should read our `developer guide `. From 89f576babb88722f3273fe770971a4942b23ac96 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Fri, 29 Jul 2016 16:51:33 -0700 Subject: [PATCH 083/126] Primarily simple s/apache/nginx/ and the like --- .../configurators/nginx/Dockerfile | 20 +++ .../configurators/nginx/__init__.py | 1 + .../configurators/nginx/common.py | 153 ++++++++++++++++++ .../certbot_compatibility_test/test_driver.py | 5 +- 4 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/Dockerfile create mode 100644 certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/__init__.py create mode 100644 certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/Dockerfile b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/Dockerfile new file mode 100644 index 000000000..ea9bb857f --- /dev/null +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/Dockerfile @@ -0,0 +1,20 @@ +FROM httpd +MAINTAINER Brad Warren + +RUN mkdir /var/run/apache2 + +ENV APACHE_RUN_USER=daemon \ + APACHE_RUN_GROUP=daemon \ + APACHE_PID_FILE=/usr/local/apache2/logs/httpd.pid \ + APACHE_RUN_DIR=/var/run/apache2 \ + APACHE_LOCK_DIR=/var/lock \ + APACHE_LOG_DIR=/usr/local/apache2/logs + +COPY certbot-compatibility-test/certbot_compatibility_test/configurators/apache/a2enmod.sh /usr/local/bin/ +COPY certbot-compatibility-test/certbot_compatibility_test/configurators/apache/a2dismod.sh /usr/local/bin/ +COPY certbot-compatibility-test/certbot_compatibility_test/testdata/rsa1024_key2.pem /usr/local/apache2/conf/ +COPY certbot-compatibility-test/certbot_compatibility_test/testdata/empty_cert.pem /usr/local/apache2/conf/ + +# Note: this only exposes the port to other docker containers. You +# still have to bind to 443@host at runtime. +EXPOSE 443 diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/__init__.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/__init__.py new file mode 100644 index 000000000..d559d0645 --- /dev/null +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/__init__.py @@ -0,0 +1 @@ +"""Certbot compatibility test Apache configurators""" diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py new file mode 100644 index 000000000..29f46ca4f --- /dev/null +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -0,0 +1,153 @@ +"""Provides a common base for Apache proxies""" +import re +import os +import shutil +import subprocess + +import mock +import zope.interface + +from certbot import configuration +from certbot import errors as le_errors +from certbot_nginx import configurator +from certbot_nginx import constants +from certbot_compatibility_test import errors +from certbot_compatibility_test import interfaces +from certbot_compatibility_test import util +from certbot_compatibility_test.configurators import common as configurators_common + + +# APACHE_VERSION_REGEX = re.compile(r"Apache/([0-9\.]*)", re.IGNORECASE) +# XXX APACHE_COMMANDS = ["apachectl", "a2enmod", "a2dismod"] + + +@zope.interface.implementer(interfaces.IConfiguratorProxy) +class Proxy(configurators_common.Proxy): + # pylint: disable=too-many-instance-attributes + """A common base for Nginx test configurators""" + + def __init__(self, args): + # XXX: This is still apache-specific + """Initializes the plugin with the given command line args""" + super(Proxy, self).__init__(args) + self.le_config.apache_le_vhost_ext = "-le-ssl.conf" + + self.modules = self.server_root = self.test_conf = self.version = None + self._nginx_configurator = self._all_names = self._test_names = None + patch = mock.patch( + "certbot_apache.configurator.display_ops.select_vhost") + mock_display = patch.start() + mock_display.side_effect = le_errors.PluginError( + "Unable to determine vhost") + + def __getattr__(self, name): + """Wraps the Nginx Configurator methods""" + method = getattr(self._nginx_configurator, name, None) + if callable(method): + return method + else: + raise AttributeError() + + def load_config(self): + """Loads the next configuration for the plugin to test""" + + config = super(Proxy, self).load_config() + self._all_names, self._test_names = _get_names(config) + + server_root = _get_server_root(config) + # with open(os.path.join(config, "config_file")) as f: + # config_file = os.path.join(server_root, f.readline().rstrip()) + + # XXX: Deleting all of this is kind of scary unless the test + # instances really each have a complete configuration! + shutil.rmtree("/etc/nginx") + shutil.copytree(server_root, "/etc/nginx", symlinks=True) + + self._prepare_configurator() + + try: + subprocess.check_call("nginx".split()) + except errors.Error: + raise errors.Error( + "Nginx failed to load {0} before tests started".format( + config)) + + return config + + def _prepare_configurator(self): + """Prepares the Nginx plugin for testing""" + for k in constants.CLI_DEFAULTS.keys(): + setattr(self.le_config, "nginx_" + k, constants.os_constant(k)) + + # An alias + self.le_config.nginx_handle_modules = self.le_config.nginx_handle_mods + + self._nginx_configurator = configurator.NginxConfigurator( + config=configuration.NamespaceConfig(self.le_config), + name="nginx") + self._nginx_configurator.prepare() + + def cleanup_from_tests(self): + """Performs any necessary cleanup from running plugin tests""" + super(Proxy, self).cleanup_from_tests() + mock.patch.stopall() + + def get_all_names_answer(self): + """Returns the set of domain names that the plugin should find""" + if self._all_names: + return self._all_names + else: + raise errors.Error("No configuration file loaded") + + def get_testable_domain_names(self): + """Returns the set of domain names that can be tested against""" + if self._test_names: + return self._test_names + else: + return {"example.com"} + + def deploy_cert(self, domain, cert_path, key_path, chain_path=None, + fullchain_path=None): + """Installs cert""" + cert_path, key_path, chain_path = self.copy_certs_and_keys( + cert_path, key_path, chain_path) + self._nginx_configurator.deploy_cert( + domain, cert_path, key_path, chain_path, fullchain_path) + + +def _get_server_root(config): + """Returns the server root directory in config""" + subdirs = [ + name for name in os.listdir(config) + if os.path.isdir(os.path.join(config, name))] + + if len(subdirs) != 1: + errors.Error("Malformed configuration directory {0}".format(config)) + + return os.path.join(config, subdirs[0].rstrip()) + + +def _get_names(config): + """Returns all and testable domain names in config""" + # XXX: This is still Apache-specific + all_names = set() + non_ip_names = set() + with open(os.path.join(config, "vhosts")) as f: + for line in f: + # If parsing a specific vhost + if line[0].isspace(): + words = line.split() + if words[0] == "alias": + all_names.add(words[1]) + non_ip_names.add(words[1]) + # If for port 80 and not IP vhost + elif words[1] == "80" and not util.IP_REGEX.match(words[3]): + all_names.add(words[3]) + non_ip_names.add(words[3]) + elif "NameVirtualHost" not in line: + words = line.split() + if (words[0].endswith("*") or words[0].endswith("80") and + not util.IP_REGEX.match(words[1]) and + words[1].find(".") != -1): + all_names.add(words[1]) + return all_names, non_ip_names diff --git a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py index 2c78eea1f..3d03f7771 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py +++ b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py @@ -22,7 +22,8 @@ from certbot_compatibility_test import errors from certbot_compatibility_test import util from certbot_compatibility_test import validator -from certbot_compatibility_test.configurators.apache import common +from certbot_compatibility_test.configurators.apache import common as a_common +from certbot_compatibility_test.configurators.nginx import common as n_common DESCRIPTION = """ @@ -32,7 +33,7 @@ tests that the plugin supports are performed. """ -PLUGINS = {"apache": common.Proxy} +PLUGINS = {"apache": a_common.Proxy, "nginx": n_common.Proxy} logger = logging.getLogger(__name__) From 7b67ba6797ce41aad1ec70e0ad894b90204c51f0 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Fri, 29 Jul 2016 17:14:23 -0700 Subject: [PATCH 084/126] Remove unused Apache-related variables --- .../certbot_compatibility_test/configurators/apache/common.py | 4 ---- .../certbot_compatibility_test/configurators/nginx/common.py | 4 ---- 2 files changed, 8 deletions(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py index ed3d9d67a..0c53058de 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py @@ -17,10 +17,6 @@ from certbot_compatibility_test import util from certbot_compatibility_test.configurators import common as configurators_common -APACHE_VERSION_REGEX = re.compile(r"Apache/([0-9\.]*)", re.IGNORECASE) -APACHE_COMMANDS = ["apachectl", "a2enmod", "a2dismod"] - - @zope.interface.implementer(interfaces.IConfiguratorProxy) class Proxy(configurators_common.Proxy): # pylint: disable=too-many-instance-attributes diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index 29f46ca4f..c474d078c 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -17,10 +17,6 @@ from certbot_compatibility_test import util from certbot_compatibility_test.configurators import common as configurators_common -# APACHE_VERSION_REGEX = re.compile(r"Apache/([0-9\.]*)", re.IGNORECASE) -# XXX APACHE_COMMANDS = ["apachectl", "a2enmod", "a2dismod"] - - @zope.interface.implementer(interfaces.IConfiguratorProxy) class Proxy(configurators_common.Proxy): # pylint: disable=too-many-instance-attributes From 04fd293ec2bf91bb1fef80aeb43ab7140e531e3b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 29 Jul 2016 18:56:03 -0700 Subject: [PATCH 085/126] add underscore to broken developer guide link --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index fe66f8af2..72188608b 100644 --- a/README.rst +++ b/README.rst @@ -39,4 +39,4 @@ Current Features .. Do not modify this comment unless you know what you're doing. tag:features-end -For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. If you would like to contribute to the project or run the latest code from git, you should read our `developer guide `. +For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. If you would like to contribute to the project or run the latest code from git, you should read our `developer guide `_. From 95fad04fdd69c8768ff126bdd7b43fa76c6151b1 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Sat, 30 Jul 2016 10:39:35 +0300 Subject: [PATCH 086/126] Added method to get the LIKE var contents as a list --- certbot/util.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/certbot/util.py b/certbot/util.py index 65aae59e2..1d3e5953c 100644 --- a/certbot/util.py +++ b/certbot/util.py @@ -268,6 +268,19 @@ def get_systemd_os_info(filepath="/etc/os-release"): return (os_name, os_version) +def get_systemd_os_like(filepath="/etc/os-release"): + """ + Get a list of strings that indicate the distribution likeness to + other distributions. + + :param str filepath: File path of os-release file + :returns: List of distribution acronyms + :rtype: `list` of `str` + """ + + return _get_systemd_os_release_var("LIKE", filepath).split(" ") + + def _get_systemd_os_release_var(varname, filepath="/etc/os-release"): """ Get single value from systemd /etc/os-release From a5859910e757667b573b9675f0e6c9d546e7c46c Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Sat, 30 Jul 2016 10:43:38 +0300 Subject: [PATCH 087/126] If os name is not found, try LIKE var from os-release --- certbot-apache/certbot_apache/constants.py | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/certbot-apache/certbot_apache/constants.py b/certbot-apache/certbot_apache/constants.py index 9252814c4..a65a12c5e 100644 --- a/certbot-apache/certbot_apache/constants.py +++ b/certbot-apache/certbot_apache/constants.py @@ -115,13 +115,36 @@ HEADER_ARGS = {"Strict-Transport-Security": HSTS_ARGS, def os_constant(key): - """Get a constant value for operating system + """ + Get a constant value for operating system + :param key: name of cli constant :return: value of constant for active os """ + os_info = util.get_os_info() try: constants = CLI_DEFAULTS[os_info[0].lower()] except KeyError: - constants = CLI_DEFAULTS["debian"] + constants = os_like_constants() + if not constants: + constants = CLI_DEFAULTS["default"] return constants[key] + + +def os_like_constants(): + """ + Try to get constants for distribution with + similar layout and configuration, indicated by + /etc/os-release variable "LIKE" + + :returns: Constants dictionary + :rtype: `dict` + """ + + os_like = util.get_systemd_os_like() + if os_like: + for os_name in os_like: + if os_name in CLI_DEFAULTS.keys(): + return CLI_DEFAULTS[os_name] + return {} From c87282d5aa8e0eb0762bbf5804edf0b32563721c Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Sat, 30 Jul 2016 10:44:46 +0300 Subject: [PATCH 088/126] Un-debian the defaults --- certbot-apache/certbot_apache/constants.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/certbot-apache/certbot_apache/constants.py b/certbot-apache/certbot_apache/constants.py index a65a12c5e..d4ec2d8a8 100644 --- a/certbot-apache/certbot_apache/constants.py +++ b/certbot-apache/certbot_apache/constants.py @@ -2,7 +2,23 @@ import pkg_resources from certbot import util - +CLI_DEFAULTS_DEFAULT = dict( + server_root="/etc/apache2", + vhost_root="/etc/apache2/sites-available", + vhost_files="*", + version_cmd=['apache2ctl', '-v'], + define_cmd=['apache2ctl', '-t', '-D', 'DUMP_RUN_CFG'], + restart_cmd=['apache2ctl', 'graceful'], + conftest_cmd=['apache2ctl', 'configtest'], + enmod="a2enmod", + dismod="a2dismod", + le_vhost_ext="-le-ssl.conf", + handle_mods=False, + handle_sites=False, + challenge_location="/etc/apache2", + MOD_SSL_CONF_SRC=pkg_resources.resource_filename( + "certbot_apache", "options-ssl-apache.conf") +) CLI_DEFAULTS_DEBIAN = dict( server_root="/etc/apache2", vhost_root="/etc/apache2/sites-available", @@ -72,6 +88,7 @@ CLI_DEFAULTS_DARWIN = dict( "certbot_apache", "options-ssl-apache.conf") ) CLI_DEFAULTS = { + "default": CLI_DEFAULTS_DEFAULT, "debian": CLI_DEFAULTS_DEBIAN, "ubuntu": CLI_DEFAULTS_DEBIAN, "centos": CLI_DEFAULTS_CENTOS, From 63a47f8b6baf53e194194798d992890f56bd30c2 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Sat, 30 Jul 2016 11:07:04 +0300 Subject: [PATCH 089/126] Fix variable name --- certbot/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/util.py b/certbot/util.py index 1d3e5953c..73985719a 100644 --- a/certbot/util.py +++ b/certbot/util.py @@ -278,7 +278,7 @@ def get_systemd_os_like(filepath="/etc/os-release"): :rtype: `list` of `str` """ - return _get_systemd_os_release_var("LIKE", filepath).split(" ") + return _get_systemd_os_release_var("ID_LIKE", filepath).split(" ") def _get_systemd_os_release_var(varname, filepath="/etc/os-release"): From 093ebd2f0342c23e7d3e28fd0963e1ffc9f1e14a Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Sat, 30 Jul 2016 11:49:04 +0300 Subject: [PATCH 090/126] Tests --- .../certbot_apache/tests/constants_test.py | 17 +++++++++++++++++ certbot/tests/testdata/os-release | 2 +- certbot/tests/util_test.py | 9 +++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/certbot-apache/certbot_apache/tests/constants_test.py b/certbot-apache/certbot_apache/tests/constants_test.py index c040030df..1c842aee9 100644 --- a/certbot-apache/certbot_apache/tests/constants_test.py +++ b/certbot-apache/certbot_apache/tests/constants_test.py @@ -25,3 +25,20 @@ class ConstantsTest(unittest.TestCase): os_info.return_value = ('Nonexistent Linux', '', '') self.assertEqual(constants.os_constant("vhost_root"), "/etc/apache2/sites-available") + + @mock.patch("certbot.util.get_os_info") + def test_get_default_constants(self, os_info): + os_info.return_value = ('Nonexistent Linux', '', '') + with mock.patch("certbot.util.get_systemd_os_like") as os_like: + # Get defaults + os_like.return_value = False + c_hm = constants.os_constant("handle_mods") + c_sr = constants.os_constant("server_root") + self.assertFalse(c_hm) + self.assertEqual(c_sr, "/etc/apache2") + # Use darwin as like test target + os_like.return_value = ["something", "nonexistent", "darwin"] + d_vr = constants.os_constant("vhost_root") + d_em = constants.os_constant("enmod") + self.assertFalse(d_em) + self.assertEqual(d_vr, "/etc/apache2/other") diff --git a/certbot/tests/testdata/os-release b/certbot/tests/testdata/os-release index cd5297acf..15bc5fb3c 100644 --- a/certbot/tests/testdata/os-release +++ b/certbot/tests/testdata/os-release @@ -1,7 +1,7 @@ NAME="SystemdOS" VERSION="42.42.42 LTS, Unreal" ID=systemdos -ID_LIKE=debian +ID_LIKE="something nonexistent debian" VERSION_ID="42" HOME_URL="http://www.example.com/" SUPPORT_URL="http://help.example.com/" diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index 8e1b330ed..36676443a 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -359,6 +359,15 @@ class OsInfoTest(unittest.TestCase): with mock.patch('os.path.isfile', return_value=False): self.assertEqual(get_systemd_os_info(), ("", "")) + def test_systemd_os_release_like(self): + from certbot.util import get_systemd_os_like + + with mock.patch('os.path.isfile', return_value=True): + id_likes = get_systemd_os_like(test_util.vector_path( + "os-release")) + self.assertEqual(len(id_likes), 3) + self.assertTrue("debian" in id_likes) + @mock.patch("certbot.util.subprocess.Popen") def test_non_systemd_os_info(self, popen_mock): from certbot.util import (get_os_info, get_python_os_info, From 28fc02143bd9b235ba569c0045795e18c916fe66 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Sat, 30 Jul 2016 11:59:58 +0300 Subject: [PATCH 091/126] Remove enmod and dismod values as they are not needed --- certbot-apache/certbot_apache/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot-apache/certbot_apache/constants.py b/certbot-apache/certbot_apache/constants.py index d4ec2d8a8..5e296ba0a 100644 --- a/certbot-apache/certbot_apache/constants.py +++ b/certbot-apache/certbot_apache/constants.py @@ -10,8 +10,8 @@ CLI_DEFAULTS_DEFAULT = dict( define_cmd=['apache2ctl', '-t', '-D', 'DUMP_RUN_CFG'], restart_cmd=['apache2ctl', 'graceful'], conftest_cmd=['apache2ctl', 'configtest'], - enmod="a2enmod", - dismod="a2dismod", + enmod=None, + dismod=None, le_vhost_ext="-le-ssl.conf", handle_mods=False, handle_sites=False, From 8a09a7ed6715e345ee03041b933a9f815e815dd8 Mon Sep 17 00:00:00 2001 From: Yen Chi Hsuan Date: Sat, 30 Jul 2016 18:15:32 +0800 Subject: [PATCH 092/126] Python 3 support for certonly --- certbot/auth_handler.py | 6 +++--- certbot/cli.py | 6 ++++-- certbot/constants.py | 2 +- certbot/plugins/disco.py | 11 ++++++----- certbot/plugins/manual.py | 3 ++- certbot/plugins/selection.py | 2 +- certbot/util.py | 3 +++ setup.py | 7 ++++++- 8 files changed, 26 insertions(+), 14 deletions(-) diff --git a/certbot/auth_handler.py b/certbot/auth_handler.py index f5557d604..a94734572 100644 --- a/certbot/auth_handler.py +++ b/certbot/auth_handler.py @@ -1,8 +1,8 @@ """ACME AuthHandler.""" -import itertools import logging import time +import six import zope.component from acme import challenges @@ -141,7 +141,7 @@ class AuthHandler(object): """ active_achalls = [] - for achall, resp in itertools.izip(achalls, resps): + for achall, resp in six.moves.zip(achalls, resps): # This line needs to be outside of the if block below to # ensure failed challenges are cleaned up correctly active_achalls.append(achall) @@ -472,7 +472,7 @@ def _report_failed_challs(failed_achalls): problems.setdefault(achall.error.typ, []).append(achall) reporter = zope.component.getUtility(interfaces.IReporter) - for achalls in problems.itervalues(): + for achalls in six.itervalues(problems): reporter.add_message( _generate_failed_chall_msg(achalls), reporter.MEDIUM_PRIORITY) diff --git a/certbot/cli.py b/certbot/cli.py index 5813af730..b01b0a7f1 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -343,8 +343,10 @@ class HelpfulArgumentParser(object): self.determine_verb() help1 = self.prescan_for_flag("-h", self.help_topics) help2 = self.prescan_for_flag("--help", self.help_topics) - assert max(True, "a") == "a", "Gravity changed direction" - self.help_arg = max(help1, help2) + if isinstance(help1, bool) and isinstance(help2, bool): + self.help_arg = help1 or help2 + else: + self.help_arg = help1 if isinstance(help1, str) else help2 if self.help_arg is True: # just --help with no topic; avoid argparse altogether print(usage) diff --git a/certbot/constants.py b/certbot/constants.py index fb278161d..1ddb9fedf 100644 --- a/certbot/constants.py +++ b/certbot/constants.py @@ -18,7 +18,7 @@ CLI_DEFAULTS = dict( os.path.join(os.environ.get("XDG_CONFIG_HOME", "~/.config"), "letsencrypt", "cli.ini"), ], - verbose_count=-(logging.INFO / 10), + verbose_count=-int(logging.INFO / 10), server="https://acme-v01.api.letsencrypt.org/directory", rsa_key_size=2048, rollback_checkpoints=1, diff --git a/certbot/plugins/disco.py b/certbot/plugins/disco.py index d88b871f6..59410757c 100644 --- a/certbot/plugins/disco.py +++ b/certbot/plugins/disco.py @@ -3,6 +3,7 @@ import collections import itertools import logging import pkg_resources +import six import zope.interface import zope.interface.verify @@ -194,12 +195,12 @@ class PluginsRegistry(collections.Mapping): def init(self, config): """Initialize all plugins in the registry.""" return [plugin_ep.init(config) for plugin_ep - in self._plugins.itervalues()] + in six.itervalues(self._plugins)] def filter(self, pred): """Filter plugins based on predicate.""" return type(self)(dict((name, plugin_ep) for name, plugin_ep - in self._plugins.iteritems() if pred(plugin_ep))) + in six.iteritems(self._plugins) if pred(plugin_ep))) def visible(self): """Filter plugins based on visibility.""" @@ -216,7 +217,7 @@ class PluginsRegistry(collections.Mapping): def prepare(self): """Prepare all plugins in the registry.""" - return [plugin_ep.prepare() for plugin_ep in self._plugins.itervalues()] + return [plugin_ep.prepare() for plugin_ep in six.itervalues(self._plugins)] def available(self): """Filter plugins based on availability.""" @@ -238,7 +239,7 @@ class PluginsRegistry(collections.Mapping): """ # use list instead of set because PluginEntryPoint is not hashable - candidates = [plugin_ep for plugin_ep in self._plugins.itervalues() + candidates = [plugin_ep for plugin_ep in six.itervalues(self._plugins) if plugin_ep.initialized and plugin_ep.init() is plugin] assert len(candidates) <= 1 if candidates: @@ -249,7 +250,7 @@ class PluginsRegistry(collections.Mapping): def __repr__(self): return "{0}({1})".format( self.__class__.__name__, ','.join( - repr(p_ep) for p_ep in self._plugins.itervalues())) + repr(p_ep) for p_ep in six.itervalues(self._plugins))) def __str__(self): if not self._plugins: diff --git a/certbot/plugins/manual.py b/certbot/plugins/manual.py index 9b722aef4..6c7b822ab 100644 --- a/certbot/plugins/manual.py +++ b/certbot/plugins/manual.py @@ -10,6 +10,7 @@ import sys import tempfile import time +import six import zope.component import zope.interface @@ -187,7 +188,7 @@ s.serve_forever()" """ #answer = zope.component.getUtility(interfaces.IDisplay).notification( # message=message, height=25, pause=True) sys.stdout.write(message) - raw_input("Press ENTER to continue") + six.moves.input("Press ENTER to continue") def cleanup(self, achalls): # pylint: disable=missing-docstring,no-self-use,unused-argument diff --git a/certbot/plugins/selection.py b/certbot/plugins/selection.py index 21ebe9029..b16515d8f 100644 --- a/certbot/plugins/selection.py +++ b/certbot/plugins/selection.py @@ -84,7 +84,7 @@ def pick_plugin(config, default, plugins, question, ifaces): else: return plugin_ep.init() elif len(prepared) == 1: - plugin_ep = prepared.values()[0] + plugin_ep = list(prepared.values())[0] logger.debug("Single candidate plugin: %s", plugin_ep) if plugin_ep.misconfigured: return None diff --git a/certbot/util.py b/certbot/util.py index 65aae59e2..2ad2c4535 100644 --- a/certbot/util.py +++ b/certbot/util.py @@ -409,6 +409,9 @@ def enforce_domain_sanity(domain): else: raise errors.ConfigurationError(str(error_fmt).format(domain)) + if six.PY3: + domain = domain.decode('ascii') + # Remove trailing dot domain = domain[:-1] if domain.endswith('.') else domain diff --git a/setup.py b/setup.py index 21cda901a..093cbc449 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,6 @@ install_requires = [ 'psutil>=2.2.1', # 2.1.0 for net_connections and 2.2.1 resolves #1080 'PyOpenSSL', 'pyrfc3339', - 'python2-pythondialog>=3.2.2rc1', # Debian squeeze support, cf. #280 'pytz', # For pkg_resources. >=1.0 so pip resolves it to a version cryptography # will tolerate; see #2599: @@ -53,6 +52,12 @@ install_requires = [ 'zope.interface', ] +# Debian squeeze support, cf. #280 +if sys.version_info[0] == 2: + install_requires.append('python2-pythondialog>=3.2.2rc1') +else: + install_requires.append('pythondialog>=3.2.2rc1') + # env markers in extras_require cause problems with older pip: #517 # Keep in sync with conditional_requirements.py. if sys.version_info < (2, 7): From b891cac3dc4661a8f4ff99c53955884b727b0975 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Sun, 31 Jul 2016 01:10:28 +0300 Subject: [PATCH 093/126] Added suse constants --- certbot-apache/certbot_apache/constants.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/certbot-apache/certbot_apache/constants.py b/certbot-apache/certbot_apache/constants.py index 5e296ba0a..001ef1caa 100644 --- a/certbot-apache/certbot_apache/constants.py +++ b/certbot-apache/certbot_apache/constants.py @@ -87,6 +87,23 @@ CLI_DEFAULTS_DARWIN = dict( MOD_SSL_CONF_SRC=pkg_resources.resource_filename( "certbot_apache", "options-ssl-apache.conf") ) +CLI_DEFAULTS_SUSE = dict( + server_root="/etc/apache2", + vhost_root="/etc/apache2/vhosts.d", + vhost_files="*.conf", + version_cmd=['apache2ctl', '-v'], + define_cmd=['apache2ctl', '-t', '-D', 'DUMP_RUN_CFG'], + restart_cmd=['apache2ctl', 'graceful'], + conftest_cmd=['apache2ctl', 'configtest'], + enmod="a2enmod", + dismod="a2dismod", + le_vhost_ext="-le-ssl.conf", + handle_mods=True, + handle_sites=False, + challenge_location="/etc/apache2/vhosts.d", + MOD_SSL_CONF_SRC=pkg_resources.resource_filename( + "certbot_apache", "options-ssl-apache.conf") +) CLI_DEFAULTS = { "default": CLI_DEFAULTS_DEFAULT, "debian": CLI_DEFAULTS_DEBIAN, @@ -100,6 +117,8 @@ CLI_DEFAULTS = { "gentoo": CLI_DEFAULTS_GENTOO, "gentoo base system": CLI_DEFAULTS_GENTOO, "darwin": CLI_DEFAULTS_DARWIN, + "opensuse": CLI_DEFAULTS_SUSE, + "suse": CLI_DEFAULTS_SUSE, } """CLI defaults.""" From b2505b996fe4739739f2ec57bac0d6b9a99e226b Mon Sep 17 00:00:00 2001 From: Wilfried Teiken Date: Sun, 31 Jul 2016 20:36:00 -0400 Subject: [PATCH 094/126] Switch to always using dnspython (requires dnspthon>=1.12). Also, address some documentation nits. --- acme/acme/challenges.py | 8 ++++---- acme/acme/dns_resolver.py | 4 +++- acme/setup.py | 12 ++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 23841c2b4..6242c376c 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -207,7 +207,7 @@ class KeyAuthorizationChallenge(_TokenChallenge): @ChallengeResponse.register class DNS01Response(KeyAuthorizationChallengeResponse): - """ACME "dns-01" challenge response.""" + """ACME dns-01 challenge response.""" typ = "dns-01" def simple_verify(self, chall, domain, account_public_key): @@ -215,7 +215,7 @@ class DNS01Response(KeyAuthorizationChallengeResponse): :param challenges.DNS01 chall: Corresponding challenge. :param unicode domain: Domain name being verified. - :param account_public_key: Public key for the key pair + :param JWK account_public_key: Public key for the key pair being authorized. :returns: ``True`` iff validation with the TXT records resolved from a @@ -247,7 +247,7 @@ class DNS01Response(KeyAuthorizationChallengeResponse): @Challenge.register # pylint: disable=too-many-ancestors class DNS01(KeyAuthorizationChallenge): - """ACME "dns-01" challenge.""" + """ACME dns-01 challenge.""" response_cls = DNS01Response typ = response_cls.typ @@ -298,7 +298,7 @@ class HTTP01Response(KeyAuthorizationChallengeResponse): being authorized. :param int port: Port used in the validation. - :returns: ``True`` iff validation of the files currently server by the + :returns: ``True`` iff validation with the files currently served by the HTTP server is successful. :rtype: bool diff --git a/acme/acme/dns_resolver.py b/acme/acme/dns_resolver.py index 15638e5d0..f551c6095 100644 --- a/acme/acme/dns_resolver.py +++ b/acme/acme/dns_resolver.py @@ -25,4 +25,6 @@ def txt_records_for_name(name): except dns.exception.DNSException as error: logger.error("Error resolving %s: %s", name, str(error)) return [] - return [txt_rec for rdata in dns_response for txt_rec in rdata.strings] + + return [txt_rec.decode("utf-8") for rdata in dns_response + for txt_rec in rdata.strings] diff --git a/acme/setup.py b/acme/setup.py index 75565f7f8..94f78d4cd 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -35,14 +35,10 @@ if sys.version_info < (2, 7): else: install_requires.append('mock') -if sys.version_info < (3, 0): - dns_extras = [ - 'dnspython', - ] -else: - dns_extras = [ - 'dnspython3', - ] +# dnspython 1.12 is required to support both Python 2 and Python 3. +dns_extras = [ + 'dnspython>=1.12', +] dev_extras = [ 'nose', From c346cdf2f33e136950ef7ad324215f9d8752ba9f Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Tue, 2 Aug 2016 09:57:34 +0300 Subject: [PATCH 095/126] Changed SUSE mod handling constant --- certbot-apache/certbot_apache/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-apache/certbot_apache/constants.py b/certbot-apache/certbot_apache/constants.py index 001ef1caa..ba545c613 100644 --- a/certbot-apache/certbot_apache/constants.py +++ b/certbot-apache/certbot_apache/constants.py @@ -98,7 +98,7 @@ CLI_DEFAULTS_SUSE = dict( enmod="a2enmod", dismod="a2dismod", le_vhost_ext="-le-ssl.conf", - handle_mods=True, + handle_mods=False, handle_sites=False, challenge_location="/etc/apache2/vhosts.d", MOD_SSL_CONF_SRC=pkg_resources.resource_filename( From 353cb6e6c627e680c8e573a101a3548c193fc769 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Wed, 3 Aug 2016 17:10:20 -0700 Subject: [PATCH 096/126] New _get_names approach for nginx test --- .../configurators/nginx/common.py | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index c474d078c..779ba26a7 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -125,25 +125,12 @@ def _get_server_root(config): def _get_names(config): """Returns all and testable domain names in config""" - # XXX: This is still Apache-specific all_names = set() - non_ip_names = set() - with open(os.path.join(config, "vhosts")) as f: - for line in f: - # If parsing a specific vhost - if line[0].isspace(): - words = line.split() - if words[0] == "alias": - all_names.add(words[1]) - non_ip_names.add(words[1]) - # If for port 80 and not IP vhost - elif words[1] == "80" and not util.IP_REGEX.match(words[3]): - all_names.add(words[3]) - non_ip_names.add(words[3]) - elif "NameVirtualHost" not in line: - words = line.split() - if (words[0].endswith("*") or words[0].endswith("80") and - not util.IP_REGEX.match(words[1]) and - words[1].find(".") != -1): - all_names.add(words[1]) + for root, _dirs, files in os.walk(config): + for this_file in files: + for line in open(os.path.join(root, this_file)): + if line.strip().starts_with("server_name"): + names = line.partition("server_name")[2].rstrip(";") + [all_names.add(n) for n in names.split()] + non_ip_names = set(n for n in all_names if not util.IP_REGEX.match(n)) return all_names, non_ip_names From 2cd2228ca6a8e3e2b311d5974afa816084695bb7 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Fri, 5 Aug 2016 15:07:35 -0700 Subject: [PATCH 097/126] starts_with is actually called startswith --- .../certbot_compatibility_test/configurators/nginx/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index 779ba26a7..9fbb538e8 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -129,7 +129,7 @@ def _get_names(config): for root, _dirs, files in os.walk(config): for this_file in files: for line in open(os.path.join(root, this_file)): - if line.strip().starts_with("server_name"): + if line.strip().startswith("server_name"): names = line.partition("server_name")[2].rstrip(";") [all_names.add(n) for n in names.split()] non_ip_names = set(n for n in all_names if not util.IP_REGEX.match(n)) From ae6ca4d4ca932dd364b7c6367c96cff25987fad6 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Fri, 5 Aug 2016 15:13:04 -0700 Subject: [PATCH 098/126] Minimal fake os_constant() for nginx constants.py --- certbot-nginx/certbot_nginx/constants.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/certbot-nginx/certbot_nginx/constants.py b/certbot-nginx/certbot_nginx/constants.py index 5dde30efc..453266878 100644 --- a/certbot-nginx/certbot_nginx/constants.py +++ b/certbot-nginx/certbot_nginx/constants.py @@ -16,3 +16,10 @@ MOD_SSL_CONF_SRC = pkg_resources.resource_filename( "certbot_nginx", "options-ssl-nginx.conf") """Path to the nginx mod_ssl config file found in the Certbot distribution.""" + +def os_constant(key): + # XXX TODO: In the future, this could return different constants + # based on what OS we are running under. To see an + # approach to how to handle different OSes, see the + # apache version of this file. + return CLI_DEFAULTS From e49a41be34b572a6a01160bf38fbfa1f10c46965 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Mon, 8 Aug 2016 12:17:42 -0700 Subject: [PATCH 099/126] Change "hacking" to "getting started" in the docs --- docs/contributing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index f1eec04df..a5b9b5688 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -6,9 +6,9 @@ Developer Guide :local: -.. _hacking: +.. _getting_started: -Hacking +Getting Started ======= Running a local copy of the client From 262eb778fe54890e4d36c2093a7a836ac3603b8b Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Mon, 8 Aug 2016 15:29:23 -0700 Subject: [PATCH 100/126] Update Apache plugin supported OSes --- docs/using.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index f43fd15c5..15658b2c5 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -20,8 +20,10 @@ but for most users who want to avoid running an ACME client as root, either `letsencrypt-nosudo `_ or `simp_le `_ are more appropriate choices. -The Apache plugin currently requires a Debian-based OS with augeas version -1.0; this includes Ubuntu 12.04+ and Debian 7+. +The Apache plugin currently requires OS with augeas version 1.0; currently `it +supports +`_ +modern OSes based on Debian, Fedora, SUSE, Gentoo and Darwin. Getting Certbot From e77a3ed7b968470c908960fb45079c9a2e9e8708 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 8 Aug 2016 17:22:53 -0700 Subject: [PATCH 101/126] Return individual key, not entire config dictionary! --- certbot-nginx/certbot_nginx/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-nginx/certbot_nginx/constants.py b/certbot-nginx/certbot_nginx/constants.py index 453266878..98f924b2b 100644 --- a/certbot-nginx/certbot_nginx/constants.py +++ b/certbot-nginx/certbot_nginx/constants.py @@ -22,4 +22,4 @@ def os_constant(key): # based on what OS we are running under. To see an # approach to how to handle different OSes, see the # apache version of this file. - return CLI_DEFAULTS + return CLI_DEFAULTS[key] From d41ceff86d22e8ec774771fdd4ab0ee093cb9b64 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 8 Aug 2016 17:24:54 -0700 Subject: [PATCH 102/126] Various WIP on nginx compatibility test --- .../configurators/nginx/common.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index 9fbb538e8..aff9d9467 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -75,12 +75,13 @@ class Proxy(configurators_common.Proxy): for k in constants.CLI_DEFAULTS.keys(): setattr(self.le_config, "nginx_" + k, constants.os_constant(k)) - # An alias - self.le_config.nginx_handle_modules = self.le_config.nginx_handle_mods + # This does not appear to exist in nginx (yet?) + # self.le_config.nginx_handle_modules = self.le_config.nginx_handle_mods + conf=configuration.NamespaceConfig(self.le_config) + zope.component.provideUtility(conf) self._nginx_configurator = configurator.NginxConfigurator( - config=configuration.NamespaceConfig(self.le_config), - name="nginx") + config=conf, name="nginx") self._nginx_configurator.prepare() def cleanup_from_tests(self): @@ -118,7 +119,7 @@ def _get_server_root(config): if os.path.isdir(os.path.join(config, name))] if len(subdirs) != 1: - errors.Error("Malformed configuration directory {0}".format(config)) + raise errors.Error("Malformed configuration directory {0}".format(config)) return os.path.join(config, subdirs[0].rstrip()) From 0504882e083252f2ed820bb96586235fdebd09d0 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Mon, 8 Aug 2016 17:50:20 -0700 Subject: [PATCH 103/126] Always newline config edits Even if they're transient --- certbot-nginx/certbot_nginx/tls_sni_01.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot-nginx/certbot_nginx/tls_sni_01.py b/certbot-nginx/certbot_nginx/tls_sni_01.py index ebc92f5e3..c7ec80931 100644 --- a/certbot-nginx/certbot_nginx/tls_sni_01.py +++ b/certbot-nginx/certbot_nginx/tls_sni_01.py @@ -91,10 +91,10 @@ class NginxTlsSni01(common.TLSSNI01): # Add the 'include' statement for the challenges if it doesn't exist # already in the main config included = False - include_directive = ['include', ' ', self.challenge_conf] + include_directive = ['\n', 'include', ' ', self.challenge_conf] root = self.configurator.parser.loc["root"] - bucket_directive = ['server_names_hash_bucket_size', ' ', '128'] + bucket_directive = ['\n', 'server_names_hash_bucket_size', ' ', '128'] main = self.configurator.parser.parsed[root] for key, body in main: From 7d27c1f50020a3594b5bc05c0db023139aec8578 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 8 Aug 2016 17:51:55 -0700 Subject: [PATCH 104/126] More correct parsing of lines containing trailing space --- .../certbot_compatibility_test/configurators/nginx/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index aff9d9467..8e2899933 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -131,7 +131,7 @@ def _get_names(config): for this_file in files: for line in open(os.path.join(root, this_file)): if line.strip().startswith("server_name"): - names = line.partition("server_name")[2].rstrip(";") + names = line.partition("server_name")[2].rpartition(";")[0] [all_names.add(n) for n in names.split()] non_ip_names = set(n for n in all_names if not util.IP_REGEX.match(n)) return all_names, non_ip_names From 6e86c71259bfd0128f9d002aaec801768637df1f Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Mon, 8 Aug 2016 18:03:07 -0700 Subject: [PATCH 105/126] Provide a copy of the self-signed cert as the fullchain as well --- .../certbot_compatibility_test/test_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py index 3d03f7771..b5e023f36 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py +++ b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py @@ -144,7 +144,7 @@ def test_deploy_cert(plugin, temp_dir, domains): for domain in domains: try: - plugin.deploy_cert(domain, cert_path, util.KEY_PATH, cert_path) + plugin.deploy_cert(domain, cert_path, util.KEY_PATH, cert_path, cert_path) plugin.save() # Needed by the Apache plugin except le_errors.Error as error: logger.error("Plugin failed to deploy ceritificate for %s:", domain) From c29e8c3332640611909c5f7c6913525c86d9d8d5 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Tue, 9 Aug 2016 23:43:11 +0300 Subject: [PATCH 106/126] Refactored get_file_path --- certbot-apache/certbot_apache/configurator.py | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/certbot-apache/certbot_apache/configurator.py b/certbot-apache/certbot_apache/configurator.py index 238255133..4a68461ce 100644 --- a/certbot-apache/certbot_apache/configurator.py +++ b/certbot-apache/certbot_apache/configurator.py @@ -1801,25 +1801,17 @@ def get_file_path(vhost_path): :rtype: str """ - # Strip off /files - avail_fp = vhost_path[6:] - # This can be optimized... - while True: - # Cast all to lowercase to be case insensitive - find_if = avail_fp.lower().find("/ifmodule") - if find_if != -1: - avail_fp = avail_fp[:find_if] - continue - find_vh = avail_fp.lower().find("/virtualhost") - if find_vh != -1: - avail_fp = avail_fp[:find_vh] - continue - find_macro = avail_fp.lower().find("/macro") - if find_macro != -1: - avail_fp = avail_fp[:find_macro] - continue - break - return avail_fp + # Strip off /files/ + avail_fp = vhost_path[7:].split("/") + last_good = "" + # Loop through the path parts and validate after every addition + for p in avail_fp: + cur_path = last_good+"/"+p + if os.path.exists(cur_path): + last_good = cur_path + else: + break + return last_good def install_ssl_options_conf(options_ssl): From f4948855f02b1e1dde4434e7c8e15beb8c06a150 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 10 Aug 2016 00:25:35 +0300 Subject: [PATCH 107/126] Added None check and according test --- certbot-apache/certbot_apache/configurator.py | 8 +++++++- certbot-apache/certbot_apache/tests/configurator_test.py | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/certbot-apache/certbot_apache/configurator.py b/certbot-apache/certbot_apache/configurator.py index 4a68461ce..abe3edede 100644 --- a/certbot-apache/certbot_apache/configurator.py +++ b/certbot-apache/certbot_apache/configurator.py @@ -538,6 +538,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): is_ssl = True filename = get_file_path(self.aug.get("/augeas/files%s/path" % get_file_path(path))) + if filename is None: + return None + if self.conf("handle-sites"): is_enabled = self.is_site_enabled(filename) else: @@ -1802,7 +1805,10 @@ def get_file_path(vhost_path): """ # Strip off /files/ - avail_fp = vhost_path[7:].split("/") + try: + avail_fp = vhost_path[7:].split("/") + except TypeError: + return None last_good = "" # Loop through the path parts and validate after every addition for p in avail_fp: diff --git a/certbot-apache/certbot_apache/tests/configurator_test.py b/certbot-apache/certbot_apache/tests/configurator_test.py index ac692ae54..59692302d 100644 --- a/certbot-apache/certbot_apache/tests/configurator_test.py +++ b/certbot-apache/certbot_apache/tests/configurator_test.py @@ -125,6 +125,10 @@ class MultipleVhostsTest(util.ApacheTest): self.assertTrue("google.com" in names) self.assertTrue("certbot.demo" in names) + def test_get_bad_path(self): + from certbot_apache.configurator import get_file_path + self.assertEqual(get_file_path(None), None) + def test_bad_servername_alias(self): ssl_vh1 = obj.VirtualHost( "fp1", "ap1", set([obj.Addr(("*", "443"))]), From 6c3ae10f9b1e94d0f38d73c15f593b348556e5d4 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 10 Aug 2016 01:39:53 +0300 Subject: [PATCH 108/126] Added test case --- certbot-apache/certbot_apache/tests/configurator_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/certbot-apache/certbot_apache/tests/configurator_test.py b/certbot-apache/certbot_apache/tests/configurator_test.py index 59692302d..2a8960564 100644 --- a/certbot-apache/certbot_apache/tests/configurator_test.py +++ b/certbot-apache/certbot_apache/tests/configurator_test.py @@ -128,6 +128,7 @@ class MultipleVhostsTest(util.ApacheTest): def test_get_bad_path(self): from certbot_apache.configurator import get_file_path self.assertEqual(get_file_path(None), None) + self.assertEqual(self.config._create_vhost("nonexistent"), None) def test_bad_servername_alias(self): ssl_vh1 = obj.VirtualHost( From 51191c2ea54de8fad135c93b13bb6ab0bc22410c Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 10 Aug 2016 01:50:40 +0300 Subject: [PATCH 109/126] Added linter exception --- certbot-apache/certbot_apache/tests/configurator_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-apache/certbot_apache/tests/configurator_test.py b/certbot-apache/certbot_apache/tests/configurator_test.py index 2a8960564..f8bf7676c 100644 --- a/certbot-apache/certbot_apache/tests/configurator_test.py +++ b/certbot-apache/certbot_apache/tests/configurator_test.py @@ -128,7 +128,7 @@ class MultipleVhostsTest(util.ApacheTest): def test_get_bad_path(self): from certbot_apache.configurator import get_file_path self.assertEqual(get_file_path(None), None) - self.assertEqual(self.config._create_vhost("nonexistent"), None) + self.assertEqual(self.config._create_vhost("nonexistent"), None) # pylint: disable=protected-access def test_bad_servername_alias(self): ssl_vh1 = obj.VirtualHost( From 14f371025049bbc5621da943e0ee04cf4e4add8d Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 10 Aug 2016 10:39:10 +0300 Subject: [PATCH 110/126] Added check for /files/ --- certbot-apache/certbot_apache/configurator.py | 9 +++++++-- certbot-apache/certbot_apache/tests/configurator_test.py | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/certbot-apache/certbot_apache/configurator.py b/certbot-apache/certbot_apache/configurator.py index abe3edede..02602ace6 100644 --- a/certbot-apache/certbot_apache/configurator.py +++ b/certbot-apache/certbot_apache/configurator.py @@ -1806,9 +1806,14 @@ def get_file_path(vhost_path): """ # Strip off /files/ try: - avail_fp = vhost_path[7:].split("/") - except TypeError: + if vhost_path.startswith("/files/"): + avail_fp = vhost_path[7:].split("/") + else: + return None + except AttributeError: + # If we recieved a None path return None + last_good = "" # Loop through the path parts and validate after every addition for p in avail_fp: diff --git a/certbot-apache/certbot_apache/tests/configurator_test.py b/certbot-apache/certbot_apache/tests/configurator_test.py index f8bf7676c..dc953174e 100644 --- a/certbot-apache/certbot_apache/tests/configurator_test.py +++ b/certbot-apache/certbot_apache/tests/configurator_test.py @@ -128,6 +128,7 @@ class MultipleVhostsTest(util.ApacheTest): def test_get_bad_path(self): from certbot_apache.configurator import get_file_path self.assertEqual(get_file_path(None), None) + self.assertEqual(get_file_path("nonexistent"), None) self.assertEqual(self.config._create_vhost("nonexistent"), None) # pylint: disable=protected-access def test_bad_servername_alias(self): From 3591667d026c32fd92d2aa9440f98b007ee3f578 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 10 Aug 2016 10:43:54 +0300 Subject: [PATCH 111/126] Fix tox tests --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 27979d9df..b53e598f8 100644 --- a/tox.ini +++ b/tox.ini @@ -35,6 +35,7 @@ deps = py{26,27}-oldest: psutil==2.1.0 py{26,27}-oldest: PyOpenSSL==0.13 py{26,27}-oldest: python2-pythondialog==3.2.2rc1 + py{26,27}-oldest: dnspython>=1.12 [testenv:py33] commands = From cb9921f4b1c919ba337aca90309fe8a958033f4b Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Wed, 10 Aug 2016 11:14:39 -0700 Subject: [PATCH 112/126] Add more ignored files to gitignore. --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b653cb06c..48ec7910b 100644 --- a/.gitignore +++ b/.gitignore @@ -17,9 +17,11 @@ letsencrypt-auto-source/letsencrypt-auto.sig.lzma.base64 /.vagrant +tags + # editor temporary files *~ -*.swp +*.sw? \#*# .idea From dd1de2bc9e4d6de7ffb7192dede23fcc68618510 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 11:49:55 -0700 Subject: [PATCH 113/126] Fix travis --- tests/boulder-fetch.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/boulder-fetch.sh b/tests/boulder-fetch.sh index 469c5cd80..0c0a8009b 100755 --- a/tests/boulder-fetch.sh +++ b/tests/boulder-fetch.sh @@ -5,6 +5,6 @@ set -xe # Check out special branch until latest docker changes land in Boulder master. git clone -b docker-integration https://github.com/letsencrypt/boulder $BOULDERPATH cd $BOULDERPATH -sed -i 's/FAKE_DNS: .*/FAKE_DNS: 172.17.42.1/' docker-compose.yml +FAKE_DNS=$(ifconfig docker0 | grep "inet addr:" | cut -d: -f2 | awk '{ print $1}') +sed -i "s/FAKE_DNS: .*/FAKE_DNS: $FAKE_DNS/" docker-compose.yml docker-compose up -d - From fd1629e347a3fce7cf2bc63b7e05063e3d294cd8 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 11:51:12 -0700 Subject: [PATCH 114/126] Make letstest docker ip more robust --- tests/letstest/scripts/boulder_install.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/letstest/scripts/boulder_install.sh b/tests/letstest/scripts/boulder_install.sh index 7e298783f..f997268bd 100755 --- a/tests/letstest/scripts/boulder_install.sh +++ b/tests/letstest/scripts/boulder_install.sh @@ -5,5 +5,6 @@ # Check out special branch until latest docker changes land in Boulder master. git clone -b docker-integration https://github.com/letsencrypt/boulder $BOULDERPATH cd $BOULDERPATH -sed -i 's/FAKE_DNS: .*/FAKE_DNS: 172.17.42.1/' docker-compose.yml +FAKE_DNS=$(ifconfig docker0 | grep "inet addr:" | cut -d: -f2 | awk '{ print $1}') +sed -i "s/FAKE_DNS: .*/FAKE_DNS: $FAKE_DNS/" docker-compose.yml docker-compose up -d From 595e51551866d39593e0e61f2a0dcbe7fa7ad844 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Wed, 10 Aug 2016 14:57:44 -0700 Subject: [PATCH 115/126] Restart web servers before beginning tests --- .../certbot_compatibility_test/configurators/apache/common.py | 2 +- .../certbot_compatibility_test/configurators/nginx/common.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py index 0c53058de..4e612bbd5 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py @@ -58,7 +58,7 @@ class Proxy(configurators_common.Proxy): self._prepare_configurator() try: - subprocess.check_call("apachectl -k start".split()) + subprocess.check_call("apachectl -k restart".split()) except errors.Error: raise errors.Error( "Apache failed to load {0} before tests started".format( diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index 8e2899933..0d72605b7 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -62,7 +62,7 @@ class Proxy(configurators_common.Proxy): self._prepare_configurator() try: - subprocess.check_call("nginx".split()) + subprocess.check_call("service nginx reload".split()) except errors.Error: raise errors.Error( "Nginx failed to load {0} before tests started".format( From 4c596311b068974fd090495be8355323d711c440 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 15:39:35 -0700 Subject: [PATCH 116/126] Add nginx compatibility test data tarball --- .../testdata/nginx.tar.gz | Bin 0 -> 6625 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 certbot-compatibility-test/certbot_compatibility_test/testdata/nginx.tar.gz diff --git a/certbot-compatibility-test/certbot_compatibility_test/testdata/nginx.tar.gz b/certbot-compatibility-test/certbot_compatibility_test/testdata/nginx.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..4ca5cc9775a35f64534f90b1db4fb7ef272672a8 GIT binary patch literal 6625 zcmV<786M^ziwFQ)A*ojY1MFRGbK5wQp0CueK*dvgd$%K5?-IvXS4C1};@c$l+RDs% zzNlytk{I)C2+ESPwg3IP0m>vG((-O{p4}Ux%CXY@paJxQ7lMG=tBksNJ6;9xuI(l9 zGFY8{_pMVG(quH^zago=`R87LGV1qx{r+(HUAH&r4+r0o(KoM2P1>;B%?SA}OOpI4 z+%f&XXj&ce&+^T3`7L|F-_QSWFzLVY{}QQ@|GOk;Z}R20C<6%|Bd_)RkB0pb^530I zx*c8cx&Qjl-D7Mi)wbj#QBmuBpVV_>hIgY zYm>vjZsuc&KadThyx1(bJ>A5Cm-w{Ld;h+}gCXvVnB~;dO}m8H{b}E@$Qd~ybdx1Qp^vztYxKF|7OF(^LS+zQ^^Gnl2&n!L-?H?qP}!(5 zCwo;C_-5pA@L@nSwdK_iVMB)RJYL( z_tjg0<-VHQ3bw{up9Cd)BXm7%*`tSr&K0UYSIMm23Kj2v zQ@QixOz61pO}YR1LN(&5kz5ffbi6-K0P|di?l2nmU*<3Y~RIyMwTqP4z%o?*U*Ey0d6{;R@ zw5)m%q|N$VC-a#Jl^{*#Q*bupbH=nU^C?s#u9BTE`p%3G9#ifGUxf2#f-~9Ty-*3x zWMA=q&&LUe=o}(@`a!4!b@G(-MW{@kOD3EZ^|824W zPVOsfTxH4;Z*v|Ebrj!x5?Vg|4(0dZC27Fs?Cb#(%q2_+wf z`be#kEwr3fL(S?4C8t#%C`vJ5*;AfVwfpCHLd%DvK2@}0g0(rTx~?eyTPXRE)D6|H zQ1U^kn~L(iQ1W4^TZ;07Q1XGP&lKfHq2xnTS82Ntq&l2b-BGlcLdiKbROO8z)#0QX zD&to|DM(cr7o0krQ=_jkE|i>8LnTJ^GKW*Dt9|7cL5w3fRqg&Hl!8;$gYs~7IJJh# z!HrM~YSp##7op_T8fvGwE^5ZPHB^Q~KXo{_hT3JW-&sXwPOqVsyVr7l4Yf~|gZFQ( z-}<5a1ykexkBd4e`sy-{?Em`X@mSgajR%v_>;CU066}XEvfXamzMH#et!N>eus?&%^ABARS+G9DrBA*F1wcG()XZ@UExzEINd4n@_V<*?^mI_DmGd^sVN^zEj~=?det+N}79vY|;w2#?^Y_>HJ@Id6 z|GSUdkXe?bDelX`#Qoq0lF{XlW?7Qep}0bT_9eaj5~OM|E0l4H@zcT&n0pJo;!VT? zI({P<;~KDD^o2qI-q{8CDjpusfEfag zEj64+lG9y&nuf4{6CXXsBr-oU$R`QhdzX1x07HRi*hQhFulfI4G?!cl^`;;IsN!ErbO*Wo;UxlL5(xYwIL(gAfMn33f$F33HO}ySG6YbEWc}~;CPQ`oA9p9O>;FrnR>?CV zSN2~%+1K;M2YdeRV#Yh&_Zj_lLs`CvXueKh*{{QYx;iICdc<$CKn4T!>Sl30zdHZ; zb`J(<_OO8E4rY8AZC!kv+aKqP`OT%hN8@{2m^k?C3v*xf&OqqLFABer>&dY+sRj3c|kn$-Y`#UR}&Dtc&;DV6mj`2X(#YuB~_W2hqUq z8O(wam2vOp^UG_w=cCSC`HC_UM4Nh@}4;#bm7SAQ|$o+%sQ9p?*=k^_~ z=5!tpaI1$2L#pV(lB@GLsn=GTT_aLgF86yo(@Q)neYsMH&j0Nl#Uya7( z)&=5?2`VNklmnAe4$u#$5@{1js z*+W^;{xsaMb`-=LR#d?3qt$WqO%2T)Ai?9N8!ehSMCy7^-cr%b5msU(KvCfB?{8=( zGHMpq(;x)RcCSKC&53eVM>D5bAE~?t80V(w=K5H@BBGfFW*9c!+|f+r)GRpVqw#s9 zLQV%wPZ~@IfUvq69!0As(VEpmxza05kRu;@Up+O{tO3dg>It!C4N6$;_MyaUAq6-xj51>`t>aF&!0m^DjBxvriqYZeY7Tpr|OWz8~CZmK8Bnq{Hf zQV)|gYliZfdXB7FHp-Q`35K(U<3o4U!{Zi6wOQ9tD7XSSQeY?)T!S1bFcb>rAV&%e zg#wrXXGnpeP~d9HJ<*A?fc1Qf7?m3(dnioUv$!JbhSCFN`U|y z9c@Z0F3f*6df9a3i%l)f>EcQ*xfqs9hp+FFi{Ww0!KHjExfmWc9Gw5Bl8ZMW9imin z@e-sXlu9nX17A906iY77vAhY2B^P^$#tD8Z`4}H>9392FEarHe-=~tFE8W~NQ7ifT z0i+g6C4X1CxHChoVxCCbn7zMP6uI5wn4ro?c#N8dzoY&Z9_5b{l$|* zKg`arYzz3G8}m<`-F~-QbL7%E|CjewzIu*1GXGCTWA*z#<6(dBI{&{!YKf~Xf8|#r z`8|_$9);wo!~yURJlVjfvoa^%e|a(ipaS0=DTnO#)`Q4h(bE--il-9jtMJb$T|EWo z`p@Y~7q#TzPO0=M9O!01%4m< z9kz)(pZhS*p?+O#PlVp)J zURBA>gXNQ*0rdDIb%@6%+(v0_3qW4Q@7e*(h|OhyR)&9mvJIc*7VO#)Yd6#clTsOW zziQ|;B7q)%zEtyU>20HVOsFqNsCLjLJXy83NsWWI$=;*taA~`lw+`;9(qx!fx9~&V ztR@?4axQ8P@saDbZ-aPEcf+oXU;nzRfwOG_`>UD+4_k-u)Nkrfps9f;EU%v;;IWCq zj~mpC{Jg0Q&>X_CzvBOCCxWSJla=I0gUz%a4}FU6JgW4QU05@36>wxbx&4fnSNDk~ zc_Tbcwlw1}9?KS|4e(;V@Z`#%q#nOYk`+ANKyS&{ox3O$9sX`Vu^fSa5$55;A$-@K zeBm=vhPRrly<$>}_TZV?t>MYr4|y409RY2>oSLBj`$651DYATy!?ewBIX@;8)!`%e zjxrh^bf9cgGgNl%lxDSaMH-T{W=(<&L73D{)oJFz2)M1wlDS!}PqVtwzQae=H9Tsj zu6GBM6ErA>U$E9>^%Y{YjsTeGs9OtPC*IxG1^+KYm#s_qw$}ap88@~)kG z^)oNZ^SinnyHQtfdv4pKnN*4oO-^Y-q$mnw6t^dtJuE#7*dq5{Bu^x z6Q%uz2V#+OCZmT>fx$aN8Gg)}ppW)D9+BtQP2k<(cV?RMB==P~JTgWNNS;t%#qVG` zzJCG_S{WVMe=&z>;ucrvFrwG5FQ-s&_ zubLXy|ILOq+A8Lctb=vv=2ft^v5jk59s2dV zfxmTXod5Y3&tGKz@Ak*)_rE7y`1Lyfzd#Z+&T4U5;K#5SxgB3nEI;|lJlp@nQc9romDy`kE$jgYdcCR8X zqtQC!intPq)~*s-MxnJw)k4b%v`!UXMxV8-U8{^d>r|~&qR!gYPFzNuwe^a)j5cdm zyLK6A);25RGRmxNRm5e4S$kFym(gYIs&gxmW$o%vD5J_cRdFSvtW)Kpj3(<;xhNya zI@RG(Mv--@PAntH+EwN%(PQnZl`?XyQ*HlY)L5tLwK8I?J*gHV#3qk!Sus{digl{q zEThCax&*I8h;^#=E74({Dz|l!VQqOLD5Jt!T}e|$gte3bClmwj%&MXi3Dz1)nlcKk zB@gmy1Xwvs8U587NQz42SJ_r2>Z>Ksc4fp@OP3U7v{y@>1qPofoDWa>SsYG*?*{VcxmFMtE6j#~7Wdv7C=C=~P)sk&h zBDcz3sfpSu`?HMLYE9(Agu>)wP-;*mQmgFgN|aVz$x@BbDwk7@&MNnT-)Uslmq|zB zzm$PjzM>3q$^SX=fBM}~kMIA7gW+rZpO;9_=Km`K?;P9zb;kpl|9-EF@tlRae;z#({Z&>>6xp^bRs@ATBo_I@R{4+FojEd1}wgE=MapN588YTBs{OuZkWf%X- z&2~*Q`osRu%w)w0t4lm+5B_Bw4!qsu1mhEnyl$3&x4^d<;h}eF?9mRn$jE2tiDVz& zHo(9jl>l5FUb{FTIo+`Al)=&nBQq(Yx3=*U-SOzG?35P~B^f0?&0!Q%|9{)N zmgcl!Abf^jp$^O>nIsr6kJL;LeN2u$w8y5+IA9VF#P(oO!lC``-ESqofE3zh=w-jm zWQ?ViWNEeb+N)10OQX^n_-6dU%xTMJTpcW`Fefg}XiKl!Dq}7-X`?*pi|2jycBE(Y z#nrNF%wB6ndp%dB>3qBBJO>y4d^Y6#80)|*D{|J8OdyP|Kr8gZN0ei$ZkTL6){B%B z<8FDMwk81>j94>@c$L-i z8PVN%%%Ooo)NrcqSs69`zFYI$pxRA9u??bz*oQbe(afPlIUb=nzDgGHWNGPTxR+kp zIx@!JGzya>(5aI~{w#>YxupcI*I?!hRr6}Ka!eR8B;QUZBs~e9K);JiM|&_lh%&%b z!In%*1hpdO0Nlcq*Glk$vHZ{;S&cQFk=0ZB1f={`fGKuq&b6%WQbU;-8|=A!fe!SO z8h9O&0V2z#@#PB*WI1I&{wd$g+6%NhVgWj1q8{SK+MHHXezQP*3wctYWbUtdQ!CYL z_h>k4da=GWMy$D9g#6D@Zzz$}@CWx(;)Ac5`Ua5~CPIic<=Rg*XhiLtGK!6|K`q@K zw%YX9@m|yI&}&_--rQkIO?8RFCuP%A4sO=Tm{Ir>?MZi+|rJU zAJ(>xkhL;JDsuvf)!AE3-kOp|q%x5jzg6)UC!ZGlcRc(2Z^`0cqK*Uozb+}+pgnZ) z{iomSi~n~FJn#QycbI>##4e#lo0urQyx4WntSzMZzt*>OEPbz0|VO z!4xm7;9|lz4t2fcj_hiXaZIS_ckA5qp88{LE6IhidR3>@wsS*y>uLLn#&aCK@W-VW zgl2h(4zd52<90iBDn&JmtK2ScbL~bEV%#j{$upIGGTzrHbMVW{@5Go11OkCTAP@)y f0)apv5C{YUfj}S-2m}IwU>|+~rQ-ge0H6Q>$7DuA literal 0 HcmV?d00001 From 2d099680d01c117fa3d2177e95bb297ff908c1b4 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 15:39:59 -0700 Subject: [PATCH 117/126] Rename apache compatibility test tarball --- .../testdata/{configs.tar.gz => apache.tar.gz} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename certbot-compatibility-test/certbot_compatibility_test/testdata/{configs.tar.gz => apache.tar.gz} (100%) diff --git a/certbot-compatibility-test/certbot_compatibility_test/testdata/configs.tar.gz b/certbot-compatibility-test/certbot_compatibility_test/testdata/apache.tar.gz similarity index 100% rename from certbot-compatibility-test/certbot_compatibility_test/testdata/configs.tar.gz rename to certbot-compatibility-test/certbot_compatibility_test/testdata/apache.tar.gz From a76c36bf1273320da724f727a26ebc73a663c8ff Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 15:52:33 -0700 Subject: [PATCH 118/126] Remove old Dockerfiles --- .../configurators/apache/Dockerfile | 20 ------------------- .../configurators/nginx/Dockerfile | 20 ------------------- 2 files changed, 40 deletions(-) delete mode 100644 certbot-compatibility-test/certbot_compatibility_test/configurators/apache/Dockerfile delete mode 100644 certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/Dockerfile diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/Dockerfile b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/Dockerfile deleted file mode 100644 index ea9bb857f..000000000 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM httpd -MAINTAINER Brad Warren - -RUN mkdir /var/run/apache2 - -ENV APACHE_RUN_USER=daemon \ - APACHE_RUN_GROUP=daemon \ - APACHE_PID_FILE=/usr/local/apache2/logs/httpd.pid \ - APACHE_RUN_DIR=/var/run/apache2 \ - APACHE_LOCK_DIR=/var/lock \ - APACHE_LOG_DIR=/usr/local/apache2/logs - -COPY certbot-compatibility-test/certbot_compatibility_test/configurators/apache/a2enmod.sh /usr/local/bin/ -COPY certbot-compatibility-test/certbot_compatibility_test/configurators/apache/a2dismod.sh /usr/local/bin/ -COPY certbot-compatibility-test/certbot_compatibility_test/testdata/rsa1024_key2.pem /usr/local/apache2/conf/ -COPY certbot-compatibility-test/certbot_compatibility_test/testdata/empty_cert.pem /usr/local/apache2/conf/ - -# Note: this only exposes the port to other docker containers. You -# still have to bind to 443@host at runtime. -EXPOSE 443 diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/Dockerfile b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/Dockerfile deleted file mode 100644 index ea9bb857f..000000000 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM httpd -MAINTAINER Brad Warren - -RUN mkdir /var/run/apache2 - -ENV APACHE_RUN_USER=daemon \ - APACHE_RUN_GROUP=daemon \ - APACHE_PID_FILE=/usr/local/apache2/logs/httpd.pid \ - APACHE_RUN_DIR=/var/run/apache2 \ - APACHE_LOCK_DIR=/var/lock \ - APACHE_LOG_DIR=/usr/local/apache2/logs - -COPY certbot-compatibility-test/certbot_compatibility_test/configurators/apache/a2enmod.sh /usr/local/bin/ -COPY certbot-compatibility-test/certbot_compatibility_test/configurators/apache/a2dismod.sh /usr/local/bin/ -COPY certbot-compatibility-test/certbot_compatibility_test/testdata/rsa1024_key2.pem /usr/local/apache2/conf/ -COPY certbot-compatibility-test/certbot_compatibility_test/testdata/empty_cert.pem /usr/local/apache2/conf/ - -# Note: this only exposes the port to other docker containers. You -# still have to bind to 443@host at runtime. -EXPOSE 443 From 0edb1f6792575d303d592acafd9441cf3ed17367 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 16:08:30 -0700 Subject: [PATCH 119/126] Add certbot-compatibility-test Dockerfiles --- certbot-compatibility-test/Dockerfile | 51 ++++++++++++++++++++ certbot-compatibility-test/Dockerfile-apache | 6 +++ certbot-compatibility-test/Dockerfile-nginx | 6 +++ 3 files changed, 63 insertions(+) create mode 100644 certbot-compatibility-test/Dockerfile create mode 100644 certbot-compatibility-test/Dockerfile-apache create mode 100644 certbot-compatibility-test/Dockerfile-nginx diff --git a/certbot-compatibility-test/Dockerfile b/certbot-compatibility-test/Dockerfile new file mode 100644 index 000000000..d5ef9841c --- /dev/null +++ b/certbot-compatibility-test/Dockerfile @@ -0,0 +1,51 @@ +FROM debian:jessie +MAINTAINER Brad Warren + +WORKDIR /opt/certbot + +# no need to mkdir anything: +# https://docs.docker.com/reference/builder/#copy +# If doesn't exist, it is created along with all missing +# directories in its path. + +# TODO: Install non-default Python versions for tox. +# TODO: Install Apache/Nginx for plugin development. +COPY certbot-auto /opt/certbot/src/certbot-auto +RUN /opt/certbot/src/certbot-auto -n --os-packages-only + +# the above is not likely to change, so by putting it further up the +# Dockerfile we make sure we cache as much as possible + +COPY setup.py README.rst CHANGES.rst MANIFEST.in linter_plugin.py tox.cover.sh tox.ini pep8.travis.sh .pep8 .pylintrc /opt/certbot/src/ + +# all above files are necessary for setup.py, however, package source +# code directory has to be copied separately to a subdirectory... +# https://docs.docker.com/reference/builder/#copy: "If is a +# directory, the entire contents of the directory are copied, +# including filesystem metadata. Note: The directory itself is not +# copied, just its contents." Order again matters, three files are far +# more likely to be cached than the whole project directory + +COPY certbot /opt/certbot/src/certbot/ +COPY acme /opt/certbot/src/acme/ +COPY certbot-apache /opt/certbot/src/certbot-apache/ +COPY certbot-nginx /opt/certbot/src/certbot-nginx/ +COPY certbot-compatibility-test /opt/certbot/src/certbot-compatibility-test/ + +RUN virtualenv --no-site-packages -p python2 /opt/certbot/venv && \ + /opt/certbot/venv/bin/pip install -U setuptools && \ + /opt/certbot/venv/bin/pip install -U pip && \ + /opt/certbot/venv/bin/pip install \ + -e /opt/certbot/src/acme \ + -e /opt/certbot/src \ + -e /opt/certbot/src/certbot-apache \ + -e /opt/certbot/src/certbot-nginx \ + -e /opt/certbot/src/certbot-compatibility-test \ + -e /opt/certbot/src[dev,docs] + +# install in editable mode (-e) to save space: it's not possible to +# "rm -rf /opt/certbot/src" (it's stays in the underlaying image); +# this might also help in debugging: you can "docker run --entrypoint +# bash" and investigate, apply patches, etc. + +ENV PATH /opt/certbot/venv/bin:$PATH diff --git a/certbot-compatibility-test/Dockerfile-apache b/certbot-compatibility-test/Dockerfile-apache new file mode 100644 index 000000000..5c0495966 --- /dev/null +++ b/certbot-compatibility-test/Dockerfile-apache @@ -0,0 +1,6 @@ +FROM certbot-compatibility-test +MAINTAINER Brad Warren + +RUN apt-get install apache2 -y + +ENTRYPOINT [ "certbot-compatibility-test", "-p", "apache" ] diff --git a/certbot-compatibility-test/Dockerfile-nginx b/certbot-compatibility-test/Dockerfile-nginx new file mode 100644 index 000000000..4ade03065 --- /dev/null +++ b/certbot-compatibility-test/Dockerfile-nginx @@ -0,0 +1,6 @@ +FROM certbot-compatibility-test +MAINTAINER Brad Warren + +RUN apt-get install nginx -y + +ENTRYPOINT [ "certbot-compatibility-test", "-p", "nginx" ] From 07b85f9f90a12b3b52c19fb0b379955f728095ca Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 16:32:38 -0700 Subject: [PATCH 120/126] Make testdata the CWD of compatibility test dockerfiles --- certbot-compatibility-test/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot-compatibility-test/Dockerfile b/certbot-compatibility-test/Dockerfile index d5ef9841c..e445a3555 100644 --- a/certbot-compatibility-test/Dockerfile +++ b/certbot-compatibility-test/Dockerfile @@ -1,8 +1,6 @@ FROM debian:jessie MAINTAINER Brad Warren -WORKDIR /opt/certbot - # no need to mkdir anything: # https://docs.docker.com/reference/builder/#copy # If doesn't exist, it is created along with all missing @@ -48,4 +46,6 @@ RUN virtualenv --no-site-packages -p python2 /opt/certbot/venv && \ # this might also help in debugging: you can "docker run --entrypoint # bash" and investigate, apply patches, etc. +WORKDIR /opt/certbot/src/certbot-compatibility-test/certbot_compatibility_test/testdata + ENV PATH /opt/certbot/venv/bin:$PATH From fc86f869a71db80c613e60dbd206e2764908c354 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 16:33:56 -0700 Subject: [PATCH 121/126] add compatibility tests to travis --- tox.ini | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 27979d9df..30c895199 100644 --- a/tox.ini +++ b/tox.ini @@ -79,7 +79,6 @@ commands = pip install -e acme -e .[dev] -e certbot-apache -e certbot-nginx -e certbot-compatibility-test -e letshelp-certbot {toxinidir}/certbot-apache/certbot_apache/tests/apache-conf-files/apache-conf-test --debian-modules - [testenv:le_auto] # At the moment, this tests under Python 2.7 only, as only that version is # readily available on the Trusty Docker image. @@ -89,3 +88,21 @@ commands = whitelist_externals = docker passenv = DOCKER_* + +[testenv:apache_compat] +commands = + docker build -t certbot-compatibility-test -f certbot-compatibility-test/Dockerfile . + docker build -t apache-compat -f certbot-compatibility-test/Dockerfile-apache . + docker run --rm -it apache-compat -c apache.tar.gz -vvvv +whitelist_externals = + docker +passenv = DOCKER_* + +[testenv:nginx_compat] +commands = + docker build -t certbot-compatibility-test -f certbot-compatibility-test/Dockerfile . + docker build -t nginx-compat -f certbot-compatibility-test/Dockerfile-nginx . + docker run --rm -it nginx-compat -c nginx.tar.gz -vvvv +whitelist_externals = + docker +passenv = DOCKER_* From f864cd0cfe29a1ec8caa82204fd6e71ca0e366dc Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 16:43:15 -0700 Subject: [PATCH 122/126] Add nginxroundtrip to tox --- tox.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tox.ini b/tox.ini index 30c895199..64b5170db 100644 --- a/tox.ini +++ b/tox.ini @@ -79,6 +79,11 @@ commands = pip install -e acme -e .[dev] -e certbot-apache -e certbot-nginx -e certbot-compatibility-test -e letshelp-certbot {toxinidir}/certbot-apache/certbot_apache/tests/apache-conf-files/apache-conf-test --debian-modules +[testenv:nginxroundtrip] +commands = + pip install -e acme[dev] -e .[dev] -e certbot-nginx + python certbot-compatibility-test/nginx/roundtrip.py certbot-compatibility-test/nginx/nginx-roundtrip-testdata + [testenv:le_auto] # At the moment, this tests under Python 2.7 only, as only that version is # readily available on the Trusty Docker image. From 5dda27d757b5200651eaac83bc3e62b99b112880 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 16:46:53 -0700 Subject: [PATCH 123/126] Add nginxroundtrip and compatibility-tests to travis --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6f964dbec..5ccf39811 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,8 @@ matrix: - python: "2.7" env: TOXENV=apacheconftest sudo: required + - python: "2.7" + env: TOXENV=nginxroundtrip - python: "2.7" env: TOXENV=py27 BOULDER_INTEGRATION=1 sudo: true @@ -53,6 +55,16 @@ matrix: services: docker before_install: addons: + - sudo: required + env: TOXENV=apache_compat + services: docker + before_install: + addons: + - sudo: required + env: TOXENV=nginx_compat + services: docker + before_install: + addons: - python: "2.7" env: TOXENV=cover - python: "3.3" From cfc8ce9db436d5a0265a9569bf73e1f887126431 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Wed, 10 Aug 2016 17:01:34 -0700 Subject: [PATCH 124/126] Add function docstring --- certbot-nginx/certbot_nginx/constants.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/certbot-nginx/certbot_nginx/constants.py b/certbot-nginx/certbot_nginx/constants.py index 98f924b2b..8cf1f6bc9 100644 --- a/certbot-nginx/certbot_nginx/constants.py +++ b/certbot-nginx/certbot_nginx/constants.py @@ -21,5 +21,12 @@ def os_constant(key): # XXX TODO: In the future, this could return different constants # based on what OS we are running under. To see an # approach to how to handle different OSes, see the - # apache version of this file. + # apache version of this file. Currently, we do not + # actually have any OS-specific constants on Nginx. + """ + Get a constant value for operating system + + :param key: name of cli constant + :return: value of constant for active os + """ return CLI_DEFAULTS[key] From 4bbb12f182341c4d05fe808b03424467949e13b6 Mon Sep 17 00:00:00 2001 From: Seth Schoen Date: Wed, 10 Aug 2016 17:16:54 -0700 Subject: [PATCH 125/126] Satisfying some lint complaints --- .../configurators/apache/common.py | 1 - .../configurators/nginx/__init__.py | 2 +- .../configurators/nginx/common.py | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py index 4e612bbd5..b7b1f52c2 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py @@ -1,5 +1,4 @@ """Provides a common base for Apache proxies""" -import re import os import shutil import subprocess diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/__init__.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/__init__.py index d559d0645..ed294abe6 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/__init__.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/__init__.py @@ -1 +1 @@ -"""Certbot compatibility test Apache configurators""" +"""Certbot compatibility test Nginx configurators""" diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index 0d72605b7..311ae4ba6 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -1,5 +1,4 @@ -"""Provides a common base for Apache proxies""" -import re +"""Provides a common base for Nginx proxies""" import os import shutil import subprocess @@ -78,7 +77,7 @@ class Proxy(configurators_common.Proxy): # This does not appear to exist in nginx (yet?) # self.le_config.nginx_handle_modules = self.le_config.nginx_handle_mods - conf=configuration.NamespaceConfig(self.le_config) + conf = configuration.NamespaceConfig(self.le_config) zope.component.provideUtility(conf) self._nginx_configurator = configurator.NginxConfigurator( config=conf, name="nginx") @@ -132,6 +131,7 @@ def _get_names(config): for line in open(os.path.join(root, this_file)): if line.strip().startswith("server_name"): names = line.partition("server_name")[2].rpartition(";")[0] - [all_names.add(n) for n in names.split()] + for n in names.split(): + all_names.add(n) non_ip_names = set(n for n in all_names if not util.IP_REGEX.match(n)) return all_names, non_ip_names From 1f471da7685a790d9bc4f0d66b5f359df0877025 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 10 Aug 2016 17:39:29 -0700 Subject: [PATCH 126/126] Remove code duplication to make pylint happy --- .../configurators/apache/common.py | 38 +------------ .../configurators/common.py | 35 ++++++++++++ .../configurators/nginx/common.py | 57 +------------------ 3 files changed, 39 insertions(+), 91 deletions(-) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py index b7b1f52c2..64170ca72 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py @@ -27,30 +27,18 @@ class Proxy(configurators_common.Proxy): self.le_config.apache_le_vhost_ext = "-le-ssl.conf" self.modules = self.server_root = self.test_conf = self.version = None - self._apache_configurator = self._all_names = self._test_names = None patch = mock.patch( "certbot_apache.configurator.display_ops.select_vhost") mock_display = patch.start() mock_display.side_effect = le_errors.PluginError( "Unable to determine vhost") - def __getattr__(self, name): - """Wraps the Apache Configurator methods""" - method = getattr(self._apache_configurator, name, None) - if callable(method): - return method - else: - raise AttributeError() - def load_config(self): """Loads the next configuration for the plugin to test""" - config = super(Proxy, self).load_config() self._all_names, self._test_names = _get_names(config) server_root = _get_server_root(config) - # with open(os.path.join(config, "config_file")) as f: - # config_file = os.path.join(server_root, f.readline().rstrip()) shutil.rmtree("/etc/apache2") shutil.copytree(server_root, "/etc/apache2", symlinks=True) @@ -73,38 +61,16 @@ class Proxy(configurators_common.Proxy): # An alias self.le_config.apache_handle_modules = self.le_config.apache_handle_mods - self._apache_configurator = configurator.ApacheConfigurator( + self._configurator = configurator.ApacheConfigurator( config=configuration.NamespaceConfig(self.le_config), name="apache") - self._apache_configurator.prepare() + self._configurator.prepare() def cleanup_from_tests(self): """Performs any necessary cleanup from running plugin tests""" super(Proxy, self).cleanup_from_tests() mock.patch.stopall() - def get_all_names_answer(self): - """Returns the set of domain names that the plugin should find""" - if self._all_names: - return self._all_names - else: - raise errors.Error("No configuration file loaded") - - def get_testable_domain_names(self): - """Returns the set of domain names that can be tested against""" - if self._test_names: - return self._test_names - else: - return {"example.com"} - - def deploy_cert(self, domain, cert_path, key_path, chain_path=None, - fullchain_path=None): - """Installs cert""" - cert_path, key_path, chain_path = self.copy_certs_and_keys( - cert_path, key_path, chain_path) - self._apache_configurator.deploy_cert( - domain, cert_path, key_path, chain_path, fullchain_path) - def _get_server_root(config): """Returns the server root directory in config""" diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py index 03128cc86..2a800c1c2 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py @@ -5,6 +5,7 @@ import shutil import tempfile from certbot import constants +from certbot_compatibility_test import errors from certbot_compatibility_test import util @@ -31,6 +32,18 @@ class Proxy(object): self.args = args self.http_port = 80 self.https_port = 443 + self._configurator = self._all_names = self._test_names = None + + def __getattr__(self, name): + """Wraps the configurator methods""" + if self._configurator is None: + raise AttributeError() + + method = getattr(self._configurator, name, None) + if callable(method): + return method + else: + raise AttributeError() def has_more_configs(self): """Returns true if there are more configs to test""" @@ -63,3 +76,25 @@ class Proxy(object): chain = None return cert, key, chain + + def get_all_names_answer(self): + """Returns the set of domain names that the plugin should find""" + if self._all_names: + return self._all_names + else: + raise errors.Error("No configuration file loaded") + + def get_testable_domain_names(self): + """Returns the set of domain names that can be tested against""" + if self._test_names: + return self._test_names + else: + return {"example.com"} + + def deploy_cert(self, domain, cert_path, key_path, chain_path=None, + fullchain_path=None): + """Installs cert""" + cert_path, key_path, chain_path = self.copy_certs_and_keys( + cert_path, key_path, chain_path) + self._configurator.deploy_cert( + domain, cert_path, key_path, chain_path, fullchain_path) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index 311ae4ba6..3622bee41 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -3,11 +3,9 @@ import os import shutil import subprocess -import mock import zope.interface from certbot import configuration -from certbot import errors as le_errors from certbot_nginx import configurator from certbot_nginx import constants from certbot_compatibility_test import errors @@ -22,36 +20,15 @@ class Proxy(configurators_common.Proxy): """A common base for Nginx test configurators""" def __init__(self, args): - # XXX: This is still apache-specific """Initializes the plugin with the given command line args""" super(Proxy, self).__init__(args) - self.le_config.apache_le_vhost_ext = "-le-ssl.conf" - - self.modules = self.server_root = self.test_conf = self.version = None - self._nginx_configurator = self._all_names = self._test_names = None - patch = mock.patch( - "certbot_apache.configurator.display_ops.select_vhost") - mock_display = patch.start() - mock_display.side_effect = le_errors.PluginError( - "Unable to determine vhost") - - def __getattr__(self, name): - """Wraps the Nginx Configurator methods""" - method = getattr(self._nginx_configurator, name, None) - if callable(method): - return method - else: - raise AttributeError() def load_config(self): """Loads the next configuration for the plugin to test""" - config = super(Proxy, self).load_config() self._all_names, self._test_names = _get_names(config) server_root = _get_server_root(config) - # with open(os.path.join(config, "config_file")) as f: - # config_file = os.path.join(server_root, f.readline().rstrip()) # XXX: Deleting all of this is kind of scary unless the test # instances really each have a complete configuration! @@ -74,41 +51,11 @@ class Proxy(configurators_common.Proxy): for k in constants.CLI_DEFAULTS.keys(): setattr(self.le_config, "nginx_" + k, constants.os_constant(k)) - # This does not appear to exist in nginx (yet?) - # self.le_config.nginx_handle_modules = self.le_config.nginx_handle_mods - conf = configuration.NamespaceConfig(self.le_config) zope.component.provideUtility(conf) - self._nginx_configurator = configurator.NginxConfigurator( + self._configurator = configurator.NginxConfigurator( config=conf, name="nginx") - self._nginx_configurator.prepare() - - def cleanup_from_tests(self): - """Performs any necessary cleanup from running plugin tests""" - super(Proxy, self).cleanup_from_tests() - mock.patch.stopall() - - def get_all_names_answer(self): - """Returns the set of domain names that the plugin should find""" - if self._all_names: - return self._all_names - else: - raise errors.Error("No configuration file loaded") - - def get_testable_domain_names(self): - """Returns the set of domain names that can be tested against""" - if self._test_names: - return self._test_names - else: - return {"example.com"} - - def deploy_cert(self, domain, cert_path, key_path, chain_path=None, - fullchain_path=None): - """Installs cert""" - cert_path, key_path, chain_path = self.copy_certs_and_keys( - cert_path, key_path, chain_path) - self._nginx_configurator.deploy_cert( - domain, cert_path, key_path, chain_path, fullchain_path) + self._configurator.prepare() def _get_server_root(config):