Skip to content

Add v1alpha1 api#259

Merged
k8s-ci-robot merged 4 commits into
kubernetes-sigs:mainfrom
LiorLieberman:mcp-and-ext-auth-changes
May 7, 2026
Merged

Add v1alpha1 api#259
k8s-ci-robot merged 4 commits into
kubernetes-sigs:mainfrom
LiorLieberman:mcp-and-ext-auth-changes

Conversation

@LiorLieberman
Copy link
Copy Markdown
Member

What type of PR is this?

What this PR does / why we need it:
Add v1alpha1 API
Move ExternalAuth to top level and add more native mcp support as discussed.
Which issue(s) this PR fixes:

Relates to #255

Does this PR introduce a user-facing change?:

add v1alpha1 api for XAccessPolicy

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 29, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 29, 2026

Deploy Preview for kube-agentic-networking ready!

Name Link
🔨 Latest commit 7b2e1ae
🔍 Latest deploy log https://app.netlify.com/projects/kube-agentic-networking/deploys/69fa6c6c37ad6b0008433a4b
😎 Deploy Preview https://deploy-preview-259--kube-agentic-networking.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Apr 29, 2026
@k8s-ci-robot k8s-ci-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Apr 29, 2026
@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch 4 times, most recently from bdfd3c7 to 2ae1a91 Compare April 29, 2026 18:20
@LiorLieberman LiorLieberman marked this pull request as ready for review April 30, 2026 14:57
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 30, 2026
@haiyanmeng
Copy link
Copy Markdown
Contributor

/retest

Copy link
Copy Markdown
Contributor

@haiyanmeng haiyanmeng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=10
// +listType=atomic
// +kubebuilder:validation:XValidation:rule="self.all(ref, ref.kind == self[0].kind)",message="All targetRefs must have the same Kind"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why

// +kubebuilder:validation:XValidation:rule="self.all(x, (x.group == 'agentic.networking.x-k8s.io' && x.kind == 'XBackend') || (x.group == 'gateway.networking.k8s.io' && x.kind == 'Gateway'))",message="TargetRef must have group agentic.networking.x-k8s.io and kind XBackend, or group gateway.networking.k8s.io and kind Gateway"
is not included in this PR?

If we decide to keep supporting Backend-targeted AccessPolicy in the reference implementation, we should allow the target to be either Gatway or Backend.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think given there is no official support for XBackend, we should leave references to it out of the validation. When the support is official, then it makes sense to add it back in.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Haiyan, as we indicated before, the release is not going to include XBackend in it. Therefore Core support for targeting AccessPolicy is going to be only Gateway. However, we still want to allow room for extensibility for targeting any GVK (one example would be the protoype in this repo which will continue to target v0alpha0 backend) so can not have this validation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we validate the targetRef in control plane?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TargetRef validation would be in each control plane, yes. And if invalid status will be posted.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is about not mixing targetRefs?
So all can be Gateways, or all can be XBackends, but not a mix of both?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. To start simple. I think this came out of a conclusion in extAuth discussion where Backend and Gateway could have been confusing to be together. This may not be required though anymore since we are not releasing this with XBackend support. I still think its smart to include (easier to relax this later)

Comment thread api/v1alpha1/accesspolicy_types.go Outdated
// 1. ExternalAuth runs before all other Allow policies.
// 2. If an ExternalAuth server denies the request, the request is denied.
// 3. If it allows the request, processing continues for all other allow policies for that target.
// 4. The request is allowed only if all allow policies allow it.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#220 proposes that the request is allowed if any allow policy allows it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we can let ExternalAuth deny early. Having it allow early has several concerns.

External Auth servers typically handle global context (like JWTs or tokens), but they don't necessarily anything about local boundaries inside the cluster. There may be cases where we still need our downstream policies (like SPIFFE identity matching or MCP method whitelisting) to validate that workload A is actually authorized to communicate with workload B, after external auth callout.

Hope thats clear

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that proposal is still in discussion? v1alpha1 is getting cut with the current behavior -- it is still alpha and can change.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we can let ExternalAuth deny early. Having it allow early has several concerns.

This is not what #220 proposes. allow policies means inline policies. I am trying to suggest that we define the rules here to address #237.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to ask for some clarification on a user/group scenario with multiple rules having to be allowed, but I think this discussion is moreso about rules across different policies?

Also, we don't have support for groups or spiffe wildcards right now? So that wouldn't be relevant here (which is probably a good motivation for CEL/OIDC)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not what #220 proposes. allow policies means inline policies. I am trying to suggest that we define the rules here to address #237.

We currently propose Allow and ExternalAuth. We dont propose deny in this version given the consensus we got with other folks in the group. This rules are just outlining some guidance on how ExternalAuth and Allow should work across different policies (as @david-martin suggested)

David - right - I would really love to see CEL and OIDC support, hopefully you/gui can pick this up soon and we release it as part of 0.2.

(there is someone thats working on CEL right now, hopefully we incorporate this soon)

