ratelimit: Overhaul metrics for the our existing rate limits (#7054)

- Use constants for each rate limit name to ensure consistency when
labeling metrics
- Consistently check `.Enabled()` outside of each limit check RA method
- Replace the existing checks counter with a latency histogram

Part of #5545
This commit is contained in:
Samantha 2023-09-11 15:06:16 -04:00 committed by GitHub
parent 7068db96fe
commit 636d30f4a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 173 additions and 81 deletions

193
ra/ra.go
View File

@ -46,6 +46,7 @@ import (
pubpb "github.com/letsencrypt/boulder/publisher/proto"
rapb "github.com/letsencrypt/boulder/ra/proto"
"github.com/letsencrypt/boulder/ratelimit"
"github.com/letsencrypt/boulder/ratelimits"
"github.com/letsencrypt/boulder/reloader"
"github.com/letsencrypt/boulder/revocation"
sapb "github.com/letsencrypt/boulder/sa/proto"
@ -106,9 +107,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
@ -159,11 +160,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", ratelimits.Allowed, ratelimits.Denied),
}, []string{"limit", "decision"})
stats.MustRegister(rlCheckLatency)
newRegCounter := prometheus.NewCounter(prometheus.CounterOpts{
Name: "new_registrations",
@ -251,7 +252,7 @@ func NewRegistrationAuthorityImpl(
issuersByNameID: issuersByNameID,
issuersByID: issuersByID,
namesPerCert: namesPerCert,
rateLimitCounter: rateLimitCounter,
rlCheckLatency: rlCheckLatency,
newRegCounter: newRegCounter,
recheckCAACounter: recheckCAACounter,
newCertCounter: newCertCounter,
@ -364,10 +365,6 @@ type registrationCounter func(context.Context, *sapb.CountRegistrationsByIPReque
// 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
}
now := ra.clk.Now()
count, err := counter(ctx, &sapb.CountRegistrationsByIPRequest{
Ip: ip,
@ -393,13 +390,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(ratelimit.RegistrationsPerIP, ratelimits.Denied).Observe(elapsed.Seconds())
ra.log.Infof("Rate limit exceeded, RegistrationsPerIP, by IP: %q", ip)
}
return err
}
ra.rlCheckLatency.WithLabelValues(ratelimit.RegistrationsPerIP, ratelimits.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
@ -412,15 +415,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(ratelimit.RegistrationsPerIPRange, ratelimits.Denied).Observe(elapsed.Seconds())
ra.log.Infof("Rate limit exceeded, RegistrationsByIPRange, 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(ratelimit.RegistrationsPerIPRange, ratelimits.Allowed).Observe(elapsed.Seconds())
}
ra.rateLimitCounter.WithLabelValues("registrations_by_ip_range", "pass").Inc()
return nil
}
@ -553,38 +564,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 ratelimit.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 ratelimit.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
@ -599,11 +605,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 ratelimit.RateLimitPolicy) error {
latest := ra.clk.Now().Add(ra.pendingAuthorizationLifetime)
earliest := latest.Add(-limit.Window.Duration)
req := &sapb.CountInvalidAuthorizationsRequest{
@ -631,11 +633,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 ratelimit.RateLimitPolicy) error {
now := ra.clk.Now()
count, err := ra.SA.CountOrders(ctx, &sapb.CountOrdersRequest{
AccountID: acctID,
@ -650,10 +648,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
}
@ -1403,7 +1399,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
}
@ -1421,7 +1416,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 {
@ -1434,7 +1428,6 @@ 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
}
@ -1483,40 +1476,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(ratelimit.NewOrdersPerAccount, ratelimits.Denied).Observe(elapsed.Seconds())
}
return err
}
ra.rlCheckLatency.WithLabelValues(ratelimit.NewOrdersPerAccount, ratelimits.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(ratelimit.CertificatesPerName, ratelimits.Denied).Observe(elapsed.Seconds())
}
return err
}
ra.rlCheckLatency.WithLabelValues(ratelimit.CertificatesPerName, ratelimits.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(ratelimit.CertificatesPerFQDNSetFast, ratelimits.Denied).Observe(elapsed.Seconds())
}
return err
}
ra.rlCheckLatency.WithLabelValues(ratelimit.CertificatesPerFQDNSetFast, ratelimits.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(ratelimit.CertificatesPerFQDNSet, ratelimits.Denied).Observe(elapsed.Seconds())
}
return err
}
ra.rlCheckLatency.WithLabelValues(ratelimit.CertificatesPerFQDNSet, ratelimits.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(ratelimit.InvalidAuthorizationsPerAccount, ratelimits.Denied).Observe(elapsed.Seconds())
}
return err
}
ra.rlCheckLatency.WithLabelValues(ratelimit.InvalidAuthorizationsPerAccount, ratelimits.Allowed).Observe(elapsed.Seconds())
}
return nil
@ -2366,7 +2394,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
}
@ -2444,9 +2472,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(ratelimit.PendingAuthorizationsPerAccount, ratelimits.Denied).Observe(elapsed.Seconds())
}
return nil, err
}
ra.rlCheckLatency.WithLabelValues(ratelimit.PendingAuthorizationsPerAccount, ratelimits.Allowed).Observe(elapsed.Seconds())
}
}

View File

