Skip to content

Commit e356160

Browse files
committed
Add --group-add keep-groups: suplimentary groups into container
Currently we have rootless users who want to leak their groups access into containers, but this group access is only able to be pushed in by a hard to find OCI Runtime annotation. This PR makes this option a lot more visable and hides the complexity within the podman client. This option is only really needed for local rootless users. It makes no sense for remote clients, and probably makes little sense for rootfull containers. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
1 parent 9c82772 commit e356160

File tree

7 files changed

+133
-25
lines changed

7 files changed

+133
-25
lines changed

cmd/podman/common/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
277277
createFlags.StringSliceVar(
278278
&cf.GroupAdd,
279279
groupAddFlagName, []string{},
280-
"Add additional groups to join",
280+
"Add additional groups to the primary container process. 'keep-groups' allows container processes to use suplementary groups.",
281281
)
282282
_ = cmd.RegisterFlagCompletionFunc(groupAddFlagName, completion.AutocompleteNone)
283283

cmd/podman/containers/create.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,25 @@ func createInit(c *cobra.Command) error {
193193
val := c.Flag("entrypoint").Value.String()
194194
cliVals.Entrypoint = &val
195195
}
196+
197+
if c.Flags().Changed("group-add") {
198+
groups := []string{}
199+
for _, g := range cliVals.GroupAdd {
200+
if g == "keep-groups" {
201+
if len(cliVals.GroupAdd) > 1 {
202+
return errors.New("the '--group-add keep-groups' option is not allowed with any other --group-add options")
203+
}
204+
if registry.IsRemote() {
205+
return errors.New("the '--group-add keep-groups' option is not supported in remote mode")
206+
}
207+
cliVals.Annotation = append(cliVals.Annotation, "run.oci.keep_original_groups=1")
208+
} else {
209+
groups = append(groups, g)
210+
}
211+
}
212+
cliVals.GroupAdd = groups
213+
}
214+
196215
if c.Flags().Changed("pids-limit") {
197216
val := c.Flag("pids-limit").Value.String()
198217
pidsLimit, err := strconv.ParseInt(val, 10, 32)

docs/source/markdown/podman-build.1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ Set the architecture variant of the image to be pulled.
688688
bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman
689689
container. (This option is not available with the remote Podman client)
690690

691-
The `OPTIONS` are a comma delimited list and can be: <sup>[[1]](#Footnote1)</sup>
691+
The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup>
692692

693693
* [rw|ro]
694694
* [z|Z|O]

docs/source/markdown/podman-create.1.md

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ Note: if _host_device_ is a symbolic link then it will be resolved first.
261261
The container will only store the major and minor numbers of the host device.
262262

263263
Note: if the user only has access rights via a group, accessing the device
264-
from inside a rootless container will fail. The **crun**(1) runtime offers a
265-
workaround for this by adding the option **\-\-annotation run.oci.keep_original_groups=1**.
264+
from inside a rootless container will fail. Use the `--group-add keep-groups`
265+
flag to pass the user's supplementary group access into the container.
266266

267267
Podman may load kernel modules required for using the specified
268268
device. The devices that podman will load modules when necessary are:
@@ -361,9 +361,17 @@ GID map for the user namespace. Using this flag will run the container with user
361361

362362
The following example maps uids 0-2000 in the container to the uids 30000-31999 on the host and gids 0-2000 in the container to the gids 30000-31999 on the host. `--gidmap=0:30000:2000`
363363

364-
#### **\-\-group-add**=*group*
364+
#### **\-\-group-add**=*group|keep-groups*
365365

366-
Add additional groups to run as
366+
Add additional groups to assign to primary user running within the container process.
367+
368+
- `keep-groups` is a special flag that tells Podman to keep the supplementary group access.
369+
370+
Allows container to use the user's supplementary group access. If file systems or
371+
devices are only accessible by the rootless user's group, this flag tells the OCI
372+
runtime to pass the group access into the container. Currently only available
373+
with the `crun` OCI runtime. Note: `keep-groups` is exclusive, you cannot add any other groups
374+
with this flag. (Not available for remote commands)
367375

368376
#### **\-\-health-cmd**=*"command"* | *'["command", "arg1", ...]'*
369377

@@ -634,7 +642,7 @@ Valid _mode_ values are:
634642
- **none**: no networking;
635643
- **container:**_id_: reuse another container's network stack;
636644
- **host**: use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure;
637-
- _network-id_: connect to a user-defined network, multiple networks should be comma separated;
645+
- _network-id_: connect to a user-defined network, multiple networks should be comma-separated;
638646
- **ns:**_path_: path to a network namespace to join;
639647
- **private**: create a new namespace for the container (default)
640648
- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options:
@@ -861,6 +869,8 @@ Security Options
861869
- `label=filetype:TYPE` : Set the label file type for the container files
862870
- `label=disable` : Turn off label separation for the container
863871

872+
Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file.
873+
864874
- `mask=/path/1:/path/2` : The paths to mask separated by a colon. A masked path
865875
cannot be accessed inside the container.
866876

@@ -869,13 +879,13 @@ Security Options
869879
- `seccomp=unconfined` : Turn off seccomp confinement for the container
870880
- `seccomp=profile.json` : White listed syscalls seccomp Json file to be used as a seccomp filter
871881

882+
- `proc-opts=OPTIONS` : Comma-separated list of options to use for the /proc mount. More details for the
883+
possible mount options are specified in the **proc(5)** man page.
884+
872885
- `unmask=ALL or /path/1:/path/2` : Paths to unmask separated by a colon. If set to **ALL**, it will
873886
unmask all the paths that are masked or made read only by default.
874887
The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**.
875888

876-
- `proc-opts=OPTIONS` : Comma separated list of options to use for the /proc mount. More details for the
877-
possible mount options are specified at **proc(5)** man page.
878-
879889
Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file.
880890

881891
#### **\-\-shm-size**=*size*
@@ -1093,9 +1103,9 @@ Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman
10931103
bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman
10941104
container. Similarly, `-v SOURCE-VOLUME:/CONTAINER-DIR` will mount the volume
10951105
in the host to the container. If no such named volume exists, Podman will
1096-
create one. The `OPTIONS` are a comma delimited list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, the volumes will be mounted from the remote server, not necessarly the client machine.)
1106+
create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, the volumes will be mounted from the remote server, not necessarly the client machine.)
10971107

