Skip to content

Commit c5f020c

Browse files
committed
KEP-3619: Fine-grained SupplementalGroups control
1 parent 0fc04db commit c5f020c

File tree

5 files changed

+219
-2
lines changed

5 files changed

+219
-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: 173 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, since `supplementalGroups` field is specified, all processes of the container are also part of the
70+
specified group IDs. If this field is omitted, it means empty.
6971

7072
Create the Pod:
7173

@@ -142,20 +144,189 @@ 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 `groups`
154+
contains the group IDs which are specified by `fsGroup` and `supplementalGroups` other
155+
than `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 for the container's primary user defined in
166+
`/etc/group` in the container image.
167+
168+
{{% code_sample file="pods/security/security-context-5.yaml" %}}
169+
170+
In this configuration, it just specifies `runAsUser`, `runAsGroup` and `supplementalGroups`.
171+
However, you can see that the actual supplementary groups attached to the container process
172+
will include group IDs which come from `/etc/group` in the container image.
173+
174+
Create the Pod:
175+
176+
```shell
177+
kubectl apply -f https://k8s.io/examples/pods/security/security-context-5.yaml
178+
```
179+
180+
Verify that the Pod's Container is running:
181+
182+
```shell
183+
kubectl get pod security-context-demo
184+
```
185+
186+
Get a shell to the running Container:
187+
188+
```shell
189+
kubectl exec -it security-context-demo -- sh
190+
```
191+
192+
Check the process identity:
193+
194+
```shell
195+
$ id
196+
```
197+
198+
The output is similar to this:
199+
200+
```none
201+
uid=1000(user-defined-in-image) gid=3000 groups=3000,4000,50000(group-defined-in-image)
202+
```
203+
204+
You can see `groups` includes group ID `50000`. This is because the user (`uid=1000(user-defined-in-image)`)
205+
belongs to the group `group-defined-in-image(gid=50000)` which is defined in `/etc/group` in 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 the group entry that `user-defined-in-image(uid=1000)` belongs to `group-defined-in-image(gid=50000)`.
214+
215+
```none
216+
...
217+
group-defined-in-image:x:50000:user-defined-in-image
218+
```
219+
220+
Exit your shell:
221+
222+
```shell
223+
exit
224+
```
225+
226+
{{<note>}}
227+
Implicitly _merged_ supplementary groups may cause security concerns particularly in accessing
228+
the volumes (see [kubernetes/kubernetes#112879](https://issue.k8s.io/112879) for details).
229+
If you want to avoid this. Please see the below section.
230+
{{</note>}}
231+
232+
## Configure fine-grained SupplementalGroups control for a Pod {#supplementalgroupspolicy}
233+
234+
{{< feature-state feature_gate_name="SupplementalGroupsPolicy" >}}
235+
236+
This feature can be enabled by setting the `SupplementalGroupsPolicy`
237+
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) for kubelet and
238+
kube-apiserver, and setting the `.spec.securityContext.supplementalGroupsPolicy` field for a pod.
239+
240+
**supplementalGroupsPolicy** - `supplementalGroupsPolicy` defines behavior for calculating
241+
supplementary groups for the container processes in a pod.
242+
243+
* _Merge_: The group membership defined in `/etc/group` for the container's primary user will be merged. If not specified, this policy will be applied.
244+
245+
* _Strict_: it only attaches group IDs in `fsGroup`, `supplementalGroups`, or `runAsGroup` fields as the supplementary groups of the container processess. This means no group membership defined in `/etc/group` for the container's primary user will be merged.
246+
247+
When the feature is enabled, it also exposes the process identity attached to the first container process of the container
248+
in `.status.containerStatuses[].user.linux` field. It would be helpful to detect if implicit group ID's are attached.
249+
250+
{{% code_sample file="pods/security/security-context-6.yaml" %}}
251+
252+
This pod manifest defines `supplementalGroupsPolicy=Strict`. You can see no group membership defined in `/etc/group` will be merged to the supplementary groups for container processes.
253+
254+
Create the Pod:
255+
256+
```shell
257+
kubectl apply -f https://k8s.io/examples/pods/security/security-context-6.yaml
258+
```
259+
260+
Verify that the Pod's Container is running:
261+
262+
```shell
263+
kubectl get pod security-context-demo
264+
```
265+
266+
Check the process identity:
267+
268+
```shell
269+
kubectl exec -it security-context-demo -- id
270+
```
271+
272+
The output is similar to this:
273+
274+
```none
275+
uid=1000(user-defined-in-image) gid=3000 groups=3000,4000
276+
```
277+
278+
See the Pod's status:
279+
280+
```shell
281+
kubectl get pod security-context-demo -o yaml
282+
```
283+
284+
You can see `status.containerStatuses[].user.linux` field exposes the process identitiy
285+
attached to the first container process.
286+
287+
```none
288+
...
289+
status:
290+
containerStatuses:
291+
- name: sec-ctx-demo
292+
user:
293+
linux:
294+
gid: 3000
295+
supplementalGroups:
296+
- 3000
297+
- 4000
298+
uid: 1000
299+
...
300+
```
301+
302+
{{<note>}}
303+
Please note that the values in `status.containerStatuses[].user.linux` field is _the firstly attached_
304+
process identity to the first container process in the container. If the container has sufficient privilege
305+
to call system calls related to process identity (e.g. [`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html), [`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html) or [`setgroups(2)`](https://man7.org/linux/man-pages/man2/setgroups.2.html), etc.),
306+
the container process can change its identity. Thus, the _actual_ process identity will be dynamic.
307+
{{</note>}}
308+
309+
### Implementations {#implementations-supplementalgroupspolicy}
310+
311+
{{% thirdparty-content %}}
312+
313+
The following container runtimes are known to support fine-grained SupplementalGroups control.
314+
315+
CRI-level:
316+
- [containerd](https://containerd.io/), since v2.0
317+
- [CRI-O](https://cri-o.io/), since v1.31
318+
319+
You can see if the feature is supported in the node status.
320+
321+
```yaml
322+
apiVersion: v1
323+
kind: Node
324+
...
325+
status:
326+
features:
327+
supplementalGroupsPolicy: true
328+
```
329+
159330
## Configure volume permission and ownership change policy for Pods
160331
161332
{{< 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)