mirror of
https://github.com/containers/podman.git
synced 2026-10-24 10:49:10 -04:00
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:
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
@@ -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
|
||||
@@ -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
|
||||
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
Reference in new issue
Block a user