1098-
The _options_ is a comma delimited list and can be:
1108+
The _options_ is a comma-separated list and can be:
10991109

11001110
* **rw**|**ro**
11011111
* **z**|**Z**
@@ -1185,7 +1195,7 @@ host into the container to allow speeding up builds.
11851195
Content mounted into the container is labeled with the private label.
11861196
On SELinux systems, labels in the source directory must be readable
11871197
by the container label. Usually containers can read/execute `container_share_t`
1188-
and can read/write `container_file_t`. If you can not change the labels on a
1198+
and can read/write `container_file_t`. If you cannot change the labels on a
11891199
source volume, SELinux container separation must be disabled for the container
11901200
to work.
11911201
- The source directory mounted into the container with an overlay mount
@@ -1245,10 +1255,14 @@ will convert /foo into a `shared` mount point. Alternatively one can directly
12451255
change propagation properties of source mount. Say `/` is source mount for
12461256
`/foo`, then use `mount --make-shared /` to convert `/` into a `shared` mount.
12471257

1258+
Note: if the user only has access rights via a group, accessing the volume
1259+
from inside a rootless container will fail. Use the `--group-add keep-groups`
1260+
flag to pass the user's supplementary group access into the container.
1261+
12481262
#### **\-\-volumes-from**[=*CONTAINER*[:*OPTIONS*]]
12491263

12501264
Mount volumes from the specified container(s). Used to share volumes between
1251-
containers. The *options* is a comma delimited list with the following available elements:
1265+
containers. The *options* is a comma-separated list with the following available elements:
12521266

12531267
* **rw**|**ro**
12541268
* **z**
@@ -1351,6 +1365,11 @@ $ podman create --name container1 -t -i fedora bash
13511365
$ podman create --name container2 -t -i fedora bash
13521366
$ podman create --name container3 --requires container1,container2 -t -i fedora bash
13531367
$ podman start --attach container3
1368+
1369+
### Configure keep supplemental groups for access to volume
1370+
1371+
```
1372+
$ podman create -v /var/lib/design:/var/lib/design --group-add keep-groups ubi8
13541373
```
13551374
13561375
### Rootless Containers

docs/source/markdown/podman-pod-create.1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ If another pod with the same name already exists, replace and remove it. The de
125125

126126
#### **\-\-share**=*namespace*
127127

128-
A comma delimited list of kernel namespaces to share. If none or "" is specified, no namespaces will be shared. The namespaces to choose from are ipc, net, pid, uts.
128+
A comma-separated list of kernel namespaces to share. If none or "" is specified, no namespaces will be shared. The namespaces to choose from are ipc, net, pid, uts.
129129

