-
-
Notifications
You must be signed in to change notification settings - Fork 608
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ratelimits: API improvements necessary for batches and limit fixes (#…
…7117) 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.
- Loading branch information
1 parent
d9b97c7
commit ca6314f
Showing
12 changed files
with
332 additions
and
319 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package ratelimits | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
) | ||
|
||
// BucketId should only be created using the New*BucketId functions. It is used | ||
// by the Limiter to look up the bucket and limit overrides for a specific | ||
// subscriber and limit. | ||
type BucketId struct { | ||
// limit is the name of the associated rate limit. It is used for looking up | ||
// default limits. | ||
limit Name | ||
|
||
// bucketKey is the limit Name enum (e.g. "1") concatenated with the | ||
// subscriber identifier specific to the associate limit Name type. | ||
bucketKey string | ||
} | ||
|
||
// NewRegistrationsPerIPAddressBucketId returns a BucketId for the provided IP | ||
// address. | ||
func NewRegistrationsPerIPAddressBucketId(ip net.IP) (BucketId, error) { | ||
id := ip.String() | ||
err := validateIdForName(NewRegistrationsPerIPAddress, id) | ||
if err != nil { | ||
return BucketId{}, err | ||
} | ||
return BucketId{ | ||
limit: NewRegistrationsPerIPAddress, | ||
bucketKey: joinWithColon(NewRegistrationsPerIPAddress.EnumString(), id), | ||
}, nil | ||
} | ||
|
||
// NewRegistrationsPerIPv6RangeBucketId returns a BucketId for the /48 IPv6 | ||
// range containing the provided IPv6 address. | ||
func NewRegistrationsPerIPv6RangeBucketId(ip net.IP) (BucketId, error) { | ||
if ip.To4() != nil { | ||
return BucketId{}, fmt.Errorf("invalid IPv6 address, %q must be an IPv6 address", ip.String()) | ||
} | ||
ipMask := net.CIDRMask(48, 128) | ||
ipNet := &net.IPNet{IP: ip.Mask(ipMask), Mask: ipMask} | ||
id := ipNet.String() | ||
err := validateIdForName(NewRegistrationsPerIPv6Range, id) | ||
if err != nil { | ||
return BucketId{}, err | ||
} | ||
return BucketId{ | ||
limit: NewRegistrationsPerIPv6Range, | ||
bucketKey: joinWithColon(NewRegistrationsPerIPv6Range.EnumString(), id), | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.