Hardening a container that starts as root and drops privileges itself
Some images start as root, chown their data directory and then switch user. runAsNonRoot breaks them. Dropping all capabilities and adding back CHOWN, SETUID and SETGID is the tightest setup that still starts.
I deployed a small web app whose image has an entrypoint that starts as root,
chowns the data directory and then drops to an unprivileged user with
setpriv. The README says nothing about Kubernetes, so I read the Dockerfile
and the entrypoint to see what the container needs.
The obvious hardening, runAsNonRoot: true, would break it: the entrypoint
needs root for the first few lines. The tightest setting that still starts is to
drop every capability and add back only what the entrypoint uses:
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
add: ["CHOWN", "SETUID", "SETGID"]On the cluster the pod starts cleanly, and the main process ends up as uid 1000
with no effective capabilities, which you can read from /proc/1/status (the
Uid and CapEff lines).
One side effect to expect: kubectl exec as root can’t read the data directory
afterwards, because DAC_OVERRIDE is gone too. That’s the hardening working,
not a bug.
The namespace may still warn that the pod starts as root. That’s accurate, and for an image like this the warning is the price of the design.