Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dag warning endpoint permissions #34355

Merged
merged 4 commits into from
Sep 15, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions airflow/api_connexion/endpoints/dag_warning_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@

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,
dag_warning_collection_schema,
)
from airflow.models.dagwarning import DagWarning as DagWarningModel
from airflow.security import permissions
from airflow.utils.db import get_query_count
from airflow.utils.airflow_flask_app import get_airflow_app
from airflow.utils.session import NEW_SESSION, provide_session

if TYPE_CHECKING:
Expand Down Expand Up @@ -57,12 +59,20 @@ 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):
Copy link
Contributor

@ephraimbuddy ephraimbuddy Sep 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel we should have the DAG permission in the decorator instead of handling this by ourselves. My vote would go to just adding (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG) to the list of permissions.
That should solve this. Assuming it's dag_ids instead of dag_id, then we can do as you're doing now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see that if dag_id is not provided, then it gets all dag warning, my bad.

raise PermissionDenied(detail=f"User not allowed to access this DAG: {dag_id}")
query = query.where(DagWarningModel.dag_id == dag_id)
if warning_type:
query = query.where(DagWarningModel.warning_type == warning_type)
total_entries = get_query_count(query, session=session)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useless query, the count could be calculated from the list

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually not useless, because the is limit in the query, I will fix it

query = apply_sorting(query=query, order_by=order_by, allowed_attrs=allowed_filter_attrs)
dag_warnings = session.scalars(query.offset(offset).limit(limit)).all()
if not dag_id:
dag_warnings = [
dag_warning
for dag_warning in dag_warnings
if get_airflow_app().appbuilder.sm.can_read_dag(dag_warning.dag_id, g.user)
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filtering should happen before limit, otherwise this would show a weird number of entries if some of the warnings are not viewable by the current user, even possibly an empty list.

total_entries = len(dag_warnings)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is supposed to show the actual total, not the paginated value

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. This is the total not paginated

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, I changed it but I forgot to push my commit. Just pushed it

return dag_warning_collection_schema.dump(
DagWarningCollection(dag_warnings=dag_warnings, total_entries=total_entries)
)
Loading