130130
The operator can identify a pod in three ways:
131131
UUID long identifier (“f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778”)

docs/source/markdown/podman-run.1.md

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,8 @@ Note: if _host_device_ is a symbolic link then it will be resolved first.
299299
The container will only store the major and minor numbers of the host device.
300300

301301
Note: if the user only has access rights via a group, accessing the device
302-
from inside a rootless container will fail. The **crun**(1) runtime offers a
303-
workaround for this by adding the option **\-\-annotation run.oci.keep_original_groups=1**.
302+
from inside a rootless container will fail. Use the `--group-add keep-groups`
303+
flag to pass the user's supplementary group access into the container.
304304

305305
Podman may load kernel modules required for using the specified
306306
device. The devices that Podman will load modules when necessary are:
@@ -405,9 +405,17 @@ Meaning **groupname** is initially mapped to gid **100000** which is referenced
405405
above: The group **groupname** is mapped to group **100000** of the initial namespace then the
406406
**30000**st id of this namespace (which is gid 130000 in this namespace) is mapped to container namespace group id **0**. (groupname -> 100000 / 30000 -> 0)
407407

408-
#### **\-\-group-add**=*group*
408+
#### **\-\-group-add**=*group|keep-groups*
409409

410-
Add additional groups to run as
410+
Add additional groups to assign to primary user running within the container process.
411+
412+
- `keep-groups` is a special flag that tells Podman to keep the supplementary group access.
413+
414+
Allows container to use the user's supplementary group access. If file systems or
415+
devices are only accessible by the rootless user's group, this flag tells the OCI
416+
runtime to pass the group access into the container. Currently only available
417+
with the `crun` OCI runtime. Note: `keep-groups` is exclusive, you cannot add any other groups
418+
with this flag. (Not available for remote commands)
411419

412420
#### **\-\-health-cmd**=*"command"* | *'["command", "arg1", ...]'*
413421

@@ -670,7 +678,7 @@ Valid _mode_ values are:
670678
- **none**: no networking;
671679
- **container:**_id_: reuse another container's network stack;
672680
- **host**: use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure;
673-
- _network-id_: connect to a user-defined network, multiple networks should be comma separated;
681+
- _network-id_: connect to a user-defined network, multiple networks should be comma-separated;
674682
- **ns:**_path_: path to a network namespace to join;
675683
- **private**: create a new namespace for the container (default)
676684
- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options:
@@ -905,19 +913,27 @@ Security Options
905913

906914
- **apparmor=unconfined** : Turn off apparmor confinement for the container
907915
- **apparmor**=_your-profile_ : Set the apparmor confinement profile for the container
916+
908917
- **label=user:**_USER_: Set the label user for the container processes
909918
- **label=role:**_ROLE_: Set the label role for the container processes
910919
- **label=type:**_TYPE_: Set the label process type for the container processes
911920
- **label=level:**_LEVEL_: Set the label level for the container processes
912921
- **label=filetype:**TYPE_: Set the label file type for the container files
913922
- **label=disable**: Turn off label separation for the container
923+
924+
Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file.
925+
914926
- **mask**=_/path/1:/path/2_: The paths to mask separated by a colon. A masked path
915927
cannot be accessed inside the container.
928+
916929
- **no-new-privileges**: Disable container processes from gaining additional privileges
930+
917931
- **seccomp=unconfined**: Turn off seccomp confinement for the container
918932
- **seccomp**=_profile.json_: Allowed syscall list seccomp JSON file to be used as a seccomp filter
919-
- **proc-opts**=_OPTIONS_ : Comma separated list of options to use for the /proc mount. More details
920-
for the possible mount options are specified at **proc(5)** man page.
933+
934+
- **proc-opts**=_OPTIONS_ : Comma-separated list of options to use for the /proc mount. More details
935+
for the possible mount options are specified in the **proc(5)** man page.
936+
921937
- **unmask**=_ALL_ or _/path/1:/path/2_: Paths to unmask separated by a colon. If set to **ALL**, it will
922938
unmask all the paths that are masked or made read only by default.
923939
The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.**. The default paths that are read only are **/proc/asound**, **/proc/bus**, **/proc/fs**, **/proc/irq**, **/proc/sys**, **/proc/sysrq-trigger**, **/sys/fs/cgroup**.
@@ -1164,7 +1180,7 @@ container. Similarly, _SOURCE-VOLUME_:_/CONTAINER-DIR_ will mount the volume
11641180
in the host to the container. If no such named volume exists, Podman will
11651181
create one. (Note when using the remote client, the volumes will be mounted from the remote server, not necessarly the client machine.)
11661182

