Skip to content

Commit a46c388

Browse files
authored
va: compute maxRemoteFailures based on MPIC (#7810)
Previously this was a configuration field. Ports `maxAllowedFailures()` from `determineMaxAllowedFailures()` in #7794. Test updates: Remove the `maxRemoteFailures` param from `setup` in all VA tests. Some tests were depending on setting this param directly to provoke failures. For example, `TestMultiVAEarlyReturn` previously relied on "zero allowed failures". Since the number of allowed failures is now 1 for the number of remote VAs we were testing (2), the VA wasn't returning early with an error; it was succeeding! To fix that, make sure there are two failures. Since two failures from two RVAs wouldn't exercise the right situation, add a third RVA, so we get two failures from three RVAs. Similarly, TestMultiCAARechecking had several test cases that omitted this field, effectively setting it to zero allowed failures. I updated the "1 RVA failure" test case to expect overall success and added a "2 RVA failures" test case to expect overall failure (we previously expected overall failure from a single RVA failing). In TestMultiVA I had to change a test for `len(lines) != 1` to `len(lines) == 0`, because with more backends we were now logging more errors, and finding e.g. `len(lines)` to be 2.
1 parent 20fdcbc commit a46c388

File tree

11 files changed

+273
-137
lines changed

11 files changed

+273
-137
lines changed

cmd/boulder-va/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ import (
1818
type Config struct {
1919
VA struct {
2020
vaConfig.Common
21-
RemoteVAs []cmd.GRPCClientConfig `validate:"omitempty,dive"`
22-
MaxRemoteValidationFailures int `validate:"omitempty,min=0,required_with=RemoteVAs"`
21+
RemoteVAs []cmd.GRPCClientConfig `validate:"omitempty,dive"`
22+
// Deprecated and ignored
23+
MaxRemoteValidationFailures int `validate:"omitempty,min=0,required_with=RemoteVAs"`
2324
Features features.Config
2425
}
2526

@@ -109,7 +110,6 @@ func main() {
109110
vai, err := va.NewValidationAuthorityImpl(
110111
resolver,
111112
remotes,
112-
c.VA.MaxRemoteValidationFailures,
113113
c.VA.UserAgent,
114114
c.VA.IssuerDomain,
115115
scope,

cmd/remoteva/main.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ func main() {
135135
vai, err := va.NewValidationAuthorityImpl(
136136
resolver,
137137
nil, // Our RVAs will never have RVAs of their own.
138-
0, // Only the VA is concerned with max validation failures
139138
c.RVA.UserAgent,
140139
c.RVA.IssuerDomain,
141140
scope,

docs/multi-va.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ and
3838
as their config files.
3939

4040
We require that almost all remote validation requests succeed; the exact number
41-
is controlled by the VA's `maxRemoteFailures` config variable. If the number of
41+
is controlled by the VA based on the thresholds required by MPIC. If the number of
4242
failing remote VAs exceeds that threshold, validation is terminated. If the
4343
number of successful remote VAs is high enough that it would be impossible for
4444
the outstanding remote VAs to exceed that threshold, validation immediately

features/features.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ type Config struct {
5353

5454
// MultiCAAFullResults will cause the main VA to block and wait for all of
5555
// the remote VA CAA recheck results instead of returning early if the
56-
// number of failures is greater than the configured
57-
// maxRemoteValidationFailures. Only used when EnforceMultiCAA is true.
56+
// number of failures is greater than the number allowed by MPIC.
57+
// Only used when EnforceMultiCAA is true.
5858
MultiCAAFullResults bool
5959

6060
// MultipleCertificateProfiles, when enabled, triggers the following

test/config-next/va.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
"hostOverride": "rva1.boulder"
5555
}
5656
],
57-
"maxRemoteValidationFailures": 1,
5857
"accountURIPrefixes": [
5958
"http://boulder.service.consul:4000/acme/reg/",
6059
"http://boulder.service.consul:4001/acme/acct/"

va/caa_test.go

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func (mock caaMockDNS) LookupCAA(_ context.Context, domain string) ([]*dns.CAA,
191191
}
192192

193193
func TestCAATimeout(t *testing.T) {
194-
va, _ := setup(nil, 0, "", nil, caaMockDNS{})
194+
va, _ := setup(nil, "", nil, caaMockDNS{})
195195

196196
params := &caaParams{
197197
accountURIID: 12345,
@@ -408,7 +408,7 @@ func TestCAAChecking(t *testing.T) {
408408
method := core.ChallengeTypeHTTP01
409409
params := &caaParams{accountURIID: accountURIID, validationMethod: method}
410410

411-
va, _ := setup(nil, 0, "", nil, caaMockDNS{})
411+
va, _ := setup(nil, "", nil, caaMockDNS{})
412412
va.accountURIPrefixes = []string{"https://letsencrypt.org/acct/reg/"}
413413

414414
for _, caaTest := range testCases {
@@ -431,7 +431,7 @@ func TestCAAChecking(t *testing.T) {
431431
}
432432

433433
func TestCAALogging(t *testing.T) {
434-
va, _ := setup(nil, 0, "", nil, caaMockDNS{})
434+
va, _ := setup(nil, "", nil, caaMockDNS{})
435435

436436
testCases := []struct {
437437
Name string
@@ -521,7 +521,7 @@ func TestCAALogging(t *testing.T) {
521521
// TestIsCAAValidErrMessage tests that an error result from `va.IsCAAValid`
522522
// includes the domain name that was being checked in the failure detail.
523523
func TestIsCAAValidErrMessage(t *testing.T) {
524-
va, _ := setup(nil, 0, "", nil, caaMockDNS{})
524+
va, _ := setup(nil, "", nil, caaMockDNS{})
525525

526526
// Call IsCAAValid with a domain we know fails with a generic error from the
527527
// caaMockDNS.
@@ -546,7 +546,7 @@ func TestIsCAAValidErrMessage(t *testing.T) {
546546
// which do not have the necessary parameters to do CAA Account and Method
547547
// Binding checks.
548548
func TestIsCAAValidParams(t *testing.T) {
549-
va, _ := setup(nil, 0, "", nil, caaMockDNS{})
549+
va, _ := setup(nil, "", nil, caaMockDNS{})
550550

551551
// Calling IsCAAValid without a ValidationMethod should fail.
552552
_, err := va.IsCAAValid(ctx, &vapb.IsCAAValidRequest{
@@ -592,7 +592,7 @@ func (b caaBrokenDNS) LookupCAA(_ context.Context, domain string) ([]*dns.CAA, s
592592
func TestDisabledMultiCAARechecking(t *testing.T) {
593593
brokenRVA := setupRemote(nil, "broken", caaBrokenDNS{}, "", "")
594594
remoteVAs := []RemoteVA{{brokenRVA, "broken"}}
595-
va, _ := setup(nil, 0, "local", remoteVAs, nil)
595+
va, _ := setup(nil, "local", remoteVAs, nil)
596596

597597
features.Set(features.Config{
598598
EnforceMultiCAA: false,
@@ -671,7 +671,6 @@ func TestMultiCAARechecking(t *testing.T) {
671671

672672
testCases := []struct {
673673
name string
674-
maxLookupFailures int
675674
domains string
676675
remoteVAs []RemoteVA
677676
expectedProbSubstring string
@@ -719,13 +718,31 @@ func TestMultiCAARechecking(t *testing.T) {
719718
{
720719
name: "functional localVA, 1 broken RVA, no CAA records",
721720
domains: "present-dns-only.com",
721+
localDNSClient: caaMockDNS{},
722+
expectedDiffLogSubstring: `RemoteSuccesses":2,"RemoteFailures":[{"VAHostname":"broken","Problem":{"type":"dns","detail":"While processing CAA for`,
723+
remoteVAs: []RemoteVA{
724+
{brokenVA, brokenUA},
725+
{remoteVA, remoteUA},
726+
{remoteVA, remoteUA},
727+
},
728+
expectedLabels: prometheus.Labels{
729+
"operation": opCAA,
730+
"perspective": allPerspectives,
731+
"challenge_type": string(core.ChallengeTypeDNS01),
732+
"problem_type": "",
733+
"result": pass,
734+
},
735+
},
736+
{
737+
name: "functional localVA, 2 broken RVAs, no CAA records",
738+
domains: "present-dns-only.com",
722739
expectedProbSubstring: "During secondary CAA checking: While processing CAA",
723740
expectedProbType: probs.DNSProblem,
724-
expectedDiffLogSubstring: `RemoteSuccesses":2,"RemoteFailures":[{"VAHostname":"broken","Problem":{"type":"dns","detail":"While processing CAA for`,
741+
expectedDiffLogSubstring: `RemoteSuccesses":1,"RemoteFailures":[{"VAHostname":"broken","Problem":{"type":"dns","detail":"While processing CAA for`,
725742
localDNSClient: caaMockDNS{},
726743
remoteVAs: []RemoteVA{
727744
{brokenVA, brokenUA},
728-
{remoteVA, remoteUA},
745+
{brokenVA, brokenUA},
729746
{remoteVA, remoteUA},
730747
},
731748
expectedLabels: prometheus.Labels{
@@ -776,15 +793,33 @@ func TestMultiCAARechecking(t *testing.T) {
776793
{
777794
name: "functional localVA, 1 broken RVA, CAA issue type present",
778795
domains: "present.com",
779-
expectedProbSubstring: "During secondary CAA checking: While processing CAA",
780-
expectedProbType: probs.DNSProblem,
781796
expectedDiffLogSubstring: `RemoteSuccesses":2,"RemoteFailures":[{"VAHostname":"broken","Problem":{"type":"dns","detail":"While processing CAA for`,
782797
localDNSClient: caaMockDNS{},
783798
remoteVAs: []RemoteVA{
784799
{brokenVA, brokenUA},
785800
{remoteVA, remoteUA},
786801
{remoteVA, remoteUA},
787802
},
803+
expectedLabels: prometheus.Labels{
804+
"operation": opCAA,
805+
"perspective": allPerspectives,
806+
"challenge_type": string(core.ChallengeTypeDNS01),
807+
"problem_type": "",
808+
"result": pass,
809+
},
810+
},
811+
{
812+
name: "functional localVA, 2 broken RVA, CAA issue type present",
813+
domains: "present.com",
814+
expectedProbSubstring: "During secondary CAA checking: While processing CAA",
815+
expectedProbType: probs.DNSProblem,
816+
expectedDiffLogSubstring: `RemoteSuccesses":1,"RemoteFailures":[{"VAHostname":"broken","Problem":{"type":"dns","detail":"While processing CAA for`,
817+
localDNSClient: caaMockDNS{},
818+
remoteVAs: []RemoteVA{
819+
{brokenVA, brokenUA},
820+
{brokenVA, brokenUA},
821+
{remoteVA, remoteUA},
822+
},
788823
expectedLabels: prometheus.Labels{
789824
"operation": opCAA,
790825
"perspective": allPerspectives,
@@ -831,8 +866,6 @@ func TestMultiCAARechecking(t *testing.T) {
831866
{
832867
name: "1 hijacked RVA, CAA issue type present",
833868
domains: "present.com",
834-
expectedProbSubstring: "CAA record for present.com prevents issuance",
835-
expectedProbType: probs.CAAProblem,
836869
expectedDiffLogSubstring: `RemoteSuccesses":2,"RemoteFailures":[{"VAHostname":"hijacked","Problem":{"type":"caa","detail":"While processing CAA for`,
837870
localDNSClient: caaMockDNS{},
838871
remoteVAs: []RemoteVA{
@@ -870,8 +903,6 @@ func TestMultiCAARechecking(t *testing.T) {
870903
{
871904
name: "1 hijacked RVA, CAA issuewild type present",
872905
domains: "satisfiable-wildcard.com",
873-
expectedProbSubstring: "During secondary CAA checking: While processing CAA",
874-
expectedProbType: probs.CAAProblem,
875906
expectedDiffLogSubstring: `RemoteSuccesses":2,"RemoteFailures":[{"VAHostname":"hijacked","Problem":{"type":"caa","detail":"While processing CAA for`,
876907
localDNSClient: caaMockDNS{},
877908
remoteVAs: []RemoteVA{
@@ -907,9 +938,8 @@ func TestMultiCAARechecking(t *testing.T) {
907938
},
908939
},
909940
{
910-
name: "1 hijacked RVA, CAA issuewild type present, 1 failure allowed",
941+
name: "1 hijacked RVA, CAA issuewild type present",
911942
domains: "satisfiable-wildcard.com",
912-
maxLookupFailures: 1,
913943
expectedDiffLogSubstring: `RemoteSuccesses":2,"RemoteFailures":[{"VAHostname":"hijacked","Problem":{"type":"caa","detail":"While processing CAA for`,
914944
localDNSClient: caaMockDNS{},
915945
remoteVAs: []RemoteVA{
@@ -919,9 +949,8 @@ func TestMultiCAARechecking(t *testing.T) {
919949
},
920950
},
921951
{
922-
name: "2 hijacked RVAs, CAA issuewild type present, 1 failure allowed",
952+
name: "2 hijacked RVAs, CAA issuewild type present",
923953
domains: "satisfiable-wildcard.com",
924-
maxLookupFailures: 1,
925954
expectedProbSubstring: "During secondary CAA checking: While processing CAA",
926955
expectedProbType: probs.CAAProblem,
927956
expectedDiffLogSubstring: `RemoteSuccesses":1,"RemoteFailures":[{"VAHostname":"hijacked","Problem":{"type":"caa","detail":"While processing CAA for`,
@@ -933,9 +962,8 @@ func TestMultiCAARechecking(t *testing.T) {
933962
},
934963
},
935964
{
936-
name: "3 hijacked RVAs, CAA issuewild type present, 1 failure allowed",
965+
name: "3 hijacked RVAs, CAA issuewild type present",
937966
domains: "satisfiable-wildcard.com",
938-
maxLookupFailures: 1,
939967
expectedProbSubstring: "During secondary CAA checking: While processing CAA",
940968
expectedProbType: probs.CAAProblem,
941969
expectedDiffLogSubstring: `RemoteSuccesses":0,"RemoteFailures":[{"VAHostname":"hijacked","Problem":{"type":"caa","detail":"While processing CAA for`,
@@ -950,7 +978,7 @@ func TestMultiCAARechecking(t *testing.T) {
950978

951979
for _, tc := range testCases {
952980
t.Run(tc.name, func(t *testing.T) {
953-
va, mockLog := setup(nil, tc.maxLookupFailures, localUA, tc.remoteVAs, tc.localDNSClient)
981+
va, mockLog := setup(nil, localUA, tc.remoteVAs, tc.localDNSClient)
954982
defer mockLog.Clear()
955983

956984
// MultiCAAFullResults: false is inherently flaky because of the
@@ -971,12 +999,14 @@ func TestMultiCAARechecking(t *testing.T) {
971999
test.AssertNotError(t, err, "Should not have errored, but did")
9721000

9731001
if tc.expectedProbSubstring != "" {
1002+
test.AssertNotNil(t, isValidRes.Problem, "IsCAAValidRequest returned nil problem, but should not have")
9741003
test.AssertContains(t, isValidRes.Problem.Detail, tc.expectedProbSubstring)
9751004
} else if isValidRes.Problem != nil {
9761005
test.AssertBoxedNil(t, isValidRes.Problem, "IsCAAValidRequest returned a problem, but should not have")
9771006
}
9781007

9791008
if tc.expectedProbType != "" {
1009+
test.AssertNotNil(t, isValidRes.Problem, "IsCAAValidRequest returned nil problem, but should not have")
9801010
test.AssertEquals(t, string(tc.expectedProbType), isValidRes.Problem.ProblemType)
9811011
}
9821012

@@ -1017,7 +1047,7 @@ func TestCAAFailure(t *testing.T) {
10171047
hs := httpSrv(t, expectedToken)
10181048
defer hs.Close()
10191049

1020-
va, _ := setup(hs, 0, "", nil, caaMockDNS{})
1050+
va, _ := setup(hs, "", nil, caaMockDNS{})
10211051

10221052
err := va.checkCAA(ctx, dnsi("reserved.com"), &caaParams{1, core.ChallengeTypeHTTP01})
10231053
if err == nil {

va/dns_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
)
2020

2121
func TestDNSValidationEmpty(t *testing.T) {
22-
va, _ := setup(nil, 0, "", nil, nil)
22+
va, _ := setup(nil, "", nil, nil)
2323

2424
// This test calls PerformValidation directly, because that is where the
2525
// metrics checked below are incremented.
@@ -38,7 +38,7 @@ func TestDNSValidationEmpty(t *testing.T) {
3838
}
3939

4040
func TestDNSValidationWrong(t *testing.T) {
41-
va, _ := setup(nil, 0, "", nil, nil)
41+
va, _ := setup(nil, "", nil, nil)
4242
_, err := va.validateDNS01(context.Background(), dnsi("wrong-dns01.com"), expectedKeyAuthorization)
4343
if err == nil {
4444
t.Fatalf("Successful DNS validation with wrong TXT record")
@@ -48,7 +48,7 @@ func TestDNSValidationWrong(t *testing.T) {
4848
}
4949

5050
func TestDNSValidationWrongMany(t *testing.T) {
51-
va, _ := setup(nil, 0, "", nil, nil)
51+
va, _ := setup(nil, "", nil, nil)
5252

5353
_, err := va.validateDNS01(context.Background(), dnsi("wrong-many-dns01.com"), expectedKeyAuthorization)
5454
if err == nil {
@@ -59,7 +59,7 @@ func TestDNSValidationWrongMany(t *testing.T) {
5959
}
6060

6161
func TestDNSValidationWrongLong(t *testing.T) {
62-
va, _ := setup(nil, 0, "", nil, nil)
62+
va, _ := setup(nil, "", nil, nil)
6363

6464
_, err := va.validateDNS01(context.Background(), dnsi("long-dns01.com"), expectedKeyAuthorization)
6565
if err == nil {
@@ -70,7 +70,7 @@ func TestDNSValidationWrongLong(t *testing.T) {
7070
}
7171

7272
func TestDNSValidationFailure(t *testing.T) {
73-
va, _ := setup(nil, 0, "", nil, nil)
73+
va, _ := setup(nil, "", nil, nil)
7474

7575
_, err := va.validateDNS01(ctx, dnsi("localhost"), expectedKeyAuthorization)
7676
prob := detailedError(err)
@@ -84,7 +84,7 @@ func TestDNSValidationInvalid(t *testing.T) {
8484
Value: "790DB180-A274-47A4-855F-31C428CB1072",
8585
}
8686

87-
va, _ := setup(nil, 0, "", nil, nil)
87+
va, _ := setup(nil, "", nil, nil)
8888

8989
_, err := va.validateDNS01(ctx, notDNS, expectedKeyAuthorization)
9090
prob := detailedError(err)
@@ -93,7 +93,7 @@ func TestDNSValidationInvalid(t *testing.T) {
9393
}
9494

9595
func TestDNSValidationServFail(t *testing.T) {
96-
va, _ := setup(nil, 0, "", nil, nil)
96+
va, _ := setup(nil, "", nil, nil)
9797

9898
_, err := va.validateDNS01(ctx, dnsi("servfail.com"), expectedKeyAuthorization)
9999

@@ -102,7 +102,7 @@ func TestDNSValidationServFail(t *testing.T) {
102102
}
103103

104104
func TestDNSValidationNoServer(t *testing.T) {
105-
va, log := setup(nil, 0, "", nil, nil)
105+
va, log := setup(nil, "", nil, nil)
106106
staticProvider, err := bdns.NewStaticProvider([]string{})
107107
test.AssertNotError(t, err, "Couldn't make new static provider")
108108

@@ -121,15 +121,15 @@ func TestDNSValidationNoServer(t *testing.T) {
121121
}
122122

123123
func TestDNSValidationOK(t *testing.T) {
124-
va, _ := setup(nil, 0, "", nil, nil)
124+
va, _ := setup(nil, "", nil, nil)
125125

126126
_, prob := va.validateDNS01(ctx, dnsi("good-dns01.com"), expectedKeyAuthorization)
127127

128128
test.Assert(t, prob == nil, "Should be valid.")
129129
}
130130

131131
func TestDNSValidationNoAuthorityOK(t *testing.T) {
132-
va, _ := setup(nil, 0, "", nil, nil)
132+
va, _ := setup(nil, "", nil, nil)
133133

134134
_, prob := va.validateDNS01(ctx, dnsi("no-authority-dns01.com"), expectedKeyAuthorization)
135135

0 commit comments

Comments
 (0)