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 <