Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the "dns-account-01" Challenge in Pebble #425

Closed
sheurich opened this issue Jan 11, 2024 · 9 comments
Closed

Implement the "dns-account-01" Challenge in Pebble #425

sheurich opened this issue Jan 11, 2024 · 9 comments
Assignees

Comments

@sheurich
Copy link
Contributor

sheurich commented Jan 11, 2024

Objective

Implement the "dns-account-01" challenge in Pebble, setting the groundwork for subsequent Boulder alignment (referencing boulder#7240).

Rationale

Establishing this feature in Pebble first is crucial for a consistent and forward-compatible testing framework.

@orangepizza
Copy link
Contributor

orangepizza commented Jan 31, 2024

I found that it's nontrival for pebble to do this: because accountURL needed to calculate this is dependent to domain of ACME uses, which pebble doesn't configed and not known. and just listen on everything:
Edit: solved with wfe send to what domain name it got

@sheurich
Copy link
Contributor Author

sheurich commented Feb 6, 2024

In addition to the ongoing work from @orangepizza, I have prepared two changes to support Pebble integration tests using dns-account-01.

In conjunction with my proposed change to #430 (see #430 (comment)), the preceding changes to certbot/acme and pebble/test/chisel2.py enable a successful integration test between pebble, challtestsrv and chisel2.

Example run:

REQUESTS_CA_BUNDLE=pebble/test/certs/pebble.minica.pem \
  python3 -c 'import pebble.test.chisel2; pebble.test.chisel2.auth_and_issue(["foo.com"],"dns-account-01")'

…
DEBUG:urllib3.connectionpool:https://localhost:14000 "POST /authZ/AFDXL5tMBBi6GTDqetoTuPArYOTXi7_GGL0CQWCh6Qs HTTP/1.1" 200 440
DEBUG:acme.client:Received response:
HTTP 200
Cache-Control: public, max-age=0, no-cache
Content-Type: application/json; charset=utf-8
Link: <https://localhost:14000/dir>;rel="index"
Replay-Nonce: BAMHTKcD2aNAyopsB-9zZg
Date: Tue, 06 Feb 2024 00:29:17 GMT
Content-Length: 440

{
   "status": "valid",
   "identifier": {
      "type": "dns",
      "value": "foo.com"
   },
   "challenges": [
      {
         "type": "dns-account-01",
         "url": "https://localhost:14000/chalZ/lV0CIU0zxaGkt5Ib7og8d1vkQo1A2EHzMREKbgdsZOI",
         "token": "01Wsj3RQfOinMJ7-lbKRBeElrLBI8OaUv99Jioem0_w",
         "status": "valid",
         "validated": "2024-02-06T00:29:14Z"
      }
   ],
   "expires": "2024-02-06T01:29:17Z"
}
…
…
pebble-challtestsrv - 2024/02/05 19:29:14 Added DNS-01 TXT challenge for Host "_f75qxvkvtswybx6u._acme-challenge.foo.com." - Value "jjxuv--W5N1o1TujkI12Db6jakJfAXLFfDEpjsEYVGA"
pebble-challtestsrv - 2024/02/05 19:29:18 Removed DNS-01 TXT challenge for Host "_f75qxvkvtswybx6u._acme-challenge.foo.com."

@orangepizza
Copy link
Contributor

I thought that suggestion was shot down be LE employee: https://github.com/aarongable
aaomidi/draft-ietf-acme-scoped-dns-challenges#13 (comment)

At no point do the Baseline Requirements constrain what the Authorization Domain Name may be.

This is incorrect. The Authorization Domain Name is defined as the FQDN used to obtain authorization, which sounds like a wide-open definition, but there are restrictions on what FQDNs can be used to obtain authorization, and therefore there are restrictions on what FQDNs can be Authorization Domain Names (all following quotes from the definition of Authorization Domain Name in Section 1.6.1 of the BRs):

The CA may use the FQDN returned from a DNS CNAME lookup as the FQDN for the purposes of domain validation.

i.e. the Authorization Domain Name may be the FQDN to be included in the Certificate

The CA may prune zero or more Domain Labels of the FQDN from left to right until encountering a Base Domain Name and may use any one of the values that were yielded by pruning (including the Base Domain Name itself) for the purpose of domain validation.

i.e. you can convert the Certificate FQDN into an Authorization Domain Name by pruning labels from left to right.

In other words, you cannot go the other direction: you cannot convert an Authorization Domain Name into a Certificate FQDN by trimming labels from left to right.

Therefore, if the TXT Record is _foo._bar.example.com, then the Authorization Domain Name is _bar.example.com, and you can issue for *._bar_example.com but not for example.com.
well I'm only looking at RFC draft IETF side so I don't know about at all. I think it'd caught by there too

@sheurich
Copy link
Contributor Author

sheurich commented Feb 6, 2024

@sheurich
Copy link
Contributor Author

sheurich commented Feb 6, 2024

The dns-account-01 Python client implementation is ready for review in:

After that is approved and merged the chisel2 changes will be readied in:

@aaomidi
Copy link

aaomidi commented Feb 16, 2024

Hi all, we're getting close to publishing a new draft. Here is a preview: https://aaomidi.github.io/draft-ietf-acme-scoped-dns-challenges/

Sorry for adding a ton of changes here, but ultimately we felt like we need to incorporate the teachings in https://datatracker.ietf.org/doc/draft-ietf-dnsop-domain-verification-techniques/

I believe certbot/certbot#9887 might need to be updated to follow up with this new draft as well.

@sheurich
Copy link
Contributor Author

sheurich commented Feb 16, 2024

Because subdomain auth is not yet implemented in Boulder (per letsencrypt/boulder#7050), this implementation would be:

"_" || base32(SHA-256(<ACCOUNT_RESOURCE_URL>)[0:10]) || "._acme-" || <SCOPE> || "-challenge"

for SCOPE in

  • "host"
  • "wildcard"

NOT SCOPE in

  • "domain"

based on https://github.com/aaomidi/draft-ietf-acme-scoped-dns-challenges/blob/0058e0800056698fb37f3b2cb31a727c826675fb/draft-ietf-acme-scoped-dns-challenges.mkd

@sheurich
Copy link
Contributor Author

sheurich commented Feb 16, 2024

I have a fork of https://github.com/eggsampler/acme with dns-account-01 support implemented per the latest draft (https://github.com/aaomidi/draft-ietf-acme-scoped-dns-challenges/blob/0058e0800056698fb37f3b2cb31a727c826675fb/draft-ietf-acme-scoped-dns-challenges.mkd). This will be useful for the Go integration tests.

https://github.com/sheurich/eggsampler-acme/tree/add-dns-account-01

The validation label computation is:

acctHash := sha256.Sum256([]byte(acct.URL))
acctLabel := strings.ToLower(base32.StdEncoding.EncodeToString(acctHash[0:10]))
scope := "host"
if auth.Wildcard {
    scope = "wildcard"
}
host := "_" + acctLabel + "._acme-" + scope + "-challenge." + auth.Identifier.Value + "."

as seen in https://github.com/sheurich/eggsampler-acme/blob/18317c3a082d1ab3e2db62df0808ec39e09318e7/utility_test.go#L325-L332

jsha pushed a commit that referenced this issue Mar 18, 2024
…es (#435)

This change implements the `dns-account-01` ACME challenge as specified
in
[draft-ietf-acme-scoped-dns-challenges](https://datatracker.ietf.org/doc/draft-ietf-acme-scoped-dns-challenges/).

The relevant [validation label
computation](https://github.com/aaomidi/draft-ietf-acme-scoped-dns-challenges/blob/0058e0800056698fb37f3b2cb31a727c826675fb/draft-ietf-acme-scoped-dns-challenges.mkd#dns-account-01-challenge)
is:
```plain
"_" || base32(SHA-256(<ACCOUNT_RESOURCE_URL>)[0:10]) || "._acme-" || <SCOPE> || "-challenge"
```
where SCOPE is one of { `host`, `wildcard` }. A SCOPE of { `domain` } is
unimplemented.

This implementation is interoperable with the
https://github.com/eggsampler/acme changes in
eggsampler/acme#21 and passes the
`TestWildcardDNSAccount` test.

Solves #425.
@sheurich
Copy link
Contributor Author

Solved by #435

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants