diff --git a/chart/templates/_helpers.yaml b/chart/templates/_helpers.yaml index ac2798d0604b0..da417a59d4cc6 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 0000000000000..a097a55d5565c --- /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 614399d4d51e3..79583aada47fd 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 524af23122779..4fed9574bd21d 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 }}-. 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 78b43d02f73eb..e6b247afb1cd0 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 @@ def test_should_disable_some_variables(self): "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 @@ def test_have_all_variables(self): "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 91829848f8ea2..d7977f7e5281e 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 @@ ("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 @@ def test_basic_deployments(self, version): ("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 @@ def test_basic_deployment_with_standalone_dag_processor(self, version): ("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 6271e7cfafcf0..fcd578daa608e 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 @@ ("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"),