Add user friendly wildcard error for ACMEv1 (#5636)

* add WildcardUnsupportedError

* Add friendly unsupported wildcard error msg

* correct documentation

* add version specifier
This commit is contained in:
Brad Warren 2018-03-01 14:54:48 -08:00 committed by GitHub
parent f0b337532c
commit 8121acf2c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 8 deletions

View file

@ -310,9 +310,17 @@ class Client(ClientBase):
:returns: Authorization Resource.
:rtype: `.AuthorizationResource`
:raises errors.WildcardUnsupportedError: if a wildcard is requested
"""
if new_authzr_uri is not None:
logger.debug("request_challenges with new_authzr_uri deprecated.")
if identifier.value.startswith("*"):
raise errors.WildcardUnsupportedError(
"Requesting an authorization for a wildcard name is"
" forbidden by this version of the ACME protocol.")
new_authz = messages.NewAuthorization(identifier=identifier)
response = self._post(self.directory.new_authz, new_authz)
# TODO: handle errors
@ -333,6 +341,8 @@ class Client(ClientBase):
:returns: Authorization Resource.
:rtype: `.AuthorizationResource`
:raises errors.WildcardUnsupportedError: if a wildcard is requested
"""
return self.request_challenges(messages.Identifier(
typ=messages.IDENTIFIER_FQDN, value=domain), new_authzr_uri)
@ -752,6 +762,10 @@ class BackwardsCompatibleClientV2(object):
:returns: The newly created order.
:rtype: OrderResource
:raises errors.WildcardUnsupportedError: if a wildcard domain is
requested but unsupported by the ACME version
"""
if self.acme_version == 1:
csr = OpenSSL.crypto.load_certificate_request(OpenSSL.crypto.FILETYPE_PEM, csr_pem)

View file

@ -376,6 +376,13 @@ class ClientTest(ClientTestBase):
errors.UnexpectedUpdate, self.client.request_challenges,
self.identifier)
def test_request_challenges_wildcard(self):
wildcard_identifier = messages.Identifier(
typ=messages.IDENTIFIER_FQDN, value='*.example.org')
self.assertRaises(
errors.WildcardUnsupportedError, self.client.request_challenges,
wildcard_identifier)
def test_request_domain_challenges(self):
self.client.request_challenges = mock.MagicMock()
self.assertEqual(

View file

@ -115,3 +115,6 @@ class ConflictError(ClientError):
self.location = location
super(ConflictError, self).__init__()
class WildcardUnsupportedError(Error):
"""Error for when a wildcard is requested but is unsupported by ACME CA."""

View file

@ -12,6 +12,7 @@ import zope.component
from acme import client as acme_client
from acme import crypto_util as acme_crypto_util
from acme import errors as acme_errors
from acme import messages
import certbot
@ -258,10 +259,7 @@ class Client(object):
logger.debug("CSR: %s", csr)
if orderr is None:
orderr = self.acme.new_order(csr.data)
authzr = self.auth_handler.handle_authorizations(orderr)
orderr = orderr.update(authorizations=authzr)
authzr = orderr.authorizations
orderr = self._get_order_and_authorizations(csr.data, best_effort=False)
deadline = datetime.datetime.now() + datetime.timedelta(seconds=90)
orderr = self.acme.finalize_order(orderr, deadline)
@ -292,9 +290,8 @@ class Client(object):
self.config.rsa_key_size, self.config.key_dir)
csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir)
orderr = self.acme.new_order(csr.data)
authzr = self.auth_handler.handle_authorizations(orderr, self.config.allow_subset_of_names)
orderr = orderr.update(authorizations=authzr)
orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
authzr = orderr.authorizations
auth_domains = set(a.body.identifier.value for a in authzr)
successful_domains = [d for d in domains if d in auth_domains]
@ -313,6 +310,25 @@ class Client(object):
return cert, chain, key, csr
def _get_order_and_authorizations(self, csr_pem, best_effort):
"""Request a new order and complete its authorizations.
:param str csr_pem: A CSR in PEM format.
:param bool best_effort: True if failing to complete all
authorizations should not raise an exception
:returns: order resource containing its completed authorizations
:rtype: acme.messages.OrderResource
"""
try:
orderr = self.acme.new_order(csr_pem)
except acme_errors.WildcardUnsupportedError:
raise errors.Error("The currently selected ACME CA endpoint does"
" not support issuing wildcard certificates.")
authzr = self.auth_handler.handle_authorizations(orderr, best_effort)
return orderr.update(authorizations=authzr)
# pylint: disable=no-member
def obtain_and_enroll_certificate(self, domains, certname):
"""Obtain and enroll certificate.

View file

@ -184,7 +184,7 @@ class ClientTest(ClientTestCommon):
self.client.obtain_certificate_from_csr(
test_csr,
orderr=None))
auth_handler.handle_authorizations.assert_called_with(self.eg_order)
auth_handler.handle_authorizations.assert_called_with(self.eg_order, False)
# Test for no auth_handler
self.client.auth_handler = None