From acaab3fa72e5850c7976dddb6441e85dc568c0fe Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Sat, 4 Feb 2023 07:50:54 -0500 Subject: [PATCH] Add SELinux label types support to quadlet Add support for disabeling SELinux process separation in the container. Add support for setting the process type of the container. Add support for setting the process MCS level of the container. Add support for setting the file type of the container. Signed-off-by: Daniel J Walsh --- docs/source/markdown/podman-systemd.unit.5.md | 16 ++ pkg/systemd/quadlet/quadlet.go | 178 ++++++++++-------- test/e2e/quadlet/disableselinux.container | 5 + test/e2e/quadlet/selinux.container | 9 + test/e2e/quadlet_test.go | 2 + test/system/252-quadlet.bats | 52 +++++ 6 files changed, 187 insertions(+), 75 deletions(-) create mode 100644 test/e2e/quadlet/disableselinux.container create mode 100644 test/e2e/quadlet/selinux.container diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md index d959f44d93..e5e0d12c8d 100644 --- a/docs/source/markdown/podman-systemd.unit.5.md +++ b/docs/source/markdown/podman-systemd.unit.5.md @@ -283,6 +283,22 @@ container that forwards signals and reaps processes. Set the seccomp profile to use in the container. If unset, the default podman profile is used. Set to either the pathname of a json file, or `unconfined` to disable the seccomp filters. +#### `SecurityLabelDisable=` + +Turn off label separation for the container. + +#### `SecurityLabelFileType=` + +Set the label file type for the container files. + +#### `SecurityLabelLevel=` + +Set the label process level for the container processes. + +#### `SecurityLabelType=` + +Set the label process type for the container processes. + #### `Timezone=` (if unset uses system-configured default) The timezone to run the container in. diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go index 3c7f6e2e76..2c32e3c13a 100644 --- a/pkg/systemd/quadlet/quadlet.go +++ b/pkg/systemd/quadlet/quadlet.go @@ -31,51 +31,55 @@ const ( // All the supported quadlet keys const ( - KeyContainerName = "ContainerName" - KeyImage = "Image" - KeyEnvironment = "Environment" - KeyEnvironmentFile = "EnvironmentFile" - KeyEnvironmentHost = "EnvironmentHost" - KeyExec = "Exec" - KeyNoNewPrivileges = "NoNewPrivileges" - KeyDropCapability = "DropCapability" - KeyAddCapability = "AddCapability" - KeyReadOnly = "ReadOnly" - KeyRemapUsers = "RemapUsers" - KeyRemapUID = "RemapUid" - KeyRemapGID = "RemapGid" - KeyRemapUIDSize = "RemapUidSize" - KeyRootfs = "Rootfs" - KeyNotify = "Notify" - KeyExposeHostPort = "ExposeHostPort" - KeyPublishPort = "PublishPort" - KeyUser = "User" - KeyGroup = "Group" - KeyDevice = "Device" - KeyType = "Type" - KeyOptions = "Options" - KeyCopy = "Copy" - KeyVolume = "Volume" - KeyPodmanArgs = "PodmanArgs" - KeyLabel = "Label" - KeyAnnotation = "Annotation" - KeyRunInit = "RunInit" - KeyVolatileTmp = "VolatileTmp" - KeyTimezone = "Timezone" - KeySeccompProfile = "SeccompProfile" - KeyAddDevice = "AddDevice" - KeyNetwork = "Network" - KeyYaml = "Yaml" - KeyNetworkDisableDNS = "DisableDNS" - KeyNetworkDriver = "Driver" - KeyNetworkGateway = "Gateway" - KeyNetworkInternal = "Internal" - KeyNetworkIPRange = "IPRange" - KeyNetworkIPAMDriver = "IPAMDriver" - KeyNetworkIPv6 = "IPv6" - KeyNetworkOptions = "Options" - KeyNetworkSubnet = "Subnet" - KeyConfigMap = "ConfigMap" + KeyContainerName = "ContainerName" + KeyImage = "Image" + KeyEnvironment = "Environment" + KeyEnvironmentFile = "EnvironmentFile" + KeyEnvironmentHost = "EnvironmentHost" + KeyExec = "Exec" + KeyNoNewPrivileges = "NoNewPrivileges" + KeyDropCapability = "DropCapability" + KeyAddCapability = "AddCapability" + KeyReadOnly = "ReadOnly" + KeyRemapUsers = "RemapUsers" + KeyRemapUID = "RemapUid" + KeyRemapGID = "RemapGid" + KeyRemapUIDSize = "RemapUidSize" + KeyRootfs = "Rootfs" + KeyNotify = "Notify" + KeyExposeHostPort = "ExposeHostPort" + KeyPublishPort = "PublishPort" + KeyUser = "User" + KeyGroup = "Group" + KeyDevice = "Device" + KeyType = "Type" + KeyOptions = "Options" + KeyCopy = "Copy" + KeyVolume = "Volume" + KeyPodmanArgs = "PodmanArgs" + KeyLabel = "Label" + KeyAnnotation = "Annotation" + KeyRunInit = "RunInit" + KeyVolatileTmp = "VolatileTmp" + KeyTimezone = "Timezone" + KeySeccompProfile = "SeccompProfile" + KeySecurityLabelDisable = "SecurityLabelDisable" + KeySecurityLabelFileType = "SecurityLabelFileType" + KeySecurityLabelType = "SecurityLabelType" + KeySecurityLabelLevel = "SecurityLabelLevel" + KeyAddDevice = "AddDevice" + KeyNetwork = "Network" + KeyYaml = "Yaml" + KeyNetworkDisableDNS = "DisableDNS" + KeyNetworkDriver = "Driver" + KeyNetworkGateway = "Gateway" + KeyNetworkInternal = "Internal" + KeyNetworkIPRange = "IPRange" + KeyNetworkIPAMDriver = "IPAMDriver" + KeyNetworkIPv6 = "IPv6" + KeyNetworkOptions = "Options" + KeyNetworkSubnet = "Subnet" + KeyConfigMap = "ConfigMap" ) var ( @@ -83,36 +87,40 @@ var ( // Supported keys in "Container" group supportedContainerKeys = map[string]bool{ - KeyContainerName: true, - KeyImage: true, - KeyEnvironment: true, - KeyEnvironmentFile: true, - KeyEnvironmentHost: true, - KeyExec: true, - KeyNoNewPrivileges: true, - KeyDropCapability: true, - KeyAddCapability: true, - KeyReadOnly: true, - KeyRemapUsers: true, - KeyRemapUID: true, - KeyRemapGID: true, - KeyRemapUIDSize: true, - KeyRootfs: true, - KeyNotify: true, - KeyExposeHostPort: true, - KeyPublishPort: true, - KeyUser: true, - KeyGroup: true, - KeyVolume: true, - KeyPodmanArgs: true, - KeyLabel: true, - KeyAnnotation: true, - KeyRunInit: true, - KeyVolatileTmp: true, - KeyTimezone: true, - KeySeccompProfile: true, - KeyAddDevice: true, - KeyNetwork: true, + KeyContainerName: true, + KeyImage: true, + KeyEnvironment: true, + KeyEnvironmentFile: true, + KeyEnvironmentHost: true, + KeyExec: true, + KeyNoNewPrivileges: true, + KeyDropCapability: true, + KeyAddCapability: true, + KeyReadOnly: true, + KeyRemapUsers: true, + KeyRemapUID: true, + KeyRemapGID: true, + KeyRemapUIDSize: true, + KeyRootfs: true, + KeyNotify: true, + KeyExposeHostPort: true, + KeyPublishPort: true, + KeyUser: true, + KeyGroup: true, + KeyVolume: true, + KeyPodmanArgs: true, + KeyLabel: true, + KeyAnnotation: true, + KeyRunInit: true, + KeyVolatileTmp: true, + KeyTimezone: true, + KeySeccompProfile: true, + KeySecurityLabelDisable: true, + KeySecurityLabelFileType: true, + KeySecurityLabelType: true, + KeySecurityLabelLevel: true, + KeyAddDevice: true, + KeyNetwork: true, } // Supported keys in "Volume" group @@ -353,6 +361,26 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile podman.add("--security-opt=no-new-privileges") } + securityLabelDisable := container.LookupBooleanWithDefault(ContainerGroup, KeySecurityLabelDisable, false) + if securityLabelDisable { + podman.add("--security-opt", "label:disable") + } + + securityLabelType, _ := container.Lookup(ContainerGroup, KeySecurityLabelType) + if len(securityLabelType) > 0 { + podman.add("--security-opt", fmt.Sprintf("label=type:%s", securityLabelType)) + } + + securityLabelFileType, _ := container.Lookup(ContainerGroup, KeySecurityLabelFileType) + if len(securityLabelFileType) > 0 { + podman.add("--security-opt", fmt.Sprintf("label=filetype:%s", securityLabelFileType)) + } + + securityLabelLevel, _ := container.Lookup(ContainerGroup, KeySecurityLabelLevel) + if len(securityLabelLevel) > 0 { + podman.add("--security-opt", fmt.Sprintf("label=level:%s", securityLabelLevel)) + } + // But allow overrides with AddCapability devices := container.LookupAllStrv(ContainerGroup, KeyAddDevice) for _, device := range devices { diff --git a/test/e2e/quadlet/disableselinux.container b/test/e2e/quadlet/disableselinux.container new file mode 100644 index 0000000000..5f3182b5cb --- /dev/null +++ b/test/e2e/quadlet/disableselinux.container @@ -0,0 +1,5 @@ +## assert-podman-args "--security-opt" "label:disable" + +[Container] +Image=localhost/imagename +SecurityLabelDisable=true diff --git a/test/e2e/quadlet/selinux.container b/test/e2e/quadlet/selinux.container new file mode 100644 index 0000000000..c4f6ea02fe --- /dev/null +++ b/test/e2e/quadlet/selinux.container @@ -0,0 +1,9 @@ +## assert-podman-args "--security-opt" "label=type:foobar_t" +## assert-podman-args "--security-opt" "label=level:s0:c1000,c10001" +## assert-podman-args "--security-opt" "label=filetype:foobar_file_t" + +[Container] +Image=localhost/imagename +SecurityLabelType=foobar_t +SecurityLabelFileType=foobar_file_t +SecurityLabelLevel=s0:c1000,c10001 diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go index a778e4ddc8..fd1d621e07 100644 --- a/test/e2e/quadlet_test.go +++ b/test/e2e/quadlet_test.go @@ -447,6 +447,7 @@ var _ = Describe("quadlet system generator", func() { Entry("basepodman.container", "basepodman.container"), Entry("capabilities.container", "capabilities.container"), Entry("capabilities2.container", "capabilities2.container"), + Entry("disableselinux.container", "disableselinux.container"), Entry("devices.container", "devices.container"), Entry("env.container", "env.container"), Entry("escapes.container", "escapes.container"), @@ -461,6 +462,7 @@ var _ = Describe("quadlet system generator", func() { Entry("notify.container", "notify.container"), Entry("oneshot.container", "oneshot.container"), Entry("rootfs.container", "rootfs.container"), + Entry("selinux.container", "selinux.container"), Entry("other-sections.container", "other-sections.container"), Entry("podmanargs.container", "podmanargs.container"), Entry("ports.container", "ports.container"), diff --git a/test/system/252-quadlet.bats b/test/system/252-quadlet.bats index d130ee962f..a83be32df7 100644 --- a/test/system/252-quadlet.bats +++ b/test/system/252-quadlet.bats @@ -424,5 +424,57 @@ EOF is "$output" '.*STARTED CONTAINER.*' } +@test "quadlet - selinux disable" { + skip_if_no_selinux + local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).container + cat > $quadlet_file < $quadlet_file <