1167-
The _options_ is a comma delimited list and can be: <sup>[[1]](#Footnote1)</sup>
1183+
The _options_ is a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup>
11681184

11691185
* **rw**|**ro**
11701186
* **z**|**Z**
@@ -1252,7 +1268,7 @@ host into the container to allow speeding up builds.
12521268
Content mounted into the container is labeled with the private label.
12531269
On SELinux systems, labels in the source directory must be readable
12541270
by the container label. Usually containers can read/execute `container_share_t`
1255-
and can read/write `container_file_t`. If you can not change the labels on a
1271+
and can read/write `container_file_t`. If you cannot change the labels on a
12561272
source volume, SELinux container separation must be disabled for the container
12571273
to work.
12581274
- The source directory mounted into the container with an overlay mount
@@ -1314,10 +1330,14 @@ will convert /foo into a shared mount point. Alternatively, one can directly
13141330
change propagation properties of source mount. Say, if _/_ is source mount for
13151331
_/foo_, then use **mount --make-shared /** to convert _/_ into a shared mount.
13161332

1333+
Note: if the user only has access rights via a group, accessing the volume
1334+
from inside a rootless container will fail. Use the `--group-add keep-groups`
1335+
flag to pass the user's supplementary group access into the container.
1336+
13171337
#### **\-\-volumes-from**[=*CONTAINER*[:*OPTIONS*]]
13181338

13191339
Mount volumes from the specified container(s). Used to share volumes between
1320-
containers. The *options* is a comma delimited list with the following available elements:
1340+
containers. The *options* is a comma-separated list with the following available elements:
13211341

13221342
* **rw**|**ro**
13231343
* **z**
@@ -1699,6 +1719,11 @@ Multiple containers can be required.
16991719
$ podman create --name container1 -t -i fedora bash
17001720
$ podman create --name container2 -t -i fedora bash
17011721
$ podman run --name container3 --requires container1,container2 -t -i fedora bash
1722+
1723+
### Configure keep supplemental groups for access to volume
1724+
1725+
```
1726+
$ podman run -v /var/lib/design:/var/lib/design --group-add keep-groups ubi8
17021727
```
17031728
17041729
### Rootless Containers

test/system/170-run-userns.bats

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bats -*- bats -*-
2+
# shellcheck disable=SC2096
3+
#
4+
# Tests for podman build
5+
#
6+
7+
load helpers
8+
9+
@test "podman --group-add keep-groups while in a userns" {
10+
skip_if_rootless "choot is not allowed in rootless mode"
11+
skip_if_remote "--group-add keep-groups not supported in remote mode"
12+
run chroot --groups 1234 / ${PODMAN} run --uidmap 0:200000:5000 --group-add keep-groups $IMAGE id
13+
is "$output" ".*65534(nobody)" "Check group leaked into user namespace"
14+
}
15+
16+
@test "podman --group-add keep-groups while not in a userns" {
17+
skip_if_rootless "choot is not allowed in rootless mode"
18+
skip_if_remote "--group-add keep-groups not supported in remote mode"
19+
run chroot --groups 1234,5678 / ${PODMAN} run --group-add keep-groups $IMAGE id
20+
is "$output" ".*1234" "Check group leaked into container"
21+
}
22+
23+
@test "podman --group-add without keep-groups while in a userns" {
24+
skip_if_rootless "choot is not allowed in rootless mode"
25+
skip_if_remote "--group-add keep-groups not supported in remote mode"
26+
run chroot --groups 1234,5678 / ${PODMAN} run --uidmap 0:200000:5000 --group-add 457 $IMAGE id
27+
is "$output" ".*457" "Check group leaked into container"
28+
}
29+
30+
@test "podman --remote --group-add keep-groups " {
31+
if is_remote; then
32+
run_podman 125 run --group-add keep-groups $IMAGE id
33+
is "$output" ".*not supported in remote mode" "Remote check --group-add keep-groups"
34+
fi
35+
}
36+
37+
@test "podman --group-add without keep-groups " {
38+
run_podman run --group-add 457 $IMAGE id
39+
is "$output" ".*457" "Check group leaked into container"
40+
}
41+
42+
@test "podman --group-add keep-groups plus added groups " {
43+
run_podman 125 run --group-add keep-groups --group-add 457 $IMAGE id
44+
is "$output" ".*the '--group-add keep-groups' option is not allowed with any other --group-add options" "Check group leaked into container"
45+
}

0 commit comments

Comments
 (0)