Skip to content

Commit 6262881

Browse files
committed
Add declarative RBAC to WorkspaceType initializers/terminators
Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt> On-behalf-of: SAP <mangirdas.judeikis@sap.com>
1 parent 3843bcf commit 6262881

22 files changed

Lines changed: 1511 additions & 53 deletions

File tree

config/crds/tenancy.kcp.io_workspacetypes.yaml

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,65 @@ spec:
170170
WorkspaceType `example` is created in the `root:org` workspace, the implicit
171171
initializer name is `root:org:example`.
172172
type: boolean
173+
initializerPermissions:
174+
description: |-
175+
initializerPermissions are the RBAC rules granted to initializer controllers when they
176+
access workspace content through the initializing virtual workspace's content proxy.
177+
Rules are evaluated in-process by the VW proxy on each request; no ClusterRole or
178+
ClusterRoleBinding objects are created inside the workspace.
179+
180+
When empty (the default), the VW content proxy falls back to impersonating the
181+
workspace owner (full cluster-admin), preserving the historical behavior.
182+
183+
Changes take effect immediately for all workspaces of this type.
184+
items:
185+
description: |-
186+
PolicyRule holds information that describes a policy rule, but does not contain information
187+
about who the rule applies to or which namespace the rule applies to.
188+
properties:
189+
apiGroups:
190+
description: |-
191+
APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
192+
the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
193+
items:
194+
type: string
195+
type: array
196+
x-kubernetes-list-type: atomic
197+
nonResourceURLs:
198+
description: |-
199+
NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
200+
Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
201+
Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
202+
items:
203+
type: string
204+
type: array
205+
x-kubernetes-list-type: atomic
206+
resourceNames:
207+
description: ResourceNames is an optional white list of names
208+
that the rule applies to. An empty set means that everything
209+
is allowed.
210+
items:
211+
type: string
212+
type: array
213+
x-kubernetes-list-type: atomic
214+
resources:
215+
description: Resources is a list of resources this rule applies
216+
to. '*' represents all resources.
217+
items:
218+
type: string
219+
type: array
220+
x-kubernetes-list-type: atomic
221+
verbs:
222+
description: Verbs is a list of Verbs that apply to ALL the
223+
ResourceKinds contained in this rule. '*' represents all verbs.
224+
items:
225+
type: string
226+
type: array
227+
x-kubernetes-list-type: atomic
228+
required:
229+
- verbs
230+
type: object
231+
type: array
173232
limitAllowedChildren:
174233
description: |-
175234
limitAllowedChildren specifies constraints for sub-workspaces created in workspaces
@@ -261,6 +320,65 @@ spec:
261320
WorkspaceType `example` is created in the `root:org` workspace, the implicit
262321
terminator name is `root:org:example`.
263322
type: boolean
323+
terminatorPermissions:
324+
description: |-
325+
terminatorPermissions are the RBAC rules granted to terminator controllers when they
326+
access workspace content through the terminating virtual workspace's content proxy.
327+
Rules are evaluated in-process by the VW proxy on each request; no ClusterRole or
328+
ClusterRoleBinding objects are created inside the workspace.
329+
330+
When empty (the default), the VW content proxy falls back to impersonating the
331+
workspace owner (full cluster-admin), preserving the historical behavior.
332+
333+
Changes take effect immediately for all workspaces of this type.
334+
items:
335+
description: |-
336+
PolicyRule holds information that describes a policy rule, but does not contain information
337+
about who the rule applies to or which namespace the rule applies to.
338+
properties:
339+
apiGroups:
340+
description: |-
341+
APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
342+
the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
343+
items:
344+
type: string
345+
type: array
346+
x-kubernetes-list-type: atomic
347+
nonResourceURLs:
348+
description: |-
349+
NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
350+
Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
351+
Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
352+
items:
353+
type: string
354+
type: array
355+
x-kubernetes-list-type: atomic
356+
resourceNames:
357+
description: ResourceNames is an optional white list of names
358+
that the rule applies to. An empty set means that everything
359+
is allowed.
360+
items:
361+
type: string
362+
type: array
363+
x-kubernetes-list-type: atomic
364+
resources:
365+
description: Resources is a list of resources this rule applies
366+
to. '*' represents all resources.
367+
items:
368+
type: string
369+
type: array
370+
x-kubernetes-list-type: atomic
371+
verbs:
372+
description: Verbs is a list of Verbs that apply to ALL the
373+
ResourceKinds contained in this rule. '*' represents all verbs.
374+
items:
375+
type: string
376+
type: array
377+
x-kubernetes-list-type: atomic
378+
required:
379+
- verbs
380+
type: object
381+
type: array
264382
type: object
265383
status:
266384
description: WorkspaceTypeStatus defines the observed state of WorkspaceType.

