Resolve authz ConfigMap for VirtualMCPServer#5290
Conversation
There was a problem hiding this comment.
Large PR Detected
This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.
How to unblock this PR:
Add a section to your PR description with the following format:
## Large PR Justification
[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformationAlternative:
Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.
See our Contributing Guidelines for more details.
This review will be automatically dismissed once you add the justification section.
Large PR justification has been provided. Thank you!
|
✅ Large PR justification has been provided. The size review has been dismissed and this PR can now proceed with normal review. |
|
Heads up on dropping The four Cedar fields touched here split into two buckets:
So the second bucket went onto The non-breaking alternative was just leaving
The cost is the schema break: anyone setting |
bf2fafb to
7895464
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #5290 +/- ##
==========================================
+ Coverage 68.39% 68.44% +0.04%
==========================================
Files 619 619
Lines 63318 63396 +78
==========================================
+ Hits 43305 43389 +84
+ Misses 16782 16772 -10
- Partials 3231 3235 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
A `VirtualMCPServer` with `spec.incomingAuth.authzConfig.type: configMap`
silently produced a vmcp `config.yaml` that referenced the unresolved
`configMap` type token. The vmcp binary's `AuthzConfig` validator only
accepts `cedar` or `none`, so the pod crashed in `CrashLoopBackOff` at
startup. Inline authz also silently dropped `GroupClaimName`,
`RoleClaimName`, `GroupEntityType`, and `EntitiesJSON`, so any enterprise
Cedar policy that walked a `Client → ClaimGroup → PlatformRole` hierarchy
denied every request because the runtime Cedar authorizer built
`THVGroup::` parents while the entity store contained `ClaimGroup::`
entities.
Wire the configMap path end-to-end and plumb the four missing fields
through both source paths:
* Extract `LoadAuthzConfigFromConfigMap` as the shared fetch/parse/
validate helper in `controllerutil`; `AddAuthzConfigOptions` now
delegates to it. The vMCP converter calls the same helper so the
failure modes match the `MCPServer`/`MCPRemoteProxy` runner path.
* Extend `pkg/vmcp/config.AuthzConfig` with `EntitiesJSON`,
`GroupClaimName`, `RoleClaimName`, `GroupEntityType`, and forward
all four into `cedar.ConfigOptions` in the Cedar middleware factory.
`EntitiesJSON` defaults to `"[]"` when unset to preserve the
historical Cedar contract.
* Lift `PrimaryUpstreamProvider` from `InlineAuthzConfig` onto
`AuthzConfigRef` and add `GroupClaimName`, `RoleClaimName`, and
`GroupEntityType` there as well, so these source-agnostic fields
work identically for inline and configMap users.
`ExplicitPrimaryUpstreamProvider()` reads from the new location.
For configMap users the parsed payload provides the default and the
spec-level field overrides when set.
* Pre-validate the referenced authz `ConfigMap` in the controller and
distinguish `NotFound` from other parse/validation failures via two
condition reasons on `AuthConfigured`: the existing shared
`AuthzConfigMapNotFound` and a new `AuthzConfigMapInvalid`. This
mirrors the diagnostic `MCPRemoteProxy` emits today and gives users
a status-level error before the converter fails opaquely.
* Validate `ConfigMap`-supplied `PrimaryUpstreamProvider` against the
declared embedded auth server upstreams so an unresolvable provider
is rejected at convert time regardless of source.
CRD compatibility: this is a breaking schema change. The
`spec.incomingAuth.authzConfig.inline.primaryUpstreamProvider` field is
removed; users must set
`spec.incomingAuth.authzConfig.primaryUpstreamProvider` instead.
Existing manifests that set the inline path will be rejected by the
apiserver after upgrade. The new top-level field works for both inline
and configMap users and accepts the same name format as before.
Closes #4919
Closes #5208
Closes #5277
7895464 to
f8c1696
Compare
A
VirtualMCPServerwithspec.incomingAuth.authzConfig.type: configMapsilently produced a vmcpconfig.yamlthat referenced the unresolvedconfigMaptype token. The vmcp binary'sAuthzConfigvalidator only acceptscedarornone, so the pod crashed inCrashLoopBackOffat startup. Inline authz also silently droppedGroupClaimName,RoleClaimName,GroupEntityType, andEntitiesJSON, so any enterprise Cedar policy that walked aClient → ClaimGroup → PlatformRolehierarchy denied every request because the runtime Cedar authorizer builtTHVGroup::parents while the entity store containedClaimGroup::entities.Wire the configMap path end-to-end and plumb the four missing fields through both source paths:
Extract
LoadAuthzConfigFromConfigMapas the shared fetch/parse/ validate helper incontrollerutil;AddAuthzConfigOptionsnow delegates to it. The vMCP converter calls the same helper so the failure modes match theMCPServer/MCPRemoteProxyrunner path.Extend
pkg/vmcp/config.AuthzConfigwithEntitiesJSON,GroupClaimName,RoleClaimName,GroupEntityType, and forward all four intocedar.ConfigOptionsin the Cedar middleware factory.EntitiesJSONdefaults to"[]"when unset to preserve the historical Cedar contract.Lift
PrimaryUpstreamProviderfromInlineAuthzConfigontoAuthzConfigRefand addGroupClaimName,RoleClaimName, andGroupEntityTypethere as well, so these source-agnostic fields work identically for inline and configMap users.ExplicitPrimaryUpstreamProvider()reads from the new location. For configMap users the parsed payload provides the default and the spec-level field overrides when set.Pre-validate the referenced authz
ConfigMapin the controller and distinguishNotFoundfrom other parse/validation failures via two condition reasons onAuthConfigured: the existing sharedAuthzConfigMapNotFoundand a newAuthzConfigMapInvalid. This mirrors the diagnosticMCPRemoteProxyemits today and gives users a status-level error before the converter fails opaquely.Validate
ConfigMap-suppliedPrimaryUpstreamProvideragainst the declared embedded auth server upstreams so an unresolvable provider is rejected at convert time regardless of source.CRD compatibility: this is a breaking schema change. The
spec.incomingAuth.authzConfig.inline.primaryUpstreamProviderfield is removed; users must setspec.incomingAuth.authzConfig.primaryUpstreamProviderinstead. Existing manifests that set the inline path will be rejected by the apiserver after upgrade. The new top-level field works for both inline and configMap users and accepts the same name format as before.Closes #4919
Closes #5208
Closes #5277
Large PR Justification
~950 lines of code are relevant, everything else is auto-generated.