@ -55,6 +55,7 @@ import (
pubpb "github.com/letsencrypt/boulder/publisher/proto"
rapb "github.com/letsencrypt/boulder/ra/proto"
"github.com/letsencrypt/boulder/ratelimit"
"github.com/letsencrypt/boulder/ratelimits"
"github.com/letsencrypt/boulder/sa"
sapb "github.com/letsencrypt/boulder/sa/proto"
"github.com/letsencrypt/boulder/test"
@ -230,7 +231,7 @@ var testKeyPolicy = goodkey.KeyPolicy{
var ctx = context.Background()
// dummyRateLimitConfig satisfies the ratelimit.RateLimitConfig interface while
// dummyRateLimitConfig satisfies the rl.RateLimitConfig interface while
// allowing easy mocking of the individual RateLimitPolicy's
type dummyRateLimitConfig struct {
CertificatesPerNamePolicy ratelimit.RateLimitPolicy
@ -641,6 +642,7 @@ func TestNewRegistrationRateLimit(t *testing.T) {
// There should be no errors - it is within the RegistrationsPerIP rate limit
_, err := ra.NewRegistration(ctx, reg)
test.AssertNotError(t, err, "Unexpected error adding new IPv4 registration")
test.AssertMetricWithLabelsEquals(t, ra.rlCheckLatency, prometheus.Labels{"limit": ratelimit.RegistrationsPerIP, "decision": ratelimits.Allowed}, 1)
// Create another registration for the same IPv4 address by changing the key
reg.Key = newAcctKey(t)
@ -650,6 +652,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": ratelimit.RegistrationsPerIP, "decision": ratelimits.Denied}, 1)
// Create a registration for an IPv6 address
reg.Key = newAcctKey(t)
@ -658,6 +661,7 @@ func TestNewRegistrationRateLimit(t *testing.T) {
// There should be no errors - it is within the RegistrationsPerIP rate limit
_, err = ra.NewRegistration(ctx, reg)
test.AssertNotError(t, err, "Unexpected error adding a new IPv6 registration")
test.AssertMetricWithLabelsEquals(t, ra.rlCheckLatency, prometheus.Labels{"limit": ratelimit.RegistrationsPerIP, "decision": ratelimits.Allowed}, 2)
// Create a 2nd registration for the IPv6 address by changing the key
reg.Key = newAcctKey(t)
@ -667,6 +671,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": ratelimit.RegistrationsPerIP, "decision": ratelimits.Denied}, 2)
// Create a registration for an IPv6 address in the same /48
reg.Key = newAcctKey(t)
@ -676,6 +681,7 @@ func TestNewRegistrationRateLimit(t *testing.T) {
// within the RegistrationsPerIPRange limit
_, err = ra.NewRegistration(ctx, reg)
test.AssertNotError(t, err, "Unexpected error adding second IPv6 registration in the same /48")
test.AssertMetricWithLabelsEquals(t, ra.rlCheckLatency, prometheus.Labels{"limit": ratelimit.RegistrationsPerIPRange, "decision": ratelimits.Allowed}, 2)
// Create a registration for yet another IPv6 address in the same /48
reg.Key = newAcctKey(t)
@ -686,6 +692,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": ratelimit.RegistrationsPerIPRange, "decision": ratelimits.Denied}, 1)
}
type NoUpdateSA struct {
@ -1048,9 +1055,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/")
}
@ -2157,7 +2165,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")
}

View File

@ -8,6 +8,42 @@ import (
"github.com/letsencrypt/boulder/strictyaml"
)
const (
// CertificatesPerName is the name of the CertificatesPerName rate limit
// when referenced in metric labels.
CertificatesPerName = "certificates_per_domain_per_account"
// RegistrationsPerIP is the name of the RegistrationsPerIP rate limit when
// referenced in metric labels.
RegistrationsPerIP = "registrations_per_ip"
// RegistrationsPerIPRange is the name of the RegistrationsPerIPRange rate
// limit when referenced in metric labels.
RegistrationsPerIPRange = "registrations_per_ipv6_range"
// PendingAuthorizationsPerAccount is the name of the
// PendingAuthorizationsPerAccount rate limit when referenced in metric
// labels.
PendingAuthorizationsPerAccount = "pending_authorizations_per_account"
// InvalidAuthorizationsPerAccount is the name of the
// InvalidAuthorizationsPerAccount rate limit when referenced in metric
// labels.
InvalidAuthorizationsPerAccount = "failed_authorizations_per_account"
// CertificatesPerFQDNSet is the name of the CertificatesPerFQDNSet rate
// limit when referenced in metric labels.
CertificatesPerFQDNSet = "certificates_per_fqdn_set_per_account"
// CertificatesPerFQDNSetFast is the name of the CertificatesPerFQDNSetFast
// rate limit when referenced in metric labels.
CertificatesPerFQDNSetFast = "certificates_per_fqdn_set_per_account_fast"
// NewOrdersPerAccount is the name of the NewOrdersPerAccount rate limit
// when referenced in metric labels.
NewOrdersPerAccount = "new_orders_per_account"
)
// Limits is defined to allow mock implementations be provided during unit
// testing
type Limits interface {

View File

@ -10,6 +10,16 @@ import (
"github.com/prometheus/client_golang/prometheus"
)
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"
)
// ErrInvalidCost indicates that the cost specified was <= 0.
var ErrInvalidCost = fmt.Errorf("invalid cost, must be > 0")