From e05ea70ef881cdc7e6c12b978dd0f5e5e3248470 Mon Sep 17 00:00:00 2001 From: anmol mishra Date: Sat, 18 Jul 2026 02:07:12 +0530 Subject: [PATCH] feat: per-component enableBuiltInSecretEnvVars for workers and scheduler Adds workers.celery.enableBuiltInSecretEnvVars and scheduler.enableBuiltInSecretEnvVars to override the global enableBuiltInSecretEnvVars map on a per-component basis. This allows operators to disable sensitive env vars (e.g. database conn string, broker URL, fernet key) on worker containers where untrusted DAG code executes, while keeping them on control-plane components. The standard_airflow_environment template accepts an optional envOverrides dict. Each component call site passes its component-level map. The template resolves each env var by checking the component override first, then falling back to the global enableBuiltInSecretEnvVars. Closes #70008 --- chart/templates/_helpers.yaml | 30 +- .../scheduler/scheduler-deployment.yaml | 4 +- .../templates/workers/worker-deployment.yaml | 8 +- chart/values.schema.json | 256 +++++++++++++++++- chart/values.yaml | 10 + 5 files changed, 290 insertions(+), 18 deletions(-) diff --git a/chart/templates/_helpers.yaml b/chart/templates/_helpers.yaml index 2fefc497905d1..f715670d2eb6b 100644 --- a/chart/templates/_helpers.yaml +++ b/chart/templates/_helpers.yaml @@ -60,24 +60,36 @@ If release name contains chart name it will be used as a full name. {{/* Standard Airflow environment variables */}} {{- define "standard_airflow_environment" }} + # Resolve env var overrides from component-level config (e.g. + # workers.celery.enableBuiltInSecretEnvVars, scheduler.enableBuiltInSecretEnvVars) + {{- $envOverrides := .envOverrides | default dict }} + {{- $fernetKeyEnabled := hasKey $envOverrides "AIRFLOW__CORE__FERNET_KEY" | ternary (index $envOverrides "AIRFLOW__CORE__FERNET_KEY") .Values.enableBuiltInSecretEnvVars.AIRFLOW__CORE__FERNET_KEY }} + {{- $dbConnEnabled := hasKey $envOverrides "AIRFLOW__DATABASE__SQL_ALCHEMY_CONN" | ternary (index $envOverrides "AIRFLOW__DATABASE__SQL_ALCHEMY_CONN") .Values.enableBuiltInSecretEnvVars.AIRFLOW__DATABASE__SQL_ALCHEMY_CONN }} + {{- $airflowDbEnabled := hasKey $envOverrides "AIRFLOW_CONN_AIRFLOW_DB" | ternary (index $envOverrides "AIRFLOW_CONN_AIRFLOW_DB") .Values.enableBuiltInSecretEnvVars.AIRFLOW_CONN_AIRFLOW_DB }} + {{- $apiSecretKeyEnabled := hasKey $envOverrides "AIRFLOW__API__SECRET_KEY" | ternary (index $envOverrides "AIRFLOW__API__SECRET_KEY") .Values.enableBuiltInSecretEnvVars.AIRFLOW__API__SECRET_KEY }} + {{- $jwtSecretEnabled := hasKey $envOverrides "AIRFLOW__API_AUTH__JWT_SECRET" | ternary (index $envOverrides "AIRFLOW__API_AUTH__JWT_SECRET") .Values.enableBuiltInSecretEnvVars.AIRFLOW__API_AUTH__JWT_SECRET }} + {{- $celeryResultBackendEnabled := hasKey $envOverrides "AIRFLOW__CELERY__RESULT_BACKEND" | ternary (index $envOverrides "AIRFLOW__CELERY__RESULT_BACKEND") .Values.enableBuiltInSecretEnvVars.AIRFLOW__CELERY__RESULT_BACKEND }} + {{- $celeryBrokerEnabled := hasKey $envOverrides "AIRFLOW__CELERY__BROKER_URL" | ternary (index $envOverrides "AIRFLOW__CELERY__BROKER_URL") .Values.enableBuiltInSecretEnvVars.AIRFLOW__CELERY__BROKER_URL }} + {{- $esHostEnabled := hasKey $envOverrides "AIRFLOW__ELASTICSEARCH__HOST" | ternary (index $envOverrides "AIRFLOW__ELASTICSEARCH__HOST") .Values.enableBuiltInSecretEnvVars.AIRFLOW__ELASTICSEARCH__HOST }} + {{- $osHostEnabled := hasKey $envOverrides "AIRFLOW__OPENSEARCH__HOST" | ternary (index $envOverrides "AIRFLOW__OPENSEARCH__HOST") .Values.enableBuiltInSecretEnvVars.AIRFLOW__OPENSEARCH__HOST }} # Hard Coded Airflow Envs - name: AIRFLOW_HOME value: {{ .Values.airflowHome }} - {{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW__CORE__FERNET_KEY }} + {{- if $fernetKeyEnabled }} - name: AIRFLOW__CORE__FERNET_KEY valueFrom: secretKeyRef: name: {{ template "fernet_key_secret" . }} key: fernet-key {{- end }} - {{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW__DATABASE__SQL_ALCHEMY_CONN }} + {{- if $dbConnEnabled }} - name: AIRFLOW__DATABASE__SQL_ALCHEMY_CONN valueFrom: secretKeyRef: name: {{ template "airflow_metadata_secret" . }} key: connection {{- end }} - {{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW_CONN_AIRFLOW_DB }} + {{- if $airflowDbEnabled }} - name: AIRFLOW_CONN_AIRFLOW_DB valueFrom: secretKeyRef: @@ -94,14 +106,14 @@ If release name contains chart name it will be used as a full name. name: {{ template "airflow_metadata_secret" . }} key: kedaConnection {{- end }} - {{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW__API__SECRET_KEY }} + {{- if $apiSecretKeyEnabled }} - name: AIRFLOW__API__SECRET_KEY valueFrom: secretKeyRef: name: {{ template "api_secret_key_secret" . }} key: api-secret-key {{- end }} - {{- if and .IncludeJwtSecret .Values.enableBuiltInSecretEnvVars.AIRFLOW__API_AUTH__JWT_SECRET }} + {{- if and .IncludeJwtSecret $jwtSecretEnabled }} - name: AIRFLOW__API_AUTH__JWT_SECRET valueFrom: secretKeyRef: @@ -109,14 +121,14 @@ If release name contains chart name it will be used as a full name. key: jwt-secret {{- end }} {{- if contains "CeleryExecutor" .Values.executor }} - {{- if and .Values.enableBuiltInSecretEnvVars.AIRFLOW__CELERY__RESULT_BACKEND (or .Values.data.resultBackendSecretName .Values.data.resultBackendConnection) }} + {{- if and $celeryResultBackendEnabled (or .Values.data.resultBackendSecretName .Values.data.resultBackendConnection) }} - name: AIRFLOW__CELERY__RESULT_BACKEND valueFrom: secretKeyRef: name: {{ template "airflow_result_backend_secret" . }} key: connection {{- end }} - {{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW__CELERY__BROKER_URL }} + {{- if $celeryBrokerEnabled }} - name: AIRFLOW__CELERY__BROKER_URL valueFrom: secretKeyRef: @@ -124,14 +136,14 @@ If release name contains chart name it will be used as a full name. key: connection {{- end }} {{- end }} - {{- if and .Values.elasticsearch.enabled .Values.enableBuiltInSecretEnvVars.AIRFLOW__ELASTICSEARCH__HOST }} + {{- if and .Values.elasticsearch.enabled $esHostEnabled }} - name: AIRFLOW__ELASTICSEARCH__HOST valueFrom: secretKeyRef: name: {{ template "elasticsearch_secret" . }} key: connection {{- end }} - {{- if and .Values.opensearch.enabled .Values.enableBuiltInSecretEnvVars.AIRFLOW__OPENSEARCH__HOST }} + {{- if and .Values.opensearch.enabled $osHostEnabled }} - name: AIRFLOW__OPENSEARCH__HOST valueFrom: secretKeyRef: diff --git a/chart/templates/scheduler/scheduler-deployment.yaml b/chart/templates/scheduler/scheduler-deployment.yaml index 35749fdbc5ba2..c4ed8340f566b 100644 --- a/chart/templates/scheduler/scheduler-deployment.yaml +++ b/chart/templates/scheduler/scheduler-deployment.yaml @@ -164,7 +164,7 @@ spec: envFrom: {{- include "custom_airflow_environment_from" . | default "\n []" | indent 10 }} env: {{- include "custom_airflow_environment" . | indent 10 }} - {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false) .) | indent 10 }} + {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false "envOverrides" .Values.scheduler.enableBuiltInSecretEnvVars) .) | indent 10 }} {{- if .Values.scheduler.waitForMigrations.env }} {{- tpl (toYaml .Values.scheduler.waitForMigrations.env) $ | nindent 12 }} {{- end }} @@ -192,7 +192,7 @@ spec: envFrom: {{- include "custom_airflow_environment_from" . | default "\n []" | indent 10 }} env: {{- include "custom_airflow_environment" . | indent 10 }} - {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" true) .) | indent 10 }} + {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" true "envOverrides" .Values.scheduler.enableBuiltInSecretEnvVars) .) | indent 10 }} {{- include "container_extra_envs" (list . .Values.scheduler.env) | indent 10 }} livenessProbe: initialDelaySeconds: {{ .Values.scheduler.livenessProbe.initialDelaySeconds }} diff --git a/chart/templates/workers/worker-deployment.yaml b/chart/templates/workers/worker-deployment.yaml index d45a4b15485f3..cc8717f5651f6 100644 --- a/chart/templates/workers/worker-deployment.yaml +++ b/chart/templates/workers/worker-deployment.yaml @@ -217,7 +217,7 @@ spec: - name: KRB5CCNAME value: {{ include "kerberos_ccache_path" . | quote }} {{- include "custom_airflow_environment" . | indent 10 }} - {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false) .) | indent 10 }} + {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false "envOverrides" .Values.workers.celery.enableBuiltInSecretEnvVars) .) | indent 10 }} {{- end }} {{- if .Values.workers.celery.waitForMigrations.enabled }} - name: wait-for-airflow-migrations @@ -242,7 +242,7 @@ spec: envFrom: {{- include "custom_airflow_environment_from" . | default "\n []" | indent 10 }} env: {{- include "custom_airflow_environment" . | indent 10 }} - {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false) .) | indent 10 }} + {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false "envOverrides" .Values.workers.celery.enableBuiltInSecretEnvVars) .) | indent 10 }} {{- if .Values.workers.celery.waitForMigrations.env }} {{- tpl (toYaml .Values.workers.celery.waitForMigrations.env) $ | nindent 12 }} {{- end }} @@ -325,7 +325,7 @@ spec: - name: DUMB_INIT_SETSID value: "0" {{- include "custom_airflow_environment" . | indent 10 }} - {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false) .) | indent 10 }} + {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false "envOverrides" .Values.workers.celery.enableBuiltInSecretEnvVars) .) | indent 10 }} {{- include "container_extra_envs" (list . .Values.workers.celery.env) | indent 10 }} {{- if .Values.workers.celery.kerberosSidecar.enabled }} - name: KRB5_CONFIG @@ -431,7 +431,7 @@ spec: - name: KRB5CCNAME value: {{ include "kerberos_ccache_path" . | quote }} {{- include "custom_airflow_environment" . | indent 10 }} - {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false) .) | indent 10 }} + {{- include "standard_airflow_environment" (merge (dict "IncludeJwtSecret" false "envOverrides" .Values.workers.celery.enableBuiltInSecretEnvVars) .) | indent 10 }} {{- end }} {{- if .Values.workers.celery.extraContainers }} {{- tpl (toYaml .Values.workers.celery.extraContainers) . | nindent 8 }} diff --git a/chart/values.schema.json b/chart/values.schema.json index 7eb865997c7b0..d800746eef632 100644 --- a/chart/values.schema.json +++ b/chart/values.schema.json @@ -1005,7 +1005,52 @@ } } }, - "env": { + + "enableBuiltInSecretEnvVars": { + "description": "Per-worker override for enableBuiltInSecretEnvVars. When a key is set here, it overrides the global value for worker containers only.", + "type": ["object", "null"], + "default": null, + "additionalProperties": false, + "properties": { + "AIRFLOW__CORE__FERNET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__DATABASE__SQL_ALCHEMY_CONN": { + "type": "boolean", + "default": true + }, + "AIRFLOW_CONN_AIRFLOW_DB": { + "type": "boolean", + "default": true + }, + "AIRFLOW__API__SECRET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__API_AUTH__JWT_SECRET": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__RESULT_BACKEND": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__BROKER_URL": { + "type": "boolean", + "default": true + }, + "AIRFLOW__ELASTICSEARCH__HOST": { + "type": "boolean", + "default": true + }, + "AIRFLOW__OPENSEARCH__HOST": { + "type": "boolean", + "default": true + } + } + }, + "env": { "description": "Environment variables for all Airflow containers.", "type": "array", "x-docsSection": "Airflow", @@ -2350,7 +2395,48 @@ "$ref": "#/definitions/io.k8s.api.core.v1.TopologySpreadConstraint" } }, - "hostAliases": { + + "enableBuiltInSecretEnvVars": { + "description": "Per-scheduler override for enableBuiltInSecretEnvVars. When a key is set here, it overrides the global value for scheduler containers only.", + "type": ["object", "null"], + "default": null, + "additionalProperties": false, + "properties": { + "AIRFLOW__CORE__FERNET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__DATABASE__SQL_ALCHEMY_CONN": { + "type": "boolean", + "default": true + }, + "AIRFLOW_CONN_AIRFLOW_DB": { + "type": "boolean", + "default": true + }, + "AIRFLOW__API__SECRET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__RESULT_BACKEND": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__BROKER_URL": { + "type": "boolean", + "default": true + }, + "AIRFLOW__ELASTICSEARCH__HOST": { + "type": "boolean", + "default": true + }, + "AIRFLOW__OPENSEARCH__HOST": { + "type": "boolean", + "default": true + } + } + }, + "hostAliases": { "description": "Specify HostAliases for Airflow Celery worker pods.", "items": { "$ref": "#/definitions/io.k8s.api.core.v1.HostAlias" @@ -3090,7 +3176,48 @@ "$ref": "#/definitions/io.k8s.api.core.v1.TopologySpreadConstraint" } }, - "hostAliases": { + + "enableBuiltInSecretEnvVars": { + "description": "Per-scheduler override for enableBuiltInSecretEnvVars. When a key is set here, it overrides the global value for scheduler containers only.", + "type": ["object", "null"], + "default": null, + "additionalProperties": false, + "properties": { + "AIRFLOW__CORE__FERNET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__DATABASE__SQL_ALCHEMY_CONN": { + "type": "boolean", + "default": true + }, + "AIRFLOW_CONN_AIRFLOW_DB": { + "type": "boolean", + "default": true + }, + "AIRFLOW__API__SECRET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__RESULT_BACKEND": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__BROKER_URL": { + "type": "boolean", + "default": true + }, + "AIRFLOW__ELASTICSEARCH__HOST": { + "type": "boolean", + "default": true + }, + "AIRFLOW__OPENSEARCH__HOST": { + "type": "boolean", + "default": true + } + } + }, + "hostAliases": { "description": "Specify HostAliases for pods created with pod-template-file.", "items": { "$ref": "#/definitions/io.k8s.api.core.v1.HostAlias" @@ -3209,6 +3336,47 @@ "type": "boolean", "default": true }, + + "enableBuiltInSecretEnvVars": { + "description": "Per-scheduler override for enableBuiltInSecretEnvVars. When a key is set here, it overrides the global value for scheduler containers only.", + "type": ["object", "null"], + "default": null, + "additionalProperties": false, + "properties": { + "AIRFLOW__CORE__FERNET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__DATABASE__SQL_ALCHEMY_CONN": { + "type": "boolean", + "default": true + }, + "AIRFLOW_CONN_AIRFLOW_DB": { + "type": "boolean", + "default": true + }, + "AIRFLOW__API__SECRET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__RESULT_BACKEND": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__BROKER_URL": { + "type": "boolean", + "default": true + }, + "AIRFLOW__ELASTICSEARCH__HOST": { + "type": "boolean", + "default": true + }, + "AIRFLOW__OPENSEARCH__HOST": { + "type": "boolean", + "default": true + } + } + }, "hostAliases": { "description": "HostAliases for the scheduler pod.", "items": { @@ -3795,6 +3963,47 @@ "type": "boolean", "default": true }, + + "enableBuiltInSecretEnvVars": { + "description": "Per-scheduler override for enableBuiltInSecretEnvVars. When a key is set here, it overrides the global value for scheduler containers only.", + "type": ["object", "null"], + "default": null, + "additionalProperties": false, + "properties": { + "AIRFLOW__CORE__FERNET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__DATABASE__SQL_ALCHEMY_CONN": { + "type": "boolean", + "default": true + }, + "AIRFLOW_CONN_AIRFLOW_DB": { + "type": "boolean", + "default": true + }, + "AIRFLOW__API__SECRET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__RESULT_BACKEND": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__BROKER_URL": { + "type": "boolean", + "default": true + }, + "AIRFLOW__ELASTICSEARCH__HOST": { + "type": "boolean", + "default": true + }, + "AIRFLOW__OPENSEARCH__HOST": { + "type": "boolean", + "default": true + } + } + }, "hostAliases": { "description": "HostAliases for the triggerer pod.", "items": { @@ -5738,6 +5947,47 @@ "type": "string" } }, + + "enableBuiltInSecretEnvVars": { + "description": "Per-scheduler override for enableBuiltInSecretEnvVars. When a key is set here, it overrides the global value for scheduler containers only.", + "type": ["object", "null"], + "default": null, + "additionalProperties": false, + "properties": { + "AIRFLOW__CORE__FERNET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__DATABASE__SQL_ALCHEMY_CONN": { + "type": "boolean", + "default": true + }, + "AIRFLOW_CONN_AIRFLOW_DB": { + "type": "boolean", + "default": true + }, + "AIRFLOW__API__SECRET_KEY": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__RESULT_BACKEND": { + "type": "boolean", + "default": true + }, + "AIRFLOW__CELERY__BROKER_URL": { + "type": "boolean", + "default": true + }, + "AIRFLOW__ELASTICSEARCH__HOST": { + "type": "boolean", + "default": true + }, + "AIRFLOW__OPENSEARCH__HOST": { + "type": "boolean", + "default": true + } + } + }, "hostAliases": { "description": "HostAliases for the API server pod.", "items": { diff --git a/chart/values.yaml b/chart/values.yaml index 890f9976d970c..4098d9a47c09f 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -988,6 +988,11 @@ workers: # Additional env variable configuration for Airflow Celery workers env: [] + # Per-worker override for enableBuiltInSecretEnvVars. + # When a key is set here, it overrides the global value for worker containers only. + # When nil or missing keys, the global value is used. + enableBuiltInSecretEnvVars: ~ + # Additional volume claim templates for Airflow Celery workers. # Requires mounting of specified volumes under extraVolumeMounts. volumeClaimTemplates: [] @@ -1324,6 +1329,11 @@ scheduler: # Annotations for scheduler Deployment annotations: {} + # Per-scheduler override for enableBuiltInSecretEnvVars. + # When a key is set here, it overrides the global value for scheduler containers only. + # When nil or missing keys, the global value is used. + enableBuiltInSecretEnvVars: ~ + # Pod annotations for scheduler pods (templated) podAnnotations: {}