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 b79b7f44381 Add `LIST` scope in Keycloak auth manager (#54998)
b79b7f44381 is described below

commit b79b7f4438196b032bacbbbd38232040a51318ba
Author: Vincent <[email protected]>
AuthorDate: Thu Aug 28 08:33:12 2025 -0400

    Add `LIST` scope in Keycloak auth manager (#54998)
---
 .../providers/keycloak/auth_manager/cli/commands.py    |  6 +++---
 .../keycloak/auth_manager/keycloak_auth_manager.py     |  2 ++
 .../auth_manager/test_keycloak_auth_manager.py         | 18 +++++++++---------
 3 files changed, 14 insertions(+), 12 deletions(-)

diff --git 
a/providers/keycloak/src/airflow/providers/keycloak/auth_manager/cli/commands.py
 
b/providers/keycloak/src/airflow/providers/keycloak/auth_manager/cli/commands.py
index 59bd60ef5ba..d19693b81cc 100644
--- 
a/providers/keycloak/src/airflow/providers/keycloak/auth_manager/cli/commands.py
+++ 
b/providers/keycloak/src/airflow/providers/keycloak/auth_manager/cli/commands.py
@@ -114,7 +114,7 @@ def _get_client_uuid(args):
 
 def _create_scopes(client: KeycloakAdmin, client_uuid: str):
     scopes = [{"name": method} for method in get_args(ResourceMethod)]
-    scopes.append({"name": "MENU"})
+    scopes.extend([{"name": "MENU"}, {"name": "LIST"}])
     for scope in scopes:
         client.create_client_authz_scopes(client_id=client_uuid, payload=scope)
 
@@ -126,7 +126,7 @@ def _create_resources(client: KeycloakAdmin, client_uuid: 
str):
     scopes = [
         {"id": scope["id"], "name": scope["name"]}
         for scope in all_scopes
-        if scope["name"] in ["GET", "POST", "PUT", "DELETE"]
+        if scope["name"] in ["GET", "POST", "PUT", "DELETE", "LIST"]
     ]
 
     for resource in KeycloakResource:
@@ -166,7 +166,7 @@ def _create_permissions(client: KeycloakAdmin, client_uuid: 
str):
 
 def _create_read_only_permission(client: KeycloakAdmin, client_uuid: str):
     all_scopes = client.get_client_authz_scopes(client_uuid)
-    scopes = [scope["id"] for scope in all_scopes if scope["name"] in ["GET", 
"MENU"]]
+    scopes = [scope["id"] for scope in all_scopes if scope["name"] in ["GET", 
"MENU", "LIST"]]
     payload = {
         "name": "ReadOnly",
         "type": "scope",
diff --git 
a/providers/keycloak/src/airflow/providers/keycloak/auth_manager/keycloak_auth_manager.py
 
b/providers/keycloak/src/airflow/providers/keycloak/auth_manager/keycloak_auth_manager.py
index d91b5030bda..8fdaa0b03e9 100644
--- 
a/providers/keycloak/src/airflow/providers/keycloak/auth_manager/keycloak_auth_manager.py
+++ 
b/providers/keycloak/src/airflow/providers/keycloak/auth_manager/keycloak_auth_manager.py
@@ -286,6 +286,8 @@ class 
KeycloakAuthManager(BaseAuthManager[KeycloakAuthManagerUser]):
         context_attributes = prune_dict(attributes or {})
         if resource_id:
             context_attributes[RESOURCE_ID_ATTRIBUTE_NAME] = resource_id
+        elif method == "GET":
+            method = "LIST"
 
         resp = requests.post(
             self._get_token_url(server_url, realm),
diff --git 
a/providers/keycloak/tests/unit/keycloak/auth_manager/test_keycloak_auth_manager.py
 
b/providers/keycloak/tests/unit/keycloak/auth_manager/test_keycloak_auth_manager.py
index bec66aef210..2e7478b2991 100644
--- 
a/providers/keycloak/tests/unit/keycloak/auth_manager/test_keycloak_auth_manager.py
+++ 
b/providers/keycloak/tests/unit/keycloak/auth_manager/test_keycloak_auth_manager.py
@@ -112,7 +112,7 @@ class TestKeycloakAuthManager:
                 "Configuration#GET",
                 {RESOURCE_ID_ATTRIBUTE_NAME: "test"},
             ],
-            ["is_authorized_configuration", "GET", None, "Configuration#GET", 
None],
+            ["is_authorized_configuration", "GET", None, "Configuration#LIST", 
None],
             [
                 "is_authorized_configuration",
                 "PUT",
@@ -127,7 +127,7 @@ class TestKeycloakAuthManager:
                 "Connection#DELETE",
                 {RESOURCE_ID_ATTRIBUTE_NAME: "test"},
             ],
-            ["is_authorized_connection", "GET", None, "Connection#GET", {}],
+            ["is_authorized_connection", "GET", None, "Connection#LIST", {}],
             [
                 "is_authorized_backfill",
                 "POST",
@@ -135,7 +135,7 @@ class TestKeycloakAuthManager:
                 "Backfill#POST",
                 {RESOURCE_ID_ATTRIBUTE_NAME: "1"},
             ],
-            ["is_authorized_backfill", "GET", None, "Backfill#GET", {}],
+            ["is_authorized_backfill", "GET", None, "Backfill#LIST", {}],
             [
                 "is_authorized_asset",
                 "GET",
@@ -143,7 +143,7 @@ class TestKeycloakAuthManager:
                 "Asset#GET",
                 {RESOURCE_ID_ATTRIBUTE_NAME: "test"},
             ],
-            ["is_authorized_asset", "GET", None, "Asset#GET", {}],
+            ["is_authorized_asset", "GET", None, "Asset#LIST", {}],
             [
                 "is_authorized_asset_alias",
                 "GET",
@@ -151,7 +151,7 @@ class TestKeycloakAuthManager:
                 "AssetAlias#GET",
                 {RESOURCE_ID_ATTRIBUTE_NAME: "test"},
             ],
-            ["is_authorized_asset_alias", "GET", None, "AssetAlias#GET", {}],
+            ["is_authorized_asset_alias", "GET", None, "AssetAlias#LIST", {}],
             [
                 "is_authorized_variable",
                 "PUT",
@@ -159,7 +159,7 @@ class TestKeycloakAuthManager:
                 "Variable#PUT",
                 {RESOURCE_ID_ATTRIBUTE_NAME: "test"},
             ],
-            ["is_authorized_variable", "GET", None, "Variable#GET", {}],
+            ["is_authorized_variable", "GET", None, "Variable#LIST", {}],
             [
                 "is_authorized_pool",
                 "POST",
@@ -167,7 +167,7 @@ class TestKeycloakAuthManager:
                 "Pool#POST",
                 {RESOURCE_ID_ATTRIBUTE_NAME: "test"},
             ],
-            ["is_authorized_pool", "GET", None, "Pool#GET", {}],
+            ["is_authorized_pool", "GET", None, "Pool#LIST", {}],
         ],
     )
     @pytest.mark.parametrize(
@@ -257,7 +257,7 @@ class TestKeycloakAuthManager:
                 "GET",
                 None,
                 None,
-                "Dag#GET",
+                "Dag#LIST",
                 {},
             ],
             [
@@ -278,7 +278,7 @@ class TestKeycloakAuthManager:
                 "GET",
                 DagAccessEntity.TASK_INSTANCE,
                 None,
-                "Dag#GET",
+                "Dag#LIST",
                 {"dag_entity": "TASK_INSTANCE"},
             ],
         ],

Reply via email to