put back in best_effort code, with a todo for actually supporting it in ACMEv2

This commit is contained in:
Erica Portnoy 2018-02-20 13:19:04 -08:00
parent 68e24a8ea7
commit d6b4e2001b
3 changed files with 24 additions and 11 deletions

View file

@ -48,11 +48,13 @@ class AuthHandler(object):
# List must be used to keep responses straight.
self.achalls = []
def handle_authorizations(self, orderr):
def handle_authorizations(self, orderr, best_effort=False):
"""Retrieve all authorizations for challenges.
:param acme.messages.OrderResource orderr: must have
authorizations filled in
:param bool best_effort: Whether or not all authorizations are
required (this is useful in renewal)
:returns: List of authorization resources
:rtype: list
@ -79,7 +81,7 @@ class AuthHandler(object):
'Pass "-v" for more info about challenges.', pause=True)
# Send all Responses - this modifies achalls
self._respond(resp)
self._respond(resp, best_effort)
# Just make sure all decisions are complete.
self.verify_authzr_complete()
@ -123,7 +125,7 @@ class AuthHandler(object):
return resp
def _respond(self, resp):
def _respond(self, resp, best_effort):
"""Send/Receive confirmation of all challenges.
.. note:: This method also cleans up the auth_handler state.
@ -136,7 +138,7 @@ class AuthHandler(object):
# Check for updated status...
try:
self._poll_challenges(chall_update)
self._poll_challenges(chall_update, best_effort)
finally:
# This removes challenges from self.achalls
self._cleanup_challenges(active_achalls)
@ -168,7 +170,7 @@ class AuthHandler(object):
return active_achalls
def _poll_challenges(
self, chall_update, min_sleep=3, max_rounds=15):
self, chall_update, best_effort, min_sleep=3, max_rounds=15):
"""Wait for all challenge results to be determined."""
dom_to_check = set(chall_update.keys())
comp_domains = set()
@ -189,8 +191,14 @@ class AuthHandler(object):
chall_update[domain].remove(achall)
# We failed some challenges... damage control
else:
all_failed_achalls.update(
updated for _, updated in failed_achalls)
if best_effort:
comp_domains.add(domain)
logger.warning(
"Challenge failed for domain %s",
domain)
else:
all_failed_achalls.update(
updated for _, updated in failed_achalls)
if all_failed_achalls:
_report_failed_challs(all_failed_achalls)

View file

@ -235,12 +235,13 @@ class Client(object):
else:
self.auth_handler = None
def obtain_certificate_from_csr(self, csr):
def obtain_certificate_from_csr(self, csr, best_effort=False):
"""Obtain certificate.
:param .util.CSR csr: PEM-encoded Certificate Signing
Request. The key used to generate this CSR can be different
than `authkey`.
:param bool best_effort: Whether or not all authorizations are required
:returns: `.CertificateResource` and certificate chain (as
returned by `.fetch_chain`).
@ -258,7 +259,11 @@ class Client(object):
logger.debug("CSR: %s", csr)
orderr = self.acme.new_order(csr.data)
authzr = self.auth_handler.handle_authorizations(orderr)
authzr = self.auth_handler.handle_authorizations(orderr, best_effort)
if best_effort:
# TODO: check if we passed all authorizations, and if not,
# create a new order and try again, possibly in a loop
pass
certr = self.acme.request_issuance(
jose.ComparableX509(
@ -313,7 +318,7 @@ class Client(object):
self.config.rsa_key_size, self.config.key_dir)
csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir)
certr, chain = self.obtain_certificate_from_csr(csr)
certr, chain = self.obtain_certificate_from_csr(csr, self.config.allow_subset_of_names)
return certr, chain, key, csr

View file

@ -218,7 +218,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
self.assertRaises(
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
def _validate_all(self, unused_1):
def _validate_all(self, unused_1, unused_2):
for dom in six.iterkeys(self.handler.authzr):
azr = self.handler.authzr[dom]
self.handler.authzr[dom] = acme_util.gen_authzr(