Comment thread api/v1alpha1/accesspolicy_types.go Outdated
Comment thread api/v1alpha1/accesspolicy_types.go Outdated
Comment thread api/v1alpha1/accesspolicy_types.go
Comment thread api/v1alpha1/accesspolicy_types.go
Comment thread api/v1alpha1/accesspolicy_types.go
Comment thread api/v1alpha1/accesspolicy_types.go
Comment thread api/v1alpha1/accesspolicy_types.go
@haiyanmeng
Copy link
Copy Markdown
Contributor

pull-kube-agentic-networking-e2e

@LiorLieberman , this seems unexpected. PTAL.

@LiorLieberman
Copy link
Copy Markdown
Member Author

/retest

@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch from 2ae1a91 to 28c18ed Compare May 1, 2026 18:46
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=10
// +listType=atomic
// +kubebuilder:validation:XValidation:rule="self.all(ref, ref.kind == self[0].kind)",message="All targetRefs must have the same Kind"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think given there is no official support for XBackend, we should leave references to it out of the validation. When the support is official, then it makes sense to add it back in.

Comment thread api/v1alpha1/accesspolicy_types.go
Comment thread api/v1alpha1/accesspolicy_types.go
Comment thread api/v1alpha1/accesspolicy_types.go
// 1. ExternalAuth runs before all other Allow policies.
// 2. If an ExternalAuth server denies the request, the request is denied.
// 3. If it allows the request, processing continues for all other allow policies for that target.
// 4. The request is allowed only if all allow policies allow it.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that proposal is still in discussion? v1alpha1 is getting cut with the current behavior -- it is still alpha and can change.

@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch 2 times, most recently from 47b6384 to 1004ea0 Compare May 1, 2026 22:50
@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch from 1004ea0 to d22ba83 Compare May 1, 2026 22:56
@LiorLieberman
Copy link
Copy Markdown
Member Author

@LiorLieberman: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-kube-agentic-networking-e2e dee5b7d link true /test pull-kube-agentic-networking-e2e
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Details

This test is very flaky. This API should not cause this to fail.

I think its is related to @ziyue-101 's last changes with TLS.

@LiorLieberman
Copy link
Copy Markdown
Member Author

/retest

@LiorLieberman LiorLieberman requested a review from bowei May 2, 2026 18:59
@bowei
Copy link
Copy Markdown
Contributor

bowei commented May 4, 2026

/lgtm

But you need to get the tests to pass

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 4, 2026
Comment thread api/v0alpha0/accesspolicy_types.go
Comment thread api/v1alpha1/accesspolicy_types.go Outdated
Comment thread api/v1alpha1/accesspolicy_types.go
Comment thread api/v1alpha1/accesspolicy_types.go
@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch from dee5b7d to 204c206 Compare May 4, 2026 18:52
@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 4, 2026
@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch from 204c206 to 46a4e31 Compare May 4, 2026 18:56
@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch from 46a4e31 to edcc468 Compare May 4, 2026 20:09
Comment thread k8s/crds/agentic.networking.x-k8s.io_xaccesspolicies.yaml Outdated
@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch 2 times, most recently from 7573f1b to 107d717 Compare May 5, 2026 00:08
Copy link
Copy Markdown
Contributor

@david-martin david-martin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some questions so I can better understand the changes from 0 to 1.
In general though, it looks reasonable to me.

/approve

// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=10
// +listType=atomic
// +kubebuilder:validation:XValidation:rule="self.all(ref, ref.kind == self[0].kind)",message="All targetRefs must have the same Kind"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is about not mixing targetRefs?
So all can be Gateways, or all can be XBackends, but not a mix of both?

ActionTypeAllow AccessPolicyActionType = "Allow"

// ActionTypeExternalAuth is used to identify that the request should be delegated to an external auth service if rules match.
ActionTypeExternalAuth AccessPolicyActionType = "ExternalAuth"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a contradiction here?

the request should be delegated to an external auth service if rules match

and

Evaluation logic:
// 1. ExternalAuth runs before all other Allow policies.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that if action: ExternalAuth and any rule (defined under the "rules" field) match - it goes to the externalAuth server for evaluation. If action: Allow and any rule (defined under the "rules" field) match - the evaluation of this is ALLOW.

Regardless of that, Evaluation logic between policies on the same target works in a way that if there is ExternalAuth, it before all other Allow policies. If the ExternalAuth server denies it - request is denied. If it allows it, you still need all other policies to allow it (unless they dont exist).

A concrete example:

action: extAuth
rules:

  • match path /foo
    target: Gateway1

action: Allow
rules:

  • match header bar
    target: Gateway1

If the request is "/foo", ExtAuthServer allows, and header bar is missing -- you still get the request denied.

// matched by this rule. A request originating from a pod associated with
// this Service Account will match the rule.
//
// The Service Account listed here is expected to exist within the same
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by trust domain, do we mean same kubernetes cluster, or same namespace?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its configurable. Often times it would be a cluster identifier, but its not strictly required.
Here is how it could commonly be: spiffe://<trust_domain>/ns/<namespace>/sa/<serviceaccount>

