Skip to content

Commit 5e385e4

Browse files
authored
ra: clean up countFailedValidations (#7797)
Return an error and do logging in the caller. This adds early returns on a number of error conditions, which can prevent nil pointer dereference in those cases. Also update the description for AutomaticallyPauseZombieClients. Follows up #7763.
1 parent 26a9910 commit 5e385e4

File tree

2 files changed

+18
-23
lines changed

2 files changed

+18
-23
lines changed

features/features.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,8 @@ type Config struct {
103103
InsertAuthzsIndividually bool
104104

105105
// AutomaticallyPauseZombieClients configures the RA to automatically track
106-
// limiter to be the authoritative source of rate limiting information for
107-
// automatically pausing clients who systemically fail every validation
108-
// attempt. When disabled, only manually paused accountID:identifier pairs
109-
// will be rejected.
106+
// and pause issuance for each (account, hostname) pair that repeatedly
107+
// fails validation.
110108
AutomaticallyPauseZombieClients bool
111109

112110
// IncrementRateLimits uses Redis' IncrBy, instead of Set, for rate limit

ra/ra.go

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,42 +1812,33 @@ func (ra *RegistrationAuthorityImpl) recordValidation(ctx context.Context, authI
18121812
return err
18131813
}
18141814

1815-
// countFailedValidation increments the failed authorizations per domain per
1816-
// account rate limit. If the AutomaticallyPauseZombieClients feature has been
1817-
// enabled, it also increments the failed authorizations for pausing per domain
1818-
// per account rate limit. There is no reason to surface errors from this
1819-
// function to the Subscriber, spends against this limit are best effort.
1820-
func (ra *RegistrationAuthorityImpl) countFailedValidation(ctx context.Context, regId int64, ident identifier.ACMEIdentifier) {
1815+
// countFailedValidations increments the FailedAuthorizationsPerDomainPerAccount limit.
1816+
// and the FailedAuthorizationsForPausingPerDomainPerAccountTransaction limit.
1817+
func (ra *RegistrationAuthorityImpl) countFailedValidations(ctx context.Context, regId int64, ident identifier.ACMEIdentifier) error {
18211818
if ra.limiter == nil || ra.txnBuilder == nil {
18221819
// Limiter is disabled.
1823-
return
1820+
return nil
18241821
}
18251822

18261823
txn, err := ra.txnBuilder.FailedAuthorizationsPerDomainPerAccountSpendOnlyTransaction(regId, ident.Value)
18271824
if err != nil {
1828-
ra.log.Warningf("building rate limit transaction for the %s rate limit: %s", ratelimits.FailedAuthorizationsPerDomainPerAccount, err)
1825+
return fmt.Errorf("building rate limit transaction for the %s rate limit: %w", ratelimits.FailedAuthorizationsPerDomainPerAccount, err)
18291826
}
18301827

18311828
_, err = ra.limiter.Spend(ctx, txn)
18321829
if err != nil {
1833-
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
1834-
return
1835-
}
1836-
ra.log.Warningf("spending against the %s rate limit: %s", ratelimits.FailedAuthorizationsPerDomainPerAccount, err)
1830+
return fmt.Errorf("spending against the %s rate limit: %w", ratelimits.FailedAuthorizationsPerDomainPerAccount, err)
18371831
}
18381832

18391833
if features.Get().AutomaticallyPauseZombieClients {
18401834
txn, err = ra.txnBuilder.FailedAuthorizationsForPausingPerDomainPerAccountTransaction(regId, ident.Value)
18411835
if err != nil {
1842-
ra.log.Warningf("building rate limit transaction for the %s rate limit: %s", ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount, err)
1836+
return fmt.Errorf("building rate limit transaction for the %s rate limit: %w", ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount, err)
18431837
}
18441838

18451839
decision, err := ra.limiter.Spend(ctx, txn)
18461840
if err != nil {
1847-
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
1848-
return
1849-
}
1850-
ra.log.Warningf("spending against the %s rate limit: %s", ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount, err)
1841+
return fmt.Errorf("spending against the %s rate limit: %s", ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount, err)
18511842
}
18521843

18531844
if decision.Result(ra.clk.Now()) != nil {
@@ -1861,7 +1852,7 @@ func (ra *RegistrationAuthorityImpl) countFailedValidation(ctx context.Context,
18611852
},
18621853
})
18631854
if err != nil {
1864-
ra.log.Warningf("failed to pause %d/%q: %s", regId, ident.Value, err)
1855+
return fmt.Errorf("failed to pause %d/%q: %w", regId, ident.Value, err)
18651856
}
18661857
ra.pauseCounter.With(prometheus.Labels{
18671858
"paused": strconv.FormatBool(resp.Paused > 0),
@@ -1870,6 +1861,7 @@ func (ra *RegistrationAuthorityImpl) countFailedValidation(ctx context.Context,
18701861
}).Inc()
18711862
}
18721863
}
1864+
return nil
18731865
}
18741866

18751867
// resetAccountPausingLimit resets bucket to maximum capacity for given account.
@@ -2006,7 +1998,12 @@ func (ra *RegistrationAuthorityImpl) PerformValidation(
20061998
if prob != nil {
20071999
challenge.Status = core.StatusInvalid
20082000
challenge.Error = prob
2009-
go ra.countFailedValidation(vaCtx, authz.RegistrationID, authz.Identifier)
2001+
go func() {
2002+
err := ra.countFailedValidations(vaCtx, authz.RegistrationID, authz.Identifier)
2003+
if err != nil {
2004+
ra.log.Warningf("incrementing failed validations: %s", err)
2005+
}
2006+
}()
20102007
} else {
20112008
challenge.Status = core.StatusValid
20122009
if features.Get().AutomaticallyPauseZombieClients {

0 commit comments

Comments
 (0)