Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ratelimits: API improvements necessary for batches and limit fixes #7117

Merged
merged 8 commits into from
Nov 8, 2023

Conversation

beautifulentropy
Copy link
Member

@beautifulentropy beautifulentropy commented Oct 24, 2023

The Limiter API has been adjusted significantly to both improve both safety and ergonomics and two Limit types have been corrected to match the legacy implementations.

Safety
Previously, the key used for looking up limit overrides and for fetching individual buckets from the key-value store was constructed within the WFE. This posed a risk: if the key was malformed, the default limit would still be enforced, but individual overrides would fail to function properly. This has been addressed by the introduction of a new BucketId type along with a BucketId constructor for each Limit type. Each constructor is responsible for producing a well-formed bucket key which undergoes the very same validation as any potentially matching override key.

Ergonomics
Previously, each of the Limiter methods took a Limit name, a bucket identifier, and a cost to be spent/ refunded. To simplify this, each method now accepts a new Transaction type which provides a cost, and wraps a BucketId identifying the specific bucket.

The two changes above, when taken together, make the implementation of batched rate limit transactions considerably easier, as a batch method can accept a slice of Transaction.

Limit Corrections
PR #6947 added all of the existing rate limits which could be made compatible with the key-value approach. Two of these were improperly implemented;

  • CertificatesPerDomain and CertificatesPerFQDNSet, were implemented as
  • CertificatesPerDomainPerAccount and CertificatesPerFQDNSetPerAccount.

Since we do not actually associate these limits with a particular ACME account, the regID portion of each of their bucket keys has been removed.

@beautifulentropy beautifulentropy requested a review from a team as a code owner October 24, 2023 21:14
@beautifulentropy beautifulentropy marked this pull request as draft October 24, 2023 21:30
@pgporada
Copy link
Member

The test failure is

$ ./t.sh -u -p ./ratelimits -f Test_Limiter_CheckWithLimitOverrides -v
Running Unit Tests
=== RUN   Test_Limiter_CheckWithLimitOverrides
=== PAUSE Test_Limiter_CheckWithLimitOverrides
=== CONT  Test_Limiter_CheckWithLimitOverrides
=== RUN   Test_Limiter_CheckWithLimitOverrides/inmem
cost: 41
rl.Burst: 40
--- FAIL: Test_Limiter_CheckWithLimitOverrides (0.00s)
    --- FAIL: Test_Limiter_CheckWithLimitOverrides/inmem (0.00s)
panic: invalid cost for maybeSpend [recovered]
        panic: invalid cost for maybeSpend

The test that's triggering this states:

			// Attempt to check a spend of 41 requests (a cost > the limit burst
			// capacity), this should fail with a specific error.
			_, err = l.Check(testCtx, overridenBucket.WithCost(41))
			test.AssertErrorIs(t, err, ErrInvalidCostOverLimit)

ErrInvalidCostOverLimit is only defined, not ever returned.

$ grep -r ErrInvalidCostOverLimit
ratelimits/limiter.go:// ErrInvalidCostOverLimit indicates that the cost specified was > limit.Burst.
ratelimits/limiter.go:var ErrInvalidCostOverLimit = fmt.Errorf("invalid cost, must be <= limit.Burst")

I think what you may want is for maybeSpend and maybeRefund to return a (*Decision, err) instead of panic-ing.

@beautifulentropy
Copy link
Member Author

beautifulentropy commented Oct 25, 2023

I think what you may want is for maybeSpend and maybeRefund to return a (*Decision, err) instead of panic-ing.

Thanks, it appears I got a little overzealous when chopping up the larger changeset to produce this PR. This missing clause' have been added back and now an error is returned, as intended.

@beautifulentropy beautifulentropy marked this pull request as ready for review October 25, 2023 16:55
sa/rate_limits_test.go Outdated Show resolved Hide resolved
ratelimits/limiter.go Outdated Show resolved Hide resolved
@beautifulentropy beautifulentropy force-pushed the ratelimits-qol-and-cleanup branch from 52d7bcb to 3ce9716 Compare October 25, 2023 21:13
@beautifulentropy beautifulentropy requested review from pgporada and a team October 25, 2023 21:23
ratelimits/bucket.go Outdated Show resolved Hide resolved
ratelimits/limiter_test.go Outdated Show resolved Hide resolved
ratelimits/limiter.go Outdated Show resolved Hide resolved
ratelimits/limiter.go Outdated Show resolved Hide resolved
@pgporada pgporada requested a review from a team October 26, 2023 17:24
pgporada
pgporada previously approved these changes Oct 27, 2023
@pgporada pgporada requested a review from a team October 27, 2023 16:18
pgporada
pgporada previously approved these changes Oct 27, 2023
@pgporada pgporada requested a review from a team October 27, 2023 16:28
ratelimits/limiter.go Outdated Show resolved Hide resolved
ratelimits/limiter.go Outdated Show resolved Hide resolved
ratelimits/names.go Show resolved Hide resolved
ratelimits/names.go Outdated Show resolved Hide resolved
ratelimits/utilities_test.go Outdated Show resolved Hide resolved
Co-authored-by: Aaron Gable <aaron@letsencrypt.org>
@aarongable aarongable removed this from the Sprint 2023-10-31 milestone Nov 7, 2023
@beautifulentropy beautifulentropy merged commit ca6314f into main Nov 8, 2023
19 checks passed
@beautifulentropy beautifulentropy deleted the ratelimits-qol-and-cleanup branch November 8, 2023 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants