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 <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh committed 2023-02-06 12:54:34 -05:00
1 parent 928d589b7e
commit acaab3fa72
6 files changed
+187 -75

No files matched your search

@@ -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.
+103 -75
View File
@@ -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 {
@@ -0,0 +1,5 @@
## assert-podman-args "--security-opt" "label:disable"
[Container]
Image=localhost/imagename
SecurityLabelDisable=true
+9
View File
@@ -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
+2
View File
@@ -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"),
+52
View File
@@ -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 <<EOF
[Container]
Image=$IMAGE
SecurityLabelDisable=true
Exec=sh -c "echo STARTED CONTAINER; echo "READY=1" | socat -u STDIN unix-sendto:\$NOTIFY_SOCKET; top"
EOF
run_quadlet "$quadlet_file"
service_setup $QUADLET_SERVICE_NAME
# Ensure we have output. Output is synced via sd-notify (socat in Exec)
run journalctl "--since=$STARTED_TIME" --unit="$QUADLET_SERVICE_NAME"
is "$output" '.*STARTED CONTAINER.*'
run_podman container inspect --format "{{.ProcessLabel}}" $QUADLET_CONTAINER_NAME
is "$output" "" "container should be started without specifying a Process Label"
service_cleanup $QUADLET_SERVICE_NAME failed
}
@test "quadlet - selinux labels" {
skip_if_no_selinux
NAME=$(random_string)
local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).container
cat > $quadlet_file <<EOF
[Container]
ContainerName=$NAME
Image=$IMAGE
SecurityLabelType=spc_t
SecurityLabelLevel=s0:c100,c200
SecurityLabelFileType=container_ro_file_t
Exec=sh -c "echo STARTED CONTAINER; echo "READY=1" | socat -u STDIN unix-sendto:\$NOTIFY_SOCKET; top"
EOF
run_quadlet "$quadlet_file"
service_setup $QUADLET_SERVICE_NAME
# Ensure we have output. Output is synced via sd-notify (socat in Exec)
run journalctl "--since=$STARTED_TIME" --unit="$QUADLET_SERVICE_NAME"
is "$output" '.*STARTED CONTAINER.*'
run_podman container ps
run_podman container inspect --format "{{.ProcessLabel}}" $NAME
is "$output" "system_u:system_r:spc_t:s0:c100,c200" "container should be started with correct Process Label"
run_podman container inspect --format "{{.MountLabel}}" $NAME
is "$output" "system_u:object_r:container_ro_file_t:s0:c100,c200" "container should be started with correct Mount Label"
service_cleanup $QUADLET_SERVICE_NAME failed
}
# vim: filetype=sh