Skip to content

Commit

Permalink
Count impending issuance towards utilization.
Browse files Browse the repository at this point in the history
  • Loading branch information
beautifulentropy committed Nov 6, 2023
1 parent 8df76dd commit 85deaa2
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 31 deletions.
46 changes: 22 additions & 24 deletions ra/ra.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,16 +394,15 @@ func (ra *RegistrationAuthorityImpl) checkRegistrationIPLimit(ctx context.Contex
}

threshold, overrideKey := limit.GetThreshold(ip.String(), noRegistrationID)
if count.Count >= threshold {
return berrors.RegistrationsPerIPError(0, "too many registrations for this IP")
}
if overrideKey != "" {
// We do not support overrides for the NewRegistrationsPerIPRange limit.
utilization := float64(count.Count) / float64(threshold)
utilization := float64(count.Count+1) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.RegistrationsPerIP, overrideKey).Set(utilization)
}

if count.Count >= threshold {
return berrors.RegistrationsPerIPError(0, "too many registrations for this IP")
}

return nil
}

Expand Down Expand Up @@ -600,14 +599,14 @@ func (ra *RegistrationAuthorityImpl) checkPendingAuthorizationLimit(ctx context.
if err != nil {
return err
}
if overrideKey != "" {
utilization := float64(countPB.Count) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.PendingAuthorizationsPerAccount, overrideKey).Set(utilization)
}
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)
}
if overrideKey != "" {
utilization := float64(countPB.Count+1) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.PendingAuthorizationsPerAccount, overrideKey).Set(utilization)
}
return nil
}

Expand Down Expand Up @@ -653,14 +652,14 @@ func (ra *RegistrationAuthorityImpl) checkInvalidAuthorizationLimit(ctx context.
// here.
noKey := ""
threshold, overrideKey := limit.GetThreshold(noKey, regID)
if overrideKey != "" {
utilization := float64(count.Count) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.InvalidAuthorizationsPerAccount, overrideKey).Set(utilization)
}
if count.Count >= threshold {
ra.log.Infof("Rate limit exceeded, InvalidAuthorizationsByRegID, regID: %d", regID)
return berrors.FailedValidationError(0, "too many failed authorizations recently")
}
if overrideKey != "" {
utilization := float64(count.Count+1) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.InvalidAuthorizationsPerAccount, overrideKey).Set(utilization)
}
return nil
}

Expand All @@ -684,14 +683,13 @@ func (ra *RegistrationAuthorityImpl) checkNewOrdersPerAccountLimit(ctx context.C
// There is no meaningful override key to use for this rate limit
noKey := ""
threshold, overrideKey := limit.GetThreshold(noKey, acctID)
if overrideKey != "" {
utilization := float64(count.Count) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.NewOrdersPerAccount, overrideKey).Set(utilization)
}

if count.Count >= threshold {
return berrors.RateLimitError(0, "too many new orders recently")
}
if overrideKey != "" {
utilization := float64(count.Count+1) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.NewOrdersPerAccount, overrideKey).Set(utilization)
}
return nil
}

Expand Down Expand Up @@ -1435,7 +1433,8 @@ func (ra *RegistrationAuthorityImpl) enforceNameCounts(ctx context.Context, name
threshold, overrideKey := limit.GetThreshold(name, regID)
if response.Counts[name] >= threshold {
badNames = append(badNames, name)
} else if overrideKey != "" {
}
if overrideKey != "" {
// Name is under threshold due to an override.
utilization := float64(response.Counts[name]+1) / float64(threshold)
metricsData = append(metricsData, struct {
Expand Down Expand Up @@ -1513,13 +1512,12 @@ func (ra *RegistrationAuthorityImpl) checkCertificatesPerFQDNSetLimit(ctx contex
return fmt.Errorf("checking duplicate certificate limit for %q: %s", names, err)
}

if overrideKey != "" {
utilization := float64(len(prevIssuances.TimestampsNS)) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.CertificatesPerFQDNSet, overrideKey).Set(utilization)
}

if int64(len(prevIssuances.TimestampsNS)) < threshold {
// Issuance in window is below the threshold, no need to limit.
if overrideKey != "" {
utilization := float64(len(prevIssuances.TimestampsNS)+1) / float64(threshold)
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.CertificatesPerFQDNSet, overrideKey).Set(utilization)
}
return nil
} else {
// Evaluate the rate limit using a leaky bucket algorithm. The bucket
Expand Down
15 changes: 8 additions & 7 deletions ra/ra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,12 +719,13 @@ func TestRegistrationsPerIPOverrideUsage(t *testing.T) {
}

// No error expected, the count of existing registrations for "4.5.6.7"
// should be 1 below the threshold.
// should be 1 below the override threshold.
err := ra.checkRegistrationIPLimit(ctx, rlp, regIP, mockCounterAlwaysTwo)
test.AssertNotError(t, err, "Unexpected error checking RegistrationsPerIPRange limit")

// Expecting ~66% of the override for "4.5.6.7" to be utilized.
test.AssertMetricWithLabelsEquals(t, ra.rlOverrideUsageGauge, prometheus.Labels{"limit": ratelimit.RegistrationsPerIP, "override_key": regIP.String()}, 0.6666666666666666)
// Accounting for the anticipated issuance, we expect "4.5.6.7" to be at
// 100% of their override threshold.
test.AssertMetricWithLabelsEquals(t, ra.rlOverrideUsageGauge, prometheus.Labels{"limit": ratelimit.RegistrationsPerIP, "override_key": regIP.String()}, 1)

mockCounterAlwaysThree := func(context.Context, *sapb.CountRegistrationsByIPRequest, ...grpc.CallOption) (*sapb.Count, error) {
return &sapb.Count{Count: 3}, nil
Expand Down Expand Up @@ -1226,8 +1227,8 @@ func TestCheckCertificatesPerNameLimit(t *testing.T) {
ra.rlOverrideUsageGauge.WithLabelValues(ratelimit.CertificatesPerName, "bigissuer.com").Set(.5)
err = ra.checkCertificatesPerNameLimit(ctx, []string{"www.example.com", "subdomain.bigissuer.com"}, rlp, 99)
test.AssertNotError(t, err, "incorrectly rate limited bigissuer")
// "bigissuer.com" has an override of 100 and they've issued 50. So we
// expect to see 51% utilization.
// "bigissuer.com" has an override of 100 and they've issued 50. Accounting
// for the anticipated issuance, we expect to see 51% utilization.
test.AssertMetricWithLabelsEquals(t, ra.rlOverrideUsageGauge, prometheus.Labels{"limit": ratelimit.CertificatesPerName, "override_key": "bigissuer.com"}, .51)

// Two base domains, one above its override
Expand All @@ -1237,8 +1238,8 @@ func TestCheckCertificatesPerNameLimit(t *testing.T) {
err = ra.checkCertificatesPerNameLimit(ctx, []string{"www.example.com", "subdomain.bigissuer.com"}, rlp, 99)
test.AssertError(t, err, "incorrectly failed to rate limit bigissuer")
test.AssertErrorIs(t, err, berrors.RateLimit)
// "bigissuer.com" has an override of 100 and they've issued 100. So we
// expect to see 100% utilization.
// "bigissuer.com" has an override of 100 and they've issued 100. They're
// already at 100% utilization, so we expect to see 100% utilization.
test.AssertMetricWithLabelsEquals(t, ra.rlOverrideUsageGauge, prometheus.Labels{"limit": ratelimit.CertificatesPerName, "override_key": "bigissuer.com"}, 1)

// One base domain, above its override (which is below threshold)
Expand Down

0 comments on commit 85deaa2

Please sign in to comment.