Skip to content

Commit 4bcd4d7

Browse files
authored
Remove MENU from ResourceMethod in auth manager (#52731)
1 parent 8ca1dad commit 4bcd4d7

File tree

7 files changed

+48
-13
lines changed

7 files changed

+48
-13
lines changed

airflow-core/src/airflow/api_fastapi/auth/managers/base_auth_manager.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@
6666

6767
# This cannot be in the TYPE_CHECKING block since some providers import it globally.
6868
# TODO: Move this inside once all providers drop Airflow 2.x support.
69-
ResourceMethod = Literal["GET", "POST", "PUT", "DELETE", "MENU"]
69+
# List of methods (or actions) a user can do against a resource
70+
ResourceMethod = Literal["GET", "POST", "PUT", "DELETE"]
71+
# Extends ``ResourceMethod`` to include "MENU". The method "MENU" is only supported with specific resources (menu items)
72+
ExtendedResourceMethod = Literal["GET", "POST", "PUT", "DELETE", "MENU"]
7073

7174
log = logging.getLogger(__name__)
7275
T = TypeVar("T", bound=BaseUser)

providers/amazon/src/airflow/providers/amazon/aws/auth_manager/avp/facade.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737

3838
if TYPE_CHECKING:
3939
from airflow.api_fastapi.auth.managers.base_auth_manager import ResourceMethod
40+
41+
try:
42+
from airflow.api_fastapi.auth.managers.base_auth_manager import ExtendedResourceMethod
43+
except ImportError:
44+
from airflow.api_fastapi.auth.managers.base_auth_manager import (
45+
ResourceMethod as ExtendedResourceMethod,
46+
)
4047
from airflow.providers.amazon.aws.auth_manager.user import AwsAuthManagerUser
4148

4249

@@ -48,7 +55,7 @@
4855
class IsAuthorizedRequest(TypedDict, total=False):
4956
"""Represent the parameters of ``is_authorized`` method in AVP facade."""
5057

51-
method: ResourceMethod
58+
method: ExtendedResourceMethod
5259
entity_type: AvpEntities
5360
entity_id: str | None
5461
context: dict | None

providers/fab/src/airflow/providers/fab/auth_manager/fab_auth_manager.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
from airflow import __version__ as airflow_version
3535
from airflow.api_fastapi.app import AUTH_MANAGER_FASTAPI_APP_PREFIX
3636
from airflow.api_fastapi.auth.managers.base_auth_manager import BaseAuthManager
37+
38+
try:
39+
from airflow.api_fastapi.auth.managers.base_auth_manager import ExtendedResourceMethod
40+
except ImportError:
41+
from airflow.api_fastapi.auth.managers.base_auth_manager import ResourceMethod as ExtendedResourceMethod
42+
3743
from airflow.api_fastapi.auth.managers.models.resource_details import (
3844
AccessView,
3945
BackfillDetails,
@@ -382,7 +388,7 @@ def is_authorized_variable(
382388

383389
def is_authorized_view(self, *, access_view: AccessView, user: User) -> bool:
384390
# "Docs" are only links in the menu, there is no page associated
385-
method: ResourceMethod = "MENU" if access_view == AccessView.DOCS else "GET"
391+
method: ExtendedResourceMethod = "MENU" if access_view == AccessView.DOCS else "GET"
386392
return self._is_authorized(
387393
method=method,
388394
resource_type=_MAP_ACCESS_VIEW_TO_FAB_RESOURCE_TYPE[access_view],
@@ -523,7 +529,7 @@ def get_db_manager() -> str | None:
523529
def _is_authorized(
524530
self,
525531
*,
526-
method: ResourceMethod,
532+
method: ExtendedResourceMethod,
527533
resource_type: str,
528534
user: User,
529535
) -> bool:
@@ -594,7 +600,7 @@ def _is_authorized_dag_run(
594600
return len(authorized_dags) > 0
595601

596602
@staticmethod
597-
def _get_fab_action(method: ResourceMethod) -> str:
603+
def _get_fab_action(method: ExtendedResourceMethod) -> str:
598604
"""
599605
Convert the method to a FAB action.
600606

providers/fab/src/airflow/providers/fab/www/utils.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,16 @@
4242
if TYPE_CHECKING:
4343
from sqlalchemy.orm.session import Session
4444

45-
from airflow.api_fastapi.auth.managers.base_auth_manager import ResourceMethod
45+
try:
46+
from airflow.api_fastapi.auth.managers.base_auth_manager import ExtendedResourceMethod
47+
except ImportError:
48+
from airflow.api_fastapi.auth.managers.base_auth_manager import (
49+
ResourceMethod as ExtendedResourceMethod,
50+
)
4651
from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager
4752

4853
# Convert methods to FAB action name
49-
_MAP_METHOD_NAME_TO_FAB_ACTION_NAME: dict[ResourceMethod, str] = {
54+
_MAP_METHOD_NAME_TO_FAB_ACTION_NAME: dict[ExtendedResourceMethod, str] = {
5055
"POST": ACTION_CAN_CREATE,
5156
"GET": ACTION_CAN_READ,
5257
"PUT": ACTION_CAN_EDIT,

providers/fab/www-hash.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
52c1ebe16934a7ef8ad42e05a675a3c6e662476a2d47fea3c142ff1b27305e45
1+
bba05295e6d4ef8f0bfe766b77cef4d90d62e86f3a2162de32d6e94979b236c7

providers/keycloak/src/airflow/providers/keycloak/auth_manager/cli/commands.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
from keycloak import KeycloakAdmin, KeycloakError
2424

2525
from airflow.api_fastapi.auth.managers.base_auth_manager import ResourceMethod
26+
27+
try:
28+
from airflow.api_fastapi.auth.managers.base_auth_manager import ExtendedResourceMethod
29+
except ImportError:
30+
from airflow.api_fastapi.auth.managers.base_auth_manager import ResourceMethod as ExtendedResourceMethod
2631
from airflow.api_fastapi.common.types import MenuItem
2732
from airflow.configuration import conf
2833
from airflow.providers.keycloak.auth_manager.constants import (
@@ -109,6 +114,7 @@ def _get_client_uuid(args):
109114

110115
def _create_scopes(client: KeycloakAdmin, client_uuid: str):
111116
scopes = [{"name": method} for method in get_args(ResourceMethod)]
117+
scopes.append({"name": "MENU"})
112118
for scope in scopes:
113119
client.create_client_authz_scopes(client_id=client_uuid, payload=scope)
114120

@@ -173,7 +179,7 @@ def _create_read_only_permission(client: KeycloakAdmin, client_uuid: str):
173179

174180
def _create_admin_permission(client: KeycloakAdmin, client_uuid: str):
175181
all_scopes = client.get_client_authz_scopes(client_uuid)
176-
scopes = [scope["id"] for scope in all_scopes if scope["name"] in get_args(ResourceMethod)]
182+
scopes = [scope["id"] for scope in all_scopes if scope["name"] in get_args(ExtendedResourceMethod)]
177183
payload = {
178184
"name": "Admin",
179185
"type": "scope",

providers/keycloak/src/airflow/providers/keycloak/auth_manager/keycloak_auth_manager.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727

2828
from airflow.api_fastapi.app import AUTH_MANAGER_FASTAPI_APP_PREFIX
2929
from airflow.api_fastapi.auth.managers.base_auth_manager import BaseAuthManager
30+
31+
try:
32+
from airflow.api_fastapi.auth.managers.base_auth_manager import ExtendedResourceMethod
33+
except ImportError:
34+
from airflow.api_fastapi.auth.managers.base_auth_manager import ResourceMethod as ExtendedResourceMethod
35+
3036
from airflow.api_fastapi.common.types import MenuItem
3137
from airflow.cli.cli_config import CLICommand, GroupCommand
3238
from airflow.configuration import conf
@@ -201,7 +207,9 @@ def filter_authorized_menu_items(
201207
self, menu_items: list[MenuItem], *, user: KeycloakAuthManagerUser
202208
) -> list[MenuItem]:
203209
authorized_menus = self._is_batch_authorized(
204-
permissions=[(cast("ResourceMethod", "MENU"), menu_item.value) for menu_item in menu_items],
210+
permissions=[
211+
(cast("ExtendedResourceMethod", "MENU"), menu_item.value) for menu_item in menu_items
212+
],
205213
user=user,
206214
)
207215
return [MenuItem(menu[1]) for menu in authorized_menus]
@@ -285,9 +293,9 @@ def _is_authorized(
285293
def _is_batch_authorized(
286294
self,
287295
*,
288-
permissions: list[tuple[ResourceMethod, str]],
296+
permissions: list[tuple[ExtendedResourceMethod, str]],
289297
user: KeycloakAuthManagerUser,
290-
) -> set[tuple[ResourceMethod, str]]:
298+
) -> set[tuple[ExtendedResourceMethod, str]]:
291299
client_id = conf.get(CONF_SECTION_NAME, CONF_CLIENT_ID_KEY)
292300
realm = conf.get(CONF_SECTION_NAME, CONF_REALM_KEY)
293301
server_url = conf.get(CONF_SECTION_NAME, CONF_SERVER_URL_KEY)
@@ -326,7 +334,7 @@ def _get_payload(client_id: str, permission: str, attributes: dict[str, str] | N
326334
return payload
327335

328336
@staticmethod
329-
def _get_batch_payload(client_id: str, permissions: list[tuple[ResourceMethod, str]]):
337+
def _get_batch_payload(client_id: str, permissions: list[tuple[ExtendedResourceMethod, str]]):
330338
payload: dict[str, Any] = {
331339
"grant_type": "urn:ietf:params:oauth:grant-type:uma-ticket",
332340
"audience": client_id,

0 commit comments

Comments
 (0)