Proposal Details

The x/crypto/acme package provides methods for polling ACME objects, currently it has: - WaitAuthorization - WaitOrder

These methods block until until the desired state is reached and internally respect the Retry-After header if provided by the ACME server as part of its polling logic.

Sometimes using a blocking method is not practical, for example in Kubernetes control loops. In this case case the Get methods can be used to return the Authorization or Order, allowing polling to be implemented by the API consumer. However since the Authorization and Order structs do not expose the Retry-After header as a field it cannot be respected by any external polling implementations.

I propose adding a RetryAfter field to the Order, Authorization and Challenge structs as these are the objects the ACME RFC specifies may have this header: - Order - when an order is "processing" (cert is currently being issued) then it is set (RFC 8555 §7.4) - Authorization - when the authorization is still in progress the Retry-After header may be set (RFC 8555 §7.5.1) - Challenge - if a challenge is currently being retried the Retry-After header should be set to indicate when the next challenge attempt will be complete (RFC 8555 §8.2)

The RetryAfter would be a time.Duration and would be 0 if not provided by the ACME server.

Comment From: gopherbot

Change https://go.dev/cl/685475 mentions this issue: crypto/acme: add RetryAfter field to the Authorization object returned by GetAuthorization

Comment From: sigmavirus24

Relevant bit of RFC8555:

   In responding to poll requests
   while the validation is still in progress, the server MUST return a
   200 (OK) response and MAY include a Retry-After header field to
   suggest a polling interval to the client.

Section 7.5.1 page 56

Comment From: cpu

I think it makes sense to consider surfacing the Retry-After header in /x/crypto/acme but the concept isn't something specific to authorizations in particular and so I believe we'd get a more cohesive design by broadening the scope.

As one concrete example, finalizing an order could result in an Order object with status Processing and RFC 8555 §7.4 says:

"processing": The certificate is being issued. Send a POST-as-GET request after the time given in the Retry-After header field of the response, if any.

I think folks avoiding WaitAuthorization in favour of GetAuthorization would probably also want to avoid WaitOrder in favour of GetOrder and could benefit from the Retry-After getting passed on there.

It's probably sensible to audit the other objects (challenges, registrations, etc) to consider their interaction with Retry-After as part of a more comprehensive proposal.

Comment From: ThatsMrTalbot

That makes sense - after reading the RFC again the Retry-After header is returned for the following objects: - Order - when an order is "processing" (cert is currently being issued) then it is set (RFC 8555 §7.4) - Authorization - when the authorization is still in progress the Retry-After header may be set (RFC 8555 §7.5.1) - Challenge - if a challenge is currently being retried the Retry-After header should be set to indicate when the next challenge attempt will be complete (RFC 8555 §8.2)

It is also used as part of rate-limiting requests, but the x/crypto/acme client currently handles this internally and I don't want to change too much.

Based on this I can update the proposal to add a RetryAfter field to the Order, Authorization and Challenge structs and update GetOrder, GetAuthorization and GetChallenge to set this field when appropriate.

Comment From: seankhliao

a need for retry-after was also mentioned for #60958