From 7f9d88ff00edeeb7145647fe65fbf36b04c23dd4 Mon Sep 17 00:00:00 2001 From: Henrik Brautaset Aronsen Date: Fri, 12 Jun 2026 16:01:11 +0200 Subject: [PATCH] fix(common): honor uid per entry in the containers list uid set on containers[] entries was silently ignored: the pod securityContext only read container.uid (singular) and fell back to the default 1000, and the per-container securityContext never set runAsUser. Pods using the containers list always ran as uid 1000. The pod securityContext (incl. fsGroup) now follows the first container entry's uid, and each entry's uid renders as runAsUser/runAsGroup on its own container. Same fix applied to cron.yaml. Single-container pods run as the same uid as before; the only rendered change is that each container's securityContext now also spells out runAsUser/runAsGroup (previously only the pod-level securityContext did). --- .gitignore | 2 + UPGRADE.md | 6 +++ charts/common/templates/_helpers.tpl | 4 ++ charts/common/templates/cron.yaml | 7 +-- charts/common/templates/deployment.yaml | 7 +-- charts/common/tests/cron_test.yaml | 28 ++++++++++- charts/common/tests/deployment_test.yaml | 64 ++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index f494b1b..df53122 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .tool-versions +.claude/ +.idea/ diff --git a/UPGRADE.md b/UPGRADE.md index 1b20d0f..f07cb35 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -225,6 +225,12 @@ Note: The configmap is automatically mounted via `envFrom` when `configmap.enabl - Each entry in `ingresses` list can now have its own `annotations` and `ingressClassName`. +### Per-container `uid` + +- Each entry in the `containers` list now honors its own `uid`, rendered as `runAsUser`/`runAsGroup` on that container. +- The pod-level securityContext (`runAsUser`/`runAsGroup`/`fsGroup`) follows the first `containers` entry's `uid`, falling back to `container.uid` (default `1000`). Single-container charts run as the same uid as before; the only rendered difference is that each container's securityContext now also spells out `runAsUser`/`runAsGroup` (previously only the pod-level securityContext did). +- ⚠️ Previously `uid` on `containers` entries was silently ignored and those pods ran as `1000`. If you set `uid` on `containers` entries and relied on the old `1000` behavior (e.g. volume or file ownership, `fsGroup`-dependent mounts), verify ownership after upgrading. + ### Cloud SQL Proxy v2 features - Prometheus metrics exposed on port 9801 (`/metrics`). diff --git a/charts/common/templates/_helpers.tpl b/charts/common/templates/_helpers.tpl index 5084b2d..d7add49 100644 --- a/charts/common/templates/_helpers.tpl +++ b/charts/common/templates/_helpers.tpl @@ -30,6 +30,10 @@ meta.helm.sh/release-namespace: {{ empty .Release.Namespace| ternary .Release.Na securityContext: allowPrivilegeEscalation: false runAsNonRoot: true + {{- with .uid }} + runAsUser: {{ . }} + runAsGroup: {{ . }} + {{- end }} capabilities: drop: ["ALL"] seccompProfile: diff --git a/charts/common/templates/cron.yaml b/charts/common/templates/cron.yaml index b031fcd..d58c241 100644 --- a/charts/common/templates/cron.yaml +++ b/charts/common/templates/cron.yaml @@ -6,6 +6,7 @@ {{- $releaseName := include "name" . -}} {{- $containers := .Values.containers | default (list .Values.container) -}} +{{- $podUid := (first $containers).uid | default .Values.container.uid -}} {{- $configmap := .Values.configmap -}} {{- $postgres := .Values.postgres -}} {{- $secrets := .Values.secrets -}} @@ -89,10 +90,10 @@ spec: {{- end }} restartPolicy: {{ .Values.cron.restartPolicy | default "OnFailure" }} securityContext: - runAsGroup: {{ .Values.container.uid }} + runAsGroup: {{ $podUid }} runAsNonRoot: true - runAsUser: {{ .Values.container.uid }} - fsGroup: {{ .Values.container.uid }} + runAsUser: {{ $podUid }} + fsGroup: {{ $podUid }} seccompProfile: type: RuntimeDefault {{- end -}} \ No newline at end of file diff --git a/charts/common/templates/deployment.yaml b/charts/common/templates/deployment.yaml index 019c853..f3ae637 100644 --- a/charts/common/templates/deployment.yaml +++ b/charts/common/templates/deployment.yaml @@ -6,6 +6,7 @@ {{- $releaseName := include "name" . -}} {{- $containers := .Values.containers | default (list .Values.container) -}} +{{- $podUid := (first $containers).uid | default .Values.container.uid -}} {{- $configmap := .Values.configmap -}} {{- $postgres := .Values.postgres -}} {{- $secrets := .Values.secrets -}} @@ -129,10 +130,10 @@ spec: {{- end }} restartPolicy: Always securityContext: - runAsGroup: {{ .Values.container.uid }} + runAsGroup: {{ $podUid }} runAsNonRoot: true - runAsUser: {{ .Values.container.uid }} - fsGroup: {{ .Values.container.uid }} + runAsUser: {{ $podUid }} + fsGroup: {{ $podUid }} seccompProfile: type: RuntimeDefault {{- end }} diff --git a/charts/common/tests/cron_test.yaml b/charts/common/tests/cron_test.yaml index 92b6956..ebecbdc 100644 --- a/charts/common/tests/cron_test.yaml +++ b/charts/common/tests/cron_test.yaml @@ -282,4 +282,30 @@ tests: asserts: - equal: path: spec.jobTemplate.spec.template.spec.containers[1].envFrom[0].secretRef.name - value: my-cron-creds \ No newline at end of file + value: my-cron-creds + - it: honors uid per entry in the containers list + set: + containers: + - name: app + uid: 101 + image: img + probes: + enabled: false + - name: sidecar + uid: 2000 + image: img + probes: + enabled: false + asserts: + - equal: + path: spec.jobTemplate.spec.template.spec.securityContext.runAsUser + value: 101 + - equal: + path: spec.jobTemplate.spec.template.spec.securityContext.fsGroup + value: 101 + - equal: + path: spec.jobTemplate.spec.template.spec.containers[0].securityContext.runAsUser + value: 101 + - equal: + path: spec.jobTemplate.spec.template.spec.containers[1].securityContext.runAsUser + value: 2000 diff --git a/charts/common/tests/deployment_test.yaml b/charts/common/tests/deployment_test.yaml index de06dca..7f2baab 100644 --- a/charts/common/tests/deployment_test.yaml +++ b/charts/common/tests/deployment_test.yaml @@ -366,6 +366,70 @@ tests: - equal: path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation value: false + - it: uses container uid in pod and container security context + set: + container: + uid: 101 + image: img + asserts: + - equal: + path: spec.template.spec.securityContext.runAsUser + value: 101 + - equal: + path: spec.template.spec.securityContext.fsGroup + value: 101 + - equal: + path: spec.template.spec.containers[0].securityContext.runAsUser + value: 101 + - it: honors uid per entry in the containers list + set: + containers: + - name: app + uid: 101 + image: img + probes: + enabled: false + - name: sidecar + uid: 2000 + image: img + probes: + enabled: false + - name: nouid + image: img + probes: + enabled: false + asserts: + - equal: + path: spec.template.spec.securityContext.runAsUser + value: 101 + - equal: + path: spec.template.spec.securityContext.fsGroup + value: 101 + - equal: + path: spec.template.spec.containers[0].securityContext.runAsUser + value: 101 + - equal: + path: spec.template.spec.containers[1].securityContext.runAsUser + value: 2000 + - equal: + path: spec.template.spec.containers[1].securityContext.runAsGroup + value: 2000 + - notExists: + path: spec.template.spec.containers[2].securityContext.runAsUser + - it: defaults pod security context to uid 1000 when containers list sets no uid + set: + containers: + - name: app + image: img + probes: + enabled: false + asserts: + - equal: + path: spec.template.spec.securityContext.runAsUser + value: 1000 + - equal: + path: spec.template.spec.securityContext.fsGroup + value: 1000 - it: has envFrom secrets in all containers set: containers: