This is an automated email from the ASF dual-hosted git repository.
jscheffl 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 c2e5bde10ea Treat non-sensitive-only as true and always mask sensitive
values in public api's (#59880)
c2e5bde10ea is described below
commit c2e5bde10ea84262c06910d511c93261ff1b85da
Author: Pratyush Gupta <[email protected]>
AuthorDate: Sat Jan 3 19:19:17 2026 +0530
Treat non-sensitive-only as true and always mask sensitive values in public
api's (#59880)
* Treat non-sensitive-only as true and always mask sensitive values in
public APIs.
* Add newsfragment and update docs and client references for config masking
* newline error fixed - config.yml
* Update clients/python/README.md
Co-authored-by: Bas Harenslak <[email protected]>
* CI image check resolved
* newline error in config.py fixed
---------
Co-authored-by: Jarek Potiuk <[email protected]>
Co-authored-by: Bas Harenslak <[email protected]>
---
airflow-core/newsfragments/59880.bugfix.rst | 1 +
.../src/airflow/api_fastapi/core_api/services/public/config.py | 10 +++++++++-
airflow-core/src/airflow/config_templates/config.yml | 6 +++---
.../unit/api_fastapi/core_api/routes/public/test_config.py | 8 ++++----
clients/python/README.md | 1 +
clients/python/test_python_client.py | 1 +
6 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/airflow-core/newsfragments/59880.bugfix.rst
b/airflow-core/newsfragments/59880.bugfix.rst
new file mode 100644
index 00000000000..e1c35a9d640
--- /dev/null
+++ b/airflow-core/newsfragments/59880.bugfix.rst
@@ -0,0 +1 @@
+Always mask sensitive configuration values in public config APIs and treat the
deprecated ``non-sensitive-only`` value as ``True``.
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/services/public/config.py
b/airflow-core/src/airflow/api_fastapi/core_api/services/public/config.py
index a23c957074b..0b51a6c33ae 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/services/public/config.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/services/public/config.py
@@ -16,6 +16,8 @@
# under the License.
from __future__ import annotations
+import warnings
+
from fastapi import HTTPException, status
from fastapi.responses import Response
@@ -29,9 +31,15 @@ def _check_expose_config() -> bool:
if conf.get("api", "expose_config").lower() == "non-sensitive-only":
expose_config = True
display_sensitive = False
+ warnings.warn(
+ "The value 'non-sensitive-only' for [api] expose_config is
deprecated. "
+ "Use 'true' instead; sensitive configuration values are always
masked.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
else:
expose_config = conf.getboolean("api", "expose_config")
- display_sensitive = True
+ display_sensitive = False
if not expose_config:
raise HTTPException(
diff --git a/airflow-core/src/airflow/config_templates/config.yml
b/airflow-core/src/airflow/config_templates/config.yml
index bc00638ae1e..a4ed088865a 100644
--- a/airflow-core/src/airflow/config_templates/config.yml
+++ b/airflow-core/src/airflow/config_templates/config.yml
@@ -1443,9 +1443,9 @@ api:
default: "{SECRET_KEY}"
expose_config:
description: |
- Expose the configuration file in the web server. Set to
``non-sensitive-only`` to show all values
- except those that have security implications. ``True`` shows all
values. ``False`` hides the
- configuration completely.
+ Expose the configuration file in the web server. Set to ``True`` to
expose configuration with
+ sensitive values always masked. The deprecated value
``non-sensitive-only`` is treated the same as
+ ``True`` for backward compatibility. ``False`` hides the configuration
completely.
version_added: ~
type: string
example: ~
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_config.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_config.py
index 9ceacd48ea4..aa1a74890f7 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_config.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_config.py
@@ -56,7 +56,7 @@ MOCK_CONFIG_DICT = {
OPTION_KEY_SMTP_MAIL_FROM: OPTION_VALUE_SMTP_MAIL_FROM,
},
SECTION_DATABASE: {
- OPTION_KEY_SQL_ALCHEMY_CONN: OPTION_VALUE_SQL_ALCHEMY_CONN,
+ OPTION_KEY_SQL_ALCHEMY_CONN: OPTION_VALUE_SENSITIVE_HIDDEN,
},
}
MOCK_CONFIG_DICT_SENSITIVE_HIDDEN = {
@@ -102,7 +102,7 @@ GET_CONFIG_ALL_JSON_RESPONSE = {
{
"name": SECTION_DATABASE,
"options": [
- {"key": OPTION_KEY_SQL_ALCHEMY_CONN, "value":
OPTION_VALUE_SQL_ALCHEMY_CONN},
+ {"key": OPTION_KEY_SQL_ALCHEMY_CONN, "value":
OPTION_VALUE_SENSITIVE_HIDDEN},
],
},
],
@@ -206,7 +206,7 @@ class TestGetConfig(TestConfigEndpoint):
{OPTION_KEY_SMTP_MAIL_FROM} = {OPTION_VALUE_SMTP_MAIL_FROM}
[{SECTION_DATABASE}]
- {OPTION_KEY_SQL_ALCHEMY_CONN} =
{OPTION_VALUE_SQL_ALCHEMY_CONN}
+ {OPTION_KEY_SQL_ALCHEMY_CONN} =
{OPTION_VALUE_SENSITIVE_HIDDEN}
"""
),
),
@@ -252,7 +252,7 @@ class TestGetConfig(TestConfigEndpoint):
{
"name": SECTION_DATABASE,
"options": [
- {"key": OPTION_KEY_SQL_ALCHEMY_CONN, "value":
OPTION_VALUE_SQL_ALCHEMY_CONN},
+ {"key": OPTION_KEY_SQL_ALCHEMY_CONN, "value":
OPTION_VALUE_SENSITIVE_HIDDEN},
],
},
],
diff --git a/clients/python/README.md b/clients/python/README.md
index e164f4b5ca8..6f04629a3a5 100644
--- a/clients/python/README.md
+++ b/clients/python/README.md
@@ -630,6 +630,7 @@ You can also set it by env variable: `export
AIRFLOW__CORE__LOAD_EXAMPLES=True`
* optionally expose configuration (NOTE! that this is dangerous setting). The
script will happily run with
the default setting, but if you want to see the configuration, you need to
expose it.
+ Note that sensitive configuration values are always masked.
In the `[api]` section of your `airflow.cfg` set:
```ini
diff --git a/clients/python/test_python_client.py
b/clients/python/test_python_client.py
index 9d771428f87..30cdfb2afaa 100644
--- a/clients/python/test_python_client.py
+++ b/clients/python/test_python_client.py
@@ -121,6 +121,7 @@ def test_python_client():
# Get current configuration. Note, this is disabled by default with
most installation.
# You need to set `expose_config = True` in Airflow configuration in
order to retrieve configuration.
+ # Sensitive configuration values are always masked in the response.
conf_api_instance = config_api.ConfigApi(api_client)
try:
api_response = conf_api_instance.get_config()