diff --git a/bdns/mocks.go b/bdns/mocks.go index 36bf2e88d29..d049b963013 100644 --- a/bdns/mocks.go +++ b/bdns/mocks.go @@ -19,6 +19,43 @@ type MockClient struct { // LookupTXT is a mock func (mock *MockClient) LookupTXT(_ context.Context, hostname string) ([]string, ResolverAddrs, error) { + // Use the example account-specific label prefix derived from + // "https://example.com/acme/acct/ExampleAccount" + const accountLabelPrefix = "_ujmmovf2vn55tgye._acme-challenge" + + if hostname == accountLabelPrefix+".servfail.com" { + // Mirror dns-01 servfail behaviour + return nil, ResolverAddrs{"MockClient"}, fmt.Errorf("SERVFAIL") + } + if hostname == accountLabelPrefix+".good-dns01.com" { + // Mirror dns-01 good record + // base64(sha256("LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0" + // + "." + "9jg46WB3rR_AHD-EBXdN7cBkH1WOu0tA3M9fm21mqTI")) + return []string{"LPsIwTo7o8BoG0-vjCyGQGBWSVIPxI-i_X336eUOQZo"}, ResolverAddrs{"MockClient"}, nil + } + if hostname == accountLabelPrefix+".wrong-dns01.com" { + // Mirror dns-01 wrong record + return []string{"a"}, ResolverAddrs{"MockClient"}, nil + } + if hostname == accountLabelPrefix+".wrong-many-dns01.com" { + // Mirror dns-01 wrong-many record + return []string{"a", "b", "c", "d", "e"}, ResolverAddrs{"MockClient"}, nil + } + if hostname == accountLabelPrefix+".long-dns01.com" { + // Mirror dns-01 long record + return []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, ResolverAddrs{"MockClient"}, nil + } + if hostname == accountLabelPrefix+".no-authority-dns01.com" { + // Mirror dns-01 no-authority good record + // base64(sha256("LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0" + // + "." + "9jg46WB3rR_AHD-EBXdN7cBkH1WOu0tA3M9fm21mqTI")) + return []string{"LPsIwTo7o8BoG0-vjCyGQGBWSVIPxI-i_X336eUOQZo"}, ResolverAddrs{"MockClient"}, nil + } + if hostname == accountLabelPrefix+".empty-txts.com" { + // Mirror dns-01 zero TXT records + return []string{}, ResolverAddrs{"MockClient"}, nil + } + if hostname == "_acme-challenge.servfail.com" { return nil, ResolverAddrs{"MockClient"}, fmt.Errorf("SERVFAIL") } @@ -47,6 +84,8 @@ func (mock *MockClient) LookupTXT(_ context.Context, hostname string) ([]string, if hostname == "_acme-challenge.empty-txts.com" { return []string{}, ResolverAddrs{"MockClient"}, nil } + + // Default fallback return []string{"hostname"}, ResolverAddrs{"MockClient"}, nil } diff --git a/cmd/config.go b/cmd/config.go index 3072f206c79..013e3475a83 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -100,7 +100,7 @@ type SMTPConfig struct { // it should offer. type PAConfig struct { DBConfig `validate:"-"` - Challenges map[core.AcmeChallenge]bool `validate:"omitempty,dive,keys,oneof=http-01 dns-01 tls-alpn-01,endkeys"` + Challenges map[core.AcmeChallenge]bool `validate:"omitempty,dive,keys,oneof=http-01 dns-01 tls-alpn-01 dns-account-01,endkeys"` } // CheckChallenges checks whether the list of challenges in the PA config diff --git a/core/challenges.go b/core/challenges.go index d5e7a87295e..75a20373fb0 100644 --- a/core/challenges.go +++ b/core/challenges.go @@ -25,6 +25,11 @@ func TLSALPNChallenge01(token string) Challenge { return newChallenge(ChallengeTypeTLSALPN01, token) } +// DNSAccountChallenge01 constructs a dns-account-01 challenge. +func DNSAccountChallenge01(token string) Challenge { + return newChallenge(ChallengeTypeDNSAccount01, token) +} + // NewChallenge constructs a challenge of the given kind. It returns an // error if the challenge type is unrecognized. func NewChallenge(kind AcmeChallenge, token string) (Challenge, error) { @@ -35,6 +40,8 @@ func NewChallenge(kind AcmeChallenge, token string) (Challenge, error) { return DNSChallenge01(token), nil case ChallengeTypeTLSALPN01: return TLSALPNChallenge01(token), nil + case ChallengeTypeDNSAccount01: + return DNSAccountChallenge01(token), nil default: return Challenge{}, fmt.Errorf("unrecognized challenge type %q", kind) } diff --git a/core/core_test.go b/core/core_test.go index 889f9c9fea8..1b7ff0cb50a 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -32,12 +32,16 @@ func TestChallenges(t *testing.T) { dns01 := DNSChallenge01(token) test.AssertNotError(t, dns01.CheckPending(), "CheckConsistencyForClientOffer returned an error") + dnsAccount01 := DNSAccountChallenge01(token) + test.AssertNotError(t, dnsAccount01.CheckPending(), "CheckConsistencyForClientOffer returned an error") + tlsalpn01 := TLSALPNChallenge01(token) test.AssertNotError(t, tlsalpn01.CheckPending(), "CheckConsistencyForClientOffer returned an error") test.Assert(t, ChallengeTypeHTTP01.IsValid(), "Refused valid challenge") test.Assert(t, ChallengeTypeDNS01.IsValid(), "Refused valid challenge") test.Assert(t, ChallengeTypeTLSALPN01.IsValid(), "Refused valid challenge") + test.Assert(t, ChallengeTypeDNSAccount01.IsValid(), "Refused valid challenge") test.Assert(t, !AcmeChallenge("nonsense-71").IsValid(), "Accepted invalid challenge") } diff --git a/core/objects.go b/core/objects.go index ba7e434c2cf..cb897e42b5e 100644 --- a/core/objects.go +++ b/core/objects.go @@ -53,15 +53,16 @@ type AcmeChallenge string // These types are the available challenges const ( - ChallengeTypeHTTP01 = AcmeChallenge("http-01") - ChallengeTypeDNS01 = AcmeChallenge("dns-01") - ChallengeTypeTLSALPN01 = AcmeChallenge("tls-alpn-01") + ChallengeTypeHTTP01 = AcmeChallenge("http-01") + ChallengeTypeDNS01 = AcmeChallenge("dns-01") + ChallengeTypeTLSALPN01 = AcmeChallenge("tls-alpn-01") + ChallengeTypeDNSAccount01 = AcmeChallenge("dns-account-01") ) // IsValid tests whether the challenge is a known challenge func (c AcmeChallenge) IsValid() bool { switch c { - case ChallengeTypeHTTP01, ChallengeTypeDNS01, ChallengeTypeTLSALPN01: + case ChallengeTypeHTTP01, ChallengeTypeDNS01, ChallengeTypeTLSALPN01, ChallengeTypeDNSAccount01: return true default: return false @@ -238,6 +239,16 @@ func (ch Challenge) RecordsSane() bool { return false } return true + case ChallengeTypeDNSAccount01: + if len(ch.ValidationRecord) > 1 { + return false + } + // TODO(#7140): Add a check for ResolverAddress == "" only after the + // core.proto change has been deployed. + if ch.ValidationRecord[0].DnsName == "" { + return false + } + return true default: // Unsupported challenge type return false } diff --git a/core/objects_test.go b/core/objects_test.go index 9b9d41f6508..ced0815d56d 100644 --- a/core/objects_test.go +++ b/core/objects_test.go @@ -59,7 +59,7 @@ func TestChallengeSanityCheck(t *testing.T) { }`), &accountKey) test.AssertNotError(t, err, "Error unmarshaling JWK") - types := []AcmeChallenge{ChallengeTypeHTTP01, ChallengeTypeDNS01, ChallengeTypeTLSALPN01} + types := []AcmeChallenge{ChallengeTypeHTTP01, ChallengeTypeDNS01, ChallengeTypeTLSALPN01, ChallengeTypeDNSAccount01} for _, challengeType := range types { chall := Challenge{ Type: challengeType, @@ -152,6 +152,8 @@ func TestChallengeStringID(t *testing.T) { test.AssertEquals(t, ch.StringID(), "iFVMwA") ch.Type = ChallengeTypeHTTP01 test.AssertEquals(t, ch.StringID(), "0Gexug") + ch.Type = ChallengeTypeDNSAccount01 + test.AssertEquals(t, ch.StringID(), "8z2wSg") } func TestFindChallengeByType(t *testing.T) { diff --git a/features/features.go b/features/features.go index 7a27b7ef925..261d08e61f8 100644 --- a/features/features.go +++ b/features/features.go @@ -89,6 +89,11 @@ type Config struct { // StoreARIReplacesInOrders causes the SA to store and retrieve the optional // ARI replaces field in the orders table. StoreARIReplacesInOrders bool + + // DNSAccount01Enabled enables or disables support for the dns-account-01 + // challenge type. When enabled, the server can offer and validate this + // challenge during certificate issuance. + DNSAccount01Enabled bool } var fMu = new(sync.RWMutex) diff --git a/go.mod b/go.mod index 07805198af8..a2415840fef 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.27.43 github.com/aws/aws-sdk-go-v2/service/s3 v1.65.3 github.com/aws/smithy-go v1.22.0 - github.com/eggsampler/acme/v3 v3.6.2-0.20250208073118-0466a0230941 + github.com/eggsampler/acme/v3 v3.6.2 github.com/go-jose/go-jose/v4 v4.1.0 github.com/go-logr/stdr v1.2.2 github.com/go-sql-driver/mysql v1.7.1 diff --git a/go.sum b/go.sum index 87d383d70b9..cf104f9d65e 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/eggsampler/acme/v3 v3.6.2-0.20250208073118-0466a0230941 h1:CnQwymLMJ3MSfjbZQ/bpaLfuXBZuM3LUgAHJ0gO/7d8= -github.com/eggsampler/acme/v3 v3.6.2-0.20250208073118-0466a0230941/go.mod h1:/qh0rKC/Dh7Jj+p4So7DbWmFNzC4dpcpK53r226Fhuo= +github.com/eggsampler/acme/v3 v3.6.2 h1:gvyZbQ92wNQLDASVftGpHEdFwPSfg0+17P0lLt09Tp8= +github.com/eggsampler/acme/v3 v3.6.2/go.mod h1:/qh0rKC/Dh7Jj+p4So7DbWmFNzC4dpcpK53r226Fhuo= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= diff --git a/policy/pa.go b/policy/pa.go index cf9e619a011..7200efe9747 100644 --- a/policy/pa.go +++ b/policy/pa.go @@ -18,6 +18,7 @@ import ( "github.com/letsencrypt/boulder/core" berrors "github.com/letsencrypt/boulder/errors" + "github.com/letsencrypt/boulder/features" "github.com/letsencrypt/boulder/iana" "github.com/letsencrypt/boulder/identifier" blog "github.com/letsencrypt/boulder/log" @@ -535,16 +536,28 @@ func (pa *AuthorityImpl) ChallengeTypesFor(ident identifier.ACMEIdentifier) ([]c // stating that ACME HTTP-01 and TLS-ALPN-01 are not suitable for validating // Wildcard Domains. if ident.Type == identifier.TypeDNS && strings.HasPrefix(ident.Value, "*.") { - return []core.AcmeChallenge{core.ChallengeTypeDNS01}, nil + challenges := []core.AcmeChallenge{core.ChallengeTypeDNS01} + + if features.Get().DNSAccount01Enabled { + challenges = append(challenges, core.ChallengeTypeDNSAccount01) + } + + return challenges, nil } // Return all challenge types we support for non-wildcard DNS identifiers. if ident.Type == identifier.TypeDNS { - return []core.AcmeChallenge{ + challenges := []core.AcmeChallenge{ core.ChallengeTypeHTTP01, core.ChallengeTypeDNS01, core.ChallengeTypeTLSALPN01, - }, nil + } + + if features.Get().DNSAccount01Enabled { + challenges = append(challenges, core.ChallengeTypeDNSAccount01) + } + + return challenges, nil } // Otherwise return an error because we don't support any challenges for this diff --git a/policy/pa_test.go b/policy/pa_test.go index d7c586b4f2e..666e9628161 100644 --- a/policy/pa_test.go +++ b/policy/pa_test.go @@ -18,9 +18,10 @@ import ( func paImpl(t *testing.T) *AuthorityImpl { enabledChallenges := map[core.AcmeChallenge]bool{ - core.ChallengeTypeHTTP01: true, - core.ChallengeTypeDNS01: true, - core.ChallengeTypeTLSALPN01: true, + core.ChallengeTypeHTTP01: true, + core.ChallengeTypeDNS01: true, + core.ChallengeTypeDNSAccount01: true, + core.ChallengeTypeTLSALPN01: true, } pa, err := New(enabledChallenges, blog.NewMock()) @@ -401,6 +402,9 @@ func TestChallengeTypesFor(t *testing.T) { t.Parallel() pa := paImpl(t) + features.Set(features.Config{DNSAccount01Enabled: true}) + defer features.Reset() + testCases := []struct { name string ident identifier.ACMEIdentifier @@ -411,7 +415,10 @@ func TestChallengeTypesFor(t *testing.T) { name: "dns", ident: identifier.NewDNS("example.com"), wantChalls: []core.AcmeChallenge{ - core.ChallengeTypeHTTP01, core.ChallengeTypeDNS01, core.ChallengeTypeTLSALPN01, + core.ChallengeTypeHTTP01, + core.ChallengeTypeDNS01, + core.ChallengeTypeTLSALPN01, + core.ChallengeTypeDNSAccount01, }, }, { @@ -419,6 +426,7 @@ func TestChallengeTypesFor(t *testing.T) { ident: identifier.NewDNS("*.example.com"), wantChalls: []core.AcmeChallenge{ core.ChallengeTypeDNS01, + core.ChallengeTypeDNSAccount01, }, }, { @@ -430,7 +438,6 @@ func TestChallengeTypesFor(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - t.Parallel() challs, err := pa.ChallengeTypesFor(tc.ident) if len(tc.wantChalls) != 0 { diff --git a/ra/proto/ra.pb.go b/ra/proto/ra.pb.go index f0da0b29bbc..fdb9fa72f4c 100644 --- a/ra/proto/ra.pb.go +++ b/ra/proto/ra.pb.go @@ -391,6 +391,7 @@ type PerformValidationRequest struct { Authz *proto.Authorization `protobuf:"bytes,1,opt,name=authz,proto3" json:"authz,omitempty"` ChallengeIndex int64 `protobuf:"varint,2,opt,name=challengeIndex,proto3" json:"challengeIndex,omitempty"` + AccountURI string `protobuf:"bytes,3,opt,name=accountURI,proto3" json:"accountURI,omitempty"` } func (x *PerformValidationRequest) Reset() { @@ -439,6 +440,13 @@ func (x *PerformValidationRequest) GetChallengeIndex() int64 { return 0 } +func (x *PerformValidationRequest) GetAccountURI() string { + if x != nil { + return x.AccountURI + } + return "" +} + type RevokeCertByApplicantRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -979,142 +987,144 @@ var file_ra_proto_rawDesc = []byte{ 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2b, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x18, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x29, 0x0a, 0x05, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x68, - 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x22, 0x5c, 0x0a, 0x1c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, - 0x42, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x6e, 0x73, 0x65, 0x22, 0x8d, 0x01, 0x0a, 0x18, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x29, 0x0a, 0x05, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x12, 0x26, 0x0a, 0x0e, 0x63, + 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x52, + 0x49, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x55, 0x52, 0x49, 0x22, 0x5c, 0x0a, 0x1c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, + 0x74, 0x42, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, + 0x65, 0x67, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x72, 0x65, 0x67, 0x49, + 0x44, 0x22, 0x32, 0x0a, 0x16, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, + 0x79, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, + 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x4a, + 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xe6, 0x01, 0x0a, 0x28, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, - 0x67, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x72, 0x65, 0x67, 0x49, 0x44, - 0x22, 0x32, 0x0a, 0x16, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, - 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, - 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x4a, 0x04, - 0x08, 0x02, 0x10, 0x03, 0x22, 0xe6, 0x01, 0x0a, 0x28, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x12, 0x0a, - 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x63, 0x6f, 0x64, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x22, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6d, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x65, - 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x72, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x08, 0x63, 0x72, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x22, 0xfb, 0x01, - 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x32, 0x0a, 0x0b, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x36, 0x0a, - 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x53, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, - 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x29, 0x0a, 0x17, 0x47, - 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x14, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, - 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, - 0x72, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x73, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, - 0x63, 0x73, 0x72, 0x22, 0x3f, 0x0a, 0x15, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, - 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x2e, 0x0a, 0x16, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x32, 0xaa, 0x08, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3b, - 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x19, 0x55, + 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x12, + 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x63, 0x6f, + 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x65, + 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6d, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x6d, + 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x72, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x63, 0x72, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x22, 0xfb, + 0x01, 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x32, 0x0a, 0x0b, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x36, + 0x0a, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x53, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6c, + 0x61, 0x63, 0x65, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, + 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x29, 0x0a, 0x17, + 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x14, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x21, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, + 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x73, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x03, 0x63, 0x73, 0x72, 0x22, 0x3f, 0x0a, 0x15, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, + 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x2e, 0x0a, 0x16, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0xaa, 0x08, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, + 0x3b, 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x19, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x2e, - 0x72, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x16, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x21, 0x2e, 0x72, 0x61, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x66, - 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, - 0x72, 0x61, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0x00, 0x12, 0x48, 0x0a, 0x17, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x15, - 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x41, 0x70, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x72, 0x61, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, - 0x00, 0x12, 0x47, 0x0a, 0x0f, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, - 0x79, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x2e, 0x72, 0x61, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, - 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x6b, 0x0a, 0x21, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, 0x65, - 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, - 0x2c, 0x2e, 0x72, 0x61, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x08, 0x4e, 0x65, 0x77, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x12, 0x13, 0x2e, 0x72, 0x61, 0x2e, 0x4e, 0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x72, 0x61, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, - 0x38, 0x0a, 0x0d, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x12, 0x18, 0x2e, 0x72, 0x61, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0c, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x4f, 0x43, 0x53, 0x50, 0x12, 0x17, 0x2e, 0x72, 0x61, 0x2e, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4f, 0x43, 0x53, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x63, 0x61, 0x2e, 0x4f, 0x43, 0x53, 0x50, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0e, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, - 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x6e, - 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x32, 0x3b, 0x0a, 0x0b, 0x53, 0x43, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x12, 0x2c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x43, 0x54, 0x73, 0x12, 0x0e, 0x2e, 0x72, 0x61, - 0x2e, 0x53, 0x43, 0x54, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x72, 0x61, - 0x2e, 0x53, 0x43, 0x54, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x29, - 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x65, 0x74, - 0x73, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2f, 0x62, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x72, - 0x2f, 0x72, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x20, + 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x16, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x21, 0x2e, 0x72, 0x61, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x11, 0x50, 0x65, 0x72, + 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, + 0x2e, 0x72, 0x61, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x17, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x53, 0x0a, + 0x15, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x41, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x72, 0x61, 0x2e, 0x52, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0f, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, + 0x42, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x2e, 0x72, 0x61, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, + 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x6b, 0x0a, 0x21, 0x41, + 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, + 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x12, 0x2c, 0x2e, 0x72, 0x61, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, + 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x08, 0x4e, 0x65, 0x77, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x12, 0x13, 0x2e, 0x72, 0x61, 0x2e, 0x4e, 0x65, 0x77, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x72, + 0x61, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, + 0x12, 0x38, 0x0a, 0x0d, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, 0x72, 0x64, 0x65, + 0x72, 0x12, 0x18, 0x2e, 0x72, 0x61, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0c, 0x47, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4f, 0x43, 0x53, 0x50, 0x12, 0x17, 0x2e, 0x72, 0x61, 0x2e, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4f, 0x43, 0x53, 0x50, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x63, 0x61, 0x2e, 0x4f, 0x43, 0x53, 0x50, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0e, 0x55, 0x6e, 0x70, 0x61, 0x75, + 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x72, 0x61, 0x2e, 0x55, + 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, + 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x32, 0x3b, 0x0a, 0x0b, 0x53, 0x43, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x12, 0x2c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x43, 0x54, 0x73, 0x12, 0x0e, 0x2e, 0x72, + 0x61, 0x2e, 0x53, 0x43, 0x54, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x72, + 0x61, 0x2e, 0x53, 0x43, 0x54, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, + 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x65, + 0x74, 0x73, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2f, 0x62, 0x6f, 0x75, 0x6c, 0x64, 0x65, + 0x72, 0x2f, 0x72, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/ra/proto/ra.proto b/ra/proto/ra.proto index 2b12e2b7244..a97db3c754d 100644 --- a/ra/proto/ra.proto +++ b/ra/proto/ra.proto @@ -64,6 +64,7 @@ message UpdateAuthorizationRequest { message PerformValidationRequest { core.Authorization authz = 1; int64 challengeIndex = 2; + string accountURI = 3; } message RevokeCertByApplicantRequest { diff --git a/sa/model.go b/sa/model.go index 8c6a74366af..981c49de025 100644 --- a/sa/model.go +++ b/sa/model.go @@ -474,15 +474,17 @@ func modelToOrder(om *orderModel) (*corepb.Order, error) { } var challTypeToUint = map[string]uint8{ - "http-01": 0, - "dns-01": 1, - "tls-alpn-01": 2, + "http-01": 0, + "dns-01": 1, + "tls-alpn-01": 2, + "dns-account-01": 3, } var uintToChallType = map[uint8]string{ 0: "http-01", 1: "dns-01", 2: "tls-alpn-01", + 3: "dns-account-01", } var identifierTypeToUint = map[string]uint8{ diff --git a/test/integration/validation_test.go b/test/integration/validation_test.go index 8e7a9730d18..3738e5bf1bb 100644 --- a/test/integration/validation_test.go +++ b/test/integration/validation_test.go @@ -9,7 +9,6 @@ import ( "database/sql" "os" "slices" - "sort" "strings" "testing" "time" @@ -30,6 +29,53 @@ func collectUserAgentsFromDNSRequests(requests []challtestsrvclient.DNSRequest) return userAgents } +func assertUserAgentsLength(t *testing.T, got []string, checkType string) { + t.Helper() + + if os.Getenv("BOULDER_CONFIG_DIR") != "test/config-next" { + // We only need 3 checks if the MPICFullResults feature-flag is not + // enabled. + // + // TODO(#8121): Remove this once MPICFullResults has been defaulted to + // true. + if len(got) != 4 && len(got) != 3 { + t.Errorf("During %s, expected 3 or 4 User-Agents, got %d", checkType, len(got)) + } + } else { + if len(got) != 4 { + t.Errorf("During %s, expected 4 User-Agents, got %d", checkType, len(got)) + } + } +} + +func assertExpectedUserAgents(t *testing.T, got []string, checkType string) { + t.Helper() + + if os.Getenv("BOULDER_CONFIG_DIR") != "test/config-next" { + // One User-Agent may be missing if the MPICFullResults feature-flag is + // not enabled. This will need to be modified to 2 if we have not + // removed this feature-flag by the time we get to 6+ perspectives. + // + // TODO(#8121): Remove this once MPICFullResults has been defaulted to + // true. + var alreadySkippedOne bool + for _, ua := range expectedUserAgents { + if !slices.Contains(got, ua) { + if alreadySkippedOne { + t.Errorf("During %s, missing more than 1 User-Agent in %s (got %v)", checkType, expectedUserAgents, got) + } + alreadySkippedOne = true + } + } + } else { + for _, ua := range expectedUserAgents { + if !slices.Contains(got, ua) { + t.Errorf("During %s, expected User-Agent %q in %s (got %v)", checkType, ua, expectedUserAgents, got) + } + } + } +} + func TestMPICTLSALPN01(t *testing.T) { t.Parallel() @@ -105,29 +151,14 @@ func TestMPICTLSALPN01(t *testing.T) { caaEvents = append(caaEvents, event) } } - - if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" && len(caaEvents) != 4 { - t.Errorf("expected 4 CAA checks got %d", len(caaEvents)) - } else if len(caaEvents) != 3 && len(caaEvents) != 4 { - // We only need 3 checks if the MPICFullResults feature-flag is not - // enabled. - // - // TODO(#8121): Remove this once MPICFullResults has been defaulted to - // true. - t.Errorf("expected 3 or 4 CAA checks got %d", len(caaEvents)) - } + assertUserAgentsLength(t, collectUserAgentsFromDNSRequests(caaEvents), "CAA check") if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" { // We can only check the user-agent for DNS requests if the DOH // feature-flag is enabled. // - // TODO(#8120): Remove this once the DoH feature flag has been defaulted - // to true. - gotUserAgents := collectUserAgentsFromDNSRequests(caaEvents) - for _, ua := range expectedUserAgents { - if !slices.Contains(gotUserAgents, ua) { - t.Errorf("expected a query from User-Agent %q but did not get one (got %+v).", ua, gotUserAgents) - } - } + // TODO(#8120): Remove this conditional once the DoH feature flag has + // been defaulted to true. + assertExpectedUserAgents(t, collectUserAgentsFromDNSRequests(caaEvents), "CAA check") } } @@ -183,28 +214,14 @@ func TestMPICDNS01(t *testing.T) { validationEvents = append(validationEvents, event) } } - if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" && len(validationEvents) != 4 { - t.Errorf("expected 4 validation events got %d", len(validationEvents)) - } else if len(validationEvents) != 3 && len(validationEvents) != 4 { - // We only need 3 checks if the MPICFullResults feature-flag is not - // enabled. - // - // TODO(#8121): Remove this once MPICFullResults has been defaulted to - // true. - t.Errorf("expected 3 or 4 validation events got %d", len(validationEvents)) - } + assertUserAgentsLength(t, collectUserAgentsFromDNSRequests(validationEvents), "DNS-01 validation") if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" { // We can only check the user-agent for DNS requests if the DOH // feature-flag is enabled. // // TODO(#8120): Remove this once the DoH feature flag has been defaulted // to true. - gotUserAgents := collectUserAgentsFromDNSRequests(validationEvents) - for _, ua := range expectedUserAgents { - if !slices.Contains(gotUserAgents, ua) { - t.Errorf("expected a query from User-Agent %q but did not get one (got %+v).", ua, gotUserAgents) - } - } + assertExpectedUserAgents(t, collectUserAgentsFromDNSRequests(validationEvents), "DNS-01 validation") } domainDNSEvents, err := testSrvClient.DNSRequestHistory(domain) @@ -218,29 +235,14 @@ func TestMPICDNS01(t *testing.T) { caaEvents = append(caaEvents, event) } } - - if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" && len(caaEvents) != 4 { - t.Errorf("expected 4 CAA checks got %d", len(caaEvents)) - } else if len(caaEvents) != 3 && len(caaEvents) != 4 { - // We only need 3 checks if the MPICFullResults feature-flag is not - // enabled. - // - // TODO(#8121): Remove this once MPICFullResults has been defaulted to - // true. - t.Errorf("expected 3 or 4 CAA checks got %d", len(caaEvents)) - } + assertUserAgentsLength(t, collectUserAgentsFromDNSRequests(caaEvents), "CAA check") if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" { // We can only check the user-agent for DNS requests if the DOH // feature-flag is enabled. // // TODO(#8120): Remove this once the DoH feature flag has been defaulted // to true. - gotUserAgents := collectUserAgentsFromDNSRequests(caaEvents) - for _, ua := range expectedUserAgents { - if !slices.Contains(gotUserAgents, ua) { - t.Errorf("expected a query from User-Agent %q but did not get one (got %+v).", ua, gotUserAgents) - } - } + assertExpectedUserAgents(t, collectUserAgentsFromDNSRequests(caaEvents), "CAA check") } } @@ -290,41 +292,14 @@ func TestMPICHTTP01(t *testing.T) { t.Fatal(err) } - validationCount := 0 + var validationUAs []string for _, event := range validationEvents { if event.URL == "/.well-known/acme-challenge/"+chal.Token { - validationCount++ - } - } - - if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" && validationCount != 4 { - t.Errorf("expected 4 validation events got %d", validationCount) - } else if validationCount != 3 && validationCount != 4 { - // We only need 3 checks if the MPICFullResults feature-flag is not - // enabled. - // - // TODO(#8121): Remove this once MPICFullResults has been defaulted to - // true. - t.Errorf("expected 3 or 4 validation events got %d", validationCount) - } - - sort.Slice(validationEvents, func(i, j int) bool { - return validationEvents[i].UserAgent < validationEvents[j].UserAgent - }) - for i, event := range validationEvents { - if event.UserAgent != expectedUserAgents[i] { - t.Errorf("expected user agent %s, got %s", expectedUserAgents[i], event.UserAgent) - } - } - - sort.Slice(validationEvents, func(i, j int) bool { - return validationEvents[i].UserAgent < validationEvents[j].UserAgent - }) - for i, event := range validationEvents { - if event.UserAgent != expectedUserAgents[i] { - t.Errorf("expected user agent %s, got %s", expectedUserAgents[i], event.UserAgent) + validationUAs = append(validationUAs, event.UserAgent) } } + assertUserAgentsLength(t, validationUAs, "HTTP-01 validation") + assertExpectedUserAgents(t, validationUAs, "HTTP-01 validation") dnsEvents, err := testSrvClient.DNSRequestHistory(domain) if err != nil { @@ -338,31 +313,14 @@ func TestMPICHTTP01(t *testing.T) { } } - if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" && len(caaEvents) != 4 { - t.Errorf("expected 4 CAA checks got %d", len(caaEvents)) - } else if len(caaEvents) != 3 && len(caaEvents) != 4 { - // We only need 3 checks if the MPICFullResults feature-flag is not - // enabled. - // - // TODO(#8121): Remove this once MPICFullResults has been defaulted to - // true. - t.Errorf("expected 3 or 4 CAA checks got %d", len(caaEvents)) - } + assertUserAgentsLength(t, collectUserAgentsFromDNSRequests(caaEvents), "CAA check") if os.Getenv("BOULDER_CONFIG_DIR") == "test/config-next" { // We can only check the user-agent for DNS requests if the DOH // feature-flag is enabled. // // TODO(#8120): Remove this once the DoH feature flag has been defaulted // to true. - sort.Slice(caaEvents, func(i, j int) bool { - return caaEvents[i].UserAgent < caaEvents[j].UserAgent - }) - - for i, event := range caaEvents { - if event.UserAgent != expectedUserAgents[i] { - t.Errorf("expected user agent %s, got %s", expectedUserAgents[i], event.UserAgent) - } - } + assertExpectedUserAgents(t, collectUserAgentsFromDNSRequests(caaEvents), "CAA check") } } diff --git a/va/dns.go b/va/dns.go index 7445d4fdd18..53042953b97 100644 --- a/va/dns.go +++ b/va/dns.go @@ -4,9 +4,12 @@ import ( "context" "crypto/sha256" "crypto/subtle" + "encoding/base32" "encoding/base64" + "errors" "fmt" "net" + "strings" "github.com/letsencrypt/boulder/bdns" "github.com/letsencrypt/boulder/core" @@ -48,10 +51,54 @@ func availableAddresses(allAddrs []net.IP) (v4 []net.IP, v6 []net.IP) { return } +// validateDNSAccount01 handles the dns-account-01 challenge by calculating +// the account-specific DNS query domain and expected digest, then calling +// the common DNS validation logic. +func (va *ValidationAuthorityImpl) validateDNSAccount01(ctx context.Context, ident identifier.ACMEIdentifier, keyAuthorization string, accountURI string) ([]core.ValidationRecord, error) { + if ident.Type != identifier.TypeDNS { + va.log.Infof("Identifier type for DNS-ACCOUNT-01 challenge was not DNS: %s", ident) + return nil, berrors.MalformedError("Identifier type for DNS-ACCOUNT-01 challenge was not DNS") + } + if accountURI == "" { + va.log.Infof("DNS-ACCOUNT-01 validation for %q failed: missing accountURI", ident.Value) + return nil, berrors.InternalServerError("accountURI must be provided for dns-account-01") + } + + // Compute the digest of the key authorization file + h := sha256.New() + h.Write([]byte(keyAuthorization)) + authorizedKeysDigest := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) + + // Calculate the DNS prefix label based on the account URI + sha256sum := sha256.Sum256([]byte(accountURI)) + prefixBytes := sha256sum[0:10] // First 10 bytes + prefixLabel := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(prefixBytes) + prefixLabel = strings.ToLower(prefixLabel) + + // Construct the full query domain specific to DNS-ACCOUNT-01 + challengeSubdomain := fmt.Sprintf("_%s.%s.%s", prefixLabel, core.DNSPrefix, ident.Value) + va.log.Debugf("DNS-ACCOUNT-01: Querying TXT for %q (derived from account URI %q)", challengeSubdomain, accountURI) + + // Call the common validation logic + records, err := va.validateDNS(ctx, ident, challengeSubdomain, authorizedKeysDigest) + if err != nil { + // Check if the error returned by validateDNS is of the Unauthorized type + if errors.Is(err, berrors.Unauthorized) { + // Enrich any UnauthorizedError from validateDNS with the account URI + enrichedError := berrors.UnauthorizedError("%s (account: %s)", err.Error(), accountURI) + return nil, enrichedError + } + // For other error types, return as is + return nil, err + } + + return records, nil +} + func (va *ValidationAuthorityImpl) validateDNS01(ctx context.Context, ident identifier.ACMEIdentifier, keyAuthorization string) ([]core.ValidationRecord, error) { if ident.Type != identifier.TypeDNS { - va.log.Infof("Identifier type for DNS challenge was not DNS: %s", ident) - return nil, berrors.MalformedError("Identifier type for DNS challenge was not DNS") + va.log.Infof("Identifier type for DNS-01 challenge was not DNS: %s", ident) + return nil, berrors.MalformedError("Identifier type for DNS-01 challenge was not DNS") } // Compute the digest of the key authorization file @@ -59,8 +106,16 @@ func (va *ValidationAuthorityImpl) validateDNS01(ctx context.Context, ident iden h.Write([]byte(keyAuthorization)) authorizedKeysDigest := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) - // Look for the required record in the DNS + // Construct the query domain specific to DNS-01 challengeSubdomain := fmt.Sprintf("%s.%s", core.DNSPrefix, ident.Value) + + // Call the common validation logic + return va.validateDNS(ctx, ident, challengeSubdomain, authorizedKeysDigest) +} + +// validateDNS performs the DNS TXT lookup and validation logic. +func (va *ValidationAuthorityImpl) validateDNS(ctx context.Context, ident identifier.ACMEIdentifier, challengeSubdomain string, authorizedKeysDigest string) ([]core.ValidationRecord, error) { + // Look for the required record in the DNS txts, resolvers, err := va.dnsClient.LookupTXT(ctx, challengeSubdomain) if err != nil { return nil, berrors.DNSError("%s", err) diff --git a/va/dns_account_test.go b/va/dns_account_test.go new file mode 100644 index 00000000000..3f304468a53 --- /dev/null +++ b/va/dns_account_test.go @@ -0,0 +1,164 @@ +// dns_account_test.go +package va + +import ( + "context" + "net/netip" + "testing" + "time" + + "github.com/jmhodges/clock" + + "github.com/letsencrypt/boulder/bdns" + "github.com/letsencrypt/boulder/identifier" + "github.com/letsencrypt/boulder/metrics" + "github.com/letsencrypt/boulder/probs" + "github.com/letsencrypt/boulder/test" +) + +// Use a consistent test account URI, matching the example in the draft +const testAccountURI = "https://example.com/acme/acct/ExampleAccount" + +// Expected label prefix derived from testAccountURI (as per draft example) +const expectedLabelPrefix = "_ujmmovf2vn55tgye._acme-challenge" + +func TestDNSAccount01ValidationWrong(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + _, err := va.validateDNSAccount01(context.Background(), identifier.NewDNS("wrong-dns01.com"), expectedKeyAuthorization, testAccountURI) + if err == nil { + t.Fatalf("Successful DNS validation with wrong TXT record") + } + prob := detailedError(err) + expectedErr := "unauthorized :: Incorrect TXT record \"a\" found at " + expectedLabelPrefix + ".wrong-dns01.com" + + " (account: " + testAccountURI + ")" + test.AssertEquals(t, prob.String(), expectedErr) +} + +func TestDNSAccount01ValidationWrongMany(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + + _, err := va.validateDNSAccount01(context.Background(), identifier.NewDNS("wrong-many-dns01.com"), expectedKeyAuthorization, testAccountURI) + if err == nil { + t.Fatalf("Successful DNS validation with wrong TXT record") + } + prob := detailedError(err) + expectedErr := "unauthorized :: Incorrect TXT record \"a\" (and 4 more) found at " + expectedLabelPrefix + ".wrong-many-dns01.com" + + " (account: " + testAccountURI + ")" + test.AssertEquals(t, prob.String(), expectedErr) +} + +func TestDNSAccount01ValidationWrongLong(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + + _, err := va.validateDNSAccount01(context.Background(), identifier.NewDNS("long-dns01.com"), expectedKeyAuthorization, testAccountURI) + if err == nil { + t.Fatalf("Successful DNS validation with wrong TXT record") + } + prob := detailedError(err) + expectedErr := "unauthorized :: Incorrect TXT record \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...\" found at " + expectedLabelPrefix + ".long-dns01.com" + + " (account: " + testAccountURI + ")" + test.AssertEquals(t, prob.String(), expectedErr) +} + +func TestDNSAccount01ValidationFailure(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + + _, err := va.validateDNSAccount01(ctx, identifier.NewDNS("localhost"), expectedKeyAuthorization, testAccountURI) + prob := detailedError(err) + + test.AssertEquals(t, prob.Type, probs.UnauthorizedProblem) + + expectedErr := "unauthorized :: Incorrect TXT record \"hostname\" found at " + expectedLabelPrefix + ".localhost" + + " (account: " + testAccountURI + ")" + test.AssertEquals(t, prob.String(), expectedErr) +} + +func TestDNSAccount01ValidationIP(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + + _, err := va.validateDNSAccount01(ctx, identifier.NewIP(netip.MustParseAddr("127.0.0.1")), expectedKeyAuthorization, testAccountURI) + prob := detailedError(err) + + test.AssertEquals(t, prob.Type, probs.MalformedProblem) +} + +func TestDNSAccount01ValidationInvalid(t *testing.T) { + var notDNS = identifier.ACMEIdentifier{ + Type: identifier.IdentifierType("iris"), + Value: "790DB180-A274-47A4-855F-31C428CB1072", + } + + va, _ := setup(nil, "", nil, nil) + + _, err := va.validateDNSAccount01(ctx, notDNS, expectedKeyAuthorization, testAccountURI) + prob := detailedError(err) + + test.AssertEquals(t, prob.Type, probs.MalformedProblem) +} + +func TestDNSAccount01ValidationServFail(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + + _, err := va.validateDNSAccount01(ctx, identifier.NewDNS("servfail.com"), expectedKeyAuthorization, testAccountURI) + + prob := detailedError(err) + test.AssertEquals(t, prob.Type, probs.DNSProblem) +} + +func TestDNSAccount01ValidationNoServer(t *testing.T) { + va, log := setup(nil, "", nil, nil) + staticProvider, err := bdns.NewStaticProvider([]string{}) + test.AssertNotError(t, err, "Couldn't make new static provider") + + va.dnsClient = bdns.NewTest( + time.Second*5, + staticProvider, + metrics.NoopRegisterer, + clock.New(), + 1, + "", + log, + nil) + + _, err = va.validateDNSAccount01(ctx, identifier.NewDNS("localhost"), expectedKeyAuthorization, testAccountURI) + prob := detailedError(err) + test.AssertEquals(t, prob.Type, probs.DNSProblem) +} + +func TestDNSAccount01ValidationOK(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + + _, prob := va.validateDNSAccount01(ctx, identifier.NewDNS("good-dns01.com"), expectedKeyAuthorization, testAccountURI) + + test.Assert(t, prob == nil, "Should be valid.") +} + +func TestDNSAccount01ValidationNoAuthorityOK(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + + _, prob := va.validateDNSAccount01(ctx, identifier.NewDNS("no-authority-dns01.com"), expectedKeyAuthorization, testAccountURI) + + test.Assert(t, prob == nil, "Should be valid.") +} + +func TestDNSAccount01ValidationEmptyAccountURI(t *testing.T) { + va, _ := setup(nil, "", nil, nil) + + // The specific domain doesn't matter, as the function should + // reject the empty accountURI before DNS lookup. + ident := identifier.NewDNS("empty-uri-test.com") + + // Call the validation function with an empty accountURI + _, err := va.validateDNSAccount01(ctx, ident, expectedKeyAuthorization, "") + + // Assert that an error was returned + test.Assert(t, err != nil, "validateDNSAccount01 succeeded unexpectedly with an empty account URI") + + // Assert the specific error type + prob := detailedError(err) + test.AssertEquals(t, prob.Type, probs.ConnectionProblem) + + // Assert the specific error message + expectedErrMsg := "connection :: Error getting validation data" + test.AssertEquals(t, prob.String(), expectedErrMsg) +} diff --git a/va/dns_test.go b/va/dns_test.go index e73da4fe6f3..b77e04abeda 100644 --- a/va/dns_test.go +++ b/va/dns_test.go @@ -17,7 +17,7 @@ import ( "github.com/letsencrypt/boulder/test" ) -func TestDNSValidationWrong(t *testing.T) { +func TestDNS01ValidationWrong(t *testing.T) { va, _ := setup(nil, "", nil, nil) _, err := va.validateDNS01(context.Background(), identifier.NewDNS("wrong-dns01.com"), expectedKeyAuthorization) if err == nil { @@ -27,7 +27,7 @@ func TestDNSValidationWrong(t *testing.T) { test.AssertEquals(t, prob.String(), "unauthorized :: Incorrect TXT record \"a\" found at _acme-challenge.wrong-dns01.com") } -func TestDNSValidationWrongMany(t *testing.T) { +func TestDNS01ValidationWrongMany(t *testing.T) { va, _ := setup(nil, "", nil, nil) _, err := va.validateDNS01(context.Background(), identifier.NewDNS("wrong-many-dns01.com"), expectedKeyAuthorization) @@ -38,7 +38,7 @@ func TestDNSValidationWrongMany(t *testing.T) { test.AssertEquals(t, prob.String(), "unauthorized :: Incorrect TXT record \"a\" (and 4 more) found at _acme-challenge.wrong-many-dns01.com") } -func TestDNSValidationWrongLong(t *testing.T) { +func TestDNS01ValidationWrongLong(t *testing.T) { va, _ := setup(nil, "", nil, nil) _, err := va.validateDNS01(context.Background(), identifier.NewDNS("long-dns01.com"), expectedKeyAuthorization) @@ -49,7 +49,7 @@ func TestDNSValidationWrongLong(t *testing.T) { test.AssertEquals(t, prob.String(), "unauthorized :: Incorrect TXT record \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...\" found at _acme-challenge.long-dns01.com") } -func TestDNSValidationFailure(t *testing.T) { +func TestDNS01ValidationFailure(t *testing.T) { va, _ := setup(nil, "", nil, nil) _, err := va.validateDNS01(ctx, identifier.NewDNS("localhost"), expectedKeyAuthorization) @@ -58,7 +58,7 @@ func TestDNSValidationFailure(t *testing.T) { test.AssertEquals(t, prob.Type, probs.UnauthorizedProblem) } -func TestDNSValidationIP(t *testing.T) { +func TestDNS01ValidationIP(t *testing.T) { va, _ := setup(nil, "", nil, nil) _, err := va.validateDNS01(ctx, identifier.NewIP(netip.MustParseAddr("127.0.0.1")), expectedKeyAuthorization) @@ -67,7 +67,7 @@ func TestDNSValidationIP(t *testing.T) { test.AssertEquals(t, prob.Type, probs.MalformedProblem) } -func TestDNSValidationInvalid(t *testing.T) { +func TestDNS01ValidationInvalid(t *testing.T) { var notDNS = identifier.ACMEIdentifier{ Type: identifier.IdentifierType("iris"), Value: "790DB180-A274-47A4-855F-31C428CB1072", @@ -81,7 +81,7 @@ func TestDNSValidationInvalid(t *testing.T) { test.AssertEquals(t, prob.Type, probs.MalformedProblem) } -func TestDNSValidationServFail(t *testing.T) { +func TestDNS01ValidationServFail(t *testing.T) { va, _ := setup(nil, "", nil, nil) _, err := va.validateDNS01(ctx, identifier.NewDNS("servfail.com"), expectedKeyAuthorization) @@ -90,7 +90,7 @@ func TestDNSValidationServFail(t *testing.T) { test.AssertEquals(t, prob.Type, probs.DNSProblem) } -func TestDNSValidationNoServer(t *testing.T) { +func TestDNS01ValidationNoServer(t *testing.T) { va, log := setup(nil, "", nil, nil) staticProvider, err := bdns.NewStaticProvider([]string{}) test.AssertNotError(t, err, "Couldn't make new static provider") @@ -110,7 +110,7 @@ func TestDNSValidationNoServer(t *testing.T) { test.AssertEquals(t, prob.Type, probs.DNSProblem) } -func TestDNSValidationOK(t *testing.T) { +func TestDNS01ValidationOK(t *testing.T) { va, _ := setup(nil, "", nil, nil) _, prob := va.validateDNS01(ctx, identifier.NewDNS("good-dns01.com"), expectedKeyAuthorization) @@ -118,7 +118,7 @@ func TestDNSValidationOK(t *testing.T) { test.Assert(t, prob == nil, "Should be valid.") } -func TestDNSValidationNoAuthorityOK(t *testing.T) { +func TestDNS01ValidationNoAuthorityOK(t *testing.T) { va, _ := setup(nil, "", nil, nil) _, prob := va.validateDNS01(ctx, identifier.NewDNS("no-authority-dns01.com"), expectedKeyAuthorization) diff --git a/va/proto/va.pb.go b/va/proto/va.pb.go index e5eba65845e..2580b7079f7 100644 --- a/va/proto/va.pb.go +++ b/va/proto/va.pb.go @@ -165,13 +165,14 @@ type PerformValidationRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Next unused field number: 6 + // Next unused field number: 7 // TODO(#8023): dnsNames are being deprecated in favour of identifiers. DnsName string `protobuf:"bytes,1,opt,name=dnsName,proto3" json:"dnsName,omitempty"` Identifier *proto.Identifier `protobuf:"bytes,5,opt,name=identifier,proto3" json:"identifier,omitempty"` Challenge *proto.Challenge `protobuf:"bytes,2,opt,name=challenge,proto3" json:"challenge,omitempty"` Authz *AuthzMeta `protobuf:"bytes,3,opt,name=authz,proto3" json:"authz,omitempty"` ExpectedKeyAuthorization string `protobuf:"bytes,4,opt,name=expectedKeyAuthorization,proto3" json:"expectedKeyAuthorization,omitempty"` + AccountURI string `protobuf:"bytes,6,opt,name=accountURI,proto3" json:"accountURI,omitempty"` } func (x *PerformValidationRequest) Reset() { @@ -241,6 +242,13 @@ func (x *PerformValidationRequest) GetExpectedKeyAuthorization() string { return "" } +func (x *PerformValidationRequest) GetAccountURI() string { + if x != nil { + return x.AccountURI + } + return "" +} + type AuthzMeta struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -389,7 +397,7 @@ var file_va_proto_rawDesc = []byte{ 0x6c, 0x65, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x69, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x72, 0x69, 0x72, 0x22, 0xf6, 0x01, 0x0a, 0x18, 0x50, 0x65, 0x72, 0x66, + 0x28, 0x09, 0x52, 0x03, 0x72, 0x69, 0x72, 0x22, 0x96, 0x02, 0x0a, 0x18, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, @@ -405,6 +413,8 @@ var file_va_proto_rawDesc = []byte{ 0x4b, 0x65, 0x79, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x52, 0x49, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x52, 0x49, 0x22, 0x31, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x7a, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x72, 0x65, diff --git a/va/proto/va.proto b/va/proto/va.proto index 2b384bd9366..56d5217b054 100644 --- a/va/proto/va.proto +++ b/va/proto/va.proto @@ -32,13 +32,14 @@ message IsCAAValidResponse { } message PerformValidationRequest { - // Next unused field number: 6 + // Next unused field number: 7 // TODO(#8023): dnsNames are being deprecated in favour of identifiers. string dnsName = 1; core.Identifier identifier = 5; core.Challenge challenge = 2; AuthzMeta authz = 3; string expectedKeyAuthorization = 4; + string accountURI = 6; } message AuthzMeta { diff --git a/va/va.go b/va/va.go index 3aaf6ac16d3..326442c07ee 100644 --- a/va/va.go +++ b/va/va.go @@ -407,12 +407,15 @@ func (va *ValidationAuthorityImpl) isPrimaryVA() bool { // validateChallenge simply passes through to the appropriate validation method // depending on the challenge type. +// The accountURI parameter is required for dns-account-01 challenges to +// calculate the account-specific label. func (va *ValidationAuthorityImpl) validateChallenge( ctx context.Context, ident identifier.ACMEIdentifier, kind core.AcmeChallenge, token string, keyAuthorization string, + accountURI string, ) ([]core.ValidationRecord, error) { switch kind { case core.ChallengeTypeHTTP01: @@ -423,6 +426,12 @@ func (va *ValidationAuthorityImpl) validateChallenge( return va.validateDNS01(ctx, ident, keyAuthorization) case core.ChallengeTypeTLSALPN01: return va.validateTLSALPN01(ctx, ident, keyAuthorization) + case core.ChallengeTypeDNSAccount01: + if features.Get().DNSAccount01Enabled { + // Strip a (potential) leading wildcard token from the identifier. + ident.Value = strings.TrimPrefix(ident.Value, "*.") + return va.validateDNSAccount01(ctx, ident, keyAuthorization, accountURI) + } } return nil, berrors.MalformedError("invalid challenge type %s", kind) } @@ -733,6 +742,7 @@ func (va *ValidationAuthorityImpl) DoDCV(ctx context.Context, req *vapb.PerformV chall.Type, chall.Token, req.ExpectedKeyAuthorization, + req.AccountURI, ) // Stop the clock for local validation latency. diff --git a/va/va_test.go b/va/va_test.go index e3333290893..fe57e769b3a 100644 --- a/va/va_test.go +++ b/va/va_test.go @@ -389,7 +389,7 @@ func TestPerformValidationWithMismatchedRemoteVARIRs(t *testing.T) { func TestValidateMalformedChallenge(t *testing.T) { va, _ := setup(nil, "", nil, nil) - _, err := va.validateChallenge(ctx, identifier.NewDNS("example.com"), "fake-type-01", expectedToken, expectedKeyAuthorization) + _, err := va.validateChallenge(ctx, identifier.NewDNS("example.com"), "fake-type-01", expectedToken, expectedKeyAuthorization, testAccountURI) prob := detailedError(err) test.AssertEquals(t, prob.Type, probs.MalformedProblem) diff --git a/vendor/github.com/eggsampler/acme/v3/Makefile b/vendor/github.com/eggsampler/acme/v3/Makefile index c0f3c920f11..1f56d9b9b99 100644 --- a/vendor/github.com/eggsampler/acme/v3/Makefile +++ b/vendor/github.com/eggsampler/acme/v3/Makefile @@ -60,10 +60,11 @@ boulder_setup: -git clone --depth 1 https://github.com/letsencrypt/boulder.git $(BOULDER_PATH) (cd $(BOULDER_PATH); git checkout -f main && git reset --hard HEAD && git pull -q) make boulder_stop + (cd $(BOULDER_PATH); docker compose run --rm bsetup) # runs an instance of boulder boulder_start: - docker-compose -f $(BOULDER_PATH)/docker-compose.yml -f docker-compose.boulder-temp.yml up -d + docker-compose -f $(BOULDER_PATH)/docker-compose.yml -f $(BOULDER_PATH)/docker-compose.next.yml -f docker-compose.boulder-temp.yml up -d # waits until boulder responds boulder_wait: diff --git a/vendor/modules.txt b/vendor/modules.txt index b4c83218f67..ab6004289a7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -136,7 +136,7 @@ github.com/cespare/xxhash/v2 # github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f ## explicit github.com/dgryski/go-rendezvous -# github.com/eggsampler/acme/v3 v3.6.2-0.20250208073118-0466a0230941 +# github.com/eggsampler/acme/v3 v3.6.2 ## explicit; go 1.11 github.com/eggsampler/acme/v3 # github.com/felixge/httpsnoop v1.0.4