This is an automated email from the ASF dual-hosted git repository.
vincbeck 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 89e7f3e7bd Add "MENU" permission in auth manager (#37881)
89e7f3e7bd is described below
commit 89e7f3e7bdf2126bbbcd959dc10d65ef92773cca
Author: Vincent <[email protected]>
AuthorDate: Tue Mar 5 13:56:44 2024 -0500
Add "MENU" permission in auth manager (#37881)
---
airflow/auth/managers/base_auth_manager.py | 2 +-
airflow/auth/managers/utils/fab.py | 2 +-
airflow/providers/fab/auth_manager/fab_auth_manager.py | 15 ++++-----------
airflow/www/security_manager.py | 4 +---
.../providers/fab/auth_manager/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 88164b644e..a0176fc833 100644
--- a/airflow/auth/managers/base_auth_manager.py
+++ b/airflow/auth/managers/base_auth_manager.py
@@ -57,7 +57,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/utils/fab.py
b/airflow/auth/managers/utils/fab.py
index 22b572e07f..0f2bc7c46e 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():
"""Return 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/providers/fab/auth_manager/fab_auth_manager.py
b/airflow/providers/fab/auth_manager/fab_auth_manager.py
index 90109950b3..1d3506c3df 100644
--- a/airflow/providers/fab/auth_manager/fab_auth_manager.py
+++ b/airflow/providers/fab/auth_manager/fab_auth_manager.py
@@ -54,8 +54,6 @@ from
airflow.providers.fab.auth_manager.cli_commands.definition import (
from airflow.providers.fab.auth_manager.models import Permission, Role, User
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,
@@ -263,8 +261,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(
@@ -463,18 +463,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/www/security_manager.py b/airflow/www/security_manager.py
index 5cd9c15923..bd31535983 100644
--- a/airflow/www/security_manager.py
+++ b/airflow/www/security_manager.py
@@ -39,8 +39,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,
@@ -340,7 +338,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/providers/fab/auth_manager/test_fab_auth_manager.py
b/tests/providers/fab/auth_manager/test_fab_auth_manager.py
index 65a6fb8f56..89c6352543 100644
--- a/tests/providers/fab/auth_manager/test_fab_auth_manager.py
+++ b/tests/providers/fab/auth_manager/test_fab_auth_manager.py
@@ -39,6 +39,7 @@ from airflow.security.permissions import (
RESOURCE_DAG,
RESOURCE_DAG_RUN,
RESOURCE_DATASET,
+ RESOURCE_DOCS,
RESOURCE_JOB,
RESOURCE_PLUGIN,
RESOURCE_PROVIDER,
@@ -140,10 +141,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,
),
@@ -346,6 +347,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):