wilsonjefferson opened a new issue, #71277:
URL: https://github.com/apache/airflow/issues/71277

   ### Under which category would you file this issue?
   
   Providers
   
   ### Apache Airflow version
   
   3.3.0
   
   ### What happened and how to reproduce it?
   
   With `core.multi_team=True` and the Keycloak auth manager, `GET 
/api/v2/dags`, `GET /api/v2/variables` and `GET /api/v2/connections` return 
resources belonging to every team, regardless of the requesting user's team 
membership.
   
   The docs state that Multi-Team is for organisations that "need resource 
isolation (Variables, Connections, Secrets, etc) between teams **at the UI and 
API level**" and that a use case is "You want separate views per team in the 
Airflow UI"
   ([Multi-Team → When to Use Multi-Team 
Mode](https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/multi-team.html#when-to-use-multi-team-mode)).
   
   The Work in Progress section lists "Some UI elements may not be fully 
team-aware" as a known 3.4+ gap. This report concerns the **API** layer — the 
leak reproduces against the REST endpoints directly, not only through the UI — 
so it appears to fall outside that caveat.
   
   Write operations and Task Execution API access **are** correctly scoped; 
only list/read appears to be unfiltered.
   
   **Setup**
   
   Two teams, `team-a` and `team-b`, created via `airflow teams create` and 
`airflow keycloak-auth-manager create-team`. Per-team Dag bundles:
   
   ```
   AIRFLOW__DAG_PROCESSOR__DAG_BUNDLE_CONFIG_LIST:
   [{"name": "team_a_dags", "classpath": 
"airflow.dag_processing.bundles.local.LocalDagBundle",
   "kwargs": {"path": "/opt/airflow/dags/team-a"}, "team_name": "team-a"},
   {"name": "team_b_dags", "classpath": 
"airflow.dag_processing.bundles.local.LocalDagBundle",
   "kwargs": {"path": "/opt/airflow/dags/team-b"}, "team_name": "team-b"},
   {"name": "shared_dags", "classpath": 
"airflow.dag_processing.bundles.local.LocalDagBundle",
   "kwargs": {"path": "/opt/airflow/dags/shared"}}]
   ```
   
   `airflow dags list` confirms the association:
   `dag_id | bundle_name
   check_dag_running | team_a_dags
   test_owner_dag | team_b_dags
   test_dag | shared_dags`
   
   `user-a` is a member of Keycloak group `/team-a` only, with realm role 
`Admin` (explicitly **not** `SuperAdmin`). 
   
   Decoded access token:
   
   ```json
   "realm_access": { "roles": ["default-roles-airflow", "offline_access", 
"uma_authorization", "Admin"] }, "groups": ["team-a"]
   ```
   
   **Steps to reproduce**
   
   1. Configure two teams with per-team Dag bundles as above.
   2. Log in as `user-a` (member of `team-a` only).
   3. `GET /api/v2/dags`
   
   **Observed:** all three Dags returned, including `test_owner_dag` from 
`team_b_dags`. Same in the UI Dags list.
   
   **Expected:** only `check_dag_running` (team-a) and `test_dag` (global).
   
   `GET /api/v2/variables` behaves the same way: `user-a` sees entries with 
`"team_name": "team-b"`, including their values where the key name does not 
happen to match the sensitive-keyword masker.
   
   **What IS correctly scoped**
   
   Write operations — `user-a` cannot edit or delete `team-b` Variables or 
Connections.
   
   Task Execution API, Variables — a task in a `team-a` Dag:
   `BLOCKED user-b-var: AirflowRuntimeError: VARIABLE_NOT_FOUND
   READ OK shared_var = everyone`
   
   Task Execution API, Connections — a `SQLExecuteQueryOperator` using a 
`team-b` connection succeeds in a `team-b` Dag, and the identical task in a 
`team-a` Dag fails:
   
   > AirflowNotFoundException: The conn_id user-b-conn-postgres isn't defined
   > File ".../airflow/sdk/execution_time/context.py", line 230 in 
_get_connection
   
   So enforcement is working at the Execution API and for writes, but not for 
list/read.
   
   ### What you think should happen instead?
   
   List endpoints should filter by the requesting user's team, consistent with 
the documented "resource isolation ... at the UI and API level".
   
   As it stands, a user in `team-a` can enumerate `team-b`'s Dag IDs and 
Variable keys via the REST API, and read Variable values whose names don't 
match the sensitive-keyword list.
   
   Execution-layer isolation is working correctly, so this looks like a bounded 
gap in the list/read endpoints rather than a design problem. Filing separately 
from the known "some UI elements may not be fully team-aware" caveat because it 
reproduces against the API directly.
   
   ### Operating System
   
   _No response_
   
   ### Deployment
   
   None
   
   ### Apache Airflow Provider(s)
   
   _No response_
   
   ### Versions of Apache Airflow Providers
   
   _No response_
   
   ### Official Helm Chart version
   
   Not Applicable
   
   ### Kubernetes Version
   
   _No response_
   
   ### Helm Chart configuration
   
   _No response_
   
   ### Docker Image customizations
   
   Based on apache/airflow:3.3.0 with apache-airflow-providers-keycloak==0.8.2. 
No changes to core Airflow.
   
   ### Anything else?
   
   Keycloak 26 auth manager, CeleryExecutor, Postgres 16 metadata DB, Python 
3.13. Reproduces consistently. 
   
   Note: the Keycloak client's resource-server decision strategy must be set to 
Affirmative — under the default Unanimous, role-specific permissions veto 
access and every endpoint returns 403.
   
   ### Are you willing to submit PR?
   
   - [ ] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to