Skip to content

Commit 3124df8

Browse files
rawwarYour Name
authored and
Your Name
committed
[v3-0-test] add SimpleAllAdminMiddleware to allow api usage without auth header in request (#49599)
* add SimpleAllAdminMiddleware * add tests * update test * update test name * refactor test * sort test order * hardcode endpoints * use session * db_test mark * iterate over app.routes * use fewer endpoints * update comment * update scope (cherry picked from commit 003bf6d) Co-authored-by: Kalyan R <[email protected]>
1 parent 3eee8c8 commit 3124df8

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
from __future__ import annotations
19+
20+
from fastapi import Request
21+
from starlette.middleware.base import BaseHTTPMiddleware
22+
23+
from airflow.api_fastapi.auth.managers.simple.services.login import SimpleAuthManagerLogin
24+
25+
26+
class SimpleAllAdminMiddleware(BaseHTTPMiddleware):
27+
"""Middleware that automatically generates and includes auth header for simple auth manager."""
28+
29+
async def dispatch(self, request: Request, call_next):
30+
# Starlette Request is expected to be immutable, but we modify it to add the auth header
31+
# https://github.com/fastapi/fastapi/issues/2727#issuecomment-770202019
32+
token = SimpleAuthManagerLogin.create_token_all_admins()
33+
request.scope["headers"].append((b"authorization", f"Bearer {token}".encode()))
34+
return await call_next(request)

airflow-core/src/airflow/api_fastapi/core_api/app.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,10 @@ def init_error_handlers(app: FastAPI) -> None:
167167

168168

169169
def init_middlewares(app: FastAPI) -> None:
170+
from airflow.configuration import conf
171+
170172
app.add_middleware(FlaskExceptionsMiddleware)
173+
if conf.getboolean("core", "simple_auth_manager_all_admins"):
174+
from airflow.api_fastapi.auth.managers.simple.middleware import SimpleAllAdminMiddleware
175+
176+
app.add_middleware(SimpleAllAdminMiddleware)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
from __future__ import annotations
19+
20+
import pytest
21+
from fastapi.testclient import TestClient
22+
23+
from airflow.api_fastapi.app import create_app
24+
25+
from tests_common.test_utils.config import conf_vars
26+
27+
pytestmark = pytest.mark.db_test
28+
29+
30+
@pytest.fixture
31+
def all_access_test_client():
32+
with conf_vars(
33+
{
34+
("core", "simple_auth_manager_all_admins"): "true",
35+
("webserver", "expose_config"): "true",
36+
}
37+
):
38+
app = create_app()
39+
yield TestClient(app)
40+
41+
42+
@pytest.mark.parametrize(
43+
"method, path",
44+
[
45+
("GET", "/api/v2/assets"),
46+
("POST", "/api/v2/backfills"),
47+
("GET", "/api/v2/config"),
48+
("GET", "/api/v2/dags"),
49+
("POST", "/api/v2/dags/{dag_id}/clearTaskInstances"),
50+
("GET", "/api/v2/dags/{dag_id}/dagRuns"),
51+
("GET", "/api/v2/eventLogs"),
52+
("GET", "/api/v2/jobs"),
53+
("GET", "/api/v2/variables"),
54+
("GET", "/api/v2/version"),
55+
],
56+
)
57+
def test_all_endpoints_without_auth_header(all_access_test_client, method, path):
58+
response = all_access_test_client.request(method, path)
59+
assert response.status_code not in {401, 403}, (
60+
f"Unexpected status code {response.status_code} for {method} {path}"
61+
)

0 commit comments

Comments
 (0)