ucaeon opened a new pull request, #72820:
URL: https://github.com/apache/airflow/pull/72820

   ## Summary
   
   The FAB provider currently has no configuration for provisioning custom 
roles during API server startup. Deployments must create them through the UI or 
CLI separately from their Airflow configuration.
   
   This PR adds `[fab] custom_roles` to create missing roles with their 
declared permissions. Existing roles are skipped, preserving changes made 
through the UI or CLI. This follows the same-name skip behavior of `airflow 
roles import`.
   
   Existing FAB creation helpers commit each operation individually. Reusing 
them could leave a role with incomplete permissions after a failure, and 
subsequent initialization would skip that role because it already exists.
   
   ## Change
   
   - Add `[fab] custom_roles`, defaulting to `{}`, with support for 
`AIRFLOW__FAB__CUSTOM_ROLES`.
   - Validate the entire configuration before creating any configured role, 
including entries for existing and built-in roles.
   - Create missing custom roles after default-role synchronization in 
`sync_roles()`.
   - Skip existing roles and warn when built-in role names are configured.
   - Commit each new role and its permission assignments in one transaction.
   - Document configuration, initialization behavior, and the distinction 
between declared permissions and existing FAB permission maintenance.
   
   Example:
   
   ```ini
   [fab]
   custom_roles = {"PythonTester": [{"action": "can_read", "resource": 
"DAGs"}], "Analyst": []}
   ```
   
   Permission entries contain exactly `action` and `resource`, using actual FAB 
names such as `can_read` and `DAGs`. Duplicate permission pairs are applied 
once.
   
   The creation path reuses lookup helpers but avoids the existing helpers that 
commit individual writes. If creation fails, the current role's transaction is 
rolled back; roles successfully created earlier remain committed.
   
   If another process creates the same role first, that role is skipped without 
adding permissions. Conflicts on concurrently created shared actions, 
resources, or permissions are checked after rollback and retried from the 
beginning of role creation, with at most three attempts. Other failures are 
propagated.
   
   `bulk_sync_roles()` is not reused for configured roles because it can add 
permissions to existing roles.
   
   ## Behavior change
   
   API server startup applies the configuration when `[fab] update_fab_perms` 
is enabled. Explicitly running `airflow sync-perm` also applies it, regardless 
of that flag.
   
   Changing or removing a configured role does not update or delete an existing 
database role. Deleting a configured role from the database allows it to be 
recreated during the next initialization.
   
   An empty permission list declares no permissions, but normal FAB 
initialization still grants custom roles `can_read` on `Website`. Existing 
default-role and permission maintenance remains unchanged.
   
   This PR does not make roles read-only in the UI, create users, or assign 
roles to users. Resource names remain ordinary strings; the documentation 
recommends `DAG(access_control=...)` for access to individual Dags.
   
   ## Tests
   
   - Missing roles are created with their declared permissions, including empty 
lists and duplicate permission entries.
   - Existing roles retain manually modified permissions.
   - Invalid configuration fails before any configured role is created, 
including invalid entries for existing or built-in roles.
   - Failures during permission creation or before commit leave no incomplete 
role or newly created permission objects, while preserving previously committed 
data.
   - Two independent database sessions creating the same role with different 
permissions retain only the winning role's permissions, repeated five times on 
both PostgreSQL and MySQL.
   - Concurrent creation of shared actions, resources, and permissions retries 
successfully on PostgreSQL and MySQL.
   - Startup respects `update_fab_perms`, while explicit role synchronization 
applies the configuration independently of the flag.
   
   Tested locally with Breeze using Python 3.10:
   
   - FAB and `common.compat` unit tests on SQLite: **855 passed, 9 skipped**.
   - Custom-role tests on PostgreSQL: **46 passed**.
   - Custom-role tests on MySQL: **46 passed**.
   
   Regular and manual static checks passed, including formatting, linting, 
provider type checks, and provider metadata validation.
   
   closes: #38347
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [x] Yes — Codex (GPT-6)
   
   Generated-by: Codex (GPT-6) following [[the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)


-- 
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