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]