Skip to content

Commit

Permalink
feat(challenge): add dns-account-01 support from draft rfc
Browse files Browse the repository at this point in the history
  • Loading branch information
sheurich authored and eggsampler committed Feb 23, 2024
1 parent 27ed5db commit 37325ac
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 10 deletions.
4 changes: 2 additions & 2 deletions challenge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ func TestClient_UpdateChallenge(t *testing.T) {

chal := auth.ChallengeMap[ChallengeTypeDNS01]

preChallenge(auth, chal)
defer postChallenge(auth, chal)
preChallenge(account, auth, chal)
defer postChallenge(account, auth, chal)

updatedChal, err := testClient.UpdateChallenge(account, chal)
if err != nil {
Expand Down
17 changes: 17 additions & 0 deletions misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,20 @@ func TestWildcard(t *testing.T) {
t.Fatalf("error verifying hostname %s: %v", d, err)
}
}

func TestWildcardDNSAccount(t *testing.T) {
d := "*." + randString() + ".com"
account, order, _ := makeOrderFinalised(t, []string{ChallengeTypeDNSAccount01}, Identifier{Type: "dns", Value: d})

certs, err := testClient.FetchCertificates(account, order.Certificate)
if err != nil {
t.Fatalf("error fetch cert: %v", err)
}
if len(certs) == 0 {
t.Fatal("no certs")
}

if err := certs[0].VerifyHostname(d); err != nil {
t.Fatalf("error verifying hostname %s: %v", d, err)
}
}
7 changes: 4 additions & 3 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA a
// Different possible challenge types provided by an ACME server.
// See https://tools.ietf.org/html/rfc8555#section-9.7.8
const (
ChallengeTypeDNS01 = "dns-01"
ChallengeTypeHTTP01 = "http-01"
ChallengeTypeTLSALPN01 = "tls-alpn-01"
ChallengeTypeDNS01 = "dns-01"
ChallengeTypeDNSAccount01 = "dns-account-01"
ChallengeTypeHTTP01 = "http-01"
ChallengeTypeTLSALPN01 = "tls-alpn-01"

// ChallengeTypeTLSSNI01 is deprecated and should not be used.
// See: https://community.letsencrypt.org/t/important-what-you-need-to-know-about-tls-sni-validation-issues/50811
Expand Down
45 changes: 40 additions & 5 deletions utility_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
crand "crypto/rand"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base32"
"encoding/json"
"encoding/pem"
"fmt"
Expand Down Expand Up @@ -169,7 +171,7 @@ func makeOrderFinalised(t *testing.T, supportedChalTypes []string, identifiers .
chalType := supportedChalTypes[mrand.Intn(len(supportedChalTypes))]
chal, ok := auth.ChallengeMap[chalType]
if !ok {
t.Fatalf("No supported challenge %q (%v) in challenges: %v", chalType, supportedChalTypes, auth.ChallengeTypes)
t.Skipf("skipping, no supported challenge %q (%v) in challenges: %v", chalType, supportedChalTypes, auth.ChallengeTypes)
}

if chal.Status == "valid" {
Expand All @@ -179,8 +181,8 @@ func makeOrderFinalised(t *testing.T, supportedChalTypes []string, identifiers .
t.Fatalf("unexpected status %q on challenge: %+v", chal.Status, chal)
}

preChallenge(auth, chal)
defer postChallenge(auth, chal)
preChallenge(acct, auth, chal)
defer postChallenge(acct, auth, chal)

updatedChal, err := testClient.UpdateChallenge(acct, chal)
if err != nil {
Expand Down Expand Up @@ -254,7 +256,7 @@ func doPost(name string, req interface{}) {
}
}

func preChallenge(auth Authorization, chal Challenge) {
func preChallenge(acct Account, auth Authorization, chal Challenge) {
switch chal.Type {
case ChallengeTypeDNS01:
setReq := struct {
Expand All @@ -266,6 +268,23 @@ func preChallenge(auth Authorization, chal Challenge) {
}
doPost("set-txt", setReq)

case ChallengeTypeDNSAccount01:
acctHash := sha256.Sum256([]byte(acct.URL))
acctLabel := strings.ToLower(base32.StdEncoding.EncodeToString(acctHash[0:10]))
scope := "host"
if auth.Wildcard {
scope = "wildcard"
}
setReq := struct {
Host string `json:"host"`
Value string `json:"value"`
}{
Host: "_" + acctLabel + "._acme-" + scope + "-challenge." +
auth.Identifier.Value + ".",
Value: EncodeDNS01KeyAuthorization(chal.KeyAuthorization),
}
doPost("set-txt", setReq)

case ChallengeTypeHTTP01:
addReq := struct {
Token string `json:"token"`
Expand All @@ -291,7 +310,7 @@ func preChallenge(auth Authorization, chal Challenge) {
}
}

func postChallenge(auth Authorization, chal Challenge) {
func postChallenge(acct Account, auth Authorization, chal Challenge) {
switch chal.Type {
case ChallengeTypeDNS01:
host := "_acme-challenge." + auth.Identifier.Value + "."
Expand All @@ -302,6 +321,22 @@ func postChallenge(auth Authorization, chal Challenge) {
}
doPost("clear-txt", clearReq)

case ChallengeTypeDNSAccount01:
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 + "."
clearReq := struct {
Host string `json:"host"`
}{
Host: host,
}
doPost("clear-txt", clearReq)

case ChallengeTypeHTTP01:
delReq := struct {
Token string `json:"token"`
Expand Down

0 comments on commit 37325ac

Please sign in to comment.