
After looking at this video on the current state of container security I wanted to create seccomp profiles specific to my applications.
As I usually experiment in a virtual machines (or container) when it requires significant changes at the system level I thought it was a good time to test Fedora 32 Silverblue with a real life exercise.
“Fedora Silverblue is an immutable desktop operating system. It aims to be extremely stable and reliable. It also aims to be an excellent platform for developers and for those using container-focused workflows.”
After installing the VM the first step was to create a toolbox:
$ toolbox create
and then to use it 🙂
$ toolbox enter
I just followed the clear instructions provided in this blog post to install the development environment and to build the OCI hook that will record the system calls generated by my container and create a matching seccomp profile.
When I first tried to run my container with podman inside the toolbox it failed. A toolbox runs as an unprivileged container and this issue seems to be blocking podman of running inside an unprivileged container. I could surely have run the toolbox as a privileged container by using the podman command instead of toolbox but I wanted to stay with the Silverblue approach.
To workaround this I installed the OCI hook in folders inside my home directory, which made them available on my Silverblue host. It was not more complicate than setting two environment variables:
$ export HOOK_DIR=/var/home/fgiloux/oci/hooks/config/
$ export HOOK_BIN_DIR=/var/home/fgiloux/oci/hooks/bin
$ make install
The default directories on the host for OCI hooks are /usr/libexec/oci/hooks.d and /usr/share/containers/oci/hooks.d/ Everything under /usr is read-only in Silverblue. This was fine with me and I just kept the OCI hook in my home directory. I then ran my container with the appropriate parameters to generate the seccomp profile:
$ sudo podman run --name fakeapp --hooks-dir=/var/home/fgiloux/oci/hooks/config/ --annotation io.containers.trace-syscall=of:/var/home/fgiloux/rest-json-fakeapp/seccomp.json quay.io/fgiloux/rest-json-fakeapp:1.0-SNAPSHOT / > /dev/null
I made a call to my application (in reality you would run proper soak tests) and checked that everything was fine:
$ sudo podman exec fakeapp curl -s http://localhost:8080/fruits
Then I just had to harvest my seccomp profile. For my REST app built with Java / Quarkus the number of system call types was down from around 300 to 85. That’s quite substantial!
To run my container with my new profile is an easy thing:
$ podman run --name fakeapp --security-opt seccomp=/var/home/fgiloux/rest-json-fakeapp/seccomp.json quay.io/fgiloux/rest-json-fakeapp:1.0-SNAPSHOT / > /dev/null
But what about Kubernetes and OpenShift?
The use of seccomp profiles in pods can be controlled via annotations on the PodSecurityPolicy as documented here. It is possible to specify a profile stored on the host for containers and pods by setting annotations:
seccomp.security.alpha.kubernetes.io/pod: "localhost/profile.json"
container.security.alpha.kubernetes.io/: "localhost/profile.json"
What I would really want actually is an easy way to provision my application specific seccomp profile. Seccomp is however an alpha feature in Kubernetes, although work is being done to make it GA, and it is not possible today. I have good hope that this will be made possible through a ConfigMap or another mean in a near future as it seems to be one of the aim of the seccomp-operator.
For people interested in the subject I would also recommend the reading of Seccomp in Kubernetes — Part I: 7 things you should know before you even start!
To wrap up on my Fedora 32 Silverblue small experiment I really liked it although I only scratched the surface. A few things that are clear to me is what I have described in this blog post is exploration. When I am settled on a change I am unlikely to just manually run commands inside a container/toolbox to configure my environment. I have read that people have been leveraging ansible for getting a reproducible / amendable path. I may use this approach or simple batch scripts with buildah and possibly podman compose if I happen to keep many toolboxes. The bottom line is no “dnf update” but rerunning image creation scripts pointing to newer package versions whenever required.
For now I will keep my Silverblue VM around, try to leverage it and see whether it becomes my default environment soon!