DEV Community

coulof
coulof

Posted on • Originally published at storage-chaos.io on

K8s mount PV with SELinux

TL; DR

If you want to use Kubernetes with SELinux and mount PersistentVolume, you have to make sure your mounted FS has labels. You can do it with the mountOptions -o context="system_u:object_r:container_var_lib_t:s0" and if your driver doesn’t support it, you can write an SELinux policy like this one.

The premise

The problem came from a customer who is using Docker Enterprise with CSI Driver for VxFlexOS (now PowerFlex), and SELinux enforced on the nodes.

Anytime a Pod tried to write data on the PersistentVolume, we had Permission denied error from the OS.

SELinux relies on file label (sometimes call context) in the file extended attributes to apply its policies. For examples below :

ls -lZd /root /home /etc
drwxr-xr-x. root root system_u:object_r:etc_t:s0 /etc
drwxr-xr-x. root root system_u:object_r:home_root_t:s0 /home
dr-xr-x---. root root system_u:object_r:admin_home_t:s0 /root

By default, on a newly formatted and mounted FS the files are unlabeled :

mkfs.ext4 /dev/loop0
mount -o loop /dev/loop0 /media/xxx
ls -Z
drwxr-xr-x. root root system_u:object_r:unlabeled_t:s0 xxx

On the customer setup, it was forbidden to do any action on an unlabeled file.

How to get the new FS labeled ?

The typical way to relabel a directory is to use the command restorecon against the mount point, which will restore the security context and label.Because we are in a containerized environment with volumes dynamically mounted by Kubernetes, this is not realistic to expect the restorecon command to be executed each time a volume is mounted.

Another option, especially suitable to big FileSystems with many files, is to can create a file named .autorelabel at the root level, so it forces a relabel on the mountpoint. Slightly better but, still, not feasible in a dynamic environment like ours.

A better option is to mount the FS with the context option. That option is my favorite ❣

Unfortunately, the DellEMC CSI drivers don’t have the mountOption capability at the time of that post. That feature is on the roadmap, but in the meantime, I needed a plan B.

The last possibility and the one we implemented is to write a specific policy to allow containers to manipulate unlabeled files and directories.

Since SELinux follows a model of the least-privilege (aka you can’t do anything except if explicitly allowlisted), the challenge was to have all the syscalls a container needs to do their job.

To get inspiration, I hijacked policies given in the SELinux Project and came up with that list : class file { create open getattr setattr read write append rename link unlink ioctl lock };

The full policy is :

module vxflexos-cni 1.0;

require {
    type unlabeled_t;
    type container_t;
    class file { create open getattr setattr read write append rename link unlink ioctl lock };
    class dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink write };
}

#!!!! WARNING: 'unlabeled_t' is a base type.
allow container_t unlabeled_t:dir { create open getattr setattr read write link unlink rename search add_name remove_name reparent rmdir lock ioctl };
allow container_t unlabeled_t:file { create open getattr setattr read write append rename link unlink ioctl lock };

To compile it, you will need the SELinux Devel package (in Fedora : dnf install selinux-policy-devel.noarch will do) and then compile the policy with : make -f /usr/share/selinux/devel/Makefile. To install the newly compiled policy run : semodule -i vxflexos-cni.pp.

Wrap-up

mountOptions capability is coming with every Dell Technologies CSI driver in the incoming months.

The Gentoo website is a gold mine of information for SELinux ! To understand better the issue, I mostly read these pages on Labels, the Tutorial to create a policy, and SELinux Project Policies.

Top comments (0)