RFC 8555 does not intend for Challenges to be able to be fetched
individually; their contents are bundled into the Authorization object so
that all of the relevant information can be fetched with a single request.
The fact that Let's Encrypt allows challenges to be fetched individually is
primarily a holdover from the pre-standardization days.

A particular reading of RFC 8555 might suggest that the behavior you're
seeing from more recent ACME servers is the more correct behavior:

>    If the client's response is invalid for any reason or does not
>   provide the server with appropriate information to validate the
>   challenge, then the server MUST return an HTTP error.  On receiving
>   such an error, the client SHOULD undo any actions that have been
>   taken to fulfill the challenge, e.g., removing files that have been
>   provisioned to a web server.

An empty POST-as-GET request could be interpreted to be a request that
"does not provide the server with appropriate information to validate the
challenge", and therefore MUST result in an error.

Either way, I think that you shouldn't rely on ACME servers exposing
individual challenges.

Aaron

P.S. For what it's worth, even though you can request an individual
challenge from Let's Encrypt, and even though doing so results in fewer
bytes on the wire, it doesn't reduce load on Let's Encrypt's side -- the
whole Authorization object is loaded from the database anyway:
https://github.com/letsencrypt/boulder/blob/e27634717069988a83011f0b74382ad632128c35/wfe2/wfe.go#L1076
.

On Fri, Sep 10, 2021 at 12:05 PM Ilari Liusvaara <ilariliusva...@welho.com>
wrote:

> On Fri, Sep 10, 2021 at 04:19:41PM +0100, Joshua Van Leeuwen wrote:
> > Hi all,
> >
> > I am a developer for the cert-manager <https://cert-manager.io> project
> > which is an operator for issuing
> > certificates in Kubernetes.
> >
> > I am reaching out as I have a question regarding perhaps some ambiguity
> in
> > the
> > ACME RFC.
> >
> > cert-manager implements an ACME client for requesting certificates from
> ACME
> > servers. As part of the ACME flow when requesting a certificate, the ACME
> > Challenge controller worker is responsible for self-checking whether a
> > Challenge
> > is valid, accepting that Challenge to the server, and finally waiting for
> > Authorization.
> >
> > Due to the nature of the operator model in Kubernetes, before this flow
> > takes
> > place, the controller fetches the current state of the ACME Challenge
> from
> > the
> > server. This uses an empty body ("") POST-as-GET request to the Challenge
> > endpoint in order to recover state which might have been lost.
> >
> > cert-manager has been successfully used against ACME servers for the
> past 4
> > years, including namely Let's Encrypt. Recent implementations of ACME
> > servers
> > have had issues with this call whereby they interpret it as an Accept, or
> > otherwise reject the call and effectively invalidate the Order.
> >
> > Though this behaviour can be mitigated by calling the authorization
> > endpoint and
> > pruning the Challenge that the controller is concerned with, my question
> is
> > whether or not querying the Challenge endpoint for its status is valid
> > according
> > to the ACME RFC?
>
> I have implemented an ACME client, and it never queries challenge
> endpoints, only uses them to trigger validations (it even discards the
> validation trigger responses; I do not know what LE sends back for
> these).
>
> - On valid authorizations, it never pays any attention to challenges.
>   Valid is valid.
> - On pending challenges it grabs all challenges it understands (since
>   unknown challenges might be something else than type/nonce model
>   seen in 3 challenge types in the main ACME RFC) and figures out what
>   it can do later. When it acknowledges a challenge, it uses URL pulled
>   in this step.
> - On failed authorizations, it indiscriminatedly (it pays no attention
>   if type matches or not) digs whatever error records exist, plus
>   whatever extended data Let's Encrypt includes.
>
>
> And from the spec, I get the feeling that querying challenge objects
> is ... underspecified. As well as being a footgun.
>
>
> > > To check on the status of an authorization, the client sends a POST-
> > > as-GET request to the authorization URL, and the server responds with
> > > the current authorization object. 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.
> >
> > However we are not necessarily concerned with the _authorization_, only a
> > particular child Challenge. Is querying the Challenge endpoint to
> discover
> > state ever intended as a supported call in the RFC?
>
> The client I wrote pays as little attention to challenges as possible,
> it pays attention to authorizations instead.
>
> In pre-RFC ACME (LE "ACMEv1") days, clients matching challenge types on
> accepted authorizations was a not uncommon footgun. Caused a number of
> spurious failures.
>
>
> -Ilari
>
> _______________________________________________
> Acme mailing list
> Acme@ietf.org
> https://www.ietf.org/mailman/listinfo/acme
>
_______________________________________________
Acme mailing list
Acme@ietf.org
https://www.ietf.org/mailman/listinfo/acme

Reply via email to