You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: simplify TokenRateLimitPolicy by trusting AuthPolicy validation (#543)
## Simplify TokenRateLimitPolicy by trusting AuthPolicy validation
**Jira**: https://redhat.atlassian.net/browse/RHOAIENG-53680
**jira**: https://redhat.atlassian.net/browse/RHOAIENG-53951
## Description
This PR removes ~80 lines of duplicate subscription validation logic
from the TokenRateLimitPolicy (TRLP) controller. The TRLP now trusts the
validated `auth.identity.selected_subscription` from AuthPolicy instead
of re-implementing membership checks, header validation, and deny rules.
We also now auto-select the subscription by model if the model is
available in only one subscription.
### Problem
The TRLP controller was duplicating validation that AuthPolicy already
performs:
- Checking if users belong to subscriptions (groups/users)
- Validating the `x-maas-subscription` header
- Creating 3+ deny rules per model
### Solution
AuthPolicy already validates subscriptions via
`/v1/subscriptions/select` and injects
`auth.identity.selected_subscription`. TRLP now simply uses this value.
**Before:**
```yaml
limits:
sub-a-model-tokens:
when:
- predicate: auth.identity.groups_str.split(",").exists(g, g == "team-a")
- predicate: request.headers["x-maas-subscription"] == "sub-a" || (!request.headers.exists(...) && !(exclusions...))
deny-not-member-sub-a-model: [...]
deny-unsubscribed-model: [...]
deny-invalid-header-model: [...]
```
**After:**
```yaml
limits:
sub-a-model-tokens:
when:
- predicate: auth.identity.selected_subscription == "sub-a"
```
### Changes
- Removed `buildMembershipCheck` function and validation logic (~80
lines)
- Simplified `subInfo` struct from 6 fields to 3
- Removed all deny rules
- Added 2 unit tests verifying simplified structure
- Updated E2E tests to expect 403 (not 429) for invalid subscriptions
- Enhanced logging with subscription count
**Result:** 75% fewer TRLP limit entries, 32% smaller function, better
error codes (403 vs 429)
## How Has This Been Tested?
### Unit Tests
```bash
cd maas-controller
go test ./pkg/controller/maas -run TestMaaSSubscription -v
```
All 7 tests pass (5 existing + 2 new):
- New: `TestMaaSSubscriptionReconciler_SimplifiedTRLP` - verifies single
predicate, no deny rules
- New: `TestMaaSSubscriptionReconciler_MultipleSubscriptionsSimplified`
- verifies no exclusion logic
### E2E Tests
```bash
cd test/e2e
pytest tests/test_subscription.py -v
```
Updated tests to expect 403 Forbidden (from AuthPolicy) instead of 429
(from TRLP) for subscription validation failures.
### Linter
```bash
golangci-lint run --new-from-rev=HEAD~1
```
No issues.
## Merge criteria:
- [x] The commits are squashed in a cohesive manner and have meaningful
messages.
- [x] Testing instructions have been added in the PR body (for PRs
involving changes that are not immediately obvious).
- [x] The developer has manually tested the changes and verified that
the changes work
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Invalid, missing, or ambiguous subscription validation now returns 403
Forbidden (applied before rate limiting).
* **New Features**
* Explicit model selection in subscription flows with clear
"model_not_in_subscription" responses and per-model isolation for
policies.
* Namespace-scoped subscription isolation to prevent cross-tenant
collisions.
* Simplified per-subscription rate-limit generation relying on
auth-selected subscription keys.
* **Tests**
* Expanded unit and e2e coverage for simplified rate limits,
model-scoped behavior, cross-namespace isolation, 403 expectations, and
transient command retries.
* **Diagnostics**
* Enhanced debug/reporting (test user, subscription→model mappings,
model listings, configuration summary).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
0 commit comments