Repository navigation
Keep enclave rate limits from being refilled by a restart, a rename or a stacked rule - #1122
Conversation
…r a stacked rule The enclave's rate limits lived in memory and started full, so a host could restart the enclave to refill every bucket. Buckets now start empty at launch and when a policy is loaded, and refill at their rule's rate from there. Buckets were also keyed by the host-chosen key name alone: one secret imported under two names got two sets of limits, a second rule on a key reused the first rule's capacity, and recording a signature created buckets with fixed capacities that a later check would use. Buckets are now keyed by the key's public key, the window and the rule's maximum. Checking a rule spends nothing; a successful signature is counted once against every rate rule in the policy, including rules its branch skipped, and an empty bucket stays empty rather than going into debt.
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Token bucket behavior keep-enclave/enclave/src/rate_limit.rs |
RateLimiter now stores buckets by window, public key, and maximum. Checks do not consume tokens; recording decrements configured buckets. Buckets refill over time, and policy loads drain existing state. |
Policy rate accounting keep-enclave/enclave/src/policy.rs, docs/ENCLAVE.md |
Policy checks use the signing public key for minute, hour, and day windows. Operation recording collects limits from nested And and Or rules. Documentation describes request counting, refill timing, and restart behavior. |
Signing integration keep-enclave/enclave/src/vsock_server.rs |
Signing handlers resolve the public key before policy checks and use it for destination checks and successful-operation recording. Tests cover key sharing, PSBT request counting, refused requests, policy replacement, and unknown keys. |
Priority:
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Bug fix
Sequence Diagram(s)
sequenceDiagram
participant VsockServer
participant pubkey_for
participant PolicyEngine
participant RateLimiter
VsockServer->>pubkey_for: Resolve signing public key
pubkey_for-->>VsockServer: Return public key or KeyNotFound
VsockServer->>PolicyEngine: Evaluate policy with public key
PolicyEngine->>RateLimiter: Check configured windows
RateLimiter-->>PolicyEngine: Return allowance
PolicyEngine-->>VsockServer: Return policy result
VsockServer->>PolicyEngine: Record successful operation by public key
PolicyEngine->>RateLimiter: Decrement configured buckets
Suggested reviewers: wksantiago
Merge Risk: 
Minimal · up to 67464
-
The documented rate-limit behavior has no identified blocker to merging, subject to normal test checks.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passedFull details: Docstring Coverage
-
Explanation
Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 20 functions across 3 files. (1 skipped: 1 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches: 💡 1
-
📝 Generate docstrings: 💡
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
A rabbit checks the ticking flow
Each public key gets room to grow
The buckets fill as minutes pass
One PSBT counts, though inputs amass
I nibble docs, then hop away
Comment @coderabbitai help to get the list of available commands.
Summary
The Nitro enclave's policy rate limits were in-memory token buckets that started full, so the parent host could restart the enclave to refill every bucket. They were also keyed by the host-chosen key name alone: one secret imported under two names got two sets of limits, a second
MaxPerXrule on a key reused the first rule's capacity, and recording a signature created buckets with fixed capacities that a later check would pick up.handle_signandhandle_sign_psbtrefuse an unknown key name withKeyNotFoundbefore evaluating the policy.&mut self.Cost
Every launch now waits before a key's first signature: a rule allowing
maxper window allows its first signature window/maxafter the policy is loaded, and its full burst a window after.MaxPerHour(10)signs first after six minutes. Documented in docs/ENCLAVE.md, along with the fact that each running enclave keeps its own count.Testing
cargo +1.89.0 test --manifest-path keep-enclave/enclave/Cargo.toml: 95 passed.Orbranch, a refused request, a multi-destination PSBT and unknown key names. A test-only clock skew replaces sleeping.Summary by CodeRabbit