Comment thread api/v1alpha1/accesspolicy_types.go Outdated
Comment thread api/v1alpha1/accesspolicy_types.go
// 1. ExternalAuth runs before all other Allow policies.
// 2. If an ExternalAuth server denies the request, the request is denied.
// 3. If it allows the request, processing continues for all other allow policies for that target.
// 4. The request is allowed only if all allow policies allow it.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to ask for some clarification on a user/group scenario with multiple rules having to be allowed, but I think this discussion is moreso about rules across different policies?

Also, we don't have support for groups or spiffe wildcards right now? So that wouldn't be relevant here (which is probably a good motivation for CEL/OIDC)

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: david-martin, LiorLieberman

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [LiorLieberman,david-martin]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Comment thread Makefile
generate: manifests deepcopy register clientsets ## Generate manifests, deepcopy code, and clientsets.

# TODO: Remove the python post-processing patch once XAccessPolicy v1alpha1 is fully implemented
# and flipped to `served: true` instead of v0alpha0.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a tracking issue for this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Planning to fast follow after I add ref implementation support for the new field structure (i.e moving the support to support the v1alpha1 from v0alpha0)

@david-martin
Copy link
Copy Markdown
Contributor

/hold

pending some q's

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 5, 2026

// spec defines the desired state of AccessPolicy.
// +required
Spec AccessPolicySpec `json:"spec"`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the k8s CRD convention naming would be something like this

	Spec XAccessPolicySpec `json:"spec"`

I wonder why we have two different naming here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. Looks like we have not done this in the Gateway community. I have no strong opinion, but its going to be more nice code wise to not call v1alpha1.XAcessPolicySpec. The X prefix serves primarily the purpose of safe upgrades to standard channel and to explicitly indicate that this is an experimental resource

https://github.com/kubernetes-sigs/gateway-api/blob/main/apisx/v1alpha1/xbackendtrafficpolicy_types.go
https://github.com/kubernetes-sigs/gateway-api/blob/main/apisx/v1alpha1/xmesh_types.go


const (
// ActionTypeAllow is used to identify that the request should be allowed if rules match.
ActionTypeAllow AccessPolicyActionType = "Allow"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be "LocalAuth" when the other Value of Enum is "ExternalAuth"?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that actions, will evolve to add Deny in the future as well. We already got some usecases that suggests deny will be needed.

Then you will have 3 actions. (1) this policy is an ALLOW policy, (2) this policy is a delegate to an external server and (3) this policy is a deny policy (if we ends up adding it in future releases)

//
// Implementations SHOULD return a regular HTTP formatted response if the policy is enforced against non-MCP traffic.
// Implementations MAY return a JSON-RPC formatted response if the policy is enforced against MCP traffic.
// +kubebuilder:validation:XValidation:rule="self.action == 'ExternalAuth' ? has(self.externalAuth) : true",message="externalAuth must be specified when action is set to 'ExternalAuth'"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit confused. When the AccessPolicyActionType is ExternalAuth, does the external server do both the authentication and autherization? If so, does it mean that the AccessRule field is not needed in that case?

Also, how does the external server do Authentication? What identity does the controller use to talk to the external auth sever?

}

// MCPAttributes defines the protocol-specific attributes for MCP authorization.
type MCPAttributes struct {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this imply that the rules are basically based on MCP tool name and parameters?

Copy link
Copy Markdown
Member Author

@LiorLieberman LiorLieberman May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for now yes. The group discussed to add additional support for "Inline" ways to specify other requests attributes like path, headers, etc.

That said, once CEL support is added you will be able to do more granular things with CEL. You would have AuthorizationRuleTypeCEL (in addition to the AuthorizationRuleTypeInline). See this slide for the general idea

@LiorLieberman LiorLieberman force-pushed the mcp-and-ext-auth-changes branch from 107d717 to e87c703 Compare May 5, 2026 21:24
Comment thread Makefile
.PHONY: manifests
manifests: controller-gen ## Generate CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd paths="./api/..." output:crd:artifacts:config=k8s/crds
python3 -c "p='k8s/crds/agentic.networking.x-k8s.io_xaccesspolicies.yaml'; text=open(p).read(); parts=text.split(' - name: v1alpha1'); parts[1]=parts[1].replace(' served: true', ' served: false', 1); open(p,'w').write(' - name: v1alpha1'.join(parts))"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should put this in a hack/script.py. (follow up PR)

@bowei
Copy link
Copy Markdown
Contributor

bowei commented May 6, 2026

/lgtm

Let's get an initial version in and iterate

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 6, 2026
@LiorLieberman
Copy link
Copy Markdown
Member Author

/unhold

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 7, 2026
@k8s-ci-robot k8s-ci-robot merged commit d2507a7 into kubernetes-sigs:main May 7, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants