github.com/letsencrypt/boulder@v0.20251208.0/va/dns_account_test.go (about) 1 // dns_account_test.go 2 package va 3 4 import ( 5 "errors" 6 "net/netip" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/jmhodges/clock" 12 13 "github.com/letsencrypt/boulder/bdns" 14 berrors "github.com/letsencrypt/boulder/errors" 15 "github.com/letsencrypt/boulder/identifier" 16 "github.com/letsencrypt/boulder/metrics" 17 "github.com/letsencrypt/boulder/probs" 18 "github.com/letsencrypt/boulder/test" 19 ) 20 21 // Use a consistent test account URI, matching the example in the draft 22 const testAccountURI = "https://example.com/acme/acct/ExampleAccount" 23 24 func TestDNSAccount01Validation(t *testing.T) { 25 testCases := []struct { 26 name string 27 ident identifier.ACMEIdentifier 28 wantErrType berrors.ErrorType 29 wantErrMsg string 30 }{ 31 { 32 name: "wrong TXT record", 33 ident: identifier.NewDNS("wrong-dns01.com"), 34 wantErrType: berrors.Unauthorized, 35 wantErrMsg: "Incorrect TXT record", 36 }, 37 { 38 name: "wrong TXT record with multiple values", 39 ident: identifier.NewDNS("wrong-many-dns01.com"), 40 wantErrType: berrors.Unauthorized, 41 wantErrMsg: "Incorrect TXT record", 42 }, 43 { 44 name: "wrong long TXT record", 45 ident: identifier.NewDNS("long-dns01.com"), 46 wantErrType: berrors.Unauthorized, 47 wantErrMsg: "Incorrect TXT record", 48 }, 49 { 50 name: "DNS failure on localhost", 51 ident: identifier.NewDNS("localhost"), 52 wantErrType: berrors.Unauthorized, 53 wantErrMsg: "Incorrect TXT record", 54 }, 55 { 56 name: "IP identifier not supported", 57 ident: identifier.NewIP(netip.MustParseAddr("127.0.0.1")), 58 wantErrType: berrors.Malformed, 59 wantErrMsg: "Identifier type for DNS-ACCOUNT-01 challenge was not DNS", 60 }, 61 { 62 name: "invalid identifier type", 63 ident: identifier.ACMEIdentifier{ 64 Type: identifier.IdentifierType("iris"), 65 Value: "790DB180-A274-47A4-855F-31C428CB1072", 66 }, 67 wantErrType: berrors.Malformed, 68 wantErrMsg: "Identifier type for DNS-ACCOUNT-01 challenge was not DNS", 69 }, 70 { 71 name: "DNS server failure", 72 ident: identifier.NewDNS("servfail.com"), 73 wantErrType: berrors.DNS, 74 wantErrMsg: "SERVFAIL", 75 }, 76 { 77 name: "valid DNS record", 78 ident: identifier.NewDNS("good-dns01.com"), 79 }, 80 { 81 name: "valid DNS record with no authority", 82 ident: identifier.NewDNS("no-authority-dns01.com"), 83 }, 84 } 85 86 for _, tc := range testCases { 87 t.Run(tc.name, func(t *testing.T) { 88 va, _ := setup(nil, "", nil, nil) 89 _, err := va.validateDNSAccount01(ctx, tc.ident, expectedKeyAuthorization, testAccountURI) 90 91 if tc.wantErrMsg != "" { 92 if err == nil { 93 t.Fatalf("validateDNSAccount01(%q) = success, but want error %q", tc.ident.Value, tc.wantErrMsg) 94 } 95 if !errors.Is(err, tc.wantErrType) { 96 t.Errorf("validateDNSAccount01(%q) = error type %T, but want error type %T", tc.ident.Value, err, tc.wantErrType) 97 } 98 prob := detailedError(err) 99 if !strings.Contains(prob.String(), tc.wantErrMsg) { 100 t.Errorf("validateDNSAccount01(%q) = %q, but want error containing %q", tc.ident.Value, prob.String(), tc.wantErrMsg) 101 } 102 } else { 103 if err != nil { 104 t.Errorf("validateDNSAccount01(%q) = %v, but want success", tc.ident.Value, err) 105 } 106 } 107 }) 108 } 109 } 110 111 func TestDNSAccount01ValidationNoServer(t *testing.T) { 112 va, log := setup(nil, "", nil, nil) 113 staticProvider, err := bdns.NewStaticProvider([]string{}) 114 test.AssertNotError(t, err, "Couldn't make new static provider") 115 116 va.dnsClient = bdns.NewTest( 117 time.Second*5, 118 staticProvider, 119 metrics.NoopRegisterer, 120 clock.New(), 121 1, 122 "", 123 log, 124 nil) 125 126 _, err = va.validateDNSAccount01(ctx, identifier.NewDNS("localhost"), expectedKeyAuthorization, testAccountURI) 127 prob := detailedError(err) 128 test.AssertEquals(t, prob.Type, probs.DNSProblem) 129 } 130 131 func TestDNSAccount01ValidationEmptyAccountURI(t *testing.T) { 132 va, _ := setup(nil, "", nil, nil) 133 134 // The specific domain doesn't matter, as the function should 135 // reject the empty accountURI before DNS lookup. 136 ident := identifier.NewDNS("empty-uri-test.com") 137 138 // Call the validation function with an empty accountURI 139 _, err := va.validateDNSAccount01(ctx, ident, expectedKeyAuthorization, "") 140 141 // Assert that an error was returned 142 if err == nil { 143 t.Errorf("validateDNSAccount01(%q) = success, but want error", ident.Value) 144 return 145 } 146 147 // Assert the specific error type 148 test.AssertErrorIs(t, err, berrors.InternalServer) 149 150 // Assert the specific error message using strings.Contains 151 wantErrMsg := "accountURI must be provided for dns-account-01" 152 if !strings.Contains(err.Error(), wantErrMsg) { 153 t.Errorf("validateDNSAccount01(%q) = %q, but want error containing %q", ident.Value, err.Error(), wantErrMsg) 154 } 155 }