From b06957dbde43aebd203c911c8f6b32ab80ee4097 Mon Sep 17 00:00:00 2001 From: Samantha Date: Fri, 25 Aug 2023 15:46:40 -0400 Subject: [PATCH] ratelimit: Overhaul the way we observe existing rate limits --- ra/ra.go | 216 ++++++++++++++++++++++++--------------- ra/ra_test.go | 10 +- ratelimit/rate-limits.go | 11 ++ 3 files changed, 150 insertions(+), 87 deletions(-) diff --git a/ra/ra.go b/ra/ra.go index 69ebd78c2781..18fc9dd60e76 100644 --- a/ra/ra.go +++ b/ra/ra.go @@ -47,7 +47,7 @@ import ( "github.com/letsencrypt/boulder/probs" pubpb "github.com/letsencrypt/boulder/publisher/proto" rapb "github.com/letsencrypt/boulder/ra/proto" - "github.com/letsencrypt/boulder/ratelimit" + rl "github.com/letsencrypt/boulder/ratelimit" "github.com/letsencrypt/boulder/reloader" "github.com/letsencrypt/boulder/revocation" sapb "github.com/letsencrypt/boulder/sa/proto" @@ -55,6 +55,16 @@ import ( "github.com/letsencrypt/boulder/web" ) +const ( + // allowed is used for rate limit metrics, it's the value of the 'decision' + // label when a request was allowed. + allowed = "allowed" + + // denied is used for rate limit metrics, it's the value of the 'decision' + // label when a request was denied. + denied = "denied" +) + var ( errIncompleteGRPCRequest = errors.New("incomplete gRPC request message") errIncompleteGRPCResponse = errors.New("incomplete gRPC response message") @@ -94,7 +104,7 @@ type RegistrationAuthorityImpl struct { // How long before a newly created authorization expires. authorizationLifetime time.Duration pendingAuthorizationLifetime time.Duration - rlPolicies ratelimit.Limits + rlPolicies rl.Limits maxContactsPerReg int maxNames int orderLifetime time.Duration @@ -108,9 +118,9 @@ type RegistrationAuthorityImpl struct { ctpolicy *ctpolicy.CTPolicy ctpolicyResults *prometheus.HistogramVec - rateLimitCounter *prometheus.CounterVec revocationReasonCounter *prometheus.CounterVec namesPerCert *prometheus.HistogramVec + rlCheckLatency *prometheus.HistogramVec newRegCounter prometheus.Counter recheckCAACounter prometheus.Counter newCertCounter prometheus.Counter @@ -161,11 +171,11 @@ func NewRegistrationAuthorityImpl( ) stats.MustRegister(namesPerCert) - rateLimitCounter := prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: "ra_ratelimits", - Help: "A counter of RA ratelimit checks labelled by type and pass/exceed", - }, []string{"limit", "result"}) - stats.MustRegister(rateLimitCounter) + rlCheckLatency := prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Name: "ratelimitsv1_check_latency_seconds", + Help: fmt.Sprintf("Latency of ratelimit checks labeled by limit=[name] and decision=[%s|%s], in seconds", allowed, denied), + }, []string{"limit", "decision"}) + stats.MustRegister(rlCheckLatency) newRegCounter := prometheus.NewCounter(prometheus.CounterOpts{ Name: "new_registrations", @@ -239,7 +249,7 @@ func NewRegistrationAuthorityImpl( log: logger, authorizationLifetime: authorizationLifetime, pendingAuthorizationLifetime: pendingAuthorizationLifetime, - rlPolicies: ratelimit.New(), + rlPolicies: rl.New(), maxContactsPerReg: maxContactsPerReg, keyPolicy: keyPolicy, maxNames: maxNames, @@ -253,7 +263,7 @@ func NewRegistrationAuthorityImpl( issuersByNameID: issuersByNameID, issuersByID: issuersByID, namesPerCert: namesPerCert, - rateLimitCounter: rateLimitCounter, + rlCheckLatency: rlCheckLatency, newRegCounter: newRegCounter, recheckCAACounter: recheckCAACounter, newCertCounter: newCertCounter, @@ -365,11 +375,7 @@ type registrationCounter func(context.Context, *sapb.CountRegistrationsByIPReque // checkRegistrationIPLimit checks a specific registraton limit by using the // provided registrationCounter function to determine if the limit has been // exceeded for a given IP or IP range -func (ra *RegistrationAuthorityImpl) checkRegistrationIPLimit(ctx context.Context, limit ratelimit.RateLimitPolicy, ip net.IP, counter registrationCounter) error { - if !limit.Enabled() { - return nil - } - +func (ra *RegistrationAuthorityImpl) checkRegistrationIPLimit(ctx context.Context, limit rl.RateLimitPolicy, ip net.IP, counter registrationCounter) error { now := ra.clk.Now() count, err := counter(ctx, &sapb.CountRegistrationsByIPRequest{ Ip: ip, @@ -395,13 +401,19 @@ func (ra *RegistrationAuthorityImpl) checkRegistrationLimits(ctx context.Context // Check the registrations per IP limit using the CountRegistrationsByIP SA // function that matches IP addresses exactly exactRegLimit := ra.rlPolicies.RegistrationsPerIP() - err := ra.checkRegistrationIPLimit(ctx, exactRegLimit, ip, ra.SA.CountRegistrationsByIP) - if err != nil { - ra.rateLimitCounter.WithLabelValues("registrations_by_ip", "exceeded").Inc() - ra.log.Infof("Rate limit exceeded, RegistrationsByIP, IP: %s", ip) - return err + if exactRegLimit.Enabled() { + started := ra.clk.Now() + err := ra.checkRegistrationIPLimit(ctx, exactRegLimit, ip, ra.SA.CountRegistrationsByIP) + elapsed := ra.clk.Since(started) + if err != nil { + if errors.Is(err, berrors.RateLimit) { + ra.rlCheckLatency.WithLabelValues(rl.RegistrationsPerIP, denied).Observe(elapsed.Seconds()) + ra.log.Infof("rate limit RegistrationsPerIP exceeded by IP %q", ip) + } + return err + } + ra.rlCheckLatency.WithLabelValues(rl.RegistrationsPerIP, allowed).Observe(elapsed.Seconds()) } - ra.rateLimitCounter.WithLabelValues("registrations_by_ip", "pass").Inc() // We only apply the fuzzy reg limit to IPv6 addresses. // Per https://golang.org/pkg/net/#IP.To4 "If ip is not an IPv4 address, To4 @@ -414,15 +426,23 @@ func (ra *RegistrationAuthorityImpl) checkRegistrationLimits(ctx context.Context // CountRegistrationsByIPRange SA function that fuzzy-matches IPv6 addresses // within a larger address range fuzzyRegLimit := ra.rlPolicies.RegistrationsPerIPRange() - err = ra.checkRegistrationIPLimit(ctx, fuzzyRegLimit, ip, ra.SA.CountRegistrationsByIPRange) - if err != nil { - ra.rateLimitCounter.WithLabelValues("registrations_by_ip_range", "exceeded").Inc() - ra.log.Infof("Rate limit exceeded, RegistrationsByIPRange, IP: %s", ip) - // For the fuzzyRegLimit we use a new error message that specifically - // mentions that the limit being exceeded is applied to a *range* of IPs - return berrors.RateLimitError(0, "too many registrations for this IP range") + if fuzzyRegLimit.Enabled() { + started := ra.clk.Now() + err := ra.checkRegistrationIPLimit(ctx, fuzzyRegLimit, ip, ra.SA.CountRegistrationsByIPRange) + elapsed := ra.clk.Since(started) + if err != nil { + if errors.Is(err, berrors.RateLimit) { + ra.rlCheckLatency.WithLabelValues(rl.RegistrationsPerIPRange, denied).Observe(elapsed.Seconds()) + ra.log.Infof("rate limit RegistrationsPerIPRange exceeded by IP %q", ip) + + // For the fuzzyRegLimit we use a new error message that specifically + // mentions that the limit being exceeded is applied to a *range* of IPs + return berrors.RateLimitError(0, "too many registrations for this IP range") + } + return err + } + ra.rlCheckLatency.WithLabelValues(rl.RegistrationsPerIPRange, allowed).Observe(elapsed.Seconds()) } - ra.rateLimitCounter.WithLabelValues("registrations_by_ip_range", "pass").Inc() return nil } @@ -555,38 +575,33 @@ func (ra *RegistrationAuthorityImpl) validateContacts(contacts []string) error { return nil } -func (ra *RegistrationAuthorityImpl) checkPendingAuthorizationLimit(ctx context.Context, regID int64) error { - limit := ra.rlPolicies.PendingAuthorizationsPerAccount() - if limit.Enabled() { - // This rate limit's threshold can only be overridden on a per-regID basis, - // not based on any other key. - threshold := limit.GetThreshold("", regID) - if threshold == -1 { - return nil - } - countPB, err := ra.SA.CountPendingAuthorizations2(ctx, &sapb.RegistrationID{ - Id: regID, - }) - if err != nil { - return err - } - if countPB.Count >= threshold { - ra.rateLimitCounter.WithLabelValues("pending_authorizations_by_registration_id", "exceeded").Inc() - ra.log.Infof("Rate limit exceeded, PendingAuthorizationsByRegID, regID: %d", regID) - return berrors.RateLimitError(0, "too many currently pending authorizations: %d", countPB.Count) - } - ra.rateLimitCounter.WithLabelValues("pending_authorizations_by_registration_id", "pass").Inc() +func (ra *RegistrationAuthorityImpl) checkPendingAuthorizationLimit(ctx context.Context, regID int64, limit rl.RateLimitPolicy) error { + // This rate limit's threshold can only be overridden on a per-regID basis, + // not based on any other key. + threshold := limit.GetThreshold("", regID) + if threshold == -1 { + return nil + } + countPB, err := ra.SA.CountPendingAuthorizations2(ctx, &sapb.RegistrationID{ + Id: regID, + }) + if err != nil { + return err + } + if countPB.Count >= threshold { + ra.log.Infof("Rate limit exceeded, PendingAuthorizationsByRegID, regID: %d", regID) + return berrors.RateLimitError(0, "too many currently pending authorizations: %d", countPB.Count) } return nil } // checkInvalidAuthorizationLimits checks the failed validation limit for each // of the provided hostnames. It returns the first error. -func (ra *RegistrationAuthorityImpl) checkInvalidAuthorizationLimits(ctx context.Context, regID int64, hostnames []string) error { +func (ra *RegistrationAuthorityImpl) checkInvalidAuthorizationLimits(ctx context.Context, regID int64, hostnames []string, limits rl.RateLimitPolicy) error { results := make(chan error, len(hostnames)) for _, hostname := range hostnames { go func(hostname string) { - results <- ra.checkInvalidAuthorizationLimit(ctx, regID, hostname) + results <- ra.checkInvalidAuthorizationLimit(ctx, regID, hostname, limits) }(hostname) } // We don't have to wait for all of the goroutines to finish because there's @@ -601,11 +616,7 @@ func (ra *RegistrationAuthorityImpl) checkInvalidAuthorizationLimits(ctx context return nil } -func (ra *RegistrationAuthorityImpl) checkInvalidAuthorizationLimit(ctx context.Context, regID int64, hostname string) error { - limit := ra.rlPolicies.InvalidAuthorizationsPerAccount() - if !limit.Enabled() { - return nil - } +func (ra *RegistrationAuthorityImpl) checkInvalidAuthorizationLimit(ctx context.Context, regID int64, hostname string, limit rl.RateLimitPolicy) error { latest := ra.clk.Now().Add(ra.pendingAuthorizationLifetime) earliest := latest.Add(-limit.Window.Duration) req := &sapb.CountInvalidAuthorizationsRequest{ @@ -633,11 +644,7 @@ func (ra *RegistrationAuthorityImpl) checkInvalidAuthorizationLimit(ctx context. // checkNewOrdersPerAccountLimit enforces the rlPolicies `NewOrdersPerAccount` // rate limit. This rate limit ensures a client can not create more than the // specified threshold of new orders within the specified time window. -func (ra *RegistrationAuthorityImpl) checkNewOrdersPerAccountLimit(ctx context.Context, acctID int64) error { - limit := ra.rlPolicies.NewOrdersPerAccount() - if !limit.Enabled() { - return nil - } +func (ra *RegistrationAuthorityImpl) checkNewOrdersPerAccountLimit(ctx context.Context, acctID int64, limit rl.RateLimitPolicy) error { now := ra.clk.Now() count, err := ra.SA.CountOrders(ctx, &sapb.CountOrdersRequest{ AccountID: acctID, @@ -652,10 +659,8 @@ func (ra *RegistrationAuthorityImpl) checkNewOrdersPerAccountLimit(ctx context.C // There is no meaningful override key to use for this rate limit noKey := "" if count.Count >= limit.GetThreshold(noKey, acctID) { - ra.rateLimitCounter.WithLabelValues("new_order_by_registration_id", "exceeded").Inc() return berrors.RateLimitError(0, "too many new orders recently") } - ra.rateLimitCounter.WithLabelValues("new_order_by_registration_id", "pass").Inc() return nil } @@ -1370,7 +1375,7 @@ func domainsForRateLimiting(names []string) []string { // for each of the names. If the count for any of the names exceeds the limit // for the given registration then the names out of policy are returned to be // used for a rate limit error. -func (ra *RegistrationAuthorityImpl) enforceNameCounts(ctx context.Context, names []string, limit ratelimit.RateLimitPolicy, regID int64) ([]string, time.Time, error) { +func (ra *RegistrationAuthorityImpl) enforceNameCounts(ctx context.Context, names []string, limit rl.RateLimitPolicy, regID int64) ([]string, time.Time, error) { now := ra.clk.Now() req := &sapb.CountCertificatesByNamesRequest{ Names: names, @@ -1401,7 +1406,7 @@ func (ra *RegistrationAuthorityImpl) enforceNameCounts(ctx context.Context, name return badNames, response.Earliest.AsTime(), nil } -func (ra *RegistrationAuthorityImpl) checkCertificatesPerNameLimit(ctx context.Context, names []string, limit ratelimit.RateLimitPolicy, regID int64) error { +func (ra *RegistrationAuthorityImpl) checkCertificatesPerNameLimit(ctx context.Context, names []string, limit rl.RateLimitPolicy, regID int64) error { // check if there is already an existing certificate for // the exact name set we are issuing for. If so bypass the // the certificatesPerName limit. @@ -1410,7 +1415,6 @@ func (ra *RegistrationAuthorityImpl) checkCertificatesPerNameLimit(ctx context.C return fmt.Errorf("checking renewal exemption for %q: %s", names, err) } if exists.Exists { - ra.rateLimitCounter.WithLabelValues("certificates_for_domain", "FQDN set bypass").Inc() return nil } @@ -1428,7 +1432,6 @@ func (ra *RegistrationAuthorityImpl) checkCertificatesPerNameLimit(ctx context.C retryString := earliest.Add(limit.Window.Duration).Format(time.RFC3339) ra.log.Infof("Rate limit exceeded, CertificatesForDomain, regID: %d, domains: %s", regID, strings.Join(namesOutOfLimit, ", ")) - ra.rateLimitCounter.WithLabelValues("certificates_for_domain", "exceeded").Inc() if len(namesOutOfLimit) > 1 { var subErrors []berrors.SubBoulderError for _, name := range namesOutOfLimit { @@ -1441,12 +1444,11 @@ func (ra *RegistrationAuthorityImpl) checkCertificatesPerNameLimit(ctx context.C } return berrors.RateLimitError(retryAfter, "too many certificates already issued for %q. Retry after %s", namesOutOfLimit[0], retryString) } - ra.rateLimitCounter.WithLabelValues("certificates_for_domain", "pass").Inc() return nil } -func (ra *RegistrationAuthorityImpl) checkCertificatesPerFQDNSetLimit(ctx context.Context, names []string, limit ratelimit.RateLimitPolicy, regID int64) error { +func (ra *RegistrationAuthorityImpl) checkCertificatesPerFQDNSetLimit(ctx context.Context, names []string, limit rl.RateLimitPolicy, regID int64) error { names = core.UniqueLowerNames(names) threshold := limit.GetThreshold(strings.Join(names, ","), regID) if threshold <= 0 { @@ -1490,40 +1492,75 @@ func (ra *RegistrationAuthorityImpl) checkCertificatesPerFQDNSetLimit(ctx contex } } -func (ra *RegistrationAuthorityImpl) checkLimits(ctx context.Context, names []string, regID int64) error { - // Check if there is rate limit space for a new order within the current window. - err := ra.checkNewOrdersPerAccountLimit(ctx, regID) - if err != nil { - return err +func (ra *RegistrationAuthorityImpl) checkNewOrderLimits(ctx context.Context, names []string, regID int64) error { + newOrdersPerAccountLimits := ra.rlPolicies.NewOrdersPerAccount() + if newOrdersPerAccountLimits.Enabled() { + started := ra.clk.Now() + err := ra.checkNewOrdersPerAccountLimit(ctx, regID, newOrdersPerAccountLimits) + elapsed := ra.clk.Since(started) + if err != nil { + if errors.Is(err, berrors.RateLimit) { + ra.rlCheckLatency.WithLabelValues(rl.NewOrdersPerAccount, denied).Observe(elapsed.Seconds()) + } + return err + } + ra.rlCheckLatency.WithLabelValues(rl.NewOrdersPerAccount, allowed).Observe(elapsed.Seconds()) } certNameLimits := ra.rlPolicies.CertificatesPerName() if certNameLimits.Enabled() { + started := ra.clk.Now() err := ra.checkCertificatesPerNameLimit(ctx, names, certNameLimits, regID) + elapsed := ra.clk.Since(started) if err != nil { + if errors.Is(err, berrors.RateLimit) { + ra.rlCheckLatency.WithLabelValues(rl.CertificatesPerName, denied).Observe(elapsed.Seconds()) + } return err } + ra.rlCheckLatency.WithLabelValues(rl.CertificatesPerName, allowed).Observe(elapsed.Seconds()) } - fqdnFastLimits := ra.rlPolicies.CertificatesPerFQDNSetFast() - if fqdnFastLimits.Enabled() { - err := ra.checkCertificatesPerFQDNSetLimit(ctx, names, fqdnFastLimits, regID) + fqdnLimitsFast := ra.rlPolicies.CertificatesPerFQDNSetFast() + if fqdnLimitsFast.Enabled() { + started := ra.clk.Now() + err := ra.checkCertificatesPerFQDNSetLimit(ctx, names, fqdnLimitsFast, regID) + elapsed := ra.clk.Since(started) if err != nil { + if errors.Is(err, berrors.RateLimit) { + ra.rlCheckLatency.WithLabelValues(rl.CertificatesPerFQDNSetFast, denied).Observe(elapsed.Seconds()) + } return err } + ra.rlCheckLatency.WithLabelValues(rl.CertificatesPerFQDNSetFast, allowed).Observe(elapsed.Seconds()) } fqdnLimits := ra.rlPolicies.CertificatesPerFQDNSet() if fqdnLimits.Enabled() { + started := ra.clk.Now() err := ra.checkCertificatesPerFQDNSetLimit(ctx, names, fqdnLimits, regID) + elapsed := ra.clk.Since(started) if err != nil { + if errors.Is(err, berrors.RateLimit) { + ra.rlCheckLatency.WithLabelValues(rl.CertificatesPerFQDNSet, denied).Observe(elapsed.Seconds()) + } return err } + ra.rlCheckLatency.WithLabelValues(rl.CertificatesPerFQDNSet, allowed).Observe(elapsed.Seconds()) } - err = ra.checkInvalidAuthorizationLimits(ctx, regID, names) - if err != nil { - return err + invalidAuthzPerAccountLimits := ra.rlPolicies.InvalidAuthorizationsPerAccount() + if invalidAuthzPerAccountLimits.Enabled() { + started := ra.clk.Now() + err := ra.checkInvalidAuthorizationLimits(ctx, regID, names, invalidAuthzPerAccountLimits) + elapsed := ra.clk.Since(started) + if err != nil { + if errors.Is(err, berrors.RateLimit) { + ra.rlCheckLatency.WithLabelValues(rl.InvalidAuthorizationsPerAccount, denied).Observe(elapsed.Seconds()) + } + return err + } + ra.rlCheckLatency.WithLabelValues(rl.InvalidAuthorizationsPerAccount, allowed).Observe(elapsed.Seconds()) } return nil @@ -2373,7 +2410,7 @@ func (ra *RegistrationAuthorityImpl) NewOrder(ctx context.Context, req *rapb.New } // Check if there is rate limit space for issuing a certificate. - err = ra.checkLimits(ctx, newOrder.Names, newOrder.RegistrationID) + err = ra.checkNewOrderLimits(ctx, newOrder.Names, newOrder.RegistrationID) if err != nil { return nil, err } @@ -2451,9 +2488,18 @@ func (ra *RegistrationAuthorityImpl) NewOrder(ctx context.Context, req *rapb.New // If the order isn't fully authorized we need to check that the client has // rate limit room for more pending authorizations if len(missingAuthzNames) > 0 { - err := ra.checkPendingAuthorizationLimit(ctx, newOrder.RegistrationID) - if err != nil { - return nil, err + pendingAuthzLimits := ra.rlPolicies.PendingAuthorizationsPerAccount() + if pendingAuthzLimits.Enabled() { + started := ra.clk.Now() + err := ra.checkPendingAuthorizationLimit(ctx, newOrder.RegistrationID, pendingAuthzLimits) + elapsed := ra.clk.Since(started) + if err != nil { + if errors.Is(err, berrors.RateLimit) { + ra.rlCheckLatency.WithLabelValues(rl.PendingAuthorizationsPerAccount, denied).Observe(elapsed.Seconds()) + } + return nil, err + } + ra.rlCheckLatency.WithLabelValues(rl.PendingAuthorizationsPerAccount, allowed).Observe(elapsed.Seconds()) } } diff --git a/ra/ra_test.go b/ra/ra_test.go index 1ceb6a008e8e..bbeb7f033981 100644 --- a/ra/ra_test.go +++ b/ra/ra_test.go @@ -55,6 +55,7 @@ import ( pubpb "github.com/letsencrypt/boulder/publisher/proto" rapb "github.com/letsencrypt/boulder/ra/proto" "github.com/letsencrypt/boulder/ratelimit" + rl "github.com/letsencrypt/boulder/ratelimit" "github.com/letsencrypt/boulder/sa" sapb "github.com/letsencrypt/boulder/sa/proto" "github.com/letsencrypt/boulder/test" @@ -655,6 +656,7 @@ func TestNewRegistrationRateLimit(t *testing.T) { _, err = ra.NewRegistration(ctx, reg) test.AssertError(t, err, "No error adding duplicate IPv4 registration") test.AssertEquals(t, err.Error(), "too many registrations for this IP: see https://letsencrypt.org/docs/too-many-registrations-for-this-ip/") + test.AssertMetricWithLabelsEquals(t, ra.rlCheckLatency, prometheus.Labels{"limit": rl.RegistrationsPerIP, "decision": denied}, 1) // Create a registration for an IPv6 address reg.Key = newAcctKey(t) @@ -672,6 +674,7 @@ func TestNewRegistrationRateLimit(t *testing.T) { _, err = ra.NewRegistration(ctx, reg) test.AssertError(t, err, "No error adding duplicate IPv6 registration") test.AssertEquals(t, err.Error(), "too many registrations for this IP: see https://letsencrypt.org/docs/too-many-registrations-for-this-ip/") + test.AssertMetricWithLabelsEquals(t, ra.rlCheckLatency, prometheus.Labels{"limit": rl.RegistrationsPerIP, "decision": denied}, 2) // Create a registration for an IPv6 address in the same /48 reg.Key = newAcctKey(t) @@ -691,6 +694,7 @@ func TestNewRegistrationRateLimit(t *testing.T) { _, err = ra.NewRegistration(ctx, reg) test.AssertError(t, err, "No error adding a third IPv6 registration in the same /48") test.AssertEquals(t, err.Error(), "too many registrations for this IP range: see https://letsencrypt.org/docs/rate-limits/") + test.AssertMetricWithLabelsEquals(t, ra.rlCheckLatency, prometheus.Labels{"limit": rl.RegistrationsPerIPRange, "decision": denied}, 1) } type NoUpdateSA struct { @@ -1053,9 +1057,10 @@ func TestAuthzFailedRateLimitingNewOrder(t *testing.T) { } testcase := func() { + limit := ra.rlPolicies.InvalidAuthorizationsPerAccount() ra.SA = &mockInvalidAuthorizationsAuthority{domainWithFailures: "all.i.do.is.lose.com"} err := ra.checkInvalidAuthorizationLimits(ctx, Registration.Id, - []string{"charlie.brown.com", "all.i.do.is.lose.com"}) + []string{"charlie.brown.com", "all.i.do.is.lose.com"}, limit) test.AssertError(t, err, "checkInvalidAuthorizationLimits did not encounter expected rate limit error") test.AssertEquals(t, err.Error(), "too many failed authorizations recently: see https://letsencrypt.org/docs/failed-validation-limit/") } @@ -2162,7 +2167,8 @@ func TestPendingAuthorizationsUnlimited(t *testing.T) { ra.SA = &mockSACountPendingFails{} - err := ra.checkPendingAuthorizationLimit(context.Background(), 13) + limit := ra.rlPolicies.PendingAuthorizationsPerAccount() + err := ra.checkPendingAuthorizationLimit(context.Background(), 13, limit) test.AssertNotError(t, err, "checking pending authorization limit") } diff --git a/ratelimit/rate-limits.go b/ratelimit/rate-limits.go index 422b634ad5ff..223d2a87f95c 100644 --- a/ratelimit/rate-limits.go +++ b/ratelimit/rate-limits.go @@ -8,6 +8,17 @@ import ( "github.com/letsencrypt/boulder/strictyaml" ) +const ( + CertificatesPerName = "certificates_per_domain_per_account" + RegistrationsPerIP = "registrations_per_ip" + RegistrationsPerIPRange = "registrations_per_ipv6_range" + PendingAuthorizationsPerAccount = "pending_authorizations_per_account" + InvalidAuthorizationsPerAccount = "failed_authorizations_per_account" + CertificatesPerFQDNSet = "certificates_per_fqdn_set_per_account" + CertificatesPerFQDNSetFast = "certificates_per_fqdn_set_per_account_fast" + NewOrdersPerAccount = "new_orders_per_account" +) + // Limits is defined to allow mock implementations be provided during unit // testing type Limits interface {