From 021e3c1779288bafc916817cd5bea6994e46de98 Mon Sep 17 00:00:00 2001 From: Dev Jadeja Date: Wed, 9 Sep 2026 14:14:14 +0530 Subject: [PATCH] Allow a security context on every pod py-app renders py-app produces four pod specs and only one of them could be given a security context: deployment.yaml honoured .Values.securityContext, while migrators.yaml, taskiq-worker.yaml and taskiq-scheduler.yaml silently ignored it. There was also no podSecurityContext key anywhere in the chart, so runAsNonRoot, fsGroup and seccompProfile had nowhere to go on any of the four -- pod level is where the kubelet enforces runAsNonRoot. Adds podSecurityContext at pod level and wires securityContext at container level across all four templates. Both default to {} and both are documented in values.yaml with the settings a caller is most likely to want. readOnlyRootFilesystem is deliberately not among them: the Python services write to /tmp at runtime and this chart has no volumeMounts support to give them an emptyDir there, so suggesting it would hand callers a foot-gun. No defaults are set, so this changes nothing on its own. With neither value provided, `helm template` output is identical to the published 0.1.0 apart from the helm.sh/chart version label, checked against a values set that exercises all five workloads -- web, taskiq worker, taskiq scheduler, and the pg and scylla migrator Jobs, with and without per-migrator resources. With both contexts set they land on all five at the right level and the result passes `kubectl create --dry-run=client`. Version bumped to 0.2.0. Consumers pin targetRevision in appsets/defs, so nothing picks this up until those move -- which matters, because intree-api is currently the only consumer setting securityContext and the value is `privileged: true`. Rendering its live prod values against this chart takes it from 1 privileged container to 5. ArgoCD#2179 removes that line and has to merge before the appset bump, not before this. Change-Id: 964edff23912c3c8aa1d2253a2e61328 Signed-off-by: Dev Jadeja --- charts/py-app/Chart.yaml | 2 +- charts/py-app/templates/deployment.yaml | 3 +++ charts/py-app/templates/migrators.yaml | 6 +++++ charts/py-app/templates/taskiq-scheduler.yaml | 6 +++++ charts/py-app/templates/taskiq-worker.yaml | 6 +++++ charts/py-app/values.yaml | 24 +++++++++++++++++++ 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/charts/py-app/Chart.yaml b/charts/py-app/Chart.yaml index 2348880..3f6aa23 100644 --- a/charts/py-app/Chart.yaml +++ b/charts/py-app/Chart.yaml @@ -16,7 +16,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 +version: 0.2.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/py-app/templates/deployment.yaml b/charts/py-app/templates/deployment.yaml index df7e95e..8a5118e 100644 --- a/charts/py-app/templates/deployment.yaml +++ b/charts/py-app/templates/deployment.yaml @@ -35,6 +35,9 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: {{ . | toYaml | nindent 8 }} + {{- end }} serviceAccountName: {{ include "py-app.serviceAccountName" . }} containers: - name: {{ .Chart.Name }} diff --git a/charts/py-app/templates/migrators.yaml b/charts/py-app/templates/migrators.yaml index 0be022c..d443def 100644 --- a/charts/py-app/templates/migrators.yaml +++ b/charts/py-app/templates/migrators.yaml @@ -20,6 +20,9 @@ spec: template: spec: restartPolicy: "Never" + {{- with $.Values.podSecurityContext }} + securityContext: {{ . | toYaml | nindent 8 }} + {{- end }} {{- with $.Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} @@ -33,6 +36,9 @@ spec: resources: {{- toYaml . | nindent 10 -}} {{ end -}} + {{- with $.Values.securityContext }} + securityContext: {{ . | toYaml | nindent 10 }} + {{- end }} {{- include "py-app.envs" $ | indent 8 -}} {{- end }} {{ end -}} diff --git a/charts/py-app/templates/taskiq-scheduler.yaml b/charts/py-app/templates/taskiq-scheduler.yaml index bc33def..6e21189 100644 --- a/charts/py-app/templates/taskiq-scheduler.yaml +++ b/charts/py-app/templates/taskiq-scheduler.yaml @@ -30,12 +30,18 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: {{ . | toYaml | nindent 8 }} + {{- end }} serviceAccountName: {{ include "py-app.serviceAccountName" . }} containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} command: {{ .Values.taskiq.schedulerCmd | toYaml | nindent 10 }} + {{- with .Values.securityContext }} + securityContext: {{ . | toYaml | nindent 12 }} + {{- end }} {{- include "py-app.envs" . | indent 10 -}} resources: {{- toYaml .Values.taskiq.resources | nindent 12 }} diff --git a/charts/py-app/templates/taskiq-worker.yaml b/charts/py-app/templates/taskiq-worker.yaml index d46af34..d60e541 100644 --- a/charts/py-app/templates/taskiq-worker.yaml +++ b/charts/py-app/templates/taskiq-worker.yaml @@ -36,12 +36,18 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: {{ . | toYaml | nindent 8 }} + {{- end }} serviceAccountName: {{ include "py-app.serviceAccountName" . }} containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} command: {{ .Values.taskiq.workerCmd | toYaml | nindent 10 }} + {{- with .Values.securityContext }} + securityContext: {{ . | toYaml | nindent 12 }} + {{- end }} {{- include "py-app.envs" . | indent 10 -}} resources: {{- toYaml .Values.taskiq.resources | nindent 12 }} diff --git a/charts/py-app/values.yaml b/charts/py-app/values.yaml index 1600e82..dde5a5a 100644 --- a/charts/py-app/values.yaml +++ b/charts/py-app/values.yaml @@ -92,6 +92,30 @@ serviceAccount: podAnnotations: {} +# Pod-level security context, applied to every workload this chart renders: the +# web Deployment, the taskiq worker and scheduler Deployments, and the migrator +# Jobs. runAsNonRoot belongs here rather than on a container, because that is +# where the kubelet enforces it -- and it needs the image to declare a numeric +# UID, since a `USER name` cannot be resolved at admission. +podSecurityContext: {} + # runAsNonRoot: true + # runAsUser: 1000 + # runAsGroup: 1000 + # seccompProfile: + # type: RuntimeDefault + +# Container-level security context, applied to the container in every workload +# this chart renders. Takes precedence over podSecurityContext where the two +# overlap. +securityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem is deliberately not suggested here: the Python + # services write to /tmp at runtime, and this chart has no volumeMounts + # support to give them an emptyDir there. + service: enabled: true type: ClusterIP