Security-Enhanced Linux (SELinux) is a Linux kernel security module that provides a mechanism for supporting access control security policies, including mandatory access controls (MAC). Containers support running on hosts with SELinux enabled.
If you are just getting started with SeLinux, I highly recommend watching “Security-Enhanced Linux for mere mortals by Thomas Cameron”.
In the cloud, if you are looking to run containers on SELinux you will need to run on top of CentOS or Red Hat Enterprise Linux. These operating systems have the best support for SELinux and the corresponding policy modules.
I have recently been diving into SELinux for use within highly regulated environments. I have attempted to explain how SELinux works with Containers and how you can get started.
SELinux for Containers
SELinux policies for containers are defined by the container-selinux package. Docker CE requires this package (along with its dependencies) so that the processes and files created by Docker are able to run with limited system access. Containers leverage the container_t
label which is simply an alias to svirt_lxc_net_t
and container_file_t
which is an alias to svirt_sandbox_file_t
. More informaton is available on Dan Walsh’s blog.
By default, containers are run with the label container_t
and are allowed to read/execute under /usr
and read most content from /etc
. The files under /var/lib/docker
and /var/lib/containers
have the label container_var_lib_t
.
ls -Z /var/lib/docker
# drwx------. root root system_u:object_r:container_var_lib_t:s0 builder
# drwx--x--x. root root system_u:object_r:container_var_lib_t:s0 buildkit
# drwx------. root root system_u:object_r:container_var_lib_t:s0 containers
# drwx------. root root system_u:object_r:container_var_lib_t:s0 image
# drwx------. root root system_u:object_r:container_var_lib_t:s0 lost+found
# drwxr-x---. root root system_u:object_r:container_var_lib_t:s0 network
# drwx------. root root system_u:object_r:container_share_t:s0 overlay2
# drwx------. root root system_u:object_r:container_var_lib_t:s0 plugins
# drwx------. root root system_u:object_r:container_var_lib_t:s0 runtimes
# drwx------. root root system_u:object_r:container_var_lib_t:s0 swarm
# drwx------. root root system_u:object_r:container_var_lib_t:s0 tmp
# drwx------. root root system_u:object_r:container_var_lib_t:s0 trust
# drwx------. root root system_u:object_r:container_var_lib_t:s0 volumes
ls -Z /etc/docker
# dr--r--r--. root root unconfined_u:object_r:cert_t:s0 certs.d
# -rw-r--r--. root root system_u:object_r:container_config_t:s0 daemon.json
# -rw-------. root root system_u:object_r:container_config_t:s0 key.json
Containers do not have access to these folders because it can interfere with the container engine. The SELinux policy also prevents mounting protected files into containers by default.
docker run -it \
-v /var/lib/docker/image/overlay2/repositories.json:/host/repositories.json \
centos:7 cat /host/repositories.json
# cat: /host/repositories.json: Permission denied
docker run -it \
-v /etc/passwd:/host/etc/passwd \
centos:7 cat /host/etc/passwd
# cat: /host/etc/passwd: Permission denied
Files labeled with container_file_t
are the only files that are writable by containers. If you want a volume mount to be writeable, you will needed to specify :z
or :Z
at the end. Their behavior is different so be careful which one you are using. Let’s start with :z
:
ls -Z /var/lib/misc
# -rw-r--r--. root root system_u:object_r:var_lib_t:s0 postfix.aliasesdb-stamp
docker run -it \
-v /var/lib/misc:/host/var/lib/misc:z \
centos:7 echo "Relabeled!"
ls -Z /var/lib/misc
#-rw-r--r--. root root system_u:object_r:container_file_t:s0 postfix.aliasesdb-stamp
If you want to mount a folder so that only that container can access the folder, for example such as your logging daemon, swap out :z
with :Z
.
docker run -it \
-v /var/log:/host/var/log:Z \
fluentbit:latest
How to Enable SELinux for Containers
Enabling SELinux with containers is only supported on CentOS and Red Hat Enterprise Linux.
Amazon Linux 2 currently lacks the policy modules that make containers work with SELinux.
- Enable SELinux on the host operating system
- Install Docker CE with the
container-selinux
package - Enabled the container cgroup boolean
setsebool container_manage_cgroup 1
- Add
"selinux-enabled": true
to/etc/docker/daemon.json
systemctl daemon-reload && systemctl restart docker
Conclusion
Container linux can be difficult to work with and may interfere with Kubernetes CNI drivers, CSI drivers, and some Ingress Controllers. Some common things to check for are access to privileged ports, or access to files on the host.