This is an automated email from the ASF dual-hosted git repository. ephraimanierobi pushed a commit to branch v2-8-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit a7b888240ace445b7c963ece75e847343ed9ffe0 Author: Vincent <[email protected]> AuthorDate: Tue Mar 5 13:56:44 2024 -0500 Add "MENU" permission in auth manager (#37881) (cherry picked from commit 89e7f3e7bdf2126bbbcd959dc10d65ef92773cca) --- airflow/auth/managers/base_auth_manager.py | 2 +- airflow/auth/managers/fab/fab_auth_manager.py | 15 ++++----------- airflow/auth/managers/utils/fab.py | 2 +- airflow/www/security_manager.py | 4 +--- tests/auth/managers/fab/test_fab_auth_manager.py | 17 +++++++++++++++-- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/airflow/auth/managers/base_auth_manager.py b/airflow/auth/managers/base_auth_manager.py index f64c803e6a..0b60969768 100644 --- a/airflow/auth/managers/base_auth_manager.py +++ b/airflow/auth/managers/base_auth_manager.py @@ -55,7 +55,7 @@ if TYPE_CHECKING: from airflow.www.extensions.init_appbuilder import AirflowAppBuilder from airflow.www.security_manager import AirflowSecurityManagerV2 -ResourceMethod = Literal["GET", "POST", "PUT", "DELETE"] +ResourceMethod = Literal["GET", "POST", "PUT", "DELETE", "MENU"] class BaseAuthManager(LoggingMixin): diff --git a/airflow/auth/managers/fab/fab_auth_manager.py b/airflow/auth/managers/fab/fab_auth_manager.py index 2e4014af2e..80624ef4a5 100644 --- a/airflow/auth/managers/fab/fab_auth_manager.py +++ b/airflow/auth/managers/fab/fab_auth_manager.py @@ -53,8 +53,6 @@ from airflow.exceptions import AirflowException from airflow.models import DagModel from airflow.security import permissions from airflow.security.permissions import ( - ACTION_CAN_ACCESS_MENU, - ACTION_CAN_READ, RESOURCE_AUDIT_LOG, RESOURCE_CLUSTER_ACTIVITY, RESOURCE_CONFIG, @@ -266,8 +264,10 @@ class FabAuthManager(BaseAuthManager): return self._is_authorized(method=method, resource_type=RESOURCE_VARIABLE, user=user) def is_authorized_view(self, *, access_view: AccessView, user: BaseUser | None = None) -> bool: + # "Docs" are only links in the menu, there is no page associated + method: ResourceMethod = "MENU" if access_view == AccessView.DOCS else "GET" return self._is_authorized( - method="GET", resource_type=_MAP_ACCESS_VIEW_TO_FAB_RESOURCE_TYPE[access_view], user=user + method=method, resource_type=_MAP_ACCESS_VIEW_TO_FAB_RESOURCE_TYPE[access_view], user=user ) def is_authorized_custom_view( @@ -472,18 +472,11 @@ class FabAuthManager(BaseAuthManager): """ Return the user permissions. - ACTION_CAN_READ and ACTION_CAN_ACCESS_MENU are merged into because they are very similar. - We can assume that if a user has permissions to read variables, they also have permissions to access - the menu "Variables". - :param user: the user to get permissions for :meta private: """ - perms = getattr(user, "perms") or [] - return [ - (ACTION_CAN_READ if perm[0] == ACTION_CAN_ACCESS_MENU else perm[0], perm[1]) for perm in perms - ] + return getattr(user, "perms") or [] def _get_root_dag_id(self, dag_id: str) -> str: """ diff --git a/airflow/auth/managers/utils/fab.py b/airflow/auth/managers/utils/fab.py index 316e5ecff1..5065f930fe 100644 --- a/airflow/auth/managers/utils/fab.py +++ b/airflow/auth/managers/utils/fab.py @@ -36,6 +36,7 @@ _MAP_METHOD_NAME_TO_FAB_ACTION_NAME: dict[ResourceMethod, str] = { "GET": ACTION_CAN_READ, "PUT": ACTION_CAN_EDIT, "DELETE": ACTION_CAN_DELETE, + "MENU": ACTION_CAN_ACCESS_MENU, } @@ -48,5 +49,4 @@ def get_method_from_fab_action_map(): """Returns the map associating a FAB action to a method.""" return { **{v: k for k, v in _MAP_METHOD_NAME_TO_FAB_ACTION_NAME.items()}, - ACTION_CAN_ACCESS_MENU: "GET", } diff --git a/airflow/www/security_manager.py b/airflow/www/security_manager.py index 13342ff7f7..772e672ff6 100644 --- a/airflow/www/security_manager.py +++ b/airflow/www/security_manager.py @@ -40,8 +40,6 @@ from airflow.auth.managers.utils.fab import ( from airflow.exceptions import AirflowException from airflow.models import Connection, DagRun, Pool, TaskInstance, Variable from airflow.security.permissions import ( - ACTION_CAN_ACCESS_MENU, - ACTION_CAN_READ, RESOURCE_ADMIN_MENU, RESOURCE_AUDIT_LOG, RESOURCE_BROWSE_MENU, @@ -335,7 +333,7 @@ class AirflowSecurityManagerV2(LoggingMixin): # This means the page the user is trying to access is specific to the auth manager used # Example: the user list view in FabAuthManager return lambda action, resource_pk, user: get_auth_manager().is_authorized_custom_view( - fab_action_name=ACTION_CAN_READ if action == ACTION_CAN_ACCESS_MENU else action, + fab_action_name=action, fab_resource_name=fab_resource_name, user=user, ) diff --git a/tests/auth/managers/fab/test_fab_auth_manager.py b/tests/auth/managers/fab/test_fab_auth_manager.py index bb9d507cbd..0d249a8603 100644 --- a/tests/auth/managers/fab/test_fab_auth_manager.py +++ b/tests/auth/managers/fab/test_fab_auth_manager.py @@ -40,6 +40,7 @@ from airflow.security.permissions import ( RESOURCE_DAG, RESOURCE_DAG_RUN, RESOURCE_DATASET, + RESOURCE_DOCS, RESOURCE_JOB, RESOURCE_PLUGIN, RESOURCE_PROVIDER, @@ -143,10 +144,10 @@ class TestFabAuthManager: [(ACTION_CAN_DELETE, resource_type), (ACTION_CAN_CREATE, "resource_test")], True, ), - # With permission (testing that ACTION_CAN_ACCESS_MENU gives GET permissions) + # With permission ( api_name, - "GET", + "MENU", [(ACTION_CAN_ACCESS_MENU, resource_type)], True, ), @@ -349,6 +350,18 @@ class TestFabAuthManager: [(ACTION_CAN_READ, RESOURCE_TRIGGER)], False, ), + # Docs (positive) + ( + AccessView.DOCS, + [(ACTION_CAN_ACCESS_MENU, RESOURCE_DOCS)], + True, + ), + # Without permission + ( + AccessView.DOCS, + [(ACTION_CAN_READ, RESOURCE_DOCS)], + False, + ), ], ) def test_is_authorized_view(self, access_view, user_permissions, expected_result, auth_manager):
