From c4d914d69b2fe53e56b1fd81549b14a1cf667bef Mon Sep 17 00:00:00 2001 From: vg Date: Mon, 16 Jan 2023 17:16:24 +0100 Subject: robustify nonce management by retry mechanism --- acme_dns_tiny.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'acme_dns_tiny.py') diff --git a/acme_dns_tiny.py b/acme_dns_tiny.py index 051e6ba..4903c63 100644 --- a/acme_dns_tiny.py +++ b/acme_dns_tiny.py @@ -177,17 +177,22 @@ class ACME: self.jwk_thumbprint = b64sha256(json.dumps(header['jwk'], sort_keys=True, separators=(',', ':'))) + def request_new_nonce(self): + log.info('Request new nonce') + self.jws_header['nonce'] = requests.get(self.directory["newNonce"] + ).headers['Replay-Nonce'] + def init_sreqs(self, directory_url=None): self.generate_jws_header(self.account_key_path) log.info('Fetch information from the ACME directory.') self.directory = dirmap = requests.get(directory_url, headers=self.dirheaders).json() - log.info('Request first nonce') - self.jws_header['nonce'] = requests.get(dirmap["newNonce"] - ).headers['Replay-Nonce'] + self.request_new_nonce() - def sreq(self, url=None, payload=None, headers=None): + def sreq(self, url=None, payload=None, headers=None, max_retry=10): """Sends signed requests to ACME server.""" + if max_retry < 0: + raise ValueError('max_retry exceeded') # POST-as-GET (payload=None != {}), payload64 is an empty string payload64 = '' if payload is None else b64json(payload) protected64 = b64json({**self.jws_header, 'url': url}) @@ -207,6 +212,10 @@ class ACME: with contextlib.suppress(ValueError): jmap = req.json() if req.status_code not in (200, 201): + if jmap['type'] == 'urn:ietf:params:acme:error:badNonce': + log.info('nonce expired or invalid, retry (left %d)', max_retry) + self.request_new_nonce() + return self.sreq(url, payload, headers, max_retry-1) raise ValueError(f'Request failed: {req.status_code} {jmap}, ' 'hint: {sreq.headers.get("Link", "empty")}.') return collections.namedtuple('sreq', ['code', 'headers', 'map', -- cgit v1.2.3