Skip to content

Commit 6156fd9

Browse files
authored
Merge pull request #46920 from everpeace/dev-1.31-KEP-3619-SupplementalGroupsPolicy
[dev-1.31] KEP-3619: Fine-grained SupplementalGroups control
2 parents 5b6a35b + 3fb2925 commit 6156fd9

File tree

5 files changed

+229
-2
lines changed

5 files changed

+229
-2
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
title: SupplementalGroupsPolicy
3+
content_type: feature_gate
4+
_build:
5+
list: never
6+
render: false
7+
8+
stages:
9+
- stage: alpha
10+
defaultValue: false
11+
fromVersion: "1.31"
12+
---
13+
Enables support for fine-grained SupplementalGroups control.
14+
For more details, see [Configure fine-grained SupplementalGroups control for a Pod](/content/en/docs/tasks/configure-pod-container/security-context/#supplementalgroupspolicy).

content/en/docs/tasks/configure-pod-container/security-context.md

Lines changed: 183 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ all processes within any containers of the Pod. If this field is omitted, the pr
6666
will be root(0). Any files created will also be owned by user 1000 and group 3000 when `runAsGroup` is specified.
6767
Since `fsGroup` field is specified, all processes of the container are also part of the supplementary group ID 2000.
6868
The owner for volume `/data/demo` and any files created in that volume will be Group ID 2000.
69+
Additionally, when the `supplementalGroups` field is specified, all processes of the container are also part of the
70+
specified groups. If this field is omitted, it means empty.
6971

7072
Create the Pod:
7173

@@ -142,20 +144,199 @@ id
142144
The output is similar to this:
143145

144146
```none
145-
uid=1000 gid=3000 groups=2000
147+
uid=1000 gid=3000 groups=2000,3000,4000
146148
```
147149

148150
From the output, you can see that `gid` is 3000 which is same as the `runAsGroup` field.
149151
If the `runAsGroup` was omitted, the `gid` would remain as 0 (root) and the process will
150152
be able to interact with files that are owned by the root(0) group and groups that have
151-
the required group permissions for the root (0) group.
153+
the required group permissions for the root (0) group. You can also see that `groups`
154+
contains the group IDs which are specified by `fsGroup` and `supplementalGroups`,
155+
in addition to `gid`.
152156

153157
Exit your shell:
154158

155159
```shell
156160
exit
157161
```
158162

163+
### Implicit group memberships defined in `/etc/group` in the container image
164+
165+
By default, kubernetes merges group information from the Pod with information defined in `/etc/group` in the container image.
166+
167+
{{% code_sample file="pods/security/security-context-5.yaml" %}}
168+
169+
This Pod security context contains `runAsUser`, `runAsGroup` and `supplementalGroups`.
170+
However, you can see that the actual supplementary groups attached to the container process
171+
will include group IDs which come from `/etc/group` in the container image.
172+
173+
Create the Pod:
174+
175+
```shell
176+
kubectl apply -f https://k8s.io/examples/pods/security/security-context-5.yaml
177+
```
178+
179+
Verify that the Pod's Container is running:
180+
181+
```shell
182+
kubectl get pod security-context-demo
183+
```
184+
185+
Get a shell to the running Container:
186+
187+
```shell
188+
kubectl exec -it security-context-demo -- sh
189+
```
190+
191+
Check the process identity:
192+
193+
```shell
194+
$ id
195+
```
196+
197+
The output is similar to this:
198+
199+
```none
200+
uid=1000 gid=3000 groups=3000,4000,50000
201+
```
202+
203+
You can see that `groups` includes group ID `50000`. This is because the user (`uid=1000`),
204+
which is defined in the image, belongs to the group (`gid=50000`), which is defined in `/etc/group`
205+
inside the container image.
206+
207+
Check the `/etc/group` in the container image:
208+
209+
```shell
210+
$ cat /etc/group
211+
```
212+
213+
You can see that uid `1000` belongs to group `50000`.
214+
215+
```none
216+
...
217+
user-defined-in-image:x:1000:
218+
group-defined-in-image:x:50000:user-defined-in-image
219+
```
220+
221+
Exit your shell:
222+
223+
```shell
224+
exit
225+
```
226+
227+
{{<note>}}
228+
_Implicitly merged_ supplementary groups may cause security problems particularly when accessing
229+
the volumes (see [kubernetes/kubernetes#112879](https://issue.k8s.io/112879) for details).
230+
If you want to avoid this. Please see the below section.
231+
{{</note>}}
232+
233+
## Configure fine-grained SupplementalGroups control for a Pod {#supplementalgroupspolicy}
234+
235+
{{< feature-state feature_gate_name="SupplementalGroupsPolicy" >}}
236+
237+
This feature can be enabled by setting the `SupplementalGroupsPolicy`
238+
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) for kubelet and
239+
kube-apiserver, and setting the `.spec.securityContext.supplementalGroupsPolicy` field for a pod.
240+
241+
The `supplementalGroupsPolicy` field defines the policy for calculating the
242+
supplementary groups for the container processes in a pod. There are two valid
243+
values for this field:
244+
245+
* `Merge`: The group membership defined in `/etc/group` for the container's primary user will be merged.
246+
This is the default policy if not specified.
247+
248+
* `Strict`: Only group IDs in `fsGroup`, `supplementalGroups`, or `runAsGroup` fields
249+
are attached as the supplementary groups of the container processes.
250+
This means no group membership from `/etc/group` for the container's primary user will be merged.
251+
252+
When the feature is enabled, it also exposes the process identity attached to the first container process
253+
in `.status.containerStatuses[].user.linux` field. It would be useful for detecting if
254+
implicit group ID's are attached.
255+
256+
{{% code_sample file="pods/security/security-context-6.yaml" %}}
257+
258+
This pod manifest defines `supplementalGroupsPolicy=Strict`. You can see that no group memberships
259+
defined in `/etc/group` are merged to the supplementary groups for container processes.
260+
261+
Create the Pod:
262+
263+
```shell
264+
kubectl apply -f https://k8s.io/examples/pods/security/security-context-6.yaml
265+
```
266+
267+
Verify that the Pod's Container is running:
268+
269+
```shell
270+
kubectl get pod security-context-demo
271+
```
272+
273+
Check the process identity:
274+
275+
```shell
276+
kubectl exec -it security-context-demo -- id
277+
```
278+
279+
The output is similar to this:
280+
281+
```none
282+
uid=1000 gid=3000 groups=3000,4000
283+
```
284+
285+
See the Pod's status:
286+
287+
```shell
288+
kubectl get pod security-context-demo -o yaml
289+
```
290+
291+
You can see that the `status.containerStatuses[].user.linux` field exposes the process identitiy
292+
attached to the first container process.
293+
294+
```none
295+
...
296+
status:
297+
containerStatuses:
298+
- name: sec-ctx-demo
299+
user:
300+
linux:
301+
gid: 3000
302+
supplementalGroups:
303+
- 3000
304+
- 4000
305+
uid: 1000
306+
...
307+
```
308+
309+
{{<note>}}
310+
Please note that the values in the `status.containerStatuses[].user.linux` field is _the first attached_
311+
process identity to the first container process in the container. If the container has sufficient privilege
312+
to make system calls related to process identity
313+
(e.g. [`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html),
314+
[`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html) or
315+
[`setgroups(2)`](https://man7.org/linux/man-pages/man2/setgroups.2.html), etc.),
316+
the container process can change its identity. Thus, the _actual_ process identity will be dynamic.
317+
{{</note>}}
318+
319+
### Implementations {#implementations-supplementalgroupspolicy}
320+
321+
{{% thirdparty-content %}}
322+
323+
The following container runtimes are known to support fine-grained SupplementalGroups control.
324+
325+
CRI-level:
326+
- [containerd](https://containerd.io/), since v2.0
327+
- [CRI-O](https://cri-o.io/), since v1.31
328+
329+
You can see if the feature is supported in the Node status.
330+
331+
```yaml
332+
apiVersion: v1
333+
kind: Node
334+
...
335+
status:
336+
features:
337+
supplementalGroupsPolicy: true
338+
```
339+
159340
## Configure volume permission and ownership change policy for Pods
160341
161342
{{< feature-state for_k8s_version="v1.23" state="stable" >}}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: security-context-demo
5+
spec:
6+
securityContext:
7+
runAsUser: 1000
8+
runAsGroup: 3000
9+
supplementalGroups: [4000]
10+
containers:
11+
- name: sec-ctx-demo
12+
image: registry.k8s.io/e2e-test-images/agnhost:2.45
13+
command: [ "sh", "-c", "sleep 1h" ]
14+
securityContext:
15+
allowPrivilegeEscalation: false
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: security-context-demo
5+
spec:
6+
securityContext:
7+
runAsUser: 1000
8+
runAsGroup: 3000
9+
supplementalGroups: [4000]
10+
supplementalGroupsPolicy: Strict
11+
containers:
12+
- name: sec-ctx-demo
13+
image: registry.k8s.io/e2e-test-images/agnhost:2.45
14+
command: [ "sh", "-c", "sleep 1h" ]
15+
securityContext:
16+
allowPrivilegeEscalation: false

content/en/examples/pods/security/security-context.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ spec:
77
runAsUser: 1000
88
runAsGroup: 3000
99
fsGroup: 2000
10+
supplementalGroups: [4000]
1011
volumes:
1112
- name: sec-ctx-vol
1213
emptyDir: {}

0 commit comments

Comments
 (0)