config/root-phase0/apiexport-tenancy.kcp.io.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ spec:
1818
crd: {}
1919
- group: tenancy.kcp.io
2020
name: workspacetypes
21-
schema: v251204-7c13b4e0a.workspacetypes.tenancy.kcp.io
21+
schema: v260428-f702a24c5.workspacetypes.tenancy.kcp.io
2222
storage:
2323
crd: {}
2424
status: {}

config/root-phase0/apiresourceschema-workspacetypes.tenancy.kcp.io.yaml

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
apiVersion: apis.kcp.io/v1alpha1
22
kind: APIResourceSchema
33
metadata:
4-
name: v251204-7c13b4e0a.workspacetypes.tenancy.kcp.io
4+
name: v260428-f702a24c5.workspacetypes.tenancy.kcp.io
55
spec:
66
group: tenancy.kcp.io
77
names:
@@ -167,6 +167,65 @@ spec:
167167
WorkspaceType `example` is created in the `root:org` workspace, the implicit
168168
initializer name is `root:org:example`.
169169
type: boolean
170+
initializerPermissions:
171+
description: |-
172+
initializerPermissions are the RBAC rules granted to initializer controllers when they
173+
access workspace content through the initializing virtual workspace's content proxy.
174+
Rules are evaluated in-process by the VW proxy on each request; no ClusterRole or
175+
ClusterRoleBinding objects are created inside the workspace.
176+
177+
When empty (the default), the VW content proxy falls back to impersonating the
178+
workspace owner (full cluster-admin), preserving the historical behavior.
179+
180+
Changes take effect immediately for all workspaces of this type.
181+
items:
182+
description: |-
183+
PolicyRule holds information that describes a policy rule, but does not contain information
184+
about who the rule applies to or which namespace the rule applies to.
185+
properties:
186+
apiGroups:
187+
description: |-
188+
APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
189+
the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
190+
items:
191+
type: string
192+
type: array
193+
x-kubernetes-list-type: atomic
194+
nonResourceURLs:
195+
description: |-
196+
NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
197+
Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
198+
Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
199+
items:
200+
type: string
201+
type: array
202+
x-kubernetes-list-type: atomic
203+
resourceNames:
204+
description: ResourceNames is an optional white list of names
205+
that the rule applies to. An empty set means that everything
206+
is allowed.
207+
items:
208+
type: string
209+
type: array
210+
x-kubernetes-list-type: atomic
211+
resources:
212+
description: Resources is a list of resources this rule applies
213+
to. '*' represents all resources.
214+
items:
215+
type: string
216+
type: array
217+
x-kubernetes-list-type: atomic
218+
verbs:
219+
description: Verbs is a list of Verbs that apply to ALL the ResourceKinds
220+
contained in this rule. '*' represents all verbs.
221+
items:
222+
type: string
223+
type: array
224+
x-kubernetes-list-type: atomic
225+
required:
226+
- verbs
227+
type: object
228+
type: array
170229
limitAllowedChildren:
171230
description: |-
172231
limitAllowedChildren specifies constraints for sub-workspaces created in workspaces
@@ -258,6 +317,65 @@ spec:
258317
WorkspaceType `example` is created in the `root:org` workspace, the implicit
259318
terminator name is `root:org:example`.
260319
type: boolean
320+
terminatorPermissions:
321+
description: |-
322+
terminatorPermissions are the RBAC rules granted to terminator controllers when they
323+
access workspace content through the terminating virtual workspace's content proxy.
324+
Rules are evaluated in-process by the VW proxy on each request; no ClusterRole or
325+
ClusterRoleBinding objects are created inside the workspace.
326+
327+
When empty (the default), the VW content proxy falls back to impersonating the
328+
workspace owner (full cluster-admin), preserving the historical behavior.
329+
330+
Changes take effect immediately for all workspaces of this type.
331+
items:
332+
description: |-
333+
PolicyRule holds information that describes a policy rule, but does not contain information
334+
about who the rule applies to or which namespace the rule applies to.
335+
properties:
336+
apiGroups:
337+
description: |-
338+
APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
339+
the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
340+
items:
341+
type: string
342+
type: array
343+
x-kubernetes-list-type: atomic
344+
nonResourceURLs:
345+
description: |-
346+
NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
347+
Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
348+
Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
349+
items:
350+
type: string
351+
type: array
352+
x-kubernetes-list-type: atomic
353+
resourceNames:
354+
description: ResourceNames is an optional white list of names
355+
that the rule applies to. An empty set means that everything
356+
is allowed.
357+
items:
358+
type: string
359+
type: array
360+
x-kubernetes-list-type: atomic
361+
resources:
362+
description: Resources is a list of resources this rule applies
363+
to. '*' represents all resources.
364+
items:
365+
type: string
366+
type: array
367+
x-kubernetes-list-type: atomic
368+
verbs:
369+
description: Verbs is a list of Verbs that apply to ALL the ResourceKinds
370+
contained in this rule. '*' represents all verbs.
371+
items:
372+
type: string
373+
type: array
374+
x-kubernetes-list-type: atomic
375+
required:
376+
- verbs
377+
type: object
378+
type: array
261379
type: object
262380
status:
263381
description: WorkspaceTypeStatus defines the observed state of WorkspaceType.

docs/content/concepts/authorization/authorizers.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,32 @@ By default, workspaces are only accessible to a subject if they are in `Ready` p
130130
can be accessed only by subjects who are granted `admin` verb on the `workspaces/content` resource in the
131131
parent workspace.
132132

133+
The authorizer also permits content access while the workspace is in the `Terminating` and `Deleting` phases so
134+
that terminator controllers and standard kube finalization (garbage collection, namespace deletion, finalizer
135+
removal) can complete cleanup. Permission is otherwise unchanged: subjects still need a matching binding inside
136+
the workspace.
137+
133138
ServiceAccounts declared within a workspace don't have access to content of initializing workspaces.
134139

140+
##### Lifecycle Synthetic Groups
141+
142+
The initializing and terminating virtual workspace content proxies can forward requests with one of two synthetic
143+
groups attached to the controller's identity:
144+
145+
* `system:kcp:initializer:<initializer-name>` (e.g. `system:kcp:initializer:root:tenant`)
146+
* `system:kcp:terminator:<terminator-name>`
147+
148+
When the workspace content authorizer sees one of these groups it treats the request as **pre-authorized by the
149+
VW** and delegates to the next authorizer without re-evaluating workspace RBAC. This is what allows initializer
150+
and terminator controllers with scoped `initializerPermissions` / `terminatorPermissions` (see
151+
[Workspace Types](../workspaces/workspace-types.md#lifecycle-permissions)) to act with their own identity instead
152+
of impersonating the workspace owner.
153+
154+
These groups cannot be self-asserted by clients: the front-proxy's `--authentication-drop-groups` defaults strip
155+
both prefixes (`system:kcp:initializer:*` and `system:kcp:terminator:*`) from every incoming request before any
156+
routing happens. The only code paths that can inject them are the VW content proxies, which run inside the
157+
front-proxy process and add the group **after** the in-process RBAC evaluation has already allowed the request.
158+
135159
##### Cross-Workspace
136160

137161
Subjects who do not originate from the workspace the request is being made to and are not global kcp

0 commit comments

Comments
 (0)