Skip to content

Commit

Permalink
Merge pull request #20671 from ygalblum/quadlet-uidmap
Browse files Browse the repository at this point in the history
Quadlet - add support for UID and GID Mapping
  • Loading branch information
openshift-merge-bot[bot] authored Nov 16, 2023
2 parents 50f4f59 + e35fc92 commit 638199c
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 14 deletions.
28 changes: 28 additions & 0 deletions docs/source/markdown/podman-systemd.unit.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ Valid options for `[Container]` are listed below:
| EnvironmentHost=true | --env-host |
| Exec=/usr/bin/command | Command after image specification - /usr/bin/command |
| ExposeHostPort=50-59 | --expose 50-59 |
| GIDMap=0:10000:10 | --gidmap=0:10000:10 |
| Group=1234 | --user UID:1234 |
| GlobalArgs=--log-level=debug | --log-level=debug |
| HealthCmd="/usr/bin/command" | --health-cmd="/usr/bin/command" |
Expand Down Expand Up @@ -202,9 +203,12 @@ Valid options for `[Container]` are listed below:
| SecurityLabelNested=true | --security-opt label=nested |
| SecurityLabelType=spc_t | --security-opt label=type:spc_t |
| ShmSize=100m | --shm-size=100m |
| SubGIDMap=gtest | --subgidname=gtest |
| SubUIDMap=utest | --subuidname=utest |
| Sysctl=name=value | --sysctl=name=value |
| Timezone=local | --tz local |
| Tmpfs=/work | --tmpfs /work |
| UIDMap=0:10000:10 | --uidmap=0:10000:10 |
| Ulimit=nofile:1000:10000 | --ulimit nofile:1000:10000 |
| User=bin | --user bin |
| UserNS=keep-id:uid=200,gid=210 | --userns keep-id:uid=200,gid=210 |
Expand Down Expand Up @@ -320,6 +324,13 @@ to the Podman `--expose` option.

This key can be listed multiple times.

### `GIDMap=`

Run the container in a new user namespace using the supplied GID mapping.
Equivalent to the Podman `--gidmap` option.

This key can be listed multiple times.

### `GlobalArgs=`

This key contains a list of arguments passed directly between `podman` and `run`
Expand Down Expand Up @@ -574,6 +585,16 @@ Size of /dev/shm.

This is equivalent to the Podman `--shm-size` option and generally has the form `number[unit]`

### `SubGIDMap=`

Run the container in a new user namespace using the map with name in the /etc/subgid file.
Equivalent to the Podman `--subgidname` option.

### `SubUIDMap=`

Run the container in a new user namespace using the map with name in the /etc/subuid file.
Equivalent to the Podman `--subuidname` option.

### `Sysctl=`

Configures namespaced kernel parameters for the container. The format is `Sysctl=name=value`.
Expand All @@ -596,6 +617,13 @@ This key can be listed multiple times.

The timezone to run the container in.

### `UIDMap=`

Run the container in a new user namespace using the supplied UID mapping.
Equivalent to the Podman `--uidmap` option.

This key can be listed multiple times.

### `Ulimit=`

Ulimit options. Sets the ulimits values inside of the container.
Expand Down
64 changes: 50 additions & 14 deletions pkg/systemd/quadlet/quadlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const (
KeyExec = "Exec"
KeyExitCodePropagation = "ExitCodePropagation"
KeyExposeHostPort = "ExposeHostPort"
KeyGIDMap = "GIDMap"
KeyGlobalArgs = "GlobalArgs"
KeyGroup = "Group"
KeyHealthCmd = "HealthCmd"
Expand Down Expand Up @@ -132,11 +133,14 @@ const (
KeySecurityLabelType = "SecurityLabelType"
KeySetWorkingDirectory = "SetWorkingDirectory"
KeyShmSize = "ShmSize"
KeySubGIDMap = "SubGIDMap"
KeySubUIDMap = "SubUIDMap"
KeySysctl = "Sysctl"
KeyTimezone = "Timezone"
KeyTLSVerify = "TLSVerify"
KeyTmpfs = "Tmpfs"
KeyType = "Type"
KeyUIDMap = "UIDMap"
KeyUlimit = "Ulimit"
KeyUnmask = "Unmask"
KeyUser = "User"
Expand Down Expand Up @@ -169,6 +173,7 @@ var (
KeyEnvironmentHost: true,
KeyExec: true,
KeyExposeHostPort: true,
KeyGIDMap: true,
KeyGlobalArgs: true,
KeyGroup: true,
KeyHealthCmd: true,
Expand Down Expand Up @@ -213,9 +218,12 @@ var (
KeySecurityLabelNested: true,
KeySecurityLabelType: true,
KeyShmSize: true,
KeySubGIDMap: true,
KeySubUIDMap: true,
KeySysctl: true,
KeyTimezone: true,
KeyTmpfs: true,
KeyUIDMap: true,
KeyUlimit: true,
KeyUnmask: true,
KeyUser: true,
Expand Down Expand Up @@ -625,12 +633,10 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
podman.addf("-w=%s", workdir)
}

if err := handleUserRemap(container, ContainerGroup, podman, isUser, true); err != nil {
if err := handleUserMappings(container, ContainerGroup, podman, isUser, true); err != nil {
return nil, err
}

handleUserNS(container, ContainerGroup, podman)

tmpfsValues := container.LookupAll(ContainerGroup, KeyTmpfs)
for _, tmpfs := range tmpfsValues {
if strings.Count(tmpfs, ":") > 1 {
Expand Down Expand Up @@ -1091,12 +1097,10 @@ func ConvertKube(kube *parser.UnitFile, names map[string]string, isUser bool) (*

handleLogDriver(kube, KubeGroup, execStart)

if err := handleUserRemap(kube, KubeGroup, execStart, isUser, false); err != nil {
if err := handleUserMappings(kube, KubeGroup, execStart, isUser, false); err != nil {
return nil, err
}

handleUserNS(kube, KubeGroup, execStart)

addNetworks(kube, KubeGroup, service, names, execStart)

updateMaps := kube.LookupAllStrv(KubeGroup, KeyAutoUpdate)
Expand Down Expand Up @@ -1245,12 +1249,50 @@ func handleUser(unitFile *parser.UnitFile, groupName string, podman *PodmanCmdli
return nil
}

func handleUserRemap(unitFile *parser.UnitFile, groupName string, podman *PodmanCmdline, isUser, supportManual bool) error {
// ignore Remap keys if UserNS is set
func handleUserMappings(unitFile *parser.UnitFile, groupName string, podman *PodmanCmdline, isUser, supportManual bool) error {
mappingsDefined := false

if userns, ok := unitFile.Lookup(groupName, KeyUserNS); ok && len(userns) > 0 {
podman.add("--userns", userns)
mappingsDefined = true
}

uidMaps := unitFile.LookupAllStrv(groupName, KeyUIDMap)
mappingsDefined = mappingsDefined || len(uidMaps) > 0
for _, uidMap := range uidMaps {
podman.addf("--uidmap=%s", uidMap)
}

gidMaps := unitFile.LookupAllStrv(groupName, KeyGIDMap)
mappingsDefined = mappingsDefined || len(gidMaps) > 0
for _, gidMap := range gidMaps {
podman.addf("--gidmap=%s", gidMap)
}

if subUIDMap, ok := unitFile.Lookup(groupName, KeySubUIDMap); ok && len(subUIDMap) > 0 {
podman.add("--subuidname", subUIDMap)
mappingsDefined = true
}

if subGIDMap, ok := unitFile.Lookup(groupName, KeySubGIDMap); ok && len(subGIDMap) > 0 {
podman.add("--subgidname", subGIDMap)
mappingsDefined = true
}

if mappingsDefined {
_, hasRemapUID := unitFile.Lookup(groupName, KeyRemapUID)
_, hasRemapGID := unitFile.Lookup(groupName, KeyRemapGID)
_, RemapUsers := unitFile.LookupLast(groupName, KeyRemapUsers)
if hasRemapUID || hasRemapGID || RemapUsers {
return fmt.Errorf("deprecated Remap keys are set along with explicit mapping keys")
}
return nil
}

return handleUserRemap(unitFile, groupName, podman, isUser, supportManual)
}

func handleUserRemap(unitFile *parser.UnitFile, groupName string, podman *PodmanCmdline, isUser, supportManual bool) error {
uidMaps := unitFile.LookupAllStrv(groupName, KeyRemapUID)
gidMaps := unitFile.LookupAllStrv(groupName, KeyRemapGID)
remapUsers, _ := unitFile.LookupLast(groupName, KeyRemapUsers)
Expand Down Expand Up @@ -1315,12 +1357,6 @@ func handleUserRemap(unitFile *parser.UnitFile, groupName string, podman *Podman
return nil
}

func handleUserNS(unitFile *parser.UnitFile, groupName string, podman *PodmanCmdline) {
if userns, ok := unitFile.Lookup(groupName, KeyUserNS); ok && len(userns) > 0 {
podman.add("--userns", userns)
}
}

func addNetworks(quadletUnitFile *parser.UnitFile, groupName string, serviceUnitFile *parser.UnitFile, names map[string]string, podman *PodmanCmdline) {
networks := quadletUnitFile.LookupAll(groupName, KeyNetwork)
for _, network := range networks {
Expand Down
10 changes: 10 additions & 0 deletions test/e2e/quadlet/idmapping-with-remap.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## assert-failed
## assert-stderr-contains "deprecated Remap keys are set along with explicit mapping keys"

[Container]
Image=localhost/imagename
UIDMap=0:10000:10
UIDMap=10:20000:10
GIDMap=0:10000:10
GIDMap=10:20000:10
RemapUsers=auto
11 changes: 11 additions & 0 deletions test/e2e/quadlet/idmapping.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## assert-podman-args "--uidmap=0:10000:10"
## assert-podman-args "--uidmap=10:20000:10"
## assert-podman-args "--gidmap=0:10000:10"
## assert-podman-args "--gidmap=10:20000:10"

[Container]
Image=localhost/imagename
UIDMap=0:10000:10
UIDMap=10:20000:10
GIDMap=0:10000:10
GIDMap=10:20000:10
8 changes: 8 additions & 0 deletions test/e2e/quadlet/subidmapping-with-remap.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## assert-failed
## assert-stderr-contains "deprecated Remap keys are set along with explicit mapping keys"

[Container]
Image=localhost/imagename
SubUIDMap=utest
SubGIDMap=gtest
RemapUsers=auto
7 changes: 7 additions & 0 deletions test/e2e/quadlet/subidmapping.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-args "--subuidname" "utest"
## assert-podman-args "--subgidname" "gtest"

[Container]
Image=localhost/imagename
SubUIDMap=utest
SubGIDMap=gtest
7 changes: 7 additions & 0 deletions test/e2e/quadlet/userns-with-remap.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-failed
## assert-stderr-contains "deprecated Remap keys are set along with explicit mapping keys"

[Container]
Image=localhost/imagename
RemapUsers=auto
UserNS=keep-id
5 changes: 5 additions & 0 deletions test/e2e/quadlet/userns.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## assert-podman-args "--userns" "keep-id"

[Container]
Image=localhost/imagename
UserNS=keep-id
6 changes: 6 additions & 0 deletions test/e2e/quadlet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,8 @@ BOGUS=foo
Entry("exec.container", "exec.container", 0, ""),
Entry("health.container", "health.container", 0, ""),
Entry("hostname.container", "hostname.container", 0, ""),
Entry("idmapping.container", "idmapping.container", 0, ""),
Entry("idmapping-with-remap.container", "idmapping-with-remap.container", 1, "converting \"idmapping-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys"),
Entry("image.container", "image.container", 0, ""),
Entry("install.container", "install.container", 0, ""),
Entry("ip.container", "ip.container", 0, ""),
Expand Down Expand Up @@ -733,10 +735,14 @@ BOGUS=foo
Entry("selinux.container", "selinux.container", 0, ""),
Entry("shmsize.container", "shmsize.container", 0, ""),
Entry("shortname.container", "shortname.container", 0, "Warning: shortname.container specifies the image \"shortname\" which not a fully qualified image name. This is not ideal for performance and security reasons. See the podman-pull manpage discussion of short-name-aliases.conf for details."),
Entry("subidmapping.container", "subidmapping.container", 0, ""),
Entry("subidmapping-with-remap.container", "subidmapping-with-remap.container", 1, "converting \"subidmapping-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys"),
Entry("sysctl.container", "sysctl.container", 0, ""),
Entry("timezone.container", "timezone.container", 0, ""),
Entry("unmask.container", "unmask.container", 0, ""),
Entry("user.container", "user.container", 0, ""),
Entry("userns.container", "userns.container", 0, ""),
Entry("userns-with-remap.container", "userns-with-remap.container", 1, "converting \"userns-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys"),
Entry("volume.container", "volume.container", 0, ""),
Entry("workingdir.container", "workingdir.container", 0, ""),
Entry("Container - global args", "globalargs.container", 0, ""),
Expand Down

0 comments on commit 638199c

Please sign in to comment.