This is an automated email from the ASF dual-hosted git repository.
jedcunningham 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 4f314d0304b Generate JWT secret during HELM install (#49923)
4f314d0304b is described below
commit 4f314d0304b88dfee7a2d1eed77e4c76a4b036e8
Author: Dov Benyomin Sohacheski <[email protected]>
AuthorDate: Fri Jun 13 23:19:14 2025 +0300
Generate JWT secret during HELM install (#49923)
---
chart/templates/_helpers.yaml | 11 ++++++
chart/templates/secrets/jwt-secret.yaml | 45 ++++++++++++++++++++++
chart/values.schema.json | 23 +++++++++++
chart/values.yaml | 5 +++
.../helm_tests/airflow_aux/test_airflow_common.py | 2 +
.../airflow_aux/test_basic_helm_chart.py | 3 ++
helm-tests/tests/helm_tests/security/test_rbac.py | 1 +
7 files changed, 90 insertions(+)
diff --git a/chart/templates/_helpers.yaml b/chart/templates/_helpers.yaml
index ac2798d0604..da417a59d4c 100644
--- a/chart/templates/_helpers.yaml
+++ b/chart/templates/_helpers.yaml
@@ -98,6 +98,13 @@ If release name contains chart name it will be used as a
full name.
name: {{ template "webserver_secret_key_secret" . }}
key: webserver-secret-key
{{- end }}
+ {{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW__API_AUTH__JWT_SECRET }}
+ - name: AIRFLOW__API_AUTH__JWT_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: {{ template "jwt_secret" . }}
+ key: jwt-secret
+ {{- end }}
{{- if or (contains "CeleryExecutor" .Values.executor) (contains
"CeleryKubernetesExecutor" .Values.executor) }}
{{- if or (semverCompare "<2.4.0" .Values.airflowVersion)
(.Values.data.resultBackendSecretName) (.Values.data.resultBackendConnection) }}
{{- if
.Values.enableBuiltInSecretEnvVars.AIRFLOW__CELERY__CELERY_RESULT_BACKEND }}
@@ -396,6 +403,10 @@ If release name contains chart name it will be used as a
full name.
{{- default (printf "%s-fernet-key" .Release.Name)
.Values.fernetKeySecretName }}
{{- end }}
+{{- define "jwt_secret" -}}
+ {{- default (printf "%s-jwt-secret" .Release.Name) .Values.jwtSecretName }}
+{{- end }}
+
{{- define "webserver_secret_key_secret" -}}
{{- default (printf "%s-webserver-secret-key" (include "airflow.fullname"
.)) .Values.webserverSecretKeySecretName }}
{{- end }}
diff --git a/chart/templates/secrets/jwt-secret.yaml
b/chart/templates/secrets/jwt-secret.yaml
new file mode 100644
index 00000000000..a097a55d556
--- /dev/null
+++ b/chart/templates/secrets/jwt-secret.yaml
@@ -0,0 +1,45 @@
+{{/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/}}
+
+############################################
+## Airflow JWT Secret
+############################################
+{{- if not .Values.jwtSecretName }}
+{{ $generated_secret_key := (randAlphaNum 32 | b64enc) }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ include "airflow.fullname" . }}-jwt-secret
+ labels:
+ tier: airflow
+ component: api-server
+ release: {{ .Release.Name }}
+ chart: {{ .Chart.Name }}
+ heritage: {{ .Release.Service }}
+ {{- with .Values.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ annotations:
+ "helm.sh/hook": "pre-install"
+ "helm.sh/hook-delete-policy": "before-hook-creation"
+ "helm.sh/hook-weight": "0"
+type: Opaque
+data:
+ jwt-secret: {{ (default $generated_secret_key .Values.jwtSecret) | b64enc |
quote }}
+{{- end }}
diff --git a/chart/values.schema.json b/chart/values.schema.json
index 1aaa2efc041..9636d3a07e5 100644
--- a/chart/values.schema.json
+++ b/chart/values.schema.json
@@ -1064,6 +1064,11 @@
"type": "boolean",
"default": true
},
+ "AIRFLOW__API_AUTH__JWT_SECRET": {
+ "description": "Enable ``AIRFLOW__API_AUTH__JWT_SECRET``
variable to be read from the JWT Secret",
+ "type": "boolean",
+ "default": true
+ },
"AIRFLOW__WEBSERVER__SECRET_KEY": {
"description": "Enable ``AIRFLOW__WEBSERVER__SECRET_KEY``
variable to be read from the Webserver Secret Key Secret",
"type": "boolean",
@@ -1459,6 +1464,24 @@
"type": "string"
}
},
+ "jwtSecret": {
+ "description": "Secret key used to encode and decode JWTs to
authenticate to public and private APIs (can only be set during install, not
upgrade).",
+ "type": [
+ "string",
+ "null"
+ ],
+ "x-docsSection": "Common",
+ "default": null
+ },
+ "jwtSecretName": {
+ "description": "The JWT secret name.",
+ "type": [
+ "string",
+ "null"
+ ],
+ "x-docsSection": "Airflow",
+ "default": null
+ },
"webserverSecretKey": {
"description": "The Flask secret key for Airflow Webserver to
encrypt browser session.",
"type": [
diff --git a/chart/values.yaml b/chart/values.yaml
index 6a512d8fe4d..c777b03fdd3 100644
--- a/chart/values.yaml
+++ b/chart/values.yaml
@@ -407,6 +407,7 @@ enableBuiltInSecretEnvVars:
AIRFLOW__CORE__SQL_ALCHEMY_CONN: true
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: true
AIRFLOW_CONN_AIRFLOW_DB: true
+ AIRFLOW__API_AUTH__JWT_SECRET: true
AIRFLOW__WEBSERVER__SECRET_KEY: true
AIRFLOW__CELERY__CELERY_RESULT_BACKEND: true
AIRFLOW__CELERY__RESULT_BACKEND: true
@@ -556,6 +557,10 @@ webserverSecretKey: ~
webserverSecretAnnotations: {}
webserverSecretKeySecretName: ~
+# Secret key used to encode and decode JWTs: `[api_auth] jwt_secret` in
airflow.cfg
+jwtSecret: ~
+jwtSecretName: ~
+
# In order to use kerberos you need to create secret containing the keytab file
# The secret name should follow naming convention of the application where
resources are
# name {{ .Release-name }}-<POSTFIX>. In case of the keytab file, the postfix
is "kerberos-keytab"
diff --git a/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py
b/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py
index 78b43d02f73..e6b247afb1c 100644
--- a/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py
+++ b/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py
@@ -323,6 +323,7 @@ class TestAirflowCommon:
"enableBuiltInSecretEnvVars": {
"AIRFLOW__CORE__SQL_ALCHEMY_CONN": False,
"AIRFLOW__DATABASE__SQL_ALCHEMY_CONN": False,
+ "AIRFLOW__API_AUTH__JWT_SECRET": False,
"AIRFLOW__WEBSERVER__SECRET_KEY": False,
# the following vars only appear if remote logging is set,
so disabling them in this test is kind of a no-op
"AIRFLOW__ELASTICSEARCH__HOST": False,
@@ -370,6 +371,7 @@ class TestAirflowCommon:
"AIRFLOW__DATABASE__SQL_ALCHEMY_CONN",
"AIRFLOW_CONN_AIRFLOW_DB",
"AIRFLOW__WEBSERVER__SECRET_KEY",
+ "AIRFLOW__API_AUTH__JWT_SECRET",
"AIRFLOW__CELERY__BROKER_URL",
]
expected_vars_in_worker = ["DUMB_INIT_SETSID"] + expected_vars
diff --git a/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py
b/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py
index 91829848f8e..d7977f7e528 100644
--- a/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py
+++ b/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py
@@ -38,6 +38,7 @@ OBJECTS_STD_NAMING = {
("Secret", "test-basic-airflow-metadata"),
("Secret", "test-basic-broker-url"),
("Secret", "test-basic-fernet-key"),
+ ("Secret", "test-basic-airflow-jwt-secret"),
("Secret", "test-basic-airflow-webserver-secret-key"),
("Secret", "test-basic-redis-password"),
("Secret", "test-basic-postgresql"),
@@ -136,6 +137,7 @@ class TestBaseChartTest:
("Secret", "test-basic-metadata"),
("Secret", "test-basic-broker-url"),
("Secret", "test-basic-fernet-key"),
+ ("Secret", "test-basic-jwt-secret"),
("Secret", "test-basic-webserver-secret-key"),
("Secret", "test-basic-postgresql"),
("Secret", "test-basic-redis-password"),
@@ -236,6 +238,7 @@ class TestBaseChartTest:
("Secret", "test-basic-metadata"),
("Secret", "test-basic-broker-url"),
("Secret", "test-basic-fernet-key"),
+ ("Secret", "test-basic-jwt-secret"),
("Secret", "test-basic-webserver-secret-key"),
("Secret", "test-basic-postgresql"),
("Secret", "test-basic-redis-password"),
diff --git a/helm-tests/tests/helm_tests/security/test_rbac.py
b/helm-tests/tests/helm_tests/security/test_rbac.py
index 6271e7cfafc..fcd578daa60 100644
--- a/helm-tests/tests/helm_tests/security/test_rbac.py
+++ b/helm-tests/tests/helm_tests/security/test_rbac.py
@@ -46,6 +46,7 @@ DEPLOYMENT_NO_RBAC_NO_SA_KIND_NAME_TUPLES = [
("StatefulSet", "test-rbac-worker"),
("Secret", "test-rbac-broker-url"),
("Secret", "test-rbac-fernet-key"),
+ ("Secret", "test-rbac-jwt-secret"),
("Secret", "test-rbac-redis-password"),
("Secret", "test-rbac-webserver-secret-key"),
("Job", "test-rbac-create-user"),