Skip to content

Commit f637c75

Browse files
jrhynessclaude
andcommitted
fix: use has() to check apiKeyValidation existence in CEL expressions
Fix K8s token auth failures by using has() instead of checking .valid before accessing auth.metadata.apiKeyValidation fields. When apiKeyValidation doesn't run (for K8s tokens due to the when clause), accessing .valid throws a CEL error before the ternary can evaluate the fallback path. The issue: K8s tokens were returning empty model lists because cache key CEL expressions failed to evaluate, preventing subscription-info metadata from being called properly. Changes: - All cache keys: has(auth.metadata.apiKeyValidation) instead of .valid == true - subscription-info HTTP body: same has() check - Response headers (X-MaaS-*): same has() check Pattern change: BEFORE: auth.metadata.apiKeyValidation.valid == true ? ...userId : ...username AFTER: has(auth.metadata.apiKeyValidation) ? ...userId : ...username This matches the pattern already used in auth-valid cache key which works correctly for both API keys and K8s tokens. Fixes: E2E test failures for K8s token /v1/models queries - test_explicit_subscription_header - test_user_token_returns_all_models - test_service_account_token_multiple_subs_* Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent b0bcc7a commit f637c75

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

maas-controller/pkg/controller/maas/maasauthpolicy_controller.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,9 @@ func (r *MaaSAuthPolicyReconciler) reconcileModelAuthPolicies(ctx context.Contex
265265
"method": "POST",
266266
"body": map[string]interface{}{
267267
"expression": fmt.Sprintf(`{
268-
"groups": auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups,
269-
"username": auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.username : auth.identity.user.username,
270-
"requestedSubscription": auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.subscription : ("x-maas-subscription" in request.headers ? request.headers["x-maas-subscription"] : ""),
268+
"groups": (has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups,
269+
"username": (has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.username : auth.identity.user.username,
270+
"requestedSubscription": (has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.subscription : ("x-maas-subscription" in request.headers ? request.headers["x-maas-subscription"] : ""),
271271
"requestedModel": "%s/%s"
272272
}`, ref.Namespace, ref.Name),
273273
},
@@ -280,7 +280,7 @@ func (r *MaaSAuthPolicyReconciler) reconcileModelAuthPolicies(ctx context.Contex
280280
// Groups are joined with commas to create a stable string representation.
281281
"cache": map[string]interface{}{
282282
"key": map[string]interface{}{
283-
"selector": fmt.Sprintf(`(auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.userId : auth.identity.user.username) + "|" + (auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups).join(",") + "|" + (auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.subscription : ("x-maas-subscription" in request.headers ? request.headers["x-maas-subscription"] : "")) + "|%s/%s"`, ref.Namespace, ref.Name),
283+
"selector": fmt.Sprintf(`((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.userId : auth.identity.user.username) + "|" + ((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups).join(",") + "|" + ((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.subscription : ("x-maas-subscription" in request.headers ? request.headers["x-maas-subscription"] : "")) + "|%s/%s"`, ref.Namespace, ref.Name),
284284
},
285285
"ttl": r.MetadataCacheTTL,
286286
},
@@ -380,7 +380,7 @@ allow {
380380
// TTL cannot exceed metadata TTL (subscription-valid depends on subscription-info metadata)
381381
"cache": map[string]interface{}{
382382
"key": map[string]interface{}{
383-
"selector": fmt.Sprintf(`(auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.userId : auth.identity.user.username) + "|" + (auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups).join(",") + "|" + (auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.subscription : ("x-maas-subscription" in request.headers ? request.headers["x-maas-subscription"] : "")) + "|%s/%s"`, ref.Namespace, ref.Name),
383+
"selector": fmt.Sprintf(`((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.userId : auth.identity.user.username) + "|" + ((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups).join(",") + "|" + ((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.subscription : ("x-maas-subscription" in request.headers ? request.headers["x-maas-subscription"] : "")) + "|%s/%s"`, ref.Namespace, ref.Name),
384384
},
385385
"ttl": r.authzCacheTTL(),
386386
},
@@ -432,7 +432,7 @@ allow {
432432
// TTL cannot exceed metadata TTL (require-group-membership depends on apiKeyValidation metadata for groups)
433433
"cache": map[string]interface{}{
434434
"key": map[string]interface{}{
435-
"selector": fmt.Sprintf(`(auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.userId : auth.identity.user.username) + "|" + (auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups).join(",") + "|%s/%s"`, ref.Namespace, ref.Name),
435+
"selector": fmt.Sprintf(`((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.userId : auth.identity.user.username) + "|" + ((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups).join(",") + "|%s/%s"`, ref.Namespace, ref.Name),
436436
},
437437
"ttl": r.authzCacheTTL(),
438438
},
@@ -454,23 +454,23 @@ allow {
454454
// Username from API key validation or K8s token identity
455455
"X-MaaS-Username": map[string]interface{}{
456456
"plain": map[string]interface{}{
457-
"expression": `auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.username : auth.identity.user.username`,
457+
"expression": `(has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.username : auth.identity.user.username`,
458458
},
459459
"metrics": false,
460460
"priority": int64(0),
461461
},
462462
// Groups - construct JSON array string from API key validation or K8s identity
463463
"X-MaaS-Group": map[string]interface{}{
464464
"plain": map[string]interface{}{
465-
"expression": `'["' + (auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups).join('","') + '"]'`,
465+
"expression": `'["' + ((has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.groups : auth.identity.user.groups).join('","') + '"]'`,
466466
},
467467
"metrics": false,
468468
"priority": int64(0),
469469
},
470470
// Key ID for tracking (only for API keys)
471471
"X-MaaS-Key-Id": map[string]interface{}{
472472
"plain": map[string]interface{}{
473-
"expression": `auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.keyId : ""`,
473+
"expression": `(has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.keyId : ""`,
474474
},
475475
"metrics": false,
476476
"priority": int64(0),
@@ -479,7 +479,7 @@ allow {
479479
// For K8s tokens, this header is not injected (empty string)
480480
"X-MaaS-Subscription": map[string]interface{}{
481481
"plain": map[string]interface{}{
482-
"expression": `auth.metadata.apiKeyValidation.valid == true ? auth.metadata.apiKeyValidation.subscription : ""`,
482+
"expression": `(has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ? auth.metadata.apiKeyValidation.subscription : ""`,
483483
},
484484
"metrics": false,
485485
"priority": int64(0),

0 commit comments

Comments
 (0)