Skip to content

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 the USER clause is done in the Dockerfile directly.
  • 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:

  1. runners.kubernetes.service_container_security_context should be an array of dicts, instead of a single dict.
  2. Add image_selector to those dicts. The syntax of that option would be the same as for allowed_services. The default value would be [*/*:*] to apply it to all services that have no other more specific selector.
  3. When running a job, use image_selector attribute to select the desired runners.kubernetes.service_container_security_context and 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.

Edited by Jairo Llopis