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 [email protected] https://www.ietf.org/mailman/listinfo/acme
