feat: Support for Gateway-level Access Policies and Multi-level Enforcement#127
feat: Support for Gateway-level Access Policies and Multi-level Enforcement#127chuangw6 wants to merge 3 commits intokubernetes-sigs:mainfrom
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: chuangw6 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
Hi @chuangw6. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Tip We noticed you've done this a few times! Consider joining the org to skip this step and gain Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
✅ Deploy Preview for kube-agentic-networking ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
/ok-to-test |
3f84403 to
e9161f2
Compare
|
/cc @guicassolato |
|
Lots of conflicts with #83 😞 |
@guicassolato , can you elaborate more regarding the conflicts? Are the conflicts reconcilable? |
They sure can be reconciled. It's just a lot of rework due to both PRs touching the same sections in parallel, somewhat heavily. We could probably have coordinated these two changes better IMO. |
Thanks for the explanation. If the conflicts can be reconciled, we should merge #83 first. Then we can work with @chuangw6 to make sure this PR still works. |
|
/hold Let us merge #83 first. |
b0cd4e2 to
1cf4699
Compare
7288765 to
7f9c627
Compare
|
Thanks for the great work and multiple rounds of labor-intensive rebase effort, @chuangw6 . /lgtm |
|
/lgtm |
Thanks @haiyanmeng. Regarding the ext auth discussion above, this feels out of scope for the current PR, and seems like a great candidate for a follow-up issue. I'd like to move forward with this PR to avoid further merge conflicts. @guicassolato , does that sound reasonable to you? |
api/v0alpha0/accesspolicy_types.go
Outdated
| PolicyConditionAccepted gwapiv1.PolicyConditionType = "Accepted" | ||
|
|
||
| // PolicyReasonExceededLimit indicates that the policy was rejected because the maximum number of policies per target was exceeded. | ||
| PolicyReasonExceededLimit gwapiv1.PolicyConditionReason = "ExceededLimit" |
There was a problem hiding this comment.
nit: Would something more verbal be better here? I.e PolicyLimitExceeded or PolicyLimitPerTargetExceeded?
There was a problem hiding this comment.
Renamed to PolicyLimitPerTargetExceeded
|
|
||
| // Initial check for policy limit per target. | ||
| if !c.isPolicyUnderTargetLimit(context.Background(), policy) { | ||
| return |
There was a problem hiding this comment.
isPolicyUnderTargetLimit already logs the details
pkg/controller/accesspolicy.go
Outdated
| specChanged := newPolicy.Generation != oldPolicy.Generation || !reflect.DeepEqual(newPolicy.Annotations, oldPolicy.Annotations) | ||
| deletionTimestampChanged := newPolicy.DeletionTimestamp != oldPolicy.DeletionTimestamp | ||
| acceptanceChanged := newPolicy.IsAccepted() != oldPolicy.IsAccepted() | ||
|
|
||
| if specChanged || deletionTimestampChanged || acceptanceChanged { |
There was a problem hiding this comment.
would highly benefit from a helper function
pkg/controller/accesspolicy.go
Outdated
| acceptanceChanged := newPolicy.IsAccepted() != oldPolicy.IsAccepted() | ||
|
|
||
| if specChanged || deletionTimestampChanged || acceptanceChanged { | ||
| klog.V(4).InfoS("Updating AccessPolicy", "accesspolicy", klog.KObj(oldPolicy), "specChanged", specChanged, "acceptanceChanged", acceptanceChanged) |
There was a problem hiding this comment.
this just prints true/false for spec Changed and acceptance Change etc, is this useful?
There was a problem hiding this comment.
Updated, but logging Updating AccessPolicy is still helpful imo to show it's reconciled and align with other onAccessPolicyxxx. lmk otherwise
| // If targets changed, we must re-evaluate the limit as it's equivalent to an 'Add' for the new target. | ||
| if !reflect.DeepEqual(oldPolicy.Spec.TargetRefs, newPolicy.Spec.TargetRefs) { | ||
| if !c.isPolicyUnderTargetLimit(context.Background(), newPolicy) { | ||
| return |
There was a problem hiding this comment.
isPolicyUnderTargetLimit already logs the details
| // It's deny-by-default (a.k.a ALLOW action), we explicitly allow necessary | ||
| // MCP operations for all backends. These policies are essential for MCP |
There was a problem hiding this comment.
are we allowing or denying traffic by default? (assuming no policy exist)
There was a problem hiding this comment.
- If no policy exists for the target, it's allow-by-default.
- If a policy exists for the target but tool list is empty, it denies all tool access.
See unit tests.
| allAccessPolicies, err := accessPolicyLister.XAccessPolicies(backend.Namespace).List(labels.Everything()) | ||
| // findAccessPoliciesForTarget finds all AccessPolicies that target the given resource. | ||
| // It returns only accepted policies. | ||
| func (t *Translator) findAccessPoliciesForTarget(group, kind, namespace, name string) ([]*agenticv0alpha0.XAccessPolicy, error) { |
There was a problem hiding this comment.
can we change this to work from an index? related to my previous comment about
can be a followup but lets add TODO() for both locations in the code
Makefile
Outdated
| .PHONY: fmt | ||
| fmt: ;$(info $(M)...Begin to run go fmt against code.) @ ## Run go fmt against code. | ||
| gofmt -w ./pkg | ||
| gofmt -w ./api ./cmd ./pkg |
There was a problem hiding this comment.
| gofmt -w ./api ./cmd ./pkg | |
| go fmt ./... |
There was a problem hiding this comment.
go formatting should be done with .golangci.yml -- see https://github.com/kubernetes-sigs/gateway-api/blob/main/.golangci.yml#L99-L109
There was a problem hiding this comment.
Updated to go fmt ./...
our https://github.com/kubernetes-sigs/kube-agentic-networking/blob/main/.golangci.yaml seems to have minimum checks only. It can be a follow up to update it, but it's out of scope for this PR.
Makefile
Outdated
| .PHONY: vet | ||
| vet: ;$(info $(M)...Begin to run go vet against code.) @ ## Run go vet against code. | ||
| go vet ./pkg/... | ||
| go vet ./api/... ./cmd/... ./pkg/... |
There was a problem hiding this comment.
| go vet ./api/... ./cmd/... ./pkg/... | |
| go vet ./... |
| # Run go test against code | ||
| .PHONY: test | ||
| test: vet test-pkg test-cel test-crd ## Run all tests. | ||
| test: vet test-unit test-cel test-crd ## Run all tests. |
There was a problem hiding this comment.
question: why do we need separate tests targets?
There was a problem hiding this comment.
I'd defer the question to @haiyanmeng . They were added in #58
|
@LiorLieberman: GitHub didn't allow me to request PR reviews from the following users: thing, before, HarshithaMS005, as, she, did, a, similar. Note that only kubernetes-sigs members and repo collaborators can review this PR, and authors cannot review their own PRs. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
New changes are detected. LGTM label has been removed. |
Allow 'Gateway' as a valid TargetRef in XAccessPolicy with cross-kind validation rules. Signed-off-by: Chuang Wang <chuangw@google.com>
This change implements support for AccessPolicy resources targeting Gateway
objects, enabling global authorization policies across all routes in a
Gateway. It also introduces a multi-level policy evaluation model where
both Gateway-level and Backend-level policies are enforced sequentially.
Key changes:
- Controller: Implement seniority-based policy acceptance (limit 5 policies
per target by default). Accepted policies are reflected in the resource
status via PolicyAncestorStatus.
- Translator:
- Gateway-level policies are translated into top-level Envoy HTTP RBAC
filters.
- Backend-level policies use Envoy's 'TypedPerFilterConfig' to override
placeholder filters at the cluster level.
- Enforced correct filter ordering: MCP -> Gateway RBAC -> Backend RBAC
-> Router.
Signed-off-by: Chuang Wang <chuangw@google.com>
|
/hold @chuangw6 , Let us work with @guicassolato to close the externalAuth gap in this PR. |
Signed-off-by: Chuang Wang <chuangw@google.com>
What type of PR is this?
/kind feature
What this PR does / why we need it:
This PR implements support for AccessPolicy resources targeting
Gateway objects, enabling global policy enforcement alongside specific Backend
policies. It introduces a hierarchical evaluation model where requests are
validated at both the Gateway (entry) and Backend (service) levels.
Key changes:
validation rules.
as well as all root Gateways of XBackends targeted by AccessPolicies.
filters.
placeholder filters at the cluster level.
-> Router.
both Gateway and Backend policies, and that policies fallback correctly
when modified or deleted.
Which issue(s) this PR fixes:
Fixes #55
Does this PR introduce a user-facing change?: