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

husseinawala 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 3570bbfbea Fix dag warning endpoint permissions (#34355)
3570bbfbea is described below

commit 3570bbfbea69e2965f91b9964ce28bc268c68129
Author: Hussein Awala <[email protected]>
AuthorDate: Fri Sep 15 19:08:49 2023 +0200

    Fix dag warning endpoint permissions (#34355)
    
    * Fix dag warning endpoint permissions
    
    * update the query to have an accurate result for total entries and 
pagination
    
    * add unit tests
    
    * Update test_dag_warning_endpoint.py
    
    Co-authored-by: Tzu-ping Chung <[email protected]>
    
    ---------
    
    Co-authored-by: Tzu-ping Chung <[email protected]>
---
 .../endpoints/dag_warning_endpoint.py              |  8 ++++++++
 .../endpoints/test_dag_warning_endpoint.py         | 23 +++++++++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/airflow/api_connexion/endpoints/dag_warning_endpoint.py 
b/airflow/api_connexion/endpoints/dag_warning_endpoint.py
index 203bb9d6a5..367b0ae104 100644
--- a/airflow/api_connexion/endpoints/dag_warning_endpoint.py
+++ b/airflow/api_connexion/endpoints/dag_warning_endpoint.py
@@ -18,9 +18,11 @@ from __future__ import annotations
 
 from typing import TYPE_CHECKING
 
+from flask import g
 from sqlalchemy import select
 
 from airflow.api_connexion import security
+from airflow.api_connexion.exceptions import PermissionDenied
 from airflow.api_connexion.parameters import apply_sorting, check_limit, 
format_parameters
 from airflow.api_connexion.schemas.dag_warning_schema import (
     DagWarningCollection,
@@ -28,6 +30,7 @@ from airflow.api_connexion.schemas.dag_warning_schema import (
 )
 from airflow.models.dagwarning import DagWarning as DagWarningModel
 from airflow.security import permissions
+from airflow.utils.airflow_flask_app import get_airflow_app
 from airflow.utils.db import get_query_count
 from airflow.utils.session import NEW_SESSION, provide_session
 
@@ -57,7 +60,12 @@ def get_dag_warnings(
     allowed_filter_attrs = ["dag_id", "warning_type", "message", "timestamp"]
     query = select(DagWarningModel)
     if dag_id:
+        if not get_airflow_app().appbuilder.sm.can_read_dag(dag_id, g.user):
+            raise PermissionDenied(detail=f"User not allowed to access this 
DAG: {dag_id}")
         query = query.where(DagWarningModel.dag_id == dag_id)
+    else:
+        readable_dags = 
get_airflow_app().appbuilder.sm.get_accessible_dag_ids(g.user)
+        query = query.where(DagWarningModel.dag_id.in_(readable_dags))
     if warning_type:
         query = query.where(DagWarningModel.warning_type == warning_type)
     total_entries = get_query_count(query, session=session)
diff --git a/tests/api_connexion/endpoints/test_dag_warning_endpoint.py 
b/tests/api_connexion/endpoints/test_dag_warning_endpoint.py
index 621b043667..041a61634e 100644
--- a/tests/api_connexion/endpoints/test_dag_warning_endpoint.py
+++ b/tests/api_connexion/endpoints/test_dag_warning_endpoint.py
@@ -35,14 +35,27 @@ def configured_app(minimal_app_for_api):
         app,  # type:ignore
         username="test",
         role_name="Test",
-        permissions=[(permissions.ACTION_CAN_READ, 
permissions.RESOURCE_DAG_WARNING)],  # type: ignore
+        permissions=[
+            (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_WARNING),
+            (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG),
+        ],  # type: ignore
     )
     create_user(app, username="test_no_permissions", 
role_name="TestNoPermissions")  # type: ignore
+    create_user(
+        app,  # type:ignore
+        username="test_with_dag2_read",
+        role_name="TestWithDag2Read",
+        permissions=[
+            (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_WARNING),
+            (permissions.ACTION_CAN_READ, 
f"{permissions.RESOURCE_DAG_PREFIX}dag2"),
+        ],  # type: ignore
+    )
 
     yield minimal_app_for_api
 
     delete_user(app, username="test")  # type: ignore
     delete_user(app, username="test_no_permissions")  # type: ignore
+    delete_user(app, username="test_with_dag2_read")  # type: ignore
 
 
 class TestBaseDagWarning:
@@ -147,3 +160,11 @@ class TestGetDagWarningEndpoint(TestBaseDagWarning):
             "/api/v1/dagWarnings", environ_overrides={"REMOTE_USER": 
"test_no_permissions"}
         )
         assert response.status_code == 403
+
+    def 
test_should_raise_403_forbidden_when_user_has_no_dag_read_permission(self):
+        response = self.client.get(
+            "/api/v1/dagWarnings",
+            environ_overrides={"REMOTE_USER": "test_with_dag2_read"},
+            query_string={"dag_id": "dag1"},
+        )
+        assert response.status_code == 403

Reply via email to