This commit is contained in:
Erica Portnoy 2025-01-15 09:45:25 -08:00
parent e85d3b6a83
commit fe1b963398
2 changed files with 9 additions and 41 deletions

View file

@ -380,11 +380,11 @@ class Client:
with open(old_keypath, "rb") as f:
keypath = old_keypath
keypem = f.read()
optional_key: Optional[util.Key] = util.Key(file=keypath, pem=keypem)
key: Optional[util.Key] = util.Key(file=keypath, pem=keypem)
logger.info("Reusing existing private key from %s.", old_keypath)
else:
# The key is set to None here but will be created below.
optional_key = None
key = None
key_size = self.config.rsa_key_size
elliptic_curve = "secp256r1"
@ -401,9 +401,8 @@ class Client:
key_size = self.config.rsa_key_size
# Create CSR from names
key: util.Key
if self.config.dry_run:
key = optional_key or util.Key(
key = key or util.Key(
file=None,
pem=crypto_util.make_key(
bits=key_size,
@ -416,7 +415,7 @@ class Client:
data=acme_crypto_util.make_csr(
key.pem, domains, self.config.must_staple))
else:
key = optional_key or crypto_util.generate_key(
key = key or crypto_util.generate_key(
key_size=key_size,
key_dir=None,
key_type=self.config.key_type,
@ -435,7 +434,7 @@ class Client:
if self.config.allow_subset_of_names:
successful_domains = self._successful_domains_from_error(error, domains)
if successful_domains != domains and len(successful_domains) != 0:
return self._retry_obtain_certificate(domains, successful_domains, old_keypath)
return self._retry_obtain_certificate(domains, successful_domains)
raise
authzr = orderr.authorizations
auth_domains = {a.body.identifier.value for a in authzr}
@ -447,7 +446,7 @@ class Client:
# domains contains a wildcard because the ACME spec forbids identifiers
# in authzs from containing a wildcard character.
if self.config.allow_subset_of_names and successful_domains != domains:
return self._retry_obtain_certificate(domains, successful_domains, old_keypath)
return self._retry_obtain_certificate(domains, successful_domains)
else:
try:
cert, chain = self.obtain_certificate_from_csr(csr, orderr)
@ -459,8 +458,7 @@ class Client:
if self.config.allow_subset_of_names:
successful_domains = self._successful_domains_from_error(error, domains)
if successful_domains != domains and len(successful_domains) != 0:
return self._retry_obtain_certificate(
domains, successful_domains, old_keypath)
return self._retry_obtain_certificate(domains, successful_domains)
raise
def _get_order_and_authorizations(self, csr_pem: bytes,
@ -542,14 +540,13 @@ class Client:
return successful_domains
return []
def _retry_obtain_certificate(self, domains: List[str], successful_domains: List[str],
old_keypath: Optional[str]
def _retry_obtain_certificate(self, domains: List[str], successful_domains: List[str]
) -> Tuple[bytes, bytes, util.Key, util.CSR]:
failed_domains = [d for d in domains if d not in successful_domains]
domains_list = ", ".join(failed_domains)
display_util.notify("Unable to obtain a certificate with every requested "
f"domain. Retrying without: {domains_list}")
return self.obtain_certificate(successful_domains, old_keypath)
return self.obtain_certificate(successful_domains)
def _choose_lineagename(self, domains: List[str], certname: Optional[str]) -> str:
"""Chooses a name for the new lineage.

View file

@ -646,35 +646,6 @@ class ClientTest(ClientTestCommon):
" every domain. The dry run will continue, but results"
" may not be accurate.")
@mock.patch("certbot._internal.client.crypto_util")
def test_obtain_certificate_reuse_key_with_allow_subset_of_names(self, mock_crypto_util):
csr = util.CSR(form="pem", file=mock.sentinel.csr_file, data=CSR_SAN)
key = util.Key(file="old_key_file", pem="old_key_pem")
new_key = util.Key(file="new_key_file", pem="new_key_pem")
mock_crypto_util.generate_csr.return_value = csr
mock_crypto_util.generate_key.return_value = new_key
self._set_mock_from_fullchain(mock_crypto_util.cert_and_chain_from_fullchain)
authzr = self._authzr_from_domains(["example.com"])
self.config.allow_subset_of_names = True
self.config.reuse_key = True
self._mock_obtain_certificate()
self.eg_order.authorizations = authzr
self.client.auth_handler.handle_authorizations.return_value = authzr
with test_util.patch_display_util():
mocked_open = mock.mock_open(read_data="old_key_pem")
with mock.patch('builtins.open', mocked_open):
result = self.client.obtain_certificate(self.eg_domains, "old_key_file")
assert result == \
(mock.sentinel.cert, mock.sentinel.chain, key, csr)
self._check_obtain_certificate(2)
assert mock_crypto_util.generate_key.call_count == 0
def _set_mock_from_fullchain(self, mock_from_fullchain):
mock_cert = mock.Mock()
mock_cert.encode.return_value = mock.sentinel.cert