Different security context per service using the kubernetes runner
In the docs you can see that, using the kubernetes runner, one can specify a valid security context for the pod and another for each one of the containers using the corresponding sections in config.toml:
- runners.kubernetes.pod_security_context
- runners.kubernetes.init_permissions_container_security_context
- runners.kubernetes.build_container_security_context
- runners.kubernetes.helper_container_security_context
- runners.kubernetes.service_container_security_context (the problematic one)
All of this is almost good enough. But there is a problem: one can run more than 1 service in a CI job. And services can use different images, which can have different settings.
For example, let's say I want to run a service using quay.io/containers/podman and another one using docker.io/postgres in the same pipeline, or at least in the same runner.
When using quay.io/containers/podman, it's most sensible to run the image as UID/GID 1000, which is the podman user inside that image. That user is preconfigured to run rootless container operations. And requires some specific capabilities depending on the use I want to allow. It could even require to be privileged.
However, when using docker.io/postgres, the best is to execute it as UID/GID 999 which is postgres user inside that image, and is the owner of $PGDATA directory.
The only workarounds for now:
- If you want to use the same runner for everything, you'll have to relax security, to allow both workloads. Since UID/GID cannot be specified in
.gitlab-ci.yml, you also need custom images for everything, where theUSERclause is done in theDockerfiledirectly. - If you can use a different runner for each thing, you can register them with different tags and configure the jobs to run with those tags. You still cannot run safely both services in the same job.
The situation is doomed.
The proposed solution:
-
runners.kubernetes.service_container_security_contextshould be an array of dicts, instead of a single dict. - Add
image_selectorto those dicts. The syntax of that option would be the same as forallowed_services. The default value would be[*/*:*]to apply it to all services that have no other more specific selector. - When running a job, use
image_selectorattribute to select the desiredrunners.kubernetes.service_container_security_contextand apply that policy.
Notice that this doesn't happen with the rest of runners.kubernetes.**service_*_container_security_context sections, as the service one is the only that applies to more than a single container at the same time. However, it's true that we could want to have different policies depending on the container that is executed in runners.kubernetes.build_container_security_context. I think that's another issue, but it's also a valid one.