support best_effort

This commit is contained in:
Erica Portnoy 2018-02-20 15:36:35 -08:00
parent d6af978472
commit d29c637bf9
2 changed files with 47 additions and 13 deletions

View file

@ -235,13 +235,13 @@ class Client(object):
else:
self.auth_handler = None
def obtain_certificate_from_csr(self, csr, best_effort=False):
def obtain_certificate_from_csr(self, csr, orderr=None):
"""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
:param acme.messages.OrderResource orderr: contains authzrs
:returns: `.CertificateResource` and certificate chain (as
returned by `.fetch_chain`).
@ -258,10 +258,12 @@ class Client(object):
logger.debug("CSR: %s", csr)
orderr = self.acme.new_order(csr.data)
authzr = self.auth_handler.handle_authorizations(orderr, best_effort)
# TODO: check if we passed all authorizations, and if not,
# create a new order and try again, possibly in a loop
if orderr is None:
orderr = self.acme.new_order(csr.data)
authzr = self.auth_handler.handle_authorizations(orderr)
else:
authzr = orderr.authorizations
certr = self.acme.request_issuance(
jose.ComparableX509(
@ -316,9 +318,20 @@ 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, self.config.allow_subset_of_names)
orderr = self.acme.new_order(csr.data)
authzr = self.auth_handler.handle_authorizations(orderr, self.config.allow_subset_of_names)
auth_domains = set(a.body.identifier.value for a in authzr)
successful_domains = [d for d in domains if d in auth_domains]
return certr, chain, key, csr
if successful_domains != domains:
if not self.config.dry_run:
# TODO: delete keys
pass
return self.obtain_certificate(successful_domains)
else:
certr, chain = self.obtain_certificate_from_csr(csr, orderr)
return certr, chain, key, csr
# pylint: disable=no-member
def obtain_and_enroll_certificate(self, domains, certname):

View file

@ -134,6 +134,7 @@ class ClientTest(ClientTestCommon):
self.config.allow_subset_of_names = False
self.config.dry_run = False
self.eg_domains = ["example.com", "www.example.com"]
self.eg_order = mock.MagicMock(authorizations=[None])
def test_init_acme_verify_ssl(self):
net = self.acme_client.call_args[0][0]
@ -144,11 +145,11 @@ class ClientTest(ClientTestCommon):
self.client.auth_handler.handle_authorizations.return_value = [None]
self.acme.request_issuance.return_value = mock.sentinel.certr
self.acme.fetch_chain.return_value = mock.sentinel.chain
self.acme.new_order.return_value = mock.sentinel.orderr
self.acme.new_order.return_value = self.eg_order
def _check_obtain_certificate(self):
self.client.auth_handler.handle_authorizations.assert_called_once_with(
mock.sentinel.orderr,
self.eg_order,
self.config.allow_subset_of_names)
authzr = self.client.auth_handler.handle_authorizations()
@ -166,15 +167,26 @@ class ClientTest(ClientTestCommon):
mock_logger):
self._mock_obtain_certificate()
test_csr = util.CSR(form="pem", file=None, data=CSR_SAN)
auth_handler = self.client.auth_handler
orderr = self.acme.new_order(test_csr.data)
authzr = auth_handler.handle_authorizations(orderr, False)
self.assertEqual(
(mock.sentinel.certr, mock.sentinel.chain),
self.client.obtain_certificate_from_csr(
test_csr,
best_effort=False))
orderr=orderr))
# and that the cert was obtained correctly
self._check_obtain_certificate()
# Test for orderr=None
self.assertEqual(
(mock.sentinel.certr, mock.sentinel.chain),
self.client.obtain_certificate_from_csr(
test_csr,
orderr=None))
auth_handler.handle_authorizations.assert_called_with(self.eg_order)
# Test for no auth_handler
self.client.auth_handler = None
self.assertRaises(
@ -190,11 +202,15 @@ class ClientTest(ClientTestCommon):
self.acme.fetch_chain.side_effect = [acme_errors.Error,
mock.sentinel.chain]
test_csr = util.CSR(form="der", file=None, data=CSR_SAN)
auth_handler = self.client.auth_handler
orderr = self.acme.new_order(test_csr.data)
authzr = auth_handler.handle_authorizations(orderr, False)
self.assertEqual(
(mock.sentinel.certr, mock.sentinel.chain),
self.client.obtain_certificate_from_csr(
test_csr))
test_csr,
orderr=orderr))
self.assertEqual(1, mock_get_utility().notification.call_count)
@test_util.patch_get_utility()
@ -202,11 +218,15 @@ class ClientTest(ClientTestCommon):
self._mock_obtain_certificate()
self.acme.fetch_chain.side_effect = acme_errors.Error
test_csr = util.CSR(form="der", file=None, data=CSR_SAN)
auth_handler = self.client.auth_handler
orderr = self.acme.new_order(test_csr.data)
authzr = auth_handler.handle_authorizations(orderr, False)
self.assertRaises(
acme_errors.Error,
self.client.obtain_certificate_from_csr,
test_csr)
test_csr,
orderr=orderr)
self.assertEqual(1, mock_get_utility().notification.call_count)
@mock.patch("certbot.client.crypto_util")
@ -256,6 +276,7 @@ class ClientTest(ClientTestCommon):
identifier=mock.MagicMock(
value=domain))))
self.eg_order.authorizations = authzr
self.client.auth_handler.handle_authorizations.return_value = authzr
with test_util.patch_get_utility():