Compare commits

...

7 Commits

Author SHA1 Message Date
Brad Warren
ea445ed11e Release 0.22.2 2018-03-19 17:41:17 -07:00
Brad Warren
8d061e5dfc Fix cleanup_challenges call (#5761) (#5762)
* fixes cleanup_challenges

* add test to prevent regressions

(cherry picked from commit 41ce108881)
2018-03-19 17:29:59 -07:00
Brad Warren
0131c649d0 Fix acme.client.Client.__init__ (#5747) (#5748)
* fixes #5738

* add test to prevent regressions

(cherry picked from commit ba6bdb5099)
2018-03-16 18:44:23 -07:00
Brad Warren
eda458b2da Update instances of acme-staging url to acme-staging-v02 (#5734) (#5746)
* update instances of acme-staging url to acme-staging-v02

* keep example client as v1

* keep deactivate script as v1

(cherry picked from commit 5ecb68f2ed)
2018-03-16 17:11:12 -07:00
Brad Warren
cedbf8906c removes blank line from chain.pem (#5730) (#5733)
(cherry picked from commit b3e73bd2ab)
2018-03-14 18:58:52 -07:00
Brad Warren
d0b336085c fix(acme): client._revoke sends default content_type (#5687) (#5726)
(cherry picked from commit f4bac423fb)
2018-03-14 18:34:59 -07:00
Brad Warren
c9f278e6c8 Fix --allow-subset-of-names (#5690) (#5725)
* Remove aauthzr instance variable

* If domain begins with fail, fail the challenge.

* test --allow-subset-of-names

* Fix renewal and add extra check

* test after hook checks

(cherry picked from commit cc24b4e40a)
2018-03-14 17:28:45 -07:00
36 changed files with 228 additions and 178 deletions

View File

@@ -227,8 +227,7 @@ class ClientBase(object): # pylint: disable=too-many-instance-attributes
response = self._post(url,
messages.Revocation(
certificate=cert,
reason=rsn),
content_type=None)
reason=rsn))
if response.status_code != http_client.OK:
raise errors.ClientError(
'Successful revocation must return HTTP OK status')
@@ -260,11 +259,12 @@ class Client(ClientBase):
"""
# pylint: disable=too-many-arguments
self.key = key
self.net = ClientNetwork(key, alg=alg, verify_ssl=verify_ssl) if net is None else net
if net is None:
net = ClientNetwork(key, alg=alg, verify_ssl=verify_ssl)
if isinstance(directory, six.string_types):
directory = messages.Directory.from_json(
self.net.get(directory).json())
net.get(directory).json())
super(Client, self).__init__(directory=directory,
net=net, acme_version=1)

View File

@@ -299,6 +299,16 @@ class ClientTest(ClientTestBase):
directory=uri, key=KEY, alg=jose.RS256, net=self.net)
self.net.get.assert_called_once_with(uri)
@mock.patch('acme.client.ClientNetwork')
def test_init_without_net(self, mock_net):
mock_net.return_value = mock.sentinel.net
alg = jose.RS256
from acme.client import Client
self.client = Client(
directory=self.directory, key=KEY, alg=alg)
mock_net.called_once_with(KEY, alg=alg, verify_ssl=True)
self.assertEqual(self.client.net, mock.sentinel.net)
def test_register(self):
# "Instance of 'Field' has no to_json/update member" bug:
# pylint: disable=no-member
@@ -635,8 +645,7 @@ class ClientTest(ClientTestBase):
def test_revoke(self):
self.client.revoke(self.certr.body, self.rsn)
self.net.post.assert_called_once_with(
self.directory[messages.Revocation], mock.ANY, content_type=None,
acme_version=1)
self.directory[messages.Revocation], mock.ANY, acme_version=1)
def test_revocation_payload(self):
obj = messages.Revocation(certificate=self.certr.body, reason=self.rsn)
@@ -776,8 +785,7 @@ class ClientV2Test(ClientTestBase):
def test_revoke(self):
self.client.revoke(messages_test.CERT, self.rsn)
self.net.post.assert_called_once_with(
self.directory["revokeCert"], mock.ANY, content_type=None,
acme_version=2)
self.directory["revokeCert"], mock.ANY, acme_version=2)
class MockJSONDeSerializable(jose.JSONDeSerializable):

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi
VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="0.22.0"
LE_AUTO_VERSION="0.22.2"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -1199,18 +1199,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==0.22.0 \
--hash=sha256:ebfeaf9737dc440a9f263099487523ab4c8d8da9def31a71327439d9186e00fa \
--hash=sha256:ee307dd8f194bd710a3326aa4bacf95d358877498c0b9aa187eff0dc211dcbb3
acme==0.22.0 \
--hash=sha256:37e6d8e4eb7dd18edac96de209f451300e04074f14be7fce713db6931a0e4a20 \
--hash=sha256:4a2cd52db32e914b68d8446c8e788f507c20edebbd1c36d4f3eda7b47c555fe8
certbot-apache==0.22.0 \
--hash=sha256:e91f6ec8203b636fa44f01017646fca68406224ee327fd56017103b78bc65539 \
--hash=sha256:8fbab1a358ec131996d1c00f7d0ed18ee3624f8469cab3962dfd8ba40ca3e7cd
certbot-nginx==0.22.0 \
--hash=sha256:d67210cf73cf44e8aeff04f6f228d8bde74444703ce3ccd929a450685b58c30b \
--hash=sha256:b2b26bf9112062b02518407704cad09f7136322163d529a2dde3b6e1578ecb8c
certbot==0.22.2 \
--hash=sha256:c8c63bdf0fed6258bdbc892454314ec37bcd1c35a7f62524a083d93ccdfc420d \
--hash=sha256:e6e3639293e78397f31f7d99e3c63aff82d91e2b0d50d146ee3c77f830464bef
acme==0.22.2 \
--hash=sha256:59a55244612ee305d2caa6bb4cddd400fb60ec841bf011ed29a2899832a682c2 \
--hash=sha256:0ecd0ea369f53d5bc744d6e72717f9af2e1ceb558d109dbd433148851027adb4
certbot-apache==0.22.2 \
--hash=sha256:b5340d4b9190358fde8eb6a5be0def37e32014b5142ee79ef5d2319ccbbde754 \
--hash=sha256:3cd26912bb5732d917ddf7aad2fe870090d4ece9a408b2c2de8e9723ec99c759
certbot-nginx==0.22.2 \
--hash=sha256:91feef0d879496835d355e82841f92e5ecb5abbf6f23ea0ee5bbb8f5a92b278a \
--hash=sha256:b10bf04c1a20cf878d5e0d1877deb0e0780bc31b0ffda08ce7199bbc39d0753b
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
install_requires = [
'certbot',

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -3,7 +3,7 @@ import sys
from distutils.core import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.22.0'
version = '0.22.2'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -1,4 +1,4 @@
"""Certbot client."""
# version number like 1.2.3a0, must have at least 2 parts, like 1.2
__version__ = '0.22.0'
__version__ = '0.22.2'

View File

@@ -34,8 +34,6 @@ class AuthHandler(object):
:ivar account: Client's Account
:type account: :class:`certbot.account.Account`
:ivar aauthzrs: ACME Authorization Resources and their active challenges
:type aauthzrs: `list` of `AnnotatedAuthzr`
:ivar list pref_challs: sorted user specified preferred challenges
type strings with the most preferred challenge listed first
@@ -45,7 +43,6 @@ class AuthHandler(object):
self.acme = acme
self.account = account
self.aauthzrs = []
self.pref_challs = pref_challs
def handle_authorizations(self, orderr, best_effort=False):
@@ -63,29 +60,29 @@ class AuthHandler(object):
authorizations
"""
for authzr in orderr.authorizations:
self.aauthzrs.append(AnnotatedAuthzr(authzr, []))
aauthzrs = [AnnotatedAuthzr(authzr, [])
for authzr in orderr.authorizations]
self._choose_challenges()
self._choose_challenges(aauthzrs)
config = zope.component.getUtility(interfaces.IConfig)
notify = zope.component.getUtility(interfaces.IDisplay).notification
# While there are still challenges remaining...
while self._has_challenges():
resp = self._solve_challenges()
while self._has_challenges(aauthzrs):
resp = self._solve_challenges(aauthzrs)
logger.info("Waiting for verification...")
if config.debug_challenges:
notify('Challenges loaded. Press continue to submit to CA. '
'Pass "-v" for more info about challenges.', pause=True)
# Send all Responses - this modifies achalls
self._respond(resp, best_effort)
self._respond(aauthzrs, resp, best_effort)
# Just make sure all decisions are complete.
self.verify_authzr_complete()
self.verify_authzr_complete(aauthzrs)
# Only return valid authorizations
retVal = [aauthzr.authzr for aauthzr in self.aauthzrs
retVal = [aauthzr.authzr for aauthzr in aauthzrs
if aauthzr.authzr.body.status == messages.STATUS_VALID]
if not retVal:
@@ -94,10 +91,10 @@ class AuthHandler(object):
return retVal
def _choose_challenges(self):
def _choose_challenges(self, aauthzrs):
"""Retrieve necessary challenges to satisfy server."""
logger.info("Performing the following challenges:")
for aauthzr in self.aauthzrs:
for aauthzr in aauthzrs:
aauthzr_challenges = aauthzr.authzr.body.challenges
if self.acme.acme_version == 1:
combinations = aauthzr.authzr.body.combinations
@@ -113,15 +110,15 @@ class AuthHandler(object):
aauthzr.authzr, path)
aauthzr.achalls.extend(aauthzr_achalls)
def _has_challenges(self):
def _has_challenges(self, aauthzrs):
"""Do we have any challenges to perform?"""
return any(aauthzr.achalls for aauthzr in self.aauthzrs)
return any(aauthzr.achalls for aauthzr in aauthzrs)
def _solve_challenges(self):
def _solve_challenges(self, aauthzrs):
"""Get Responses for challenges from authenticators."""
resp = []
all_achalls = self._get_all_achalls()
with error_handler.ErrorHandler(self._cleanup_challenges):
all_achalls = self._get_all_achalls(aauthzrs)
with error_handler.ErrorHandler(self._cleanup_challenges, aauthzrs, all_achalls):
try:
if all_achalls:
resp = self.auth.perform(all_achalls)
@@ -134,15 +131,15 @@ class AuthHandler(object):
return resp
def _get_all_achalls(self):
def _get_all_achalls(self, aauthzrs):
"""Return all active challenges."""
all_achalls = []
for aauthzr in self.aauthzrs:
for aauthzr in aauthzrs:
all_achalls.extend(aauthzr.achalls)
return all_achalls
def _respond(self, resp, best_effort):
def _respond(self, aauthzrs, resp, best_effort):
"""Send/Receive confirmation of all challenges.
.. note:: This method also cleans up the auth_handler state.
@@ -150,24 +147,27 @@ class AuthHandler(object):
"""
# TODO: chall_update is a dirty hack to get around acme-spec #105
chall_update = dict()
active_achalls = self._send_responses(resp, chall_update)
active_achalls = self._send_responses(aauthzrs, resp, chall_update)
# Check for updated status...
try:
self._poll_challenges(chall_update, best_effort)
self._poll_challenges(aauthzrs, chall_update, best_effort)
finally:
self._cleanup_challenges(active_achalls)
self._cleanup_challenges(aauthzrs, active_achalls)
def _send_responses(self, resps, chall_update):
def _send_responses(self, aauthzrs, resps, chall_update):
"""Send responses and make sure errors are handled.
:param aauthzrs: authorizations and the selected annotated challenges
to try and perform
:type aauthzrs: `list` of `AnnotatedAuthzr`
:param dict chall_update: parameter that is updated to hold
aauthzr index to list of outstanding solved annotated challenges
"""
active_achalls = []
resps_iter = iter(resps)
for i, aauthzr in enumerate(self.aauthzrs):
for i, aauthzr in enumerate(aauthzrs):
for achall in aauthzr.achalls:
# This line needs to be outside of the if block below to
# ensure failed challenges are cleaned up correctly
@@ -184,8 +184,8 @@ class AuthHandler(object):
return active_achalls
def _poll_challenges(
self, chall_update, best_effort, min_sleep=3, max_rounds=15):
def _poll_challenges(self, aauthzrs, chall_update,
best_effort, min_sleep=3, max_rounds=15):
"""Wait for all challenge results to be determined."""
indices_to_check = set(chall_update.keys())
comp_indices = set()
@@ -197,7 +197,7 @@ class AuthHandler(object):
all_failed_achalls = set()
for index in indices_to_check:
comp_achalls, failed_achalls = self._handle_check(
index, chall_update[index])
aauthzrs, index, chall_update[index])
if len(comp_achalls) == len(chall_update[index]):
comp_indices.add(index)
@@ -210,7 +210,7 @@ class AuthHandler(object):
comp_indices.add(index)
logger.warning(
"Challenge failed for domain %s",
self.aauthzrs[index].authzr.body.identifier.value)
aauthzrs[index].authzr.body.identifier.value)
else:
all_failed_achalls.update(
updated for _, updated in failed_achalls)
@@ -223,14 +223,14 @@ class AuthHandler(object):
comp_indices.clear()
rounds += 1
def _handle_check(self, index, achalls):
def _handle_check(self, aauthzrs, index, achalls):
"""Returns tuple of ('completed', 'failed')."""
completed = []
failed = []
original_aauthzr = self.aauthzrs[index]
original_aauthzr = aauthzrs[index]
updated_authzr, _ = self.acme.poll(original_aauthzr.authzr)
self.aauthzrs[index] = AnnotatedAuthzr(updated_authzr, original_aauthzr.achalls)
aauthzrs[index] = AnnotatedAuthzr(updated_authzr, original_aauthzr.achalls)
if updated_authzr.body.status == messages.STATUS_VALID:
return achalls, []
@@ -287,35 +287,38 @@ class AuthHandler(object):
chall_prefs.extend(plugin_pref)
return chall_prefs
def _cleanup_challenges(self, achall_list=None):
def _cleanup_challenges(self, aauthzrs, achalls):
"""Cleanup challenges.
If achall_list is not provided, cleanup all achallenges.
:param aauthzrs: authorizations and their selected annotated
challenges
:type aauthzrs: `list` of `AnnotatedAuthzr`
:param achalls: annotated challenges to cleanup
:type achalls: `list` of :class:`certbot.achallenges.AnnotatedChallenge`
"""
logger.info("Cleaning up challenges")
if achall_list is None:
achalls = self._get_all_achalls()
else:
achalls = achall_list
if achalls:
self.auth.cleanup(achalls)
for achall in achalls:
for aauthzr in self.aauthzrs:
for aauthzr in aauthzrs:
if achall in aauthzr.achalls:
aauthzr.achalls.remove(achall)
break
def verify_authzr_complete(self):
def verify_authzr_complete(self, aauthzrs):
"""Verifies that all authorizations have been decided.
:param aauthzrs: authorizations and their selected annotated
challenges
:type aauthzrs: `list` of `AnnotatedAuthzr`
:returns: Whether all authzr are complete
:rtype: bool
"""
for aauthzr in self.aauthzrs:
for aauthzr in aauthzrs:
authzr = aauthzr.authzr
if (authzr.body.status != messages.STATUS_VALID and
authzr.body.status != messages.STATUS_INVALID):

View File

@@ -107,7 +107,7 @@ CLI_DEFAULTS = dict(
dns_route53=False
)
STAGING_URI = "https://acme-staging.api.letsencrypt.org/directory"
STAGING_URI = "https://acme-staging-v02.api.letsencrypt.org/directory"
# The set of reasons for revoking a certificate is defined in RFC 5280 in
# section 5.3.1. The reasons that users are allowed to submit are restricted to

View File

@@ -445,5 +445,5 @@ def cert_and_chain_from_fullchain(fullchain_pem):
"""
cert = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM,
OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, fullchain_pem)).decode()
chain = fullchain_pem[len(cert):]
chain = fullchain_pem[len(cert):].lstrip()
return (cert, chain)

View File

@@ -101,7 +101,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
self.assertEqual(self.mock_net.answer_challenge.call_count, 1)
self.assertEqual(mock_poll.call_count, 1)
chall_update = mock_poll.call_args[0][0]
chall_update = mock_poll.call_args[0][1]
self.assertEqual(list(six.iterkeys(chall_update)), [0])
self.assertEqual(len(chall_update.values()), 1)
@@ -132,7 +132,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
self.assertEqual(self.mock_net.answer_challenge.call_count, 3)
self.assertEqual(mock_poll.call_count, 1)
chall_update = mock_poll.call_args[0][0]
chall_update = mock_poll.call_args[0][1]
self.assertEqual(list(six.iterkeys(chall_update)), [0])
self.assertEqual(len(chall_update.values()), 1)
@@ -158,7 +158,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
self.assertEqual(self.mock_net.answer_challenge.call_count, 1)
self.assertEqual(mock_poll.call_count, 1)
chall_update = mock_poll.call_args[0][0]
chall_update = mock_poll.call_args[0][1]
self.assertEqual(list(six.iterkeys(chall_update)), [0])
self.assertEqual(len(chall_update.values()), 1)
@@ -187,7 +187,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
# Check poll call
self.assertEqual(mock_poll.call_count, 1)
chall_update = mock_poll.call_args[0][0]
chall_update = mock_poll.call_args[0][1]
self.assertEqual(len(list(six.iterkeys(chall_update))), 3)
self.assertTrue(0 in list(six.iterkeys(chall_update)))
self.assertEqual(len(chall_update[0]), 1)
@@ -278,8 +278,19 @@ class HandleAuthorizationsTest(unittest.TestCase):
self.assertRaises(
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
def _validate_all(self, unused_1, unused_2):
for i, aauthzr in enumerate(self.handler.aauthzrs):
def test_perform_error(self):
self.mock_auth.perform.side_effect = errors.AuthorizationError
authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=True)
mock_order = mock.MagicMock(authorizations=[authzr])
self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
self.assertEqual(self.mock_auth.cleanup.call_count, 1)
self.assertEqual(
self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01")
def _validate_all(self, aauthzrs, unused_1, unused_2):
for i, aauthzr in enumerate(aauthzrs):
azr = aauthzr.authzr
updated_azr = acme_util.gen_authzr(
messages.STATUS_VALID,
@@ -287,7 +298,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
[challb.chall for challb in azr.body.challenges],
[messages.STATUS_VALID] * len(azr.body.challenges),
azr.body.combinations)
self.handler.aauthzrs[i] = type(aauthzr)(updated_azr, aauthzr.achalls)
aauthzrs[i] = type(aauthzr)(updated_azr, aauthzr.achalls)
class PollChallengesTest(unittest.TestCase):
@@ -304,19 +315,21 @@ class PollChallengesTest(unittest.TestCase):
None, self.mock_net, mock.Mock(key="mock_key"), [])
self.doms = ["0", "1", "2"]
self.handler.aauthzrs.append(AnnotatedAuthzr(acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[0],
[acme_util.HTTP01, acme_util.TLSSNI01],
[messages.STATUS_PENDING] * 2, False), []))
self.handler.aauthzrs.append(AnnotatedAuthzr(acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[1],
acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False), []))
self.handler.aauthzrs.append(AnnotatedAuthzr(acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[2],
acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False), []))
self.aauthzrs = [
AnnotatedAuthzr(acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[0],
[acme_util.HTTP01, acme_util.TLSSNI01],
[messages.STATUS_PENDING] * 2, False), []),
AnnotatedAuthzr(acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[1],
acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False), []),
AnnotatedAuthzr(acme_util.gen_authzr(
messages.STATUS_PENDING, self.doms[2],
acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False), [])
]
self.chall_update = {}
for i, aauthzr in enumerate(self.handler.aauthzrs):
for i, aauthzr in enumerate(self.aauthzrs):
self.chall_update[i] = [
challb_to_achall(challb, mock.Mock(key="dummy_key"), self.doms[i])
for challb in aauthzr.authzr.body.challenges]
@@ -324,17 +337,17 @@ class PollChallengesTest(unittest.TestCase):
@mock.patch("certbot.auth_handler.time")
def test_poll_challenges(self, unused_mock_time):
self.mock_net.poll.side_effect = self._mock_poll_solve_one_valid
self.handler._poll_challenges(self.chall_update, False)
self.handler._poll_challenges(self.aauthzrs, self.chall_update, False)
for aauthzr in self.handler.aauthzrs:
for aauthzr in self.aauthzrs:
self.assertEqual(aauthzr.authzr.body.status, messages.STATUS_VALID)
@mock.patch("certbot.auth_handler.time")
def test_poll_challenges_failure_best_effort(self, unused_mock_time):
self.mock_net.poll.side_effect = self._mock_poll_solve_one_invalid
self.handler._poll_challenges(self.chall_update, True)
self.handler._poll_challenges(self.aauthzrs, self.chall_update, True)
for aauthzr in self.handler.aauthzrs:
for aauthzr in self.aauthzrs:
self.assertEqual(aauthzr.authzr.body.status, messages.STATUS_PENDING)
@mock.patch("certbot.auth_handler.time")
@@ -343,7 +356,7 @@ class PollChallengesTest(unittest.TestCase):
self.mock_net.poll.side_effect = self._mock_poll_solve_one_invalid
self.assertRaises(
errors.AuthorizationError, self.handler._poll_challenges,
self.chall_update, False)
self.aauthzrs, self.chall_update, False)
@mock.patch("certbot.auth_handler.time")
def test_unable_to_find_challenge_status(self, unused_mock_time):
@@ -353,11 +366,11 @@ class PollChallengesTest(unittest.TestCase):
challb_to_achall(acme_util.DNS01_P, "key", self.doms[0]))
self.assertRaises(
errors.AuthorizationError, self.handler._poll_challenges,
self.chall_update, False)
self.aauthzrs, self.chall_update, False)
def test_verify_authzr_failure(self):
self.assertRaises(
errors.AuthorizationError, self.handler.verify_authzr_complete)
self.assertRaises(errors.AuthorizationError,
self.handler.verify_authzr_complete, self.aauthzrs)
def _mock_poll_solve_one_valid(self, authzr):
# Pending here because my dummy script won't change the full status.

View File

@@ -380,10 +380,12 @@ class CertAndChainFromFullchainTest(unittest.TestCase):
cert_pem = CERT.decode()
chain_pem = cert_pem + SS_CERT.decode()
fullchain_pem = cert_pem + chain_pem
spacey_fullchain_pem = cert_pem + u'\n' + chain_pem
from certbot.crypto_util import cert_and_chain_from_fullchain
cert_out, chain_out = cert_and_chain_from_fullchain(fullchain_pem)
self.assertEqual(cert_out, cert_pem)
self.assertEqual(chain_out, chain_pem)
for fullchain in (fullchain_pem, spacey_fullchain_pem):
cert_out, chain_out = cert_and_chain_from_fullchain(fullchain)
self.assertEqual(cert_out, cert_pem)
self.assertEqual(chain_out, chain_pem)
if __name__ == '__main__':

View File

@@ -726,7 +726,7 @@ class RenewableCertTests(BaseRenewableCertTest):
self.test_rc.configuration["renewalparams"] = {}
rp = self.test_rc.configuration["renewalparams"]
self.assertEqual(self.test_rc.is_test_cert, False)
rp["server"] = "https://acme-staging.api.letsencrypt.org/directory"
rp["server"] = "https://acme-staging-v02.api.letsencrypt.org/directory"
self.assertEqual(self.test_rc.is_test_cert, True)
rp["server"] = "https://staging.someotherca.com/directory"
self.assertEqual(self.test_rc.is_test_cert, True)

View File

@@ -61,7 +61,7 @@ chain_path = /home/ubuntu/letsencrypt/chain.pem
break_my_certs = False
standalone = True
manual = False
server = https://acme-staging.api.letsencrypt.org/directory
server = https://acme-staging-v02.api.letsencrypt.org/directory
standalone_supported_challenges = "tls-sni-01,http-01"
webroot = False
os_packages_only = False

View File

@@ -107,9 +107,9 @@ optional arguments:
case, and to know when to deprecate support for past
Python versions and flags. If you wish to hide this
information from the Let's Encrypt server, set this to
"". (default: CertbotACMEClient/0.22.0 (certbot;
"". (default: CertbotACMEClient/0.22.2 (certbot;
darwin 10.13.3) Authenticator/XXX Installer/YYY
(SUBCOMMAND; flags: FLAGS) Py/3.6.4). The flags
(SUBCOMMAND; flags: FLAGS) Py/2.7.14). The flags
encoded in the user agent are: --duplicate, --force-
renew, --allow-subset-of-names, -n, and whether any
hooks are set.
@@ -199,8 +199,8 @@ testing:
--test-cert, --staging
Use the staging server to obtain or revoke test
(invalid) certificates; equivalent to --server
https://acme-staging.api.letsencrypt.org/directory
(invalid) certificates; equivalent to --server https
://acme-staging-v02.api.letsencrypt.org/directory
(default: False)
--debug Show tracebacks in case of errors, and allow certbot-
auto execution on experimental platforms (default:
@@ -308,8 +308,8 @@ renew:
of renewed certificate domains (for example,
"example.com www.example.com" (default: None)
--disable-hook-validation
Ordinarily the commands specified for --pre-
hook/--post-hook/--deploy-hook will be checked for
Ordinarily the commands specified for --pre-hook
/--post-hook/--deploy-hook will be checked for
validity, to see if the programs being run are in the
$PATH, so that mistakes can be caught early, even when
the hooks aren't being run just yet. The validation is

View File

@@ -43,7 +43,7 @@ each shell where you're working:
.. code-block:: shell
source ./venv/bin/activate
export SERVER=https://acme-staging.api.letsencrypt.org/directory
export SERVER=https://acme-staging-v02.api.letsencrypt.org/directory
source tests/integration/_common.sh
After that, your shell will be using the virtual environment, your copy of
@@ -443,10 +443,10 @@ For squeeze you will need to:
FreeBSD
-------
Packages can be installed on FreeBSD using ``pkg``,
or any other port-management tool (``portupgrade``, ``portmanager``, etc.)
from the pre-built package or can be built and installed from ports.
Either way will ensure proper installation of all the dependencies required
Packages can be installed on FreeBSD using ``pkg``,
or any other port-management tool (``portupgrade``, ``portmanager``, etc.)
from the pre-built package or can be built and installed from ports.
Either way will ensure proper installation of all the dependencies required
for the package.
FreeBSD by default uses ``tcsh``. In order to activate virtualenv (see

View File

@@ -1,5 +1,5 @@
# Always use the staging/testing server - avoids rate limiting
server = https://acme-staging.api.letsencrypt.org/directory
server = https://acme-staging-v02.api.letsencrypt.org/directory
# This is an example configuration file for developers
config-dir = /tmp/le/conf

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi
VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="0.22.0"
LE_AUTO_VERSION="0.22.2"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -1199,18 +1199,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==0.22.0 \
--hash=sha256:ebfeaf9737dc440a9f263099487523ab4c8d8da9def31a71327439d9186e00fa \
--hash=sha256:ee307dd8f194bd710a3326aa4bacf95d358877498c0b9aa187eff0dc211dcbb3
acme==0.22.0 \
--hash=sha256:37e6d8e4eb7dd18edac96de209f451300e04074f14be7fce713db6931a0e4a20 \
--hash=sha256:4a2cd52db32e914b68d8446c8e788f507c20edebbd1c36d4f3eda7b47c555fe8
certbot-apache==0.22.0 \
--hash=sha256:e91f6ec8203b636fa44f01017646fca68406224ee327fd56017103b78bc65539 \
--hash=sha256:8fbab1a358ec131996d1c00f7d0ed18ee3624f8469cab3962dfd8ba40ca3e7cd
certbot-nginx==0.22.0 \
--hash=sha256:d67210cf73cf44e8aeff04f6f228d8bde74444703ce3ccd929a450685b58c30b \
--hash=sha256:b2b26bf9112062b02518407704cad09f7136322163d529a2dde3b6e1578ecb8c
certbot==0.22.2 \
--hash=sha256:c8c63bdf0fed6258bdbc892454314ec37bcd1c35a7f62524a083d93ccdfc420d \
--hash=sha256:e6e3639293e78397f31f7d99e3c63aff82d91e2b0d50d146ee3c77f830464bef
acme==0.22.2 \
--hash=sha256:59a55244612ee305d2caa6bb4cddd400fb60ec841bf011ed29a2899832a682c2 \
--hash=sha256:0ecd0ea369f53d5bc744d6e72717f9af2e1ceb558d109dbd433148851027adb4
certbot-apache==0.22.2 \
--hash=sha256:b5340d4b9190358fde8eb6a5be0def37e32014b5142ee79ef5d2319ccbbde754 \
--hash=sha256:3cd26912bb5732d917ddf7aad2fe870090d4ece9a408b2c2de8e9723ec99c759
certbot-nginx==0.22.2 \
--hash=sha256:91feef0d879496835d355e82841f92e5ecb5abbf6f23ea0ee5bbb8f5a92b278a \
--hash=sha256:b10bf04c1a20cf878d5e0d1877deb0e0780bc31b0ffda08ce7199bbc39d0753b
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -1,11 +1,11 @@
-----BEGIN PGP SIGNATURE-----
iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAlqgLj0ACgkQTRfJlc2X
dfIAtAf/YwRvn17fdJOSXr08LP/qDPefz8AFefUJdKoOa+ikWIOWZTh5hskGtXO0
e894FNcZqbg6NQu/KUBQAz/nBDRz8IOaWN30MFq5B4V2A3In5rn59PNaCDSKSBbC
auyU24gYkBxbDPjMpuode7yCsvHxTsB5sLNmHByMyMTBmQaiT5odAjr7PztTP52S
s/29/WOCJAYzBBFFJ9d0QD0drVSIcDM5JCuUK2vXgPuPVD4f3GankgP1nnAJ5ADV
acJp3cQ3OsofeE/HTw0qq7TiL0dGYf8yhRFovFve7tX+oujMIRALQJW6K9Qi7KTv
777V6xHuphrA+1qIrg2H8czOBDclFQ==
=Ngvl
iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAlqwWJwACgkQTRfJlc2X
dfIzmwgAghmc3W63/qpCtJdezYeGLJdu03LvKoWYc7dTNYj2+0P5qmAAgCvKNY34
qYzXA1jfCOgILSzRNE5WY+rbgjcmxxsxH+luYm6Ik0909MaMQ0D3h+5cRFs/tTtd
5cX0gxL3RQQTBwpnwbAZibe7lhjs9pXBiob2ek67hVr+xEwem69BQMlOhtYJbOs1
osccoKc4NqaKbrfgOjjtMaL8YoRPO9vJHS9rRr6hxRZlPsmvusAHAiCbIrbX4XKE
CgxJFnuHK+amtfRoZg/xCqIK3Z94yZXPezywsri/YvDteOIs+DZ2qG/StfUrNYFX
WYfFFFyld0xwQtb4Oi9u4mx4sPg7lw==
=jZDE
-----END PGP SIGNATURE-----

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi
VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="0.22.0"
LE_AUTO_VERSION="0.22.2"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -1199,18 +1199,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==0.22.0 \
--hash=sha256:ebfeaf9737dc440a9f263099487523ab4c8d8da9def31a71327439d9186e00fa \
--hash=sha256:ee307dd8f194bd710a3326aa4bacf95d358877498c0b9aa187eff0dc211dcbb3
acme==0.22.0 \
--hash=sha256:37e6d8e4eb7dd18edac96de209f451300e04074f14be7fce713db6931a0e4a20 \
--hash=sha256:4a2cd52db32e914b68d8446c8e788f507c20edebbd1c36d4f3eda7b47c555fe8
certbot-apache==0.22.0 \
--hash=sha256:e91f6ec8203b636fa44f01017646fca68406224ee327fd56017103b78bc65539 \
--hash=sha256:8fbab1a358ec131996d1c00f7d0ed18ee3624f8469cab3962dfd8ba40ca3e7cd
certbot-nginx==0.22.0 \
--hash=sha256:d67210cf73cf44e8aeff04f6f228d8bde74444703ce3ccd929a450685b58c30b \
--hash=sha256:b2b26bf9112062b02518407704cad09f7136322163d529a2dde3b6e1578ecb8c
certbot==0.22.2 \
--hash=sha256:c8c63bdf0fed6258bdbc892454314ec37bcd1c35a7f62524a083d93ccdfc420d \
--hash=sha256:e6e3639293e78397f31f7d99e3c63aff82d91e2b0d50d146ee3c77f830464bef
acme==0.22.2 \
--hash=sha256:59a55244612ee305d2caa6bb4cddd400fb60ec841bf011ed29a2899832a682c2 \
--hash=sha256:0ecd0ea369f53d5bc744d6e72717f9af2e1ceb558d109dbd433148851027adb4
certbot-apache==0.22.2 \
--hash=sha256:b5340d4b9190358fde8eb6a5be0def37e32014b5142ee79ef5d2319ccbbde754 \
--hash=sha256:3cd26912bb5732d917ddf7aad2fe870090d4ece9a408b2c2de8e9723ec99c759
certbot-nginx==0.22.2 \
--hash=sha256:91feef0d879496835d355e82841f92e5ecb5abbf6f23ea0ee5bbb8f5a92b278a \
--hash=sha256:b10bf04c1a20cf878d5e0d1877deb0e0780bc31b0ffda08ce7199bbc39d0753b
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -1 +1,3 @@
_$<24><>{<7B><><EFBFBD><EFBFBD>z<EFBFBD><7A><EFBFBD><EFBFBD><EFBFBD>Q)6("Rmn<6D>f$B|cs<63>;D<><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>V,<2C>?<3F><>8樝j<><1E><><EFBFBD><EFBFBD><EFBFBD>|<7C><>G<EFBFBD><47><EFBFBD>f<EFBFBD>b"ߘ<>,<2C><>*<02><><EFBFBD>%<25><><16>]<5D>6#<23><><08>n<EFBFBD>|\`+.X<>,<2C>)#<23><><EFBFBD>QB<51>j@<40>0G<>X<EFBFBD>z5<7A> <14>42+_H<48>`?<EFBFBD>.<2E><><1F><>X<EFBFBD><58><EFBFBD><EFBFBD><EFBFBD>0<07><1D>/<2F><><<3C>t<EFBFBD>p<>N)<29><><EFBFBD>IC<49><43>Q<EFBFBD><51>&i<>8Y<38><59>ܝ<EFBFBD>&<26>R<EFBFBD>6<EFBFBD>^<5E>]<5D>l<EFBFBD><4A><DCA1>#<EFBFBD><EFBFBD>P<EFBFBD><EFBFBD>*<2A><><EFBFBD>n<0E><>mN6B3<42>o<EFBFBD>c{^r%(<28><>dv<64><76><EFBFBD><)<29><EFBFBD>
<EFBFBD>c<EFBFBD><EFBFBD>NdC<EFBFBD>f<EFBFBD><EFBFBD><EFBFBD>*2<>;<3B>=uTM,<2C><>]K<>= jy!<EFBFBD>5M<1E>=2D<32>}/ڰ3<DAB0><EFBFBD>.><EFBFBD><EFBFBD><EFBFBD><1A><>:K<><4B>"<16>ta<74><61><EFBFBD>,<2C>Ge<47><65>C<EFBFBD><43><EFBFBD><EFBFBD>r<EFBFBD>F<06><EFBFBD><EFBFBD>q<EFBFBD><EFBFBD><EFBFBD>8d³ m<EFBFBD>q<EFBFBD>S<EFBFBD>
oGQ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Y
<EFBFBD><EFBFBD><EFBFBD>4&F<><46><EFBFBD>8<EFBFBD>W<><57><EFBFBD>xUm<55>|<7C><><EFBFBD><EFBFBD>0wٔ~<7E><1B><>g<16>R<>T)<29><>E<EFBFBD>=<3D> <EFBFBD>ڇ7<EFBFBD>(<28>տ,<2C>(\e<>f<EFBFBD>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD><EFBFBD>*<2A><17>!

View File

@@ -1,12 +1,12 @@
certbot==0.22.0 \
--hash=sha256:ebfeaf9737dc440a9f263099487523ab4c8d8da9def31a71327439d9186e00fa \
--hash=sha256:ee307dd8f194bd710a3326aa4bacf95d358877498c0b9aa187eff0dc211dcbb3
acme==0.22.0 \
--hash=sha256:37e6d8e4eb7dd18edac96de209f451300e04074f14be7fce713db6931a0e4a20 \
--hash=sha256:4a2cd52db32e914b68d8446c8e788f507c20edebbd1c36d4f3eda7b47c555fe8
certbot-apache==0.22.0 \
--hash=sha256:e91f6ec8203b636fa44f01017646fca68406224ee327fd56017103b78bc65539 \
--hash=sha256:8fbab1a358ec131996d1c00f7d0ed18ee3624f8469cab3962dfd8ba40ca3e7cd
certbot-nginx==0.22.0 \
--hash=sha256:d67210cf73cf44e8aeff04f6f228d8bde74444703ce3ccd929a450685b58c30b \
--hash=sha256:b2b26bf9112062b02518407704cad09f7136322163d529a2dde3b6e1578ecb8c
certbot==0.22.2 \
--hash=sha256:c8c63bdf0fed6258bdbc892454314ec37bcd1c35a7f62524a083d93ccdfc420d \
--hash=sha256:e6e3639293e78397f31f7d99e3c63aff82d91e2b0d50d146ee3c77f830464bef
acme==0.22.2 \
--hash=sha256:59a55244612ee305d2caa6bb4cddd400fb60ec841bf011ed29a2899832a682c2 \
--hash=sha256:0ecd0ea369f53d5bc744d6e72717f9af2e1ceb558d109dbd433148851027adb4
certbot-apache==0.22.2 \
--hash=sha256:b5340d4b9190358fde8eb6a5be0def37e32014b5142ee79ef5d2319ccbbde754 \
--hash=sha256:3cd26912bb5732d917ddf7aad2fe870090d4ece9a408b2c2de8e9723ec99c759
certbot-nginx==0.22.2 \
--hash=sha256:91feef0d879496835d355e82841f92e5ecb5abbf6f23ea0ee5bbb8f5a92b278a \
--hash=sha256:b10bf04c1a20cf878d5e0d1877deb0e0780bc31b0ffda08ce7199bbc39d0753b

View File

@@ -327,6 +327,19 @@ CheckDirHooks 1
common renew --cert-name le2.wtf
CheckDirHooks 1
# manual-dns-auth.sh will skip completing the challenge for domains that begin
# with fail.
common -a manual -d dns1.le.wtf,fail.dns1.le.wtf \
--allow-subset-of-names \
--preferred-challenges dns,tls-sni \
--manual-auth-hook ./tests/manual-dns-auth.sh \
--manual-cleanup-hook ./tests/manual-dns-cleanup.sh
if common certificates | grep "fail\.dns1\.le\.wtf"; then
echo "certificate should not have been issued for domain!" >&2
exit 1
fi
# ECDSA
openssl ecparam -genkey -name secp384r1 -out "${root}/privkey-p384.pem"
SAN="DNS:ecdsa.le.wtf" openssl req -new -sha256 \

View File

@@ -1,4 +1,8 @@
#!/bin/sh
curl -X POST 'http://localhost:8055/set-txt' -d \
"{\"host\": \"_acme-challenge.$CERTBOT_DOMAIN.\", \
\"value\": \"$CERTBOT_VALIDATION\"}"
#!/bin/bash
# If domain begins with fail, fail the challenge by not completing it.
if [[ "$CERTBOT_DOMAIN" != fail* ]]; then
curl -X POST 'http://localhost:8055/set-txt' -d \
"{\"host\": \"_acme-challenge.$CERTBOT_DOMAIN.\", \
\"value\": \"$CERTBOT_VALIDATION\"}"
fi

View File

@@ -1,3 +1,8 @@
#!/bin/sh
curl -X POST 'http://localhost:8055/clear-txt' -d \
"{\"host\": \"_acme-challenge.$CERTBOT_DOMAIN.\"}"
#!/bin/bash
# If domain begins with fail, we didn't complete the challenge so there is
# nothing to clean up.
if [[ "$CERTBOT_DOMAIN" != fail* ]]; then
curl -X POST 'http://localhost:8055/clear-txt' -d \
"{\"host\": \"_acme-challenge.$CERTBOT_DOMAIN.\"}"
fi