This is an automated email from the ASF dual-hosted git repository.
Miretpl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 3ac38517090 Add securityContexts.disableDefaults flag for OpenShift
SCC compatibility (#70238)
3ac38517090 is described below
commit 3ac385170905a327fe4363abb4404acc7bdd8eb8
Author: Aaryan Mahajan <[email protected]>
AuthorDate: Wed Aug 26 00:18:59 2026 +0530
Add securityContexts.disableDefaults flag for OpenShift SCC compatibility
(#70238)
* Allow runAsUser and fsGroup to be explicitly null in pod securityContexts
OpenShift assigns runAsUser/fsGroup automatically via SCC and rejects
pods that hard-code them, so users need to null these out in the
rendered pod securityContext. The vendored PodSecurityContext schema
required these fields to be integers, so setting them to null failed
Helm's values.schema.json validation before the templates ever
rendered (the templates already pass through explicit nulls
correctly).
Introduces a new AirflowPodSecurityContext schema definition (not
io.k8s.*-prefixed, so it survives vendor_k8s_json_schema.py
regeneration) that allows null for runAsUser/runAsGroup/fsGroup, and
points all 16 securityContexts.pod $refs at it instead of the vendored
definition.
closes: #41630
* Add newsfragment for Helm chart securityContexts fix
* Rename newsfragment to match this PR's number
Named after the GitHub issue instead of the actual PR number, which
the check-newsfragment-pr-number CI check expects.
* Replace null-based OpenShift SCC workaround with a
securityContexts.disableDefaults flag
Explicit null in securityContexts.pod/containers was fragile and made every
call site guess whether to render a key at all. A dedicated flag is more
explicit about intent and lets the chart omit the default runAsUser/fsGroup
(and related) values entirely on platforms like OpenShift where the
cluster's
SCC assigns them automatically and rejects hard-coded values.
* Update production guide for the disableDefaults securityContexts flag
The OpenShift SCC guidance still described the earlier null-based
workaround, which no longer omits the rendered securityContext keys.
* Fix docs spellcheck failure from unescaped securityContexts.* in schema
description
securityContexts.pod / securityContexts.containers appeared as plain text in
the disableDefaults description, which the docs build renders as prose
rather
than code, tripping the spellchecker on the camelCase identifier.
* Deprecate implicit securityContexts.disableDefaults default and unify
helper argument order
Address review feedback: mark the disableDefaults false default as
deprecated (surfaced via NOTES.txt, values.yaml, values.schema.json and
the newsfragment) since it will flip to true in a future release, and
align airflowPodSecurityContextsIds's argument order with the rest of
the security-context helpers in the chart. Also adds coverage for
component-level securityContexts overrides taking priority over
disableDefaults, both for Deployments and for the pod-template-file
path used by KubernetesExecutor/KubernetesPodOperator.
* Extend disableDefaults component-override test coverage to all chart
components
The disableDefaults escape hatch touches every component's security
context, but the regression test only exercised scheduler and
workers.celery. Parametrize it across all 13 affected components so a
future template change can't silently break the override behavior for
components that were previously untested, and add databaseCleanup
coverage that no other test in this file provided either.
* Tidy disableDefaults wording in values.yaml and values.schema.json
The parenthetical note doesn't need a trailing period, and the
values.yaml comment was missing backticks around the referenced keys
that every other comment in the file uses.
* Address review feedback on disableDefaults test coverage
Split the mixed CronJob/Deployment assertions in
test_disable_defaults_pod_and_container into separate tests instead of
branching on list position, replace per-doc Python loops and
init-container name comprehensions with jmespath expressions to match
the rest of the file, and drop docstrings that only restated what the
test name already says.
* Update chart/values.schema.json
Co-authored-by: Przemysław Mirowski
<[email protected]>
* Update chart/values.yaml
Co-authored-by: Przemysław Mirowski
<[email protected]>
* Fixing PR comments
---------
Co-authored-by: Przemysław Mirowski
<[email protected]>
---
chart/docs/production-guide.rst | 22 ++
chart/newsfragments/70238.significant.rst | 3 +
chart/templates/NOTES.txt | 8 +
chart/templates/_helpers.yaml | 60 ++++--
.../api-server/api-server-deployment.yaml | 6 +
chart/templates/cleanup/cleanup-cronjob.yaml | 4 +
.../dag-processor/dag-processor-deployment.yaml | 8 +
.../database-cleanup/database-cleanup-cronjob.yaml | 4 +
chart/templates/flower/flower-deployment.yaml | 4 +
chart/templates/jobs/create-user-job.yaml | 4 +
chart/templates/jobs/migrate-database-job.yaml | 4 +
.../templates/pgbouncer/pgbouncer-deployment.yaml | 12 +-
chart/templates/redis/redis-statefulset.yaml | 8 +-
.../templates/scheduler/scheduler-deployment.yaml | 8 +
chart/templates/statsd/statsd-deployment.yaml | 8 +-
.../templates/triggerer/triggerer-deployment.yaml | 8 +
chart/templates/workers/worker-deployment.yaml | 19 +-
.../airflow_aux/test_pod_template_file.py | 37 ++++
.../helm_tests/security/test_security_context.py | 231 +++++++++++++++++++++
chart/values.schema.json | 6 +
chart/values.yaml | 5 +
21 files changed, 438 insertions(+), 31 deletions(-)
diff --git a/chart/docs/production-guide.rst b/chart/docs/production-guide.rst
index aa6c1872247..029a71e7478 100644
--- a/chart/docs/production-guide.rst
+++ b/chart/docs/production-guide.rst
@@ -790,6 +790,28 @@ This will generate the following scheduler deployment:
- name: scheduler
...
+Omitting default ``securityContext`` values
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+On OpenShift, the ``restricted`` SCC assigns ``runAsUser`` and ``fsGroup``
automatically and rejects Pods
+that request specific values without the ``anyuid`` SCC in place. Since an
empty ``securityContexts.pod``
+falls back to :ref:`uid <parameters:Airflow>` / :ref:`gid
<parameters:Airflow>` (as shown above), leaving
+it empty is not enough to avoid hard-coded values. Set
``securityContexts.disableDefaults`` to stop the
+chart from filling in these defaults wherever ``securityContexts.pod`` /
``securityContexts.containers``
+(or the equivalent per-component overrides) are left empty:
+
+.. code-block:: yaml
+ :caption: values.yaml
+
+ securityContexts:
+ disableDefaults: true
+
+This omits ``runAsUser`` / ``fsGroup`` (pod) and ``runAsUser`` (container)
from the rendered
+``securityContext`` entirely wherever they are not explicitly set, allowing
the SCC to supply its own
+values. Explicit values set in ``securityContexts.pod`` /
``securityContexts.containers`` (or a
+component's local override, e.g. ``scheduler.securityContexts.pod``) still
take priority over
+``disableDefaults``.
+
Built-in secrets and environment variables
------------------------------------------
diff --git a/chart/newsfragments/70238.significant.rst
b/chart/newsfragments/70238.significant.rst
new file mode 100644
index 00000000000..369f43d7a6c
--- /dev/null
+++ b/chart/newsfragments/70238.significant.rst
@@ -0,0 +1,3 @@
+Added ``securityContexts.disableDefaults`` (default ``false``) to the Helm
chart. When set, the chart no longer fills in the default
``runAsUser``/``fsGroup`` (pod) or ``runAsUser`` (container) values when
``securityContexts.pod`` / ``securityContexts.containers`` (or the equivalent
per-component overrides) are left empty, allowing platforms such as OpenShift
to assign them automatically via SCC instead of the chart hard-coding them.
+
+Value ``false`` for ``securityContexts.disableDefaults`` is deprecated and
will be ``true`` by default in the next major release. Please adjust your
configuration accordingly.
diff --git a/chart/templates/NOTES.txt b/chart/templates/NOTES.txt
index b44ebb30735..51b7690ed01 100644
--- a/chart/templates/NOTES.txt
+++ b/chart/templates/NOTES.txt
@@ -121,6 +121,14 @@ DEPRECATION WARNING:
{{- end }}
+{{- if not .Values.securityContexts.disableDefaults }}
+
+ DEPRECATION WARNING:
+ `securityContexts.disableDefaults` equal `false` is deprecated and will
default to `true` in a future release.
+ Please set `securityContexts.disableDefaults: true` explicitly, or provide
values via `securityContexts.pod` / `securityContexts.containers` (or
per-component overrides), before the default changes.
+
+{{- end }}
+
{{- if not (or .Values.apiSecretKey .Values.apiSecretKeySecretName) }}
#####################################################
# WARNING: You should set a static API secret key #
diff --git a/chart/templates/_helpers.yaml b/chart/templates/_helpers.yaml
index 54625dd01c4..9a5238fdc8c 100644
--- a/chart/templates/_helpers.yaml
+++ b/chart/templates/_helpers.yaml
@@ -214,7 +214,10 @@ If release name contains chart name it will be used as a
full name.
- name: {{ .Values.dags.gitSync.containerName }}{{ if .is_init }}-init{{ end }}
image: {{ template "git_sync_image" . }}
imagePullPolicy: {{ .Values.images.gitSync.pullPolicy }}
- securityContext: {{- include "localContainerSecurityContext"
.Values.dags.gitSync | nindent 4 }}
+ {{- $gitSyncContainerSecurityContext := include
"localContainerSecurityContext" (list .Values.dags.gitSync .Values) }}
+ {{- if $gitSyncContainerSecurityContext }}
+ securityContext: {{ $gitSyncContainerSecurityContext | nindent 4 }}
+ {{- end }}
envFrom: {{- include "custom_git_sync_environment_from" . | default "\n []"
| indent 2 }}
env:
- name: GIT_SYNC_REV
@@ -883,7 +886,7 @@ Priority of values are from left to right, meaning if first
value is not empty,
{{- end }}
{{- if $result }}
{{- toYaml $result | print }}
- {{- else }}
+ {{- else if not $.securityContexts.disableDefaults }}
runAsUser: {{ $.uid }}
fsGroup: {{ $.gid }}
{{- end }}
@@ -898,15 +901,18 @@ If no value is passed for <node>.securityContexts.pod,
defaults to UID in the lo
+-----------------------------+ +------------+
The template can be called like so:
- include "localPodSecurityContext" (list . .Values.schedule)
+ include "localPodSecurityContext" (list .Values.redis .Values)
+Where `.Values` is the global variables scope and `.Values.redis` the local
variables scope for the redis template.
It is important to pass the local variables scope to this template as it is
used to determine the local node value for uid.
*/}}
{{- define "localPodSecurityContext" -}}
- {{- if .securityContexts.pod -}}
- {{ toYaml .securityContexts.pod | print }}
- {{- else -}}
-runAsUser: {{ .uid }}
+ {{- $ := last . }}
+ {{- $node := first . }}
+ {{- if $node.securityContexts.pod -}}
+ {{ toYaml $node.securityContexts.pod | print }}
+ {{- else if not $.securityContexts.disableDefaults -}}
+runAsUser: {{ $node.uid }}
{{- end -}}
{{- end -}}
@@ -919,15 +925,18 @@ If no value is passed for
<node>.securityContexts.container, defaults to UID in
+-----------------------------------+ +------------+
The template can be called like so:
- include "localContainerSecurityContext" .Values.statsd
+ include "localContainerSecurityContext" (list .Values.dags.gitSync .Values)
+Where `.Values` is the global variables scope and `.Values.dags.gitSync` the
local variables scope.
It is important to pass the local variables scope to this template as it is
used to determine the local node value for uid.
*/}}
{{- define "localContainerSecurityContext" -}}
- {{- if .securityContexts.container -}}
- {{ toYaml .securityContexts.container | print }}
- {{- else -}}
-runAsUser: {{ .uid }}
+ {{- $ := last . }}
+ {{- $node := first . }}
+ {{- if $node.securityContexts.container -}}
+ {{ toYaml $node.securityContexts.container | print }}
+ {{- else if not $.securityContexts.disableDefaults -}}
+runAsUser: {{ $node.uid }}
{{- end -}}
{{- end -}}
@@ -943,19 +952,22 @@ The template looks for `runAsUser` and `fsGroup`
specifically, any other paramet
Values are not accumulated meaning that if runAsUser is set to 10 in
<node>.securityContexts.pod,
any extra values set to securityContexts or uid+gid will be ignored.
+If securityContexts.disableDefaults is true and no explicit runAsUser/fsGroup
is set anywhere,
+this template renders an empty string, since there is no id to chown to.
+
The template can be called like so:
- include "airflowPodSecurityContextsIds" (list . .Values.webserver)
+ include "airflowPodSecurityContextsIds" (list .Values.webserver .)
-Where `.` is the global variables scope and `.Values.workers` the local
variables scope for the workers template.
+Where `.Values.workers` is the local variables scope for the workers template
and `.` the global variables scope.
*/}}
{{- define "airflowPodSecurityContextsIds" -}}
- {{- $ := index . 0 -}}
- {{- with index . 1 }}
+ {{- $ := last . -}}
+ {{- with first . }}
{{- if .securityContexts.pod -}}
{{ pluck "runAsUser" .securityContexts.pod | first | default
$.Values.uid }}:{{ pluck "fsGroup" .securityContexts.pod | first | default
$.Values.gid }}
{{- else if $.Values.securityContexts.pod -}}
{{ pluck "runAsUser" $.Values.securityContexts.pod | first | default
$.Values.uid }}:{{ pluck "fsGroup" $.Values.securityContexts.pod | first |
default $.Values.gid }}
- {{- else -}}
+ {{- else if not $.Values.securityContexts.disableDefaults -}}
{{ $.Values.uid }}:{{ $.Values.gid }}
{{- end -}}
{{- end -}}
@@ -988,7 +1000,7 @@ Priority of values are from left to right, meaning if
first value is not empty,
{{- toYaml $result | print }}
{{- else if and (hasKey $ "securityContexts") (hasKey $.securityContexts
"containers") $.securityContexts.containers }}
{{- toYaml $.securityContexts.containers | print }}
- {{- else -}}
+ {{- else if not $.securityContexts.disableDefaults }}
allowPrivilegeEscalation: false
capabilities:
drop:
@@ -1005,12 +1017,16 @@ If no value is passed for
<node>.securityContexts.container, defaults to deny pr
+-----------------------------------+
+------------------------------------------------------------+
The template can be called like so:
- include "externalContainerSecurityContext" .Values.statsd
+ include "externalContainerSecurityContext" (list .Values.statsd .Values)
+
+Where `.Values` is the global variables scope and `.Values.statsd` the local
variables scope.
*/}}
{{- define "externalContainerSecurityContext" -}}
- {{- if .securityContexts.container -}}
- {{ toYaml .securityContexts.container | print }}
- {{- else -}}
+ {{- $ := last . }}
+ {{- $node := first . }}
+ {{- if $node.securityContexts.container -}}
+ {{ toYaml $node.securityContexts.container | print }}
+ {{- else if not $.securityContexts.disableDefaults -}}
allowPrivilegeEscalation: false
capabilities:
drop:
diff --git a/chart/templates/api-server/api-server-deployment.yaml
b/chart/templates/api-server/api-server-deployment.yaml
index 5d6eeb3d507..de5044fdcfd 100644
--- a/chart/templates/api-server/api-server-deployment.yaml
+++ b/chart/templates/api-server/api-server-deployment.yaml
@@ -130,7 +130,9 @@ spec:
tolerations: {{- toYaml $tolerations | nindent 8 }}
topologySpreadConstraints: {{- toYaml $topologySpreadConstraints |
nindent 8 }}
restartPolicy: Always
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
imagePullSecrets: {{- include "image_pull_secrets" . | nindent 8 }}
initContainers:
{{- if .Values.apiServer.waitForMigrations.enabled }}
@@ -138,7 +140,9 @@ spec:
resources: {{- toYaml .Values.apiServer.resources | nindent 12 }}
image: {{ template "airflow_image_for_migrations" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextWaitForMigrations }}
securityContext: {{ $containerSecurityContextWaitForMigrations |
nindent 12 }}
+ {{- end }}
volumeMounts:
{{- include "airflow_config_mount" . | nindent 12 }}
{{- if .Values.volumeMounts }}
@@ -163,7 +167,9 @@ spec:
- name: api-server
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
diff --git a/chart/templates/cleanup/cleanup-cronjob.yaml
b/chart/templates/cleanup/cleanup-cronjob.yaml
index 032ff6fb092..556afaac6b5 100644
--- a/chart/templates/cleanup/cleanup-cronjob.yaml
+++ b/chart/templates/cleanup/cleanup-cronjob.yaml
@@ -88,12 +88,16 @@ spec:
serviceAccountName: {{ include "cleanup.serviceAccountName" . }}
enableServiceLinks: {{ .Values.enableServiceLinks }}
imagePullSecrets: {{- include "image_pull_secrets" . | nindent 12 }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 12 }}
+ {{- end }}
containers:
- name: airflow-cleanup-pods
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 16 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent
16 }}
{{- end }}
diff --git a/chart/templates/dag-processor/dag-processor-deployment.yaml
b/chart/templates/dag-processor/dag-processor-deployment.yaml
index 6a3865fc366..e8172e662c1 100644
--- a/chart/templates/dag-processor/dag-processor-deployment.yaml
+++ b/chart/templates/dag-processor/dag-processor-deployment.yaml
@@ -111,7 +111,9 @@ spec:
restartPolicy: Always
serviceAccountName: {{ include "dagProcessor.serviceAccountName" . }}
enableServiceLinks: {{ .Values.enableServiceLinks }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
imagePullSecrets: {{ include "image_pull_secrets" . | nindent 8 }}
initContainers:
{{- if .Values.dagProcessor.waitForMigrations.enabled }}
@@ -119,7 +121,9 @@ spec:
resources: {{- toYaml .Values.dagProcessor.resources | nindent 12 }}
image: {{ template "airflow_image_for_migrations" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextWaitForMigrations }}
securityContext: {{ $containerSecurityContextWaitForMigrations |
nindent 12 }}
+ {{- end }}
volumeMounts:
{{- if .Values.volumeMounts }}
{{- tpl (toYaml .Values.volumeMounts) . | nindent 12 }}
@@ -147,7 +151,9 @@ spec:
- name: dag-processor
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
@@ -199,7 +205,9 @@ spec:
resources: {{- toYaml
.Values.dagProcessor.logGroomerSidecar.resources | nindent 12 }}
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextLogGroomerSidecar }}
securityContext: {{ $containerSecurityContextLogGroomerSidecar |
nindent 12 }}
+ {{- end }}
{{- if .Values.dagProcessor.logGroomerSidecar.command }}
command: {{ tpl (toYaml
.Values.dagProcessor.logGroomerSidecar.command) . | nindent 12 }}
{{- end }}
diff --git a/chart/templates/database-cleanup/database-cleanup-cronjob.yaml
b/chart/templates/database-cleanup/database-cleanup-cronjob.yaml
index c0569aae725..041425920fc 100644
--- a/chart/templates/database-cleanup/database-cleanup-cronjob.yaml
+++ b/chart/templates/database-cleanup/database-cleanup-cronjob.yaml
@@ -91,12 +91,16 @@ spec:
serviceAccountName: {{ include "databaseCleanup.serviceAccountName"
. }}
enableServiceLinks: {{ .Values.enableServiceLinks }}
imagePullSecrets: {{- include "image_pull_secrets" . | nindent 12 }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 12 }}
+ {{- end }}
containers:
- name: database-cleanup
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 16 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent
16 }}
{{- end }}
diff --git a/chart/templates/flower/flower-deployment.yaml
b/chart/templates/flower/flower-deployment.yaml
index aa6cd31c0ec..1fb6031c080 100644
--- a/chart/templates/flower/flower-deployment.yaml
+++ b/chart/templates/flower/flower-deployment.yaml
@@ -84,13 +84,17 @@ spec:
priorityClassName: {{ .Values.flower.priorityClassName }}
{{- end }}
restartPolicy: Always
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
imagePullSecrets: {{- include "image_pull_secrets" . | nindent 8 }}
containers:
- name: flower
image: {{ template "flower_image" . }}
imagePullPolicy: {{ .Values.images.flower.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
diff --git a/chart/templates/jobs/create-user-job.yaml
b/chart/templates/jobs/create-user-job.yaml
index 02187b1c6e3..2136bdc08f0 100644
--- a/chart/templates/jobs/create-user-job.yaml
+++ b/chart/templates/jobs/create-user-job.yaml
@@ -73,7 +73,9 @@ spec:
{{- end }}
{{- end }}
spec:
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
restartPolicy: {{ .Values.createUserJob.restartPolicy }}
{{- if .Values.createUserJob.priorityClassName }}
priorityClassName: {{ .Values.createUserJob.priorityClassName }}
@@ -96,7 +98,9 @@ spec:
- name: create-user
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
diff --git a/chart/templates/jobs/migrate-database-job.yaml
b/chart/templates/jobs/migrate-database-job.yaml
index 23ffd6e7cb2..77fbb4b6fec 100644
--- a/chart/templates/jobs/migrate-database-job.yaml
+++ b/chart/templates/jobs/migrate-database-job.yaml
@@ -73,7 +73,9 @@ spec:
{{- end }}
{{- end }}
spec:
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
restartPolicy: {{ .Values.migrateDatabaseJob.restartPolicy }}
{{- if .Values.migrateDatabaseJob.priorityClassName }}
priorityClassName: {{ .Values.migrateDatabaseJob.priorityClassName }}
@@ -96,7 +98,9 @@ spec:
- name: run-airflow-migrations
image: {{ template "airflow_image_for_migrations" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
diff --git a/chart/templates/pgbouncer/pgbouncer-deployment.yaml
b/chart/templates/pgbouncer/pgbouncer-deployment.yaml
index 97470b79108..fd67adceee5 100644
--- a/chart/templates/pgbouncer/pgbouncer-deployment.yaml
+++ b/chart/templates/pgbouncer/pgbouncer-deployment.yaml
@@ -26,9 +26,9 @@
{{- $tolerations := or .Values.pgbouncer.tolerations .Values.tolerations }}
{{- $topologySpreadConstraints := or
.Values.pgbouncer.topologySpreadConstraints .Values.topologySpreadConstraints }}
{{- $revisionHistoryLimit := include "airflow.revisionHistoryLimit" (list
.Values.pgbouncer.revisionHistoryLimit .Values.revisionHistoryLimit) }}
-{{- $securityContext := include "localPodSecurityContext" .Values.pgbouncer }}
-{{- $containerSecurityContext := include "externalContainerSecurityContext"
.Values.pgbouncer }}
-{{- $containerSecurityContextMetricsExporter := include
"externalContainerSecurityContext" .Values.pgbouncer.metricsExporterSidecar }}
+{{- $securityContext := include "localPodSecurityContext" (list
.Values.pgbouncer .Values) }}
+{{- $containerSecurityContext := include "externalContainerSecurityContext"
(list .Values.pgbouncer .Values) }}
+{{- $containerSecurityContextMetricsExporter := include
"externalContainerSecurityContext" (list
.Values.pgbouncer.metricsExporterSidecar .Values) }}
{{- $containerLifecycleHooks := .Values.pgbouncer.containerLifecycleHooks }}
{{- $containerLifecycleHooksMetricsExporter :=
.Values.pgbouncer.metricsExporterSidecar.containerLifecycleHooks }}
apiVersion: apps/v1
@@ -90,14 +90,18 @@ spec:
terminationGracePeriodSeconds: {{
.Values.pgbouncer.terminationGracePeriodSeconds }}
serviceAccountName: {{ include "pgbouncer.serviceAccountName" . }}
enableServiceLinks: {{ .Values.enableServiceLinks }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
restartPolicy: Always
imagePullSecrets: {{- include "image_pull_secrets" . | nindent 8 }}
containers:
- name: pgbouncer
image: {{ template "pgbouncer_image" . }}
imagePullPolicy: {{ .Values.images.pgbouncer.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if .Values.pgbouncer.command }}
command: {{ tpl (toYaml .Values.pgbouncer.command) . | nindent 12 }}
{{- end }}
@@ -161,7 +165,9 @@ spec:
resources: {{- toYaml
.Values.pgbouncer.metricsExporterSidecar.resources | nindent 12 }}
image: {{ template "pgbouncer_exporter_image" . }}
imagePullPolicy: {{ .Values.images.pgbouncerExporter.pullPolicy }}
+ {{- if $containerSecurityContextMetricsExporter }}
securityContext: {{ $containerSecurityContextMetricsExporter |
nindent 12 }}
+ {{- end }}
env:
- name: DATABASE_URL
valueFrom:
diff --git a/chart/templates/redis/redis-statefulset.yaml
b/chart/templates/redis/redis-statefulset.yaml
index 361c229212a..12473c06881 100644
--- a/chart/templates/redis/redis-statefulset.yaml
+++ b/chart/templates/redis/redis-statefulset.yaml
@@ -25,8 +25,8 @@
{{- $affinity := or .Values.redis.affinity .Values.affinity }}
{{- $tolerations := or .Values.redis.tolerations .Values.tolerations }}
{{- $topologySpreadConstraints := or .Values.redis.topologySpreadConstraints
.Values.topologySpreadConstraints }}
-{{- $securityContext := include "localPodSecurityContext" .Values.redis }}
-{{- $containerSecurityContext := include "externalContainerSecurityContext"
.Values.redis }}
+{{- $securityContext := include "localPodSecurityContext" (list .Values.redis
.Values) }}
+{{- $containerSecurityContext := include "externalContainerSecurityContext"
(list .Values.redis .Values) }}
{{- $containerLifecycleHooks := .Values.redis.containerLifecycleHooks }}
{{- $persistence := .Values.redis.persistence.enabled }}
apiVersion: apps/v1
@@ -88,12 +88,16 @@ spec:
schedulerName: {{ .Values.schedulerName }}
{{- end }}
imagePullSecrets: {{ include "image_pull_secrets" . | nindent 8 }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
containers:
- name: redis
image: {{ template "redis_image" . }}
imagePullPolicy: {{ .Values.images.redis.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
diff --git a/chart/templates/scheduler/scheduler-deployment.yaml
b/chart/templates/scheduler/scheduler-deployment.yaml
index 57c60f917c0..5775676b1d3 100644
--- a/chart/templates/scheduler/scheduler-deployment.yaml
+++ b/chart/templates/scheduler/scheduler-deployment.yaml
@@ -135,7 +135,9 @@ spec:
{{- if and (eq (include "airflow.podLaunchingExecutor" .) "true") (not
.Values.scheduler.serviceAccount.automountServiceAccountToken) }}
automountServiceAccountToken: false
{{- end }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
imagePullSecrets: {{ include "image_pull_secrets" . | nindent 8 }}
{{- if .Values.scheduler.hostAliases }}
hostAliases: {{- toYaml .Values.scheduler.hostAliases | nindent 8 }}
@@ -146,7 +148,9 @@ spec:
resources: {{- toYaml .Values.scheduler.resources | nindent 12 }}
image: {{ template "airflow_image_for_migrations" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextWaitForMigrations }}
securityContext: {{ $containerSecurityContextWaitForMigrations |
nindent 12 }}
+ {{- end }}
volumeMounts:
- name: logs
mountPath: "/opt/airflow/logs"
@@ -179,7 +183,9 @@ spec:
- name: scheduler
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
@@ -255,7 +261,9 @@ spec:
resources: {{- toYaml .Values.scheduler.logGroomerSidecar.resources
| nindent 12 }}
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextLogGroomerSidecar }}
securityContext: {{ $containerSecurityContextLogGroomerSidecar |
nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooksLogGroomerSidecar }}
lifecycle: {{- tpl (toYaml
$containerLifecycleHooksLogGroomerSidecar) . | nindent 12 }}
{{- end }}
diff --git a/chart/templates/statsd/statsd-deployment.yaml
b/chart/templates/statsd/statsd-deployment.yaml
index bb47d7d0400..842ab983752 100644
--- a/chart/templates/statsd/statsd-deployment.yaml
+++ b/chart/templates/statsd/statsd-deployment.yaml
@@ -26,8 +26,8 @@
{{- $tolerations := or .Values.statsd.tolerations .Values.tolerations }}
{{- $topologySpreadConstraints := or .Values.statsd.topologySpreadConstraints
.Values.topologySpreadConstraints }}
{{- $revisionHistoryLimit := include "airflow.revisionHistoryLimit" (list
.Values.statsd.revisionHistoryLimit .Values.revisionHistoryLimit) }}
-{{- $securityContext := include "localPodSecurityContext" .Values.statsd }}
-{{- $containerSecurityContext := include "externalContainerSecurityContext"
.Values.statsd }}
+{{- $securityContext := include "localPodSecurityContext" (list .Values.statsd
.Values) }}
+{{- $containerSecurityContext := include "externalContainerSecurityContext"
(list .Values.statsd .Values) }}
{{- $containerLifecycleHooks := .Values.statsd.containerLifecycleHooks }}
apiVersion: apps/v1
kind: Deployment
@@ -85,14 +85,18 @@ spec:
terminationGracePeriodSeconds: {{
.Values.statsd.terminationGracePeriodSeconds }}
serviceAccountName: {{ include "statsd.serviceAccountName" . }}
enableServiceLinks: {{ .Values.enableServiceLinks }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
restartPolicy: Always
imagePullSecrets: {{ include "image_pull_secrets" . | nindent 8 }}
containers:
- name: statsd
image: {{ template "statsd_image" . }}
imagePullPolicy: {{ .Values.images.statsd.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
diff --git a/chart/templates/triggerer/triggerer-deployment.yaml
b/chart/templates/triggerer/triggerer-deployment.yaml
index 806a7a5df31..05bd9d2b43b 100644
--- a/chart/templates/triggerer/triggerer-deployment.yaml
+++ b/chart/templates/triggerer/triggerer-deployment.yaml
@@ -128,7 +128,9 @@ spec:
restartPolicy: Always
serviceAccountName: {{ include "triggerer.serviceAccountName" . }}
enableServiceLinks: {{ .Values.enableServiceLinks }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
imagePullSecrets: {{ include "image_pull_secrets" . | nindent 8 }}
initContainers:
{{- if .Values.triggerer.waitForMigrations.enabled }}
@@ -137,7 +139,9 @@ spec:
{{- toYaml .Values.triggerer.resources | nindent 12 }}
image: {{ template "airflow_image_for_migrations" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextWaitForMigrations }}
securityContext: {{ $containerSecurityContextWaitForMigrations |
nindent 12 }}
+ {{- end }}
volumeMounts:
- name: logs
mountPath: "/opt/airflow/logs"
@@ -170,7 +174,9 @@ spec:
- name: triggerer
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
@@ -228,7 +234,9 @@ spec:
resources: {{- toYaml .Values.triggerer.logGroomerSidecar.resources
| nindent 12 }}
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextLogGroomer }}
securityContext: {{ $containerSecurityContextLogGroomer | nindent 12
}}
+ {{- end }}
{{- if $containerLifecycleHooksLogGroomerSidecar }}
lifecycle: {{- tpl (toYaml
$containerLifecycleHooksLogGroomerSidecar) . | nindent 12 }}
{{- end }}
diff --git a/chart/templates/workers/worker-deployment.yaml
b/chart/templates/workers/worker-deployment.yaml
index ea893150c3d..6caa54703df 100644
--- a/chart/templates/workers/worker-deployment.yaml
+++ b/chart/templates/workers/worker-deployment.yaml
@@ -40,6 +40,7 @@
{{- $topologySpreadConstraints := or
.Values.workers.celery.topologySpreadConstraints
.Values.topologySpreadConstraints }}
{{- $revisionHistoryLimit := include "airflow.revisionHistoryLimit" (list
.Values.workers.celery.revisionHistoryLimit .Values.revisionHistoryLimit) }}
{{- $securityContext := include "airflowPodSecurityContext" (list
.Values.workers.celery .Values) }}
+{{- $securityContextsIds := include "airflowPodSecurityContextsIds" (list
.Values.workers.celery .) }}
{{- $containerSecurityContext := include "containerSecurityContext" (list
.Values.workers.celery .Values) }}
{{- $containerSecurityContextPersistence := include "containerSecurityContext"
(list .Values.workers.celery.persistence .Values) }}
{{- $containerSecurityContextWaitForMigrations := include
"containerSecurityContext" (list .Values.workers.celery.waitForMigrations
.Values) }}
@@ -155,10 +156,12 @@ spec:
restartPolicy: Always
serviceAccountName: {{ include "worker.celery.serviceAccountName" . }}
enableServiceLinks: {{ .Values.enableServiceLinks }}
+ {{- if $securityContext }}
securityContext: {{ $securityContext | nindent 8 }}
+ {{- end }}
imagePullSecrets: {{ include "image_pull_secrets" . | nindent 8 }}
initContainers:
- {{- if and $persistence
.Values.workers.celery.persistence.fixPermissions }}
+ {{- if and $persistence
.Values.workers.celery.persistence.fixPermissions $securityContextsIds }}
- name: volume-permissions
resources: {{- toYaml .Values.workers.celery.resources | nindent 12
}}
image: {{ template "airflow_image" . }}
@@ -166,9 +169,11 @@ spec:
command:
- chown
- -R
- - "{{ include "airflowPodSecurityContextsIds" (list .
.Values.workers.celery) }}"
+ - "{{ $securityContextsIds }}"
- {{ template "airflow_logs" . }}
+ {{- if $containerSecurityContextPersistence }}
securityContext: {{ $containerSecurityContextPersistence | nindent
12 }}
+ {{- end }}
volumeMounts:
- name: logs
mountPath: {{ template "airflow_logs" . }}
@@ -179,7 +184,9 @@ spec:
{{- if .Values.workers.celery.kerberosInitContainer.enabled }}
- name: kerberos-init
image: {{ template "airflow_image" . }}
+ {{- if $containerSecurityContextKerberosInitContainer }}
securityContext: {{ $containerSecurityContextKerberosInitContainer |
nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooksKerberosInitContainer }}
lifecycle: {{- tpl (toYaml
$containerLifecycleHooksKerberosInitContainer) . | nindent 12 }}
{{- end }}
@@ -224,7 +231,9 @@ spec:
resources: {{- toYaml .Values.workers.celery.resources | nindent 12
}}
image: {{ template "airflow_image_for_migrations" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextWaitForMigrations }}
securityContext: {{ $containerSecurityContextWaitForMigrations |
nindent 12 }}
+ {{- end }}
volumeMounts:
- name: logs
mountPath: "/opt/airflow/logs"
@@ -257,7 +266,9 @@ spec:
- name: worker
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContext }}
securityContext: {{ $containerSecurityContext | nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooks }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 12
}}
{{- end }}
@@ -343,7 +354,9 @@ spec:
- name: worker-log-groomer
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextLogGroomerSidecar }}
securityContext: {{ $containerSecurityContextLogGroomerSidecar |
nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooksLogGroomerSidecar }}
lifecycle: {{- tpl (toYaml
$containerLifecycleHooksLogGroomerSidecar) . | nindent 12 }}
{{- end }}
@@ -397,7 +410,9 @@ spec:
- name: worker-kerberos
image: {{ template "airflow_image" . }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
+ {{- if $containerSecurityContextKerberosSidecar }}
securityContext: {{ $containerSecurityContextKerberosSidecar |
nindent 12 }}
+ {{- end }}
{{- if $containerLifecycleHooksKerberosSidecar }}
lifecycle: {{- tpl (toYaml $containerLifecycleHooksKerberosSidecar)
. | nindent 12 }}
{{- end }}
diff --git a/chart/tests/helm_tests/airflow_aux/test_pod_template_file.py
b/chart/tests/helm_tests/airflow_aux/test_pod_template_file.py
index 8958fa1e17c..a071933010b 100644
--- a/chart/tests/helm_tests/airflow_aux/test_pod_template_file.py
+++ b/chart/tests/helm_tests/airflow_aux/test_pod_template_file.py
@@ -829,6 +829,43 @@ class TestPodTemplateFile:
"allowPrivilegeEscalation": False
}
+ def test_pod_security_context_disable_defaults(self):
+ docs = render_chart(
+ values={"securityContexts": {"disableDefaults": True}},
+ show_only=["templates/pod-template-file.yaml"],
+ chart_dir=self.temp_chart_dir,
+ )
+
+ assert jmespath.search("spec.securityContext", docs[0]) is None
+
+ def test_container_security_context_disable_defaults(self):
+ docs = render_chart(
+ values={"securityContexts": {"disableDefaults": True}},
+ show_only=["templates/pod-template-file.yaml"],
+ chart_dir=self.temp_chart_dir,
+ )
+
+ assert jmespath.search("spec.containers[0].securityContext", docs[0])
is None
+
+ @pytest.mark.parametrize(
+ "values",
+ [
+ {"securityContexts": {"disableDefaults": True, "pod":
{"runAsUser": 10}}},
+ {
+ "securityContexts": {"disableDefaults": True},
+ "workers": {"kubernetes": {"securityContexts": {"pod":
{"runAsUser": 10}}}},
+ },
+ ],
+ )
+ def test_pod_security_context_set_overrides_disable_defaults(self, values):
+ docs = render_chart(
+ values=values,
+ show_only=["templates/pod-template-file.yaml"],
+ chart_dir=self.temp_chart_dir,
+ )
+
+ assert jmespath.search("spec.securityContext", docs[0]) ==
{"runAsUser": 10}
+
def test_should_add_gid_to_the_pod_template(self):
docs = render_chart(
values={"gid": 1},
diff --git a/chart/tests/helm_tests/security/test_security_context.py
b/chart/tests/helm_tests/security/test_security_context.py
index 4e58fd53811..3a1be1371e1 100644
--- a/chart/tests/helm_tests/security/test_security_context.py
+++ b/chart/tests/helm_tests/security/test_security_context.py
@@ -422,6 +422,237 @@ class TestSecurityContext:
for doc in docs[1:]:
assert ctx_value ==
jmespath.search("spec.template.spec.securityContext", doc)
+ def test_disable_defaults_pod_and_container(self):
+ docs = render_chart(
+ values={
+ "securityContexts": {"disableDefaults": True},
+ "flower": {"enabled": True},
+ "pgbouncer": {"enabled": True},
+ "statsd": {"enabled": True},
+ },
+ show_only=[
+ "templates/flower/flower-deployment.yaml",
+ "templates/scheduler/scheduler-deployment.yaml",
+ "templates/api-server/api-server-deployment.yaml",
+ "templates/dag-processor/dag-processor-deployment.yaml",
+ "templates/workers/worker-deployment.yaml",
+ "templates/jobs/create-user-job.yaml",
+ "templates/jobs/migrate-database-job.yaml",
+ "templates/triggerer/triggerer-deployment.yaml",
+ "templates/pgbouncer/pgbouncer-deployment.yaml",
+ "templates/statsd/statsd-deployment.yaml",
+ "templates/redis/redis-statefulset.yaml",
+ ],
+ )
+
+ assert all(v is None for v in
jmespath.search("[].spec.template.spec.securityContext", docs))
+ assert all(
+ v is None for v in
jmespath.search("[].spec.template.spec.containers[0].securityContext", docs)
+ )
+
+ def test_disable_defaults_pod_and_container_cronjob(self):
+ docs = render_chart(
+ values={
+ "securityContexts": {"disableDefaults": True},
+ "executor": "CeleryExecutor,KubernetesExecutor",
+ "cleanup": {"enabled": True},
+ },
+ show_only=["templates/cleanup/cleanup-cronjob.yaml"],
+ )
+
+ assert
jmespath.search("spec.jobTemplate.spec.template.spec.securityContext", docs[0])
is None
+ assert (
+
jmespath.search("spec.jobTemplate.spec.template.spec.containers[0].securityContext",
docs[0])
+ is None
+ )
+
+ def test_disable_defaults_gitsync_containers(self):
+ docs = render_chart(
+ values={
+ "securityContexts": {"disableDefaults": True},
+ "dags": {"gitSync": {"enabled": True}},
+ },
+ show_only=[
+ "templates/workers/worker-deployment.yaml",
+ "templates/triggerer/triggerer-deployment.yaml",
+ "templates/dag-processor/dag-processor-deployment.yaml",
+ ],
+ )
+
+ for doc in docs:
+ assert (
+ jmespath.search(
+
"spec.template.spec.initContainers[?name=='git-sync-init'].securityContext |
[0]",
+ doc,
+ )
+ is None
+ )
+ assert (
+ jmespath.search(
+
"spec.template.spec.containers[?name=='git-sync'].securityContext | [0]",
+ doc,
+ )
+ is None
+ )
+
+ def test_disable_defaults_volume_permissions_init_container_skipped(self):
+ """With no explicit uid/gid override, the volume-permissions init
container is omitted entirely."""
+ docs = render_chart(
+ values={
+ "securityContexts": {"disableDefaults": True},
+ "workers": {
+ "celery": {
+ "persistence": {"enabled": True, "fixPermissions":
True},
+ }
+ },
+ },
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+
+ assert (
+
jmespath.search("spec.template.spec.initContainers[?name=='volume-permissions']",
docs[0]) == []
+ )
+
+ def test_disable_defaults_explicit_override_still_applied(self):
+ ctx_value = {"runAsUser": 7000}
+ docs = render_chart(
+ values={
+ "securityContexts": {"disableDefaults": True, "pod":
ctx_value},
+ "workers": {
+ "celery": {
+ "persistence": {"enabled": True, "fixPermissions":
True},
+ }
+ },
+ },
+ show_only=[
+ "templates/scheduler/scheduler-deployment.yaml",
+ "templates/workers/worker-deployment.yaml",
+ ],
+ )
+
+ for doc in docs:
+ assert ctx_value ==
jmespath.search("spec.template.spec.securityContext", doc)
+
+ assert (
+
jmespath.search("spec.template.spec.initContainers[?name=='volume-permissions']",
docs[1]) != []
+ )
+
+ @pytest.mark.parametrize(
+ ("component_values", "show_only", "security_context_path"),
+ [
+ (
+ {"scheduler": {"securityContexts": {"pod": {"runAsUser":
8000}}}},
+ "templates/scheduler/scheduler-deployment.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"apiServer": {"securityContexts": {"pod": {"runAsUser":
8000}}}},
+ "templates/api-server/api-server-deployment.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"dagProcessor": {"securityContexts": {"pod": {"runAsUser":
8000}}}},
+ "templates/dag-processor/dag-processor-deployment.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"triggerer": {"securityContexts": {"pod": {"runAsUser":
8000}}}},
+ "templates/triggerer/triggerer-deployment.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"workers": {"celery": {"securityContexts": {"pod":
{"runAsUser": 8000}}}}},
+ "templates/workers/worker-deployment.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"flower": {"enabled": True, "securityContexts": {"pod":
{"runAsUser": 8000}}}},
+ "templates/flower/flower-deployment.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"statsd": {"securityContexts": {"pod": {"runAsUser": 8000}}}},
+ "templates/statsd/statsd-deployment.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"pgbouncer": {"enabled": True, "securityContexts": {"pod":
{"runAsUser": 8000}}}},
+ "templates/pgbouncer/pgbouncer-deployment.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"redis": {"securityContexts": {"pod": {"runAsUser": 8000}}}},
+ "templates/redis/redis-statefulset.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"createUserJob": {"securityContexts": {"pod": {"runAsUser":
8000}}}},
+ "templates/jobs/create-user-job.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {"migrateDatabaseJob": {"securityContexts": {"pod":
{"runAsUser": 8000}}}},
+ "templates/jobs/migrate-database-job.yaml",
+ "spec.template.spec.securityContext",
+ ),
+ (
+ {
+ "executor": "CeleryExecutor,KubernetesExecutor",
+ "cleanup": {"enabled": True, "securityContexts": {"pod":
{"runAsUser": 8000}}},
+ },
+ "templates/cleanup/cleanup-cronjob.yaml",
+ "spec.jobTemplate.spec.template.spec.securityContext",
+ ),
+ (
+ {"databaseCleanup": {"enabled": True, "securityContexts":
{"pod": {"runAsUser": 8000}}}},
+ "templates/database-cleanup/database-cleanup-cronjob.yaml",
+ "spec.jobTemplate.spec.template.spec.securityContext",
+ ),
+ ],
+ ids=[
+ "scheduler",
+ "apiServer",
+ "dagProcessor",
+ "triggerer",
+ "workers.celery",
+ "flower",
+ "statsd",
+ "pgbouncer",
+ "redis",
+ "createUserJob",
+ "migrateDatabaseJob",
+ "cleanup",
+ "databaseCleanup",
+ ],
+ )
+ def test_disable_defaults_component_level_override_still_applied(
+ self, component_values, show_only, security_context_path
+ ):
+ docs = render_chart(
+ values={"securityContexts": {"disableDefaults": True},
**component_values},
+ show_only=[show_only],
+ )
+
+ assert jmespath.search(security_context_path, docs[0]) ==
{"runAsUser": 8000}
+
+ def
test_disable_defaults_workers_volume_permissions_init_container_still_added(self):
+ docs = render_chart(
+ values={
+ "securityContexts": {"disableDefaults": True},
+ "workers": {
+ "celery": {
+ "securityContexts": {"pod": {"runAsUser": 8000}},
+ "persistence": {"enabled": True, "fixPermissions":
True},
+ }
+ },
+ },
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+
+ assert (
+
jmespath.search("spec.template.spec.initContainers[?name=='volume-permissions']",
docs[0]) != []
+ )
+
def test_workers_overwrite_local(self):
docs = render_chart(
values={
diff --git a/chart/values.schema.json b/chart/values.schema.json
index 30fbb3fcb93..88ebcee1fae 100644
--- a/chart/values.schema.json
+++ b/chart/values.schema.json
@@ -126,6 +126,12 @@
"allowPrivilegeEscalation": false
}
]
+ },
+ "disableDefaults": {
+ "description": "If `true`, the chart will not set any
default `securityContext` values when `securityContexts.pod` /
`securityContexts.containers` (or the equivalent per-component overrides) are
left empty (default `false` is deprecated and will change to `true` in a future
release).",
+ "type": "boolean",
+ "default": false,
+ "x-docsSection": "Kubernetes"
}
}
},
diff --git a/chart/values.yaml b/chart/values.yaml
index a6f7cc9b479..07e819fe393 100644
--- a/chart/values.yaml
+++ b/chart/values.yaml
@@ -47,6 +47,11 @@ gid: 0
securityContexts:
pod: {}
containers: {}
+ # If `true`, the chart will not set any default `securityContext` values when
+ # `securityContexts.pod` / `securityContexts.containers` (or the equivalent
per-component
+ # overrides) are left empty (default `false` is deprecated and will change
to `true`
+ # in a future release).
+ disableDefaults: false
# Global container lifecycle hooks for Airflow containers
containerLifecycleHooks: {}