mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 19:02:52 +02:00
Change acme.renewal_time to only check ARI, and not also a default time. Separate out default check and use that in should_autorenew instead. (#10309)
Fixes https://github.com/certbot/certbot/issues/10298. Replacement for #10301. --------- Co-authored-by: Brad Warren <bmw@users.noreply.github.com>
This commit is contained in:
co-authored by
Brad Warren
parent
3cbe1288c9
commit
48f34938c6
@@ -463,21 +463,21 @@ class ClientV2Test(unittest.TestCase):
|
||||
ClientV2.get_directory('https://example.com/dir', self.net).to_partial_json()
|
||||
|
||||
def test_renewal_time_no_renewal_info(self):
|
||||
# A directory with no 'renewalInfo' should result in default renewal periods.
|
||||
# A directory with no 'renewalInfo' should result in None.
|
||||
self.client.directory = messages.Directory({})
|
||||
cert_pem = make_cert_for_renewal(
|
||||
not_before=datetime.datetime(2025, 3, 12, 00, 00, 00),
|
||||
not_after=datetime.datetime(2025, 3, 20, 00, 00, 00),
|
||||
)
|
||||
t, _ = self.client.renewal_time(cert_pem)
|
||||
assert t == datetime.datetime(2025, 3, 16, 00, 00, 00, tzinfo=datetime.timezone.utc)
|
||||
assert t == None
|
||||
|
||||
cert_pem = make_cert_for_renewal(
|
||||
not_before=datetime.datetime(2025, 3, 12, 00, 00, 00),
|
||||
not_after=datetime.datetime(2025, 3, 30, 00, 00, 00),
|
||||
)
|
||||
t, _ = self.client.renewal_time(cert_pem)
|
||||
assert t == datetime.datetime(2025, 3, 24, 00, 00, 00, tzinfo=datetime.timezone.utc)
|
||||
assert t == None
|
||||
|
||||
def test_renewal_time_with_renewal_info(self):
|
||||
from cryptography import x509
|
||||
@@ -526,7 +526,7 @@ class ClientV2Test(unittest.TestCase):
|
||||
self.client.directory = messages.Directory({
|
||||
'renewalInfo': 'https://www.letsencrypt-demo.org/acme/renewal-info',
|
||||
})
|
||||
# Failure to fetch the 'renewalInfo' URL should return default timings
|
||||
# Failure to fetch the 'renewalInfo' URL should return None
|
||||
self.net.get.side_effect = requests.exceptions.RequestException
|
||||
|
||||
cert_pem = make_cert_for_renewal(
|
||||
@@ -534,14 +534,14 @@ class ClientV2Test(unittest.TestCase):
|
||||
not_after=datetime.datetime(2025, 3, 20, 00, 00, 00),
|
||||
)
|
||||
t, _ = self.client.renewal_time(cert_pem)
|
||||
assert t == datetime.datetime(2025, 3, 16, 00, 00, 00, tzinfo=datetime.timezone.utc)
|
||||
assert t == None
|
||||
|
||||
cert_pem = make_cert_for_renewal(
|
||||
not_before=datetime.datetime(2025, 3, 12, 00, 00, 00),
|
||||
not_after=datetime.datetime(2025, 3, 30, 00, 00, 00),
|
||||
)
|
||||
t, _ = self.client.renewal_time(cert_pem)
|
||||
assert t == datetime.datetime(2025, 3, 24, 00, 00, 00, tzinfo=datetime.timezone.utc)
|
||||
assert t == None
|
||||
|
||||
@mock.patch('acme.client.datetime')
|
||||
def test_renewal_time_returns_retry_after(self, dt_mock):
|
||||
|
||||
+10
-12
@@ -314,7 +314,8 @@ class ClientV2:
|
||||
raise e
|
||||
return self.poll_finalization(orderr, deadline, fetch_alternative_chains)
|
||||
|
||||
def renewal_time(self, cert_pem: bytes) -> Tuple[datetime.datetime, datetime.datetime]:
|
||||
def renewal_time(self, cert_pem: bytes
|
||||
) -> Tuple[Optional[datetime.datetime], datetime.datetime]:
|
||||
"""Return an appropriate time to attempt renewal of the certificate,
|
||||
and the next time to ask the ACME server for renewal info.
|
||||
|
||||
@@ -322,11 +323,15 @@ class ClientV2:
|
||||
based on a fetch of the renewal info resource for the certificate
|
||||
(https://www.ietf.org/archive/id/draft-ietf-acme-ari-08.html).
|
||||
|
||||
If there is no "renewalInfo" field, this function will fall back to
|
||||
reasonable defaults based on the certificate lifetime.
|
||||
If there is no "renewalInfo" field, this function will return a tuple of
|
||||
None, and the next time to ask the ACME server for renewal info.
|
||||
|
||||
This function may make other network calls in the future (e.g., OCSP
|
||||
or CRL).
|
||||
|
||||
:param bytes cert_pem: cert as pem file
|
||||
|
||||
:returns: Tuple of time to attempt renewal, next time to ask for renewal info
|
||||
"""
|
||||
now = datetime.datetime.now()
|
||||
# https://www.ietf.org/archive/id/draft-ietf-acme-ari-08.html#section-4.3.3
|
||||
@@ -334,24 +339,17 @@ class ClientV2:
|
||||
|
||||
cert = x509.load_pem_x509_certificate(cert_pem)
|
||||
|
||||
not_before = cert.not_valid_before_utc
|
||||
lifetime = cert.not_valid_after_utc - not_before
|
||||
if lifetime.total_seconds() < 10 * 86400:
|
||||
default_renewal_time = not_before + lifetime / 2
|
||||
else:
|
||||
default_renewal_time = not_before + lifetime * 2 / 3
|
||||
|
||||
try:
|
||||
renewal_info_base_url = self.directory['renewalInfo']
|
||||
except KeyError:
|
||||
return default_renewal_time, now + default_retry_after
|
||||
return None, now + default_retry_after
|
||||
|
||||
ari_url = renewal_info_base_url + '/' + _renewal_info_path_component(cert)
|
||||
try:
|
||||
resp = self.net.get(ari_url, content_type='application/json')
|
||||
except (requests.exceptions.RequestException, messages.Error) as error:
|
||||
logger.warning("failed to fetch renewal_info URL (%s): %s", ari_url, error)
|
||||
return default_renewal_time, now + default_retry_after
|
||||
return None, now + default_retry_after
|
||||
|
||||
renewal_info: messages.RenewalInfo = messages.RenewalInfo.from_json(resp.json())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user