Skip to content

Commit adb71ee

Browse files
youngnickrobscott
authored andcommitted
Update with examples and clarifications after initial review
Signed-off-by: Nick Young <[email protected]>
1 parent d9b390e commit adb71ee

File tree

1 file changed

+242
-37
lines changed
  • keps/sig-network/3766-referencegrant

1 file changed

+242
-37
lines changed

keps/sig-network/3766-referencegrant/README.md

Lines changed: 242 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,16 @@
1212
- [Potential for Variations Among Implementations](#potential-for-variations-among-implementations)
1313
- [Cross-Namespace References may Weaken Namespace Boundaries](#cross-namespace-references-may-weaken-namespace-boundaries)
1414
- [Design Details](#design-details)
15+
- [General Notes](#general-notes)
16+
- [<code>ReferenceGrant</code> is half of a handshake](#-is-half-of-a-handshake)
17+
- [<code>Resource</code> vs <code>Kind</code>](#-vs-)
18+
- [Revocation behavior](#revocation-behavior)
19+
- [Example Usage](#example-usage)
20+
- [Gateway API Gateway Referencing Secret](#gateway-api-gateway-referencing-secret)
21+
- [Gateway API HTTPRoute Referencing Service](#gateway-api-httproute-referencing-service)
22+
- [PersistentVolumeClaim using cross namespace data source](#persistentvolumeclaim-using-cross-namespace-data-source)
1523
- [API Spec](#api-spec)
24+
- [Outstanding questions and clarifications](#outstanding-questions-and-clarifications)
1625
- [Test Plan](#test-plan)
1726
- [Prerequisite testing updates](#prerequisite-testing-updates)
1827
- [Unit tests](#unit-tests)
@@ -68,17 +77,19 @@ sig-storage](https://kubernetes.io/blog/2023/01/02/cross-namespace-data-sources-
6877
to enable cross-namespace data sources.
6978

7079
This KEP proposes moving ReferenceGrant from its current
71-
`gateway.networking.k8s.io` API group to a new `grants.authorization.k8s.io` API
80+
`gateway.networking.k8s.io` API group into the `authorization.k8s.io` API
7281
group.
7382

7483
## Motivation
7584

76-
Now that it's clear that ReferenceGrant is useful beyond just Gateway API, it
77-
would be good to formalize this model in a more neutral home, ideally sig-auth.
78-
At this point, each project that wants to enable cross-namespace references has
79-
to choose between introducing a dependency on Gateway API and creating a new
80-
resource that would largely duplicate ReferenceGrant. Both options would lead to
81-
confusion for Kubernetes users.
85+
Any project that wants to enable cross-namespace references currently has to choose
86+
between introducing a dependency on Gateway API's ReferenceGrant or creating a
87+
new API that would be partially redundant (leading to confusion for users).
88+
89+
Recent interest between SIGs has made it clear that ReferenceGrant is wanted for use
90+
cases other than Gateway API. We would like to move ReferenceGrant to a neutral home
91+
(ideally, under sig-auth) in order to make it the canonical API for managing references
92+
across namespaces.
8293

8394
### Goals
8495

@@ -97,13 +108,11 @@ confusion for Kubernetes users.
97108
## Proposal
98109

99110
Move the existing ReferenceGrant resource into a new
100-
`grants.authorization.k8s.io` API group, defined within the Kubernetes code base
111+
`authorization.k8s.io` API group, defined within the Kubernetes code base
101112
as part of the 1.27 release.
102113

103-
We will take this opportunity to clarify underspecified parts of the API, but
104-
will not add, change, or remove any fields as part of this transition.
105-
This resource will start with v1beta1 as the API version, matching the API version
106-
it already has within Gateway API.
114+
We will take this opportunity to clarify and update the API after SIG-Auth
115+
feedback. This resource will start with v1alpha1 as the API version.
107116

108117

109118
### Risks and Mitigations
@@ -143,28 +152,225 @@ across namespaces. It's intended that _another object_ (that is, the From object
143152
complete the handshake by creating a reference to the referent object (the To
144153
object).
145154

146-
#### `Kind` vs `Resource`
155+
#### `Resource` vs `Kind`
147156

148157
When creating a metaresource (that is, a resource that targets other resources)
149158
like ReferenceGrant, it's important to consider if the metaresource uses the more
150159
common `Kind` or the more correct `Resource`.
151160

152-
When designing the Gateway API in general, we considered this quite a bit (and
153-
@robscott even ended up making https://github.com/kubernetes/community/pull/5973
154-
to clarify the API conventions), but in the end decided to use Kind, to improve
155-
the user experience. That is, it's easier users to take the value from the `kind`
156-
field at the top of the YAML they are already using, and put it straight into
157-
these fields, rather than needing to do a kind-resource lookup for every user's
158-
interaction with the API.
161+
In the original Gateway API implementation, we chose to use `Kind` rather than
162+
`Resource`, mainly to improve the user experience. That is, it's easier users
163+
to take the value from the `kind` field at the top of the YAML they are already
164+
using, and put it straight into these fields, rather than needing to do a
165+
kind-resource lookup for every user's interaction with the API. @robscott even
166+
ended up making https://github.com/kubernetes/community/pull/5973 to clarify
167+
the API conventions.
168+
169+
However, in discussion on this KEP, it's clear that the more generic nature of
170+
_this_ API requires the additional specificity that `Resource` provides.
171+
172+
The Gateway API ReferenceGrant looked like this:
173+
```yaml
174+
apiVersion: gateway.networking.k8s.io/v1beta1
175+
kind: ReferenceGrant
176+
metadata:
177+
name: allow-gateways
178+
namespace: bar
179+
spec:
180+
from:
181+
# Note that in Gateway API, Group is currently defaulted
182+
# to this, which means you to explicitly set the group to
183+
# the empty string for Core resources. We should definitely
184+
# change this.
185+
- group: "gateway.networking.kubernetes.io"
186+
kind: Gateway
187+
namespace: foo
188+
to:
189+
- group: ""
190+
kind: Secret
191+
```
192+
193+
The new version will look like this instead:
194+
```yaml
195+
apiVersion: authorization.k8s.io/v1alpha1
196+
kind: ReferenceGrant
197+
metadata:
198+
name: allow-gateways
199+
namespace: bar
200+
spec:
201+
from:
202+
# Assuming that we leave the default for Group to the empty
203+
# string, so that Core objects don't need additional config.
204+
- group: "gateway.networking.kubernetes.io"
205+
resource: gateways
206+
namespace: foo
207+
to:
208+
- resource: secrets
209+
210+
```
159211

160-
Secondly, as in the Ingress API, the target types must be clearly defined by
161-
each implementation, so there should be no opportunity for ambiguity.
212+
The new version communicates the scope more clearly because `resource` is plural.
213+
214+
#### Revocation behavior
215+
216+
Unfortunately, there's no way to be specific about what happens when a
217+
ReferenceGrant is deleted in every possible case - the revocation behavior is
218+
dependent on what access is being granted (and revoked).
219+
220+
The general rules we've used in the past are:
221+
* Deletion of a ReferenceGrant means the granted access is revoked
222+
* ReferenceGrant controllers must remove any configuration generated by the granted
223+
access as soon as possible (eventual consistence permitting)
224+
* Implementations should err on the side of removing access rather than leaving
225+
it lying around.
226+
227+
The examples below include information about what happens when the ReferenceGrant
228+
is removed as data points.
229+
230+
### Example Usage
231+
232+
#### Gateway API Gateway Referencing Secret
233+
234+
In this example (from the Gateway API docs), we have a Gateway in the
235+
`gateway-api-example-ns1` namespace, referencing a Secret in the
236+
`gateway-api-example-ns2` namespace. The following ReferenceGrant allows this:
237+
238+
```yaml
239+
apiVersion: gateway.networking.k8s.io/v1beta1
240+
kind: Gateway
241+
metadata:
242+
name: cross-namespace-tls-gateway
243+
namespace: gateway-api-example-ns1
244+
spec:
245+
gatewayClassName: acme-lb
246+
listeners:
247+
- name: https
248+
protocol: HTTPS
249+
port: 443
250+
hostname: "*.example.com"
251+
tls:
252+
certificateRefs:
253+
# There's a Kind/Resource mismatch here, which sucks, but it is not
254+
# easily fixable, since Gateway is already a beta, close to GA
255+
# object.
256+
- kind: Secret
257+
group: ""
258+
name: wildcard-example-com-cert
259+
namespace: gateway-api-example-ns2
260+
---
261+
apiVersion: authorization.k8s.io/v1alpha1
262+
kind: ReferenceGrant
263+
metadata:
264+
name: allow-ns1-gateways-to-ref-secrets
265+
namespace: gateway-api-example-ns2
266+
spec:
267+
from:
268+
- group: gateway.networking.k8s.io
269+
resource: gateways
270+
namespace: gateway-api-example-ns1
271+
to:
272+
- resource: secrets
273+
```
274+
275+
For Gateway TLS references, if this ReferenceGrant is deleted (revoking,
276+
the grant), then the Listener will become invalid, and the configuration
277+
will be removed as soon as possible (eventual consistency permitting).
278+
279+
#### Gateway API HTTPRoute Referencing Service
280+
281+
In this example, a HTTPRoute in the `baz` namespace is directing traffic
282+
to a Service backend in the `quux` namespace.
283+
284+
```yaml
285+
apiVersion: gateway.networking.k8s.io/v1beta1
286+
kind: HTTPRoute
287+
metadata:
288+
name: quuxapp
289+
namespace: baz
290+
spec:
291+
parentRefs:
292+
- name: example-gateway
293+
sectionName: https
294+
hostnames:
295+
- quux.example.com
296+
rules:
297+
- matches:
298+
- path:
299+
type: PathPrefix
300+
value: /
301+
backendRefs:
302+
# BackendRefs are Services by default.
303+
- name: quuxapp
304+
namespace: quux
305+
port: 80
306+
---
307+
apiVersion: authorization.k8s.io/v1alpha1
308+
kind: ReferenceGrant
309+
metadata:
310+
name: allow-baz-httproutes
311+
namespace: quux
312+
spec:
313+
from:
314+
- group: gateway.networking.k8s.io
315+
resource: httproutes
316+
namespace: baz
317+
to:
318+
- resource: services
319+
```
162320

163-
Lastly, this is only half of a handshake, so the From referent must also both
164-
support referencing the To referent, and must reference the one in the To field.
321+
For HTTPRoute objects referencing a backend in another namespace, if the
322+
ReferenceGrant is deleted, the backend will become invalid (since the target
323+
can't be found). If there was more than one backend, then the valid parts of the
324+
HTTPRoute's config would persist in the data plane.
325+
326+
But in this case, the cross-namespace reference is the _only_ backend, so the
327+
removal of the ReferenceGrant will also result in the removal of the HTTPRoute's
328+
config from the data plane.
329+
#### PersistentVolumeClaim using cross namespace data source
330+
331+
This example is taken from https://kubernetes.io/blog/2023/01/02/cross-namespace-data-sources-alpha/
332+
and updated to use the proposed new spec.
333+
334+
It allows the PersistentVolumeClaim in the `dev` namespace to use a volume
335+
snapshot from the `prod` namespace as its data source.
336+
337+
```yaml
338+
apiVersion: v1
339+
kind: PersistentVolumeClaim
340+
metadata:
341+
name: example-pvc
342+
namespace: dev
343+
spec:
344+
storageClassName: example
345+
accessModes:
346+
- ReadWriteOnce
347+
resources:
348+
requests:
349+
storage: 1Gi
350+
dataSourceRef:
351+
apiGroup: snapshot.storage.k8s.io
352+
kind: VolumeSnapshot
353+
name: new-snapshot-demo
354+
namespace: prod
355+
volumeMode: Filesystem
356+
---
357+
apiVersion: authorization.k8s.io/v1alpha1
358+
kind: ReferenceGrant
359+
metadata:
360+
name: allow-prod-pvc
361+
namespace: prod
362+
spec:
363+
from:
364+
- resource: persistentvolumeclaims
365+
namespace: dev
366+
to:
367+
- group: snapshot.storage.k8s.io
368+
resource: volumesnapshots
369+
name: new-snapshot-demo
370+
```
165371

166-
With all of that in mind, we felt that the benefits in terms of specificity
167-
outweighed the costs in terms of user pain to use the more correct `Resource`.
372+
At time of writing, I'm not sure about the behavior here when the ReferenceGrant
373+
is deleted.
168374

169375
### API Spec
170376

@@ -216,10 +422,10 @@ type ReferenceGrantSpec struct {
216422
// +kubebuilder:validation:MaxItems=16
217423
From []ReferenceGrantFrom `json:"from"`
218424

219-
// To describes the resources that may be referenced by the resources
220-
// described in "From". Each entry in this list MUST be considered to be an
221-
// additional place that references can be valid to, or to put this another
222-
// way, entries MUST be combined using OR.
425+
// To describes the resources in this namespace that may be referenced by
426+
// the resources described in "From". Each entry in this list MUST be
427+
// considered to be an additional set of objects that references can be
428+
// valid to, or to put this another way, entries MUST be combined using OR.
223429
//
224430
// +kubebuilder:validation:MinItems=1
225431
// +kubebuilder:validation:MaxItems=16
@@ -232,8 +438,8 @@ type ReferenceGrantFrom struct {
232438
// When empty, the Kubernetes core API group is inferred.
233439
Group Group `json:"group"`
234440

235-
// Kind is the kind of the referent.
236-
Kind string `json:"kind"`
441+
// Kind is the resource of the referent.
442+
Resource string `json:"resource"`
237443

238444
// Namespace is the namespace of the referent.
239445
Namespace string `json:"namespace"`
@@ -246,8 +452,8 @@ type ReferenceGrantTo struct {
246452
// When empty, the Kubernetes core API group is inferred.
247453
Group string `json:"group"`
248454

249-
// Kind is the kind of the referent.
250-
Kind string `json:"kind"`
455+
// Kind is the resource of the referent.
456+
Resource string `json:"resource"`
251457

252458
// Name is the name of the referent. When unspecified, this policy
253459
// refers to all resources of the specified Group and Kind in the local
@@ -262,9 +468,8 @@ type ReferenceGrantTo struct {
262468

263469
This section lists some of the outstanding questions people have had about
264470
ReferenceGrant, and other items that we'll be clarifying in the godoc and other
265-
documentation as part of the transition to the new API group, keeping in mind
266-
that we will not be adding any new features, fields, or behavior, just clarifying
267-
what's done already.
471+
documentation as part of the transition to the new API group, along with any
472+
other changes we need to make that aren't already reflected in this document.
268473

269474
Also note that we don't consider any of these blockers for the general _idea_ of
270475
moving ReferenceGrant to the new API group, just notes to save discussion time.

0 commit comments

Comments
 (0)