Hey @_az, got another funny quirky edge case question along the same lines (@griffin you may have seen this as well) :
Does LE's implementation of the DNS-01 ACME validation allow for other values in the TXT entry?
(It seems like it doesn't, but the RFC 8555 (Pg.66) spec says it can)
This happens when requesting a wildcard and non-wildcard certificate for a single domain on the same cert, for example 'domain.com' and '*.domain.com'. Since the ACME spec treats the two names as separate, the order results in two authz, each with a different token, and thus each requiring different TXT values, however they are both under the same challenge domain, in this example `'_acme-challenge.domain.com'.
However when polling the authz url to verify the DNS entries after both TXT values have been globally propagated, LE responds with a urn:ietf:params:acme:error:unauthorized error because LE concatenates all the TXT values into one long string before testing.
For example when ordering a cert for ['link.keyblade.dev', '*.link.keyblade.dev'], the order responds with the following authz challenges for DNS records :
keyblade.dev:
- Record Name:
_acme-challenge.link.keyblade.dev
- Value:
ZxI0sxuvqB0DRIWx0w98FlzoYHHTkDU3jBb-DoFrhMY
*.keyblade.dev:
- Record Name:
_acme-challenge.link.keyblade.dev
- Value:
B1Y0HXEols5d_iBfyAdLi7asCUuaTiNEJNWUEVMAvs0
So the following TXT record is created:
$ dig txt _acme-challenge.link.domain.dev
; <<>> DiG 9.10.6 <<>> txt _acme-challenge.link.keyblade.dev
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13234
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_acme-challenge.link.keyblade.dev. IN TXT
;; ANSWER SECTION:
_acme-challenge.link.keyblade.dev. 300 IN TXT "B1Y0HXEols5d_iBfyAdLi7asCUuaTiNEJNWUEVMAvs0" "ZxI0sxuvqB0DRIWx0w98FlzoYHHTkDU3jBb-DoFrhMY"
The usual POST-as-GET to the dns-01 challenge url doesn't hit any issues.
However the response to POST-as-GET to authorization URL for the transition out of pending status returns the following response body:
authz response for link.keyblade.dev:
{
"type": "dns-01",
"status": "invalid",
"error": {
"type": "urn:ietf:params:acme:error:unauthorized",
"detail": "Incorrect TXT record \"B1Y0HXEols5d_iBfyAdLi7asCUuaTiNEJNWUEVMAvs0ZxI0sxuvqB0DRIWx0w98FlzoYHHTkDU3jBb-DoFrhMY\" found at _acme-challenge.link.keyblade.dev",
"status": 403
},
"url": "https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/149800101/gpxyFw",
"token": "xdc9s4mf3tzJZbR3Wh32UkwmwXjmEfvjRpWWryYf6Dk"
}
authz response for *.link.keyblade.dev:
{
"type": "dns-01",
"status": "invalid",
"error": {
"type": "urn:ietf:params:acme:error:unauthorized",
"detail": "Incorrect TXT record \"B1Y0HXEols5d_iBfyAdLi7asCUuaTiNEJNWUEVMAvs0ZxI0sxuvqB0DRIWx0w98FlzoYHHTkDU3jBb-DoFrhMY\" found at _acme-challenge.link.keyblade.dev",
"status": 403
},
"url": "https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/149800100/TPMgjw",
"token": "1QlolD3xqEshRNoLt26BZ1z7yjBZ4wsGcju_NhoQM3w"
}
It looks like Boulder is concatenating all the TXT values into a single contiguous string before testing the record with a straight equality, however I don't know where the relevant lines in Boulder are to validate this assumption.
Excerpt from RFC 8555 pg.66:
To validate a DNS challenge, the server performs the following steps:
- Compute the SHA-256 digest [FIPS180-4] of the stored key authorization
- Query for TXT records for the validation domain name
- Verify that the contents of one of the TXT records match the digest value
Just wondering if this behaviour is intentional or a bug.
Also cheers petercooperjr. Switched to acme-client since ACME.js didn't support the multi-value TXT record like above, and to try to get more granular control over the process. On the plus side it generally works, except the acme-client library doesn't support ES256 account keys. Not a major showstopper, but just adds to the "fun".
Cheers,
Bryan