Skip to content

Commit

Permalink
Add async interface for finalization to acme.client.ClientV2 (#9622)
Browse files Browse the repository at this point in the history
* Add async interface for finalization to acme.client.ClientV2

Add `begin_order_finalization()`/`poll_finalization()` to
`acme.client.ClientV2`, which are directly analogous to
`answer_challenge()`/`poll_authorizations()`. This allows us to
finalize an order and then later poll for its completion as separate
steps.

* Address code review feedback

Rename `begin_order_finalization` -> `begin_finalization` and tweak
wording of changelog entry
  • Loading branch information
aglasgall committed Mar 23, 2023
1 parent 5d5dc42 commit 8e28e36
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
44 changes: 36 additions & 8 deletions acme/acme/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,23 +210,35 @@ def poll_authorizations(self, orderr: messages.OrderResource, deadline: datetime
raise errors.ValidationError(failed)
return orderr.update(authorizations=responses)

def finalize_order(self, orderr: messages.OrderResource, deadline: datetime.datetime,
fetch_alternative_chains: bool = False) -> messages.OrderResource:
"""Finalize an order and obtain a certificate.
def begin_finalization(self, orderr: messages.OrderResource
) -> messages.OrderResource:
"""Start the process of finalizing an order.
:param messages.OrderResource orderr: order to finalize
:param datetime.datetime deadline: when to stop polling and timeout
:param bool fetch_alternative_chains: whether to also fetch alternative
certificate chains
:returns: finalized order
:returns: updated order
:rtype: messages.OrderResource
"""
csr = OpenSSL.crypto.load_certificate_request(
OpenSSL.crypto.FILETYPE_PEM, orderr.csr_pem)
wrapped_csr = messages.CertificateRequest(csr=jose.ComparableX509(csr))
self._post(orderr.body.finalize, wrapped_csr)
res = self._post(orderr.body.finalize, wrapped_csr)
orderr = orderr.update(body=messages.Order.from_json(res.json()))
return orderr

def poll_finalization(self, orderr: messages.OrderResource,
deadline: datetime.datetime,
fetch_alternative_chains: bool = False
) -> messages.OrderResource:
"""
Poll an order that has been finalized for its status.
If it becomes valid, obtain the certificate.
:returns: finalized order (with certificate)
:rtype: messages.OrderResource
"""

while datetime.datetime.now() < deadline:
time.sleep(1)
response = self._post_as_get(orderr.uri)
Expand All @@ -247,6 +259,22 @@ def finalize_order(self, orderr: messages.OrderResource, deadline: datetime.date
return orderr
raise errors.TimeoutError()

def finalize_order(self, orderr: messages.OrderResource, deadline: datetime.datetime,
fetch_alternative_chains: bool = False) -> messages.OrderResource:
"""Finalize an order and obtain a certificate.
:param messages.OrderResource orderr: order to finalize
:param datetime.datetime deadline: when to stop polling and timeout
:param bool fetch_alternative_chains: whether to also fetch alternative
certificate chains
:returns: finalized order
:rtype: messages.OrderResource
"""
self.begin_finalization(orderr)
return self.poll_finalization(orderr, deadline, fetch_alternative_chains)

def revoke(self, cert: jose.ComparableX509, rsn: int) -> None:
"""Revoke certificate.
Expand Down
3 changes: 3 additions & 0 deletions certbot/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).

* `acme.messages.OrderResource` now supports being round-tripped
through JSON
* acme.client.ClientV2 now provides separate `begin_finalization`
and `poll_finalization` methods, in addition to the existing
`finalize_order` method.

### Changed

Expand Down

0 comments on commit 8e28e36

Please sign in to comment.