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

ephraimanierobi pushed a commit to branch v2-6-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit c78e16588ee399f6eaf60425eb1ad7fa6d3fe352
Author: Niko Oliveira <[email protected]>
AuthorDate: Tue Jun 20 10:04:45 2023 -0700

    Check for DAG ID in query param from url as well as kwargs (#32014)
    
    Previously the dag id was only being checked in request args and form
    but not kwargs, so it was possible for the id when passed as kwargs
    to be None. This can allow auth for a user who does not have the
    permissions to view a particular DAG.
    
    (cherry picked from commit ac65b82eeeeaa670e09a83c7da65cbac7e89f8db)
---
 airflow/www/auth.py                 |  3 ++-
 tests/www/views/test_views_tasks.py | 47 +++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/airflow/www/auth.py b/airflow/www/auth.py
index 8fdafa1f63..0056af55fd 100644
--- a/airflow/www/auth.py
+++ b/airflow/www/auth.py
@@ -38,7 +38,8 @@ def has_access(permissions: Sequence[tuple[str, str]] | None 
= None) -> Callable
             appbuilder = current_app.appbuilder
 
             dag_id = (
-                request.args.get("dag_id")
+                kwargs.get("dag_id")
+                or request.args.get("dag_id")
                 or request.form.get("dag_id")
                 or (request.is_json and request.json.get("dag_id"))
                 or None
diff --git a/tests/www/views/test_views_tasks.py 
b/tests/www/views/test_views_tasks.py
index 35538e5bf9..8ed25f5614 100644
--- a/tests/www/views/test_views_tasks.py
+++ b/tests/www/views/test_views_tasks.py
@@ -369,6 +369,20 @@ def test_graph_trigger_origin_graph_view(app, 
admin_client):
     check_content_in_response(href, resp)
 
 
+def test_graph_view_without_dag_permission(app, one_dag_perm_user_client):
+    url = "/dags/example_bash_operator/graph"
+    resp = one_dag_perm_user_client.get(url, follow_redirects=True)
+    assert resp.status_code == 200
+    assert resp.request.url == 
"http://localhost/dags/example_bash_operator/graph";
+    check_content_in_response("example_bash_operator", resp)
+
+    url = "/dags/example_xcom/graph"
+    resp = one_dag_perm_user_client.get(url, follow_redirects=True)
+    assert resp.status_code == 200
+    assert resp.request.url == "http://localhost/home";
+    check_content_in_response("Access is Denied", resp)
+
+
 def test_dag_details_trigger_origin_dag_details_view(app, admin_client):
     app.dag_bag.get_dag("test_graph_view").create_dagrun(
         run_type=DagRunType.SCHEDULED,
@@ -581,6 +595,39 @@ def per_dag_perm_user_client(app, new_dag_to_delete):
     delete_roles(app)
 
 
[email protected]()
+def one_dag_perm_user_client(app):
+    username = "test_user_one_dag_perm"
+    dag_id = "example_bash_operator"
+    sm = app.appbuilder.sm
+    perm = f"{permissions.RESOURCE_DAG_PREFIX}{dag_id}"
+
+    sm.create_permission(permissions.ACTION_CAN_READ, perm)
+
+    create_user(
+        app,
+        username=username,
+        role_name="User with permission to access only one dag",
+        permissions=[
+            (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_INSTANCE),
+            (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_LOG),
+            (permissions.ACTION_CAN_READ, permissions.RESOURCE_WEBSITE),
+            (permissions.ACTION_CAN_READ, perm),
+        ],
+    )
+
+    sm.find_user(username=username)
+
+    yield client_with_login(
+        app,
+        username=username,
+        password=username,
+    )
+
+    delete_user(app, username=username)  # type: ignore
+    delete_roles(app)
+
+
 def test_delete_just_dag_per_dag_permissions(new_dag_to_delete, 
per_dag_perm_user_client):
     resp = per_dag_perm_user_client.post(
         f"delete?dag_id={new_dag_to_delete.dag_id}&next=/home", 
follow_redirects=True

Reply via email to