I’m new to SELinux and it has caused some friction with the migration from CL.
What is the best way of injecting new SELinux policies into a FCOS VM?
Right now I’m declaring the policy changes in CIL format as additional files in FCCT and executing a post-boot/provisioning command to install with sudo semodule but is there a better way?
To expand on above I have found myself having to make SELinux policy changes to allow access to the docker socket so that I can run cadvisor, a prometheus exporter, providing it the ability to give me insight into running containers.
This has involved a bit of ignition such as below and then the execution post-boot of: sudo semodule -i /etc/acme-corp/dockersock.cil
If anyone has a better way to get cadvisor running properly I’d be much obliged.
storage:
files:
# SELinux policies written in cil format can simpy be installed with
# semodule command. We do this as part of post-boot processes. Is there
# an easier way?
- path: /etc/acme-corp/dockersock.cil
mode: 0644
contents:
inline: |
(typeattributeset cil_gen_require docker_var_run_t)
(typeattributeset cil_gen_require docker_t)
(typeattributeset cil_gen_require svirt_lxc_net_t)
(allow svirt_lxc_net_t docker_t (unix_stream_socket (connectto)))
(allow svirt_lxc_net_t docker_var_run_t (sock_file (write)))
Persistently amending SELinux policies like this is to be avoided because FCOS upgrades that update the SELinux policies can result in various failure modes.
In terms of running processes that need to access the docker socket such as cadvisor it is probably preferable to run a privileged container instead of modifying the policies on the docker socket itself. If possible running the privileged container outside of docker, e.g. via podman.
The best way to do modifications like this right now unfortunately is to bundle it inside an RPM scriptlet and pkglayer that RPM. That way rpm-ostree will automatically rebuild the policy on every update.
Updated ignition snippets adding a systemd unit definition that applies the Selinux modifications automatically as a oneshot systemd unit. This negates the need for any post-boot manual activities. However, I’m not aware of the pros/cons when compared to the proposed rpm solution.
...
storage:
files:
# SELinux policies written in cil format can simpy be installed with
# semodule command. We do this as part of post-boot processes. Is there
# an easier way?
- path: /etc/acme-corp/dockersock.cil
mode: 0644
contents:
inline: |
(typeattributeset cil_gen_require docker_var_run_t)
(typeattributeset cil_gen_require docker_t)
(typeattributeset cil_gen_require svirt_lxc_net_t)
(allow svirt_lxc_net_t docker_t (unix_stream_socket (connectto)))
(allow svirt_lxc_net_t docker_var_run_t (sock_file (write)))
...
systemd:
units:
- name: acme-selinux-policy.service
enabled: true
contents: |
[Service]
Type=oneshot
ExecStart=/usr/sbin/semodule -i /etc/acme/dockersock.cil
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Having policy changes packaged as an RPM will trigger the policy rebuild while rpm-ostree is deploying the update before the next boot as the content will be included in the ostree image. This thus avoid having to rebuild and reload the policy at boot time which is not ideal and will slow down bootup.
(A bit late, but for posterity.) Note this has the same issue, which is that the SELinux policy will be marked as modified and will no longer be updated with the base. If you’ve already deployed this, I recommend following the steps in RFE: safe SELinux policy updates · Issue #701 · coreos/fedora-coreos-tracker · GitHub to get back to the base policy to avoid issues in the future.