Allow AccessPolicy to Target Gateway Objects¶
Currently, the XAccessPolicy resource is only allowed to target XBackends.
This has scalability issues when a given Tool Authorization policy needs to be enforced for all the traffic managed by a Gateway object.
This proposal allows XAccessPolicy to target Gateway objects, in addition to XBackend objects with following restrictions:
-
A single
XAccessPolicyobject targeting a Gateway and a XBackend at the same time is NOT allowed. -
It is allowed to have
XAccessPolicyobjects targeting aGatewayobject andXAccessPolicyobjects targeting aXBackendobject behind theGatewayobject. In this case, theXAccessPolicyobjects targeting theGatewayobject will be evaluated first. Among theXAccessPolicyobjects targeting theGatewayobject, the ones with earlier creationTimestamp will be evaluated first. For the policies with the same creationTimestamp, the ones appearing first in alphabetical order by{namespace}/{name}will be evaluated first.-
If any of the
XAccessPolicyobjects targeting theGatewayobject denies the access, the HTTP request will be denied. TheXAccessPolicyobjects targeting theXBackendobject will NOT be evaluated in this case. -
If all the
XAccessPolicyobjects targeting theGatewayobject allow the access, theXAccessPolicyobjects targeting theXBackendobject will be evaluated. Among theXAccessPolicyobjects targeting theXBackendobject, the ones with earlier creationTimestamp will be evaluated first. For the policies with the same creationTimestamp, the ones appearing first in alphabetical order by{namespace}/{name}will be evaluated first.-
if any of the
XAccessPolicyobjects targeting theXBackendobject denies the access, the HTTP request will be denied. -
if all the
XAccessPolicyobjects targeting theXBackendobject allow the access, the HTTP request will be allowed.
-
-
Example¶
Consider the following setup:
We have a Gateway, an HTTPRoute and a Backend:
- Gateway:
prod-gateway - HTTPRoute:
payment-route(attached toprod-gateway, routes topayment-service) - XBackend:
payment-service
We also have the following XAccessPolicies applied:
gateway-policy-audit(Targetsprod-gateway). Created at T1.gateway-policy-region(Targetsprod-gateway). Created at T2 (T1 < T2).backend-policy-admin(Targetspayment-serviceXBackend).
The graph shows the relationships between these resources:
graph TD
%% 1. Policies at the Top
subgraph PolicyLayer [Policy Attachments]
direction LR
GPA1(XAccessPolicy: gateway-policy-audit)
GPR1(XAccessPolicy: gateway-policy-region)
BPA1(XAccessPolicy: backend-policy-admin)
end
%% 2. Infrastructure & Routing on the same line
%% We define the order here: Gateway <-> Route <-> Backend
GW(Gateway: prod-gateway)
Route(HTTPRoute: payment-route)
BE(XBackend: payment-service)
%% Invisible links to force horizontal alignment
GW ~~~ Route ~~~ BE
%% 3. Vertical Arrows (Policies pointing DOWN)
GPA1 -. "TargetRefs" .-> GW
GPR1 -. "TargetRefs" .-> GW
BPA1 -. "TargetRefs" .-> BE
%% 4. Horizontal Arrows (Routing logic)
Route -- "ParentRefs" --> GW
Route -- "BackendRefs" --> BE
%% --- STYLING ---
classDef infra fill:#e3f2fd,stroke:#1565c0,stroke-width:2px;
classDef routing fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
classDef policy fill:#fff3e0,stroke:#ef6c00,stroke-width:2px,stroke-dasharray: 5 5;
class GW,BE infra;
class Route routing;
class GPA1,GPR1,BPA1 policy;
style PolicyLayer fill:none,stroke:#ccc,stroke-dasharray: 5 5;
Evaluation Flow¶
When a request comes to payment-service through prod-gateway:
-
Gateway Level Checks:
- First,
gateway-policy-auditis evaluated (earlier creation timestamp). - Next,
gateway-policy-regionis evaluated. - Rule: ALL Gateway policies must allow the request. If
gateway-policy-auditdenies it, the request is rejected immediately, and subsequent policies are skipped.
- First,
-
Backend Level Checks:
- If (and only if) all Gateway policies allow the request,
backend-policy-adminis evaluated. - Rule: Backend policies must also allow the request.
- If (and only if) all Gateway policies allow the request,
Final Result: The request is allowed ONLY if it is allowed by all three policies.
API Changes¶
We will use +kubebuilder:validation:XValidation:rule markers to make sure that:
- A
targetRefmust be eitherGatewayorBackend. - All targetRefs must have the same kind.
// AccessPolicySpec defines the desired state of AccessPolicy.
type AccessPolicySpec struct {
// TargetRefs specifies the targets of the AccessPolicy.
// An AccessPolicy must target at least one resource.
// +required
// +kubebuilder:validation:MinItems=1
// +listType=atomic
// +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"
// +kubebuilder:validation:XValidation:rule="self.all(ref, ref.kind == self[0].kind)",message="All targetRefs must have the same Kind"
TargetRefs []gwapiv1.LocalPolicyTargetReference `json:"targetRefs"`
}
In v1alpha1, the Inline authorization type uses mcp.methods (for example, tools/call with params) instead of a flat tool name list. This works well for XAccessPolicy targeting XBackend objects. It does not work well for XAccessPolicy targeting Gateway objects, because there could be tool name conflicts between different backends behind the same Gateway. We will address this in a separate proposal.
Support requirements in implementation¶
-
An implementation MUST support at least one of the following:
XAccessPolicyobjects targetingGatewayobjectsXAccessPolicyobjects targetingXBackendobjects
-
If an implementation supports allowing
XAccessPolicyto target bothGatewayandXBackendobjects, it MUST support the evaluation flow described above.