Skip to content

Commit 2ae1a91

Browse files
committed
Add v1alpha1 api
1 parent 9d6bbc1 commit 2ae1a91

24 files changed

Lines changed: 2062 additions & 1 deletion

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,20 @@ clientsets: ## Generate clientsets, listers, and informers.
133133
./'
134134

135135
.PHONY: register
136-
register: ## Generate register code for CRDs under ./api/v0alpha0
136+
register: ## Generate register code for CRDs under ./api/v0alpha0 and ./api/v1alpha1
137137
@echo "--- Ensuring code-generator is in module cache..."
138138
@go mod download k8s.io/code-generator
139139
@echo "+++ Generating register code for api/v0alpha0..."
140140
@bash -c 'source $(CODEGEN_SCRIPT); \
141141
kube::codegen::gen_register \
142142
--boilerplate $(BOILERPLATE_FILE) \
143143
./api/v0alpha0'
144+
@echo "+++ Generating register code for api/v1alpha1..."
145+
@bash -c 'source $(CODEGEN_SCRIPT); \
146+
kube::codegen::gen_register \
147+
--boilerplate $(BOILERPLATE_FILE) \
148+
./api/v1alpha1'
149+
144150

145151
## @ Dependencies
146152

api/v0alpha0/accesspolicy_types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ type AccessPolicyStatus struct {
205205
// +genclient
206206
// +kubebuilder:object:root=true
207207
// +kubebuilder:subresource:status
208+
// +kubebuilder:storageversion
208209

209210
// XAccessPolicy is the Schema for the accesspolicies API.
210211
type XAccessPolicy struct {

api/v1alpha1/accesspolicy_types.go

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
/*
2+
Copyright The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// IMPORTANT: Run "make generate" to regenerate code after modifying this file
18+
19+
package v1alpha1
20+
21+
import (
22+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23+
24+
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
25+
)
26+
27+
// AccessPolicySpec defines the desired state of AccessPolicy.
28+
//
29+
// Implementations SHOULD return a regular HTTP formatted response if the policy is enforced against non-MCP traffic.
30+
// Implementations MAY return JSON_RPC formatted response if the policy is enforced against MCP traffic.
31+
// +kubebuilder:validation:XValidation:rule="self.action == 'ExternalAuth' ? has(self.externalAuth) : true",message="externalAuth must be specified when action is set to 'ExternalAuth'"
32+
type AccessPolicySpec struct {
33+
// TargetRefs specifies the targets of the AccessPolicy.
34+
// An AccessPolicy must target at least one resource.
35+
// There is one kind of TargetRef with "Core" support:
36+
//
37+
// * Gateway
38+
//
39+
// This API may be extended in the future to support additional kinds of targetRefs.
40+
// Implementations may support additional kinds in an implementation specific manner.
41+
// +required
42+
// +kubebuilder:validation:MinItems=1
43+
// +kubebuilder:validation:MaxItems=10
44+
// +listType=atomic
45+
// +kubebuilder:validation:XValidation:rule="self.all(ref, ref.kind == self[0].kind)",message="All targetRefs must have the same Kind"
46+
TargetRefs []gwapiv1.LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"`
47+
48+
// Action specifies the action to be taken when rules match.
49+
// Evaluation logic:
50+
// 1. ExternalAuth runs before all other Allow policies.
51+
// 2. If an ExternalAuth server denies the request, the request is denied.
52+
// 3. If it allows the request, processing continues for all other allow policies for that target.
53+
// 4. The request is allowed only if all allow policies allow it.
54+
// +required
55+
Action ActionType `json:"action"`
56+
57+
// ExternalAuth specifies an external auth filter to be used for authorization.
58+
// Core support is limited to 1 extAuth callout per target.
59+
// +optional
60+
ExternalAuth *gwapiv1.HTTPExternalAuthFilter `json:"externalAuth,omitempty"`
61+
62+
// Rules defines a list of rules to be applied to the target.
63+
// An AccessPolicy must have at least one rule.
64+
// +required
65+
// +kubebuilder:validation:MinItems=1
66+
// +kubebuilder:validation:MaxItems=10
67+
// +listType=atomic
68+
// +kubebuilder:validation:XValidation:rule="self.all(r, self.filter(x, x.name == r.name).size() == 1)",message="AccessRule names must be unique"
69+
Rules []AccessRule `json:"rules"`
70+
}
71+
72+
// ActionType identifies a type of action for access policy.
73+
// +kubebuilder:validation:Enum=Allow;ExternalAuth
74+
type ActionType string
75+
76+
const (
77+
// ActionTypeAllow is used to identify that the request should be allowed if rules match.
78+
ActionTypeAllow ActionType = "Allow"
79+
80+
// ActionTypeExternalAuth is used to identify that the request should be delegated to an external auth service if rules match.
81+
ActionTypeExternalAuth ActionType = "ExternalAuth"
82+
)
83+
84+
// AccessRule specifies an authorization rule for the targeted backend.
85+
// If the tool list is empty, the rule denies access to all tools from Source.
86+
type AccessRule struct {
87+
// Name specifies the name of the rule.
88+
// +required
89+
// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
90+
// +kubebuilder:validation:MinLength=1
91+
// +kubebuilder:validation:MaxLength=63
92+
Name string `json:"name"`
93+
// Source specifies the source of the request.
94+
// +required
95+
Source Source `json:"source"`
96+
// Authorization specifies the authorization rule to be applied to requests from the source.
97+
// +optional
98+
Authorization *AuthorizationRule `json:"authorization,omitempty"`
99+
}
100+
101+
// Source specifies the source of a request.
102+
//
103+
// Type must be set to indicate the type of source type.
104+
// Similarly, either SPIFFE or Serviceaccount can be set based on the type.
105+
type Source struct {
106+
// +unionDiscriminator
107+
// +required
108+
Type AuthorizationSourceType `json:"type"`
109+
110+
// spiffe specifies an identity that is matched by this rule.
111+
//
112+
// spiffe identities must be specified as SPIFFE-formatted URIs following the pattern:
113+
// spiffe://<trust_domain>/<workload-identifier>
114+
//
115+
// The exact workload identifier structure is implementation-specific.
116+
// This will likely change in the future.
117+
//
118+
// SPIFFE identities for authorization can be derived in various ways by the underlying
119+
// implementation. Common methods include:
120+
// - From peer mTLS certificates: The identity is extracted from the client's
121+
// mTLS certificate presented during connection establishment.
122+
// - From IP-to-identity mappings: The implementation might maintain a dynamic
123+
// mapping between source IP addresses (pod IPs) and their associated
124+
// identities (e.g., Service Account, SPIFFE IDs).
125+
// - From JWTs or other request-level authentication tokens.
126+
//
127+
// +optional
128+
SPIFFE *AuthorizationSourceSPIFFE `json:"spiffe,omitempty"`
129+
130+
// serviceAccount specifies a Kubernetes Service Account that is
131+
// matched by this rule. A request originating from a pod associated with
132+
// this Service Account will match the rule.
133+
//
134+
// The Service Account listed here is expected to exist within the same
135+
// trust domain as the targeted workload. Cross-trust-domain access should
136+
// instead be expressed using the `SPIFFE` field.
137+
// +optional
138+
ServiceAccount *AuthorizationSourceServiceAccount `json:"serviceAccount,omitempty"`
139+
}
140+
141+
// AuthorizationSourceType identifies a type of source for authorization.
142+
// +kubebuilder:validation:Enum=ServiceAccount;SPIFFE
143+
type AuthorizationSourceType string
144+
145+
const (
146+
// AuthorizationSourceTypeSPIFFE is used to identify a request matches a SPIFFE Identity.
147+
AuthorizationSourceTypeSPIFFE AuthorizationSourceType = "SPIFFE"
148+
149+
// AuthorizationSourceTypeServiceAccount is used to identify a request matches a ServiceAccount from within the cluster.
150+
AuthorizationSourceTypeServiceAccount AuthorizationSourceType = "ServiceAccount"
151+
)
152+
153+
// +kubebuilder:validation:Pattern=`^spiffe://[a-z0-9._-]+(?:/[A-Za-z0-9._-]+)*$`
154+
type AuthorizationSourceSPIFFE string
155+
156+
type AuthorizationSourceServiceAccount struct {
157+
// Namespace is the namespace of the ServiceAccount
158+
// If not specified, current namespace (the namespace of the policy) is used.
159+
// +optional
160+
Namespace string `json:"namespace,omitempty"`
161+
162+
// Name is the name of the ServiceAccount.
163+
// +required
164+
Name string `json:"name"`
165+
}
166+
167+
type AuthorizationRule struct {
168+
// +unionDiscriminator
169+
// +required
170+
Type AuthorizationRuleType `json:"type"`
171+
172+
// MCP defines MCP-specific matching criteria.
173+
// +optional
174+
MCP MCPAttributes `json:"mcp,omitempty"`
175+
}
176+
177+
// MCPAttributes defines the protocol-specific attributes for MCP authorization.
178+
type MCPAttributes struct {
179+
// Methods is a list of specific MCP functional methods to match.
180+
// +kubebuilder:validation:MaxItems=10
181+
// +optional
182+
// +listType=map
183+
// +listMapKey=name
184+
Methods []MCPMethod `json:"methods,omitempty"`
185+
}
186+
187+
// MCPMethod defines a specific MCP method and its associated parameters.
188+
type MCPMethod struct {
189+
// Name is the MCP method to match against (e.g., 'tools/call').
190+
// Allowed values:
191+
// 1. 'tools', 'prompts', 'resources': Matches all sub-methods under these categories.
192+
// 2. 'prompts/list', 'tools/list', 'resources/list', 'resources/templates/list'.
193+
// 3. 'prompts/get', 'tools/call', 'resources/subscribe', 'resources/unsubscribe', 'resources/read'.
194+
// Parameters cannot be specified for categories 1 and 2.
195+
// +required
196+
Name MCPMethodName `json:"name"`
197+
198+
// Params allows matching against specific arguments in the MCP request.
199+
// Only valid for 'get', 'call', 'subscribe', 'unsubscribe', and 'read' methods.
200+
// +optional
201+
//+listType=set
202+
// +kubebuilder:validation:MaxItems=10
203+
Params []MCPMethodParam `json:"params,omitempty"`
204+
}
205+
206+
// +kubebuilder:validation:MaxLength=20
207+
type MCPMethodParam string
208+
209+
// MCPMethodName defines the allowed MCP methods for matching.
210+
// +kubebuilder:validation:Enum=tools;prompts;resources;prompts/list;tools/list;resources/list;resources/templates/list;prompts/get;tools/call;resources/subscribe;resources/unsubscribe;resources/read
211+
type MCPMethodName string
212+
213+
// AuthorizationRuleType identifies a type of authorization rule.
214+
// +kubebuilder:validation:Enum=Inline
215+
type AuthorizationRuleType string
216+
217+
const (
218+
// AuthorizationRuleTypeInline is used to identify authorization rules
219+
// declared as attributes inside the policy (inline)
220+
AuthorizationRuleTypeInline AuthorizationRuleType = "Inline"
221+
222+
// TODO: Add CEL support
223+
)
224+
225+
const (
226+
// PolicyConditionAccepted indicates whether the policy has been accepted by the controller.
227+
//
228+
// Possible reasons for this condition to be True are:
229+
//
230+
// * "Accepted"
231+
//
232+
// Possible reasons for this condition to be False are:
233+
//
234+
// * "LimitPerTargetExceeded"
235+
//
236+
PolicyConditionAccepted gwapiv1.PolicyConditionType = "Accepted"
237+
238+
// This reason is used with the "Accepted" condition when the policy
239+
// has been accepted by the controller.
240+
PolicyReasonAccepted gwapiv1.PolicyConditionReason = "Accepted"
241+
242+
// This reason is used with the "Accepted" condition when the policy
243+
// was rejected because the maximum number of policies per target was exceeded.
244+
PolicyLimitPerTargetExceeded gwapiv1.PolicyConditionReason = "LimitPerTargetExceeded"
245+
)
246+
247+
// AccessPolicyStatus defines the observed state of AccessPolicy.
248+
type AccessPolicyStatus struct {
249+
// Ancestors is a list of ancestor resources (usually Backend) that are
250+
// associated with the policy, and the status of the policy with respect to
251+
// each ancestor.
252+
//
253+
// This field is inherited from the Gateway API Policy status definition.
254+
// For more details, see the upstream documentation:
255+
// https://gateway-api.sigs.k8s.io/reference/spec/#policyancestorstatus
256+
//
257+
// +required
258+
// +listType=atomic
259+
// +kubebuilder:validation:MaxItems=16
260+
Ancestors []gwapiv1.PolicyAncestorStatus `json:"ancestors"`
261+
}
262+
263+
// +genclient
264+
// +kubebuilder:object:root=true
265+
// +kubebuilder:subresource:status
266+
// +kubebuilder:storageversion
267+
268+
// XAccessPolicy is the Schema for the accesspolicies API.
269+
type XAccessPolicy struct {
270+
metav1.TypeMeta `json:",inline"`
271+
272+
// metadata is a standard object metadata.
273+
// +optional
274+
metav1.ObjectMeta `json:"metadata,omitempty"`
275+
276+
// spec defines the desired state of AccessPolicy.
277+
// +required
278+
Spec AccessPolicySpec `json:"spec"`
279+
280+
// status defines the observed state of AccessPolicy.
281+
// +optional
282+
Status AccessPolicyStatus `json:"status,omitempty"`
283+
}
284+
285+
// +kubebuilder:object:root=true
286+
287+
// XAccessPolicyList contains a list of AccessPolicy.
288+
type XAccessPolicyList struct {
289+
metav1.TypeMeta `json:",inline"`
290+
// metadata is a standard list metadata.
291+
// +optional
292+
metav1.ListMeta `json:"metadata,omitempty"`
293+
Items []XAccessPolicy `json:"items"`
294+
}

api/v1alpha1/doc.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
Copyright The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// +k8s:deepcopy-gen=package
18+
// +groupName=agentic.networking.x-k8s.io
19+
package v1alpha1

0 commit comments

Comments
 (0)