This is an automated email from the ASF dual-hosted git repository.

jasonliu 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 af27f43fe48 Add back `SimpleAllAdminMiddleware` (#58829)
af27f43fe48 is described below

commit af27f43fe48b1b7bcdeec7df149565756853f9a0
Author: Vincent <[email protected]>
AuthorDate: Sun Nov 30 07:46:30 2025 -0500

    Add back `SimpleAllAdminMiddleware` (#58829)
---
 .../api_fastapi/auth/managers/simple/middleware.py | 34 ++++++++++++
 .../src/airflow/api_fastapi/core_api/app.py        |  5 ++
 .../auth/managers/simple/test_middleware.py        | 61 ++++++++++++++++++++++
 3 files changed, 100 insertions(+)

diff --git 
a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/middleware.py 
b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/middleware.py
new file mode 100644
index 00000000000..6c73cd015fa
--- /dev/null
+++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/middleware.py
@@ -0,0 +1,34 @@
+# 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.
+
+from __future__ import annotations
+
+from fastapi import Request
+from starlette.middleware.base import BaseHTTPMiddleware
+
+from airflow.api_fastapi.auth.managers.simple.services.login import 
SimpleAuthManagerLogin
+
+
+class SimpleAllAdminMiddleware(BaseHTTPMiddleware):
+    """Middleware that automatically generates and includes auth header for 
simple auth manager."""
+
+    async def dispatch(self, request: Request, call_next):
+        # Starlette Request is expected to be immutable, but we modify it to 
add the auth header
+        # https://github.com/fastapi/fastapi/issues/2727#issuecomment-770202019
+        token = SimpleAuthManagerLogin.create_token_all_admins()
+        request.scope["headers"].append((b"authorization", f"Bearer 
{token}".encode()))
+        return await call_next(request)
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/app.py 
b/airflow-core/src/airflow/api_fastapi/core_api/app.py
index 8db1fa66680..1f370f5844d 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/app.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/app.py
@@ -31,6 +31,7 @@ from starlette.staticfiles import StaticFiles
 from starlette.templating import Jinja2Templates
 
 from airflow.api_fastapi.auth.tokens import get_signing_key
+from airflow.configuration import conf
 from airflow.exceptions import AirflowException
 from airflow.settings import AIRFLOW_PATH
 
@@ -185,6 +186,10 @@ def init_middlewares(app: FastAPI) -> None:
     from airflow.api_fastapi.auth.middlewares.refresh_token import 
JWTRefreshMiddleware
 
     app.add_middleware(JWTRefreshMiddleware)
+    if conf.getboolean("core", "simple_auth_manager_all_admins"):
+        from airflow.api_fastapi.auth.managers.simple.middleware import 
SimpleAllAdminMiddleware
+
+        app.add_middleware(SimpleAllAdminMiddleware)
 
 
 def init_ui_plugins(app: FastAPI) -> None:
diff --git 
a/airflow-core/tests/unit/api_fastapi/auth/managers/simple/test_middleware.py 
b/airflow-core/tests/unit/api_fastapi/auth/managers/simple/test_middleware.py
new file mode 100644
index 00000000000..1f16f04ec8b
--- /dev/null
+++ 
b/airflow-core/tests/unit/api_fastapi/auth/managers/simple/test_middleware.py
@@ -0,0 +1,61 @@
+# 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.
+
+from __future__ import annotations
+
+import pytest
+from fastapi.testclient import TestClient
+
+from airflow.api_fastapi.app import create_app
+
+from tests_common.test_utils.config import conf_vars
+
+pytestmark = pytest.mark.db_test
+
+
[email protected]
+def all_access_test_client():
+    with conf_vars(
+        {
+            ("core", "simple_auth_manager_all_admins"): "true",
+            ("webserver", "expose_config"): "true",
+        }
+    ):
+        app = create_app()
+        yield TestClient(app)
+
+
[email protected](
+    ("method", "path"),
+    [
+        ("GET", "/api/v2/assets"),
+        ("POST", "/api/v2/backfills"),
+        ("GET", "/api/v2/config"),
+        ("GET", "/api/v2/dags"),
+        ("POST", "/api/v2/dags/{dag_id}/clearTaskInstances"),
+        ("GET", "/api/v2/dags/{dag_id}/dagRuns"),
+        ("GET", "/api/v2/eventLogs"),
+        ("GET", "/api/v2/jobs"),
+        ("GET", "/api/v2/variables"),
+        ("GET", "/api/v2/version"),
+    ],
+)
+def test_all_endpoints_without_auth_header(all_access_test_client, method, 
path):
+    response = all_access_test_client.request(method, path)
+    assert response.status_code not in {401, 403}, (
+        f"Unexpected status code {response.status_code} for {method} {path}"
+    )

Reply via email to