Access Control

Access Control of Airflow Webserver UI is handled by Flask AppBuilder (FAB). Please read its related security document regarding its security model.

Default Roles

Airflow ships with a set of roles by default: Admin, User, Op, Viewer, and Public. By default, only Admin users can configure/alter permissions for roles. However, it is recommended that these default roles remain unaltered, and instead Admin users create new roles with the desired permissions if changes are necessary.

Public

Public users (anonymous) don’t have any permissions.

Viewer

Viewer users have limited read permissions:

airflow/providers/fab/auth_manager/security_manager/override.py[source]

    VIEWER_PERMISSIONS = [
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_DEPENDENCIES),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_CODE),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_RUN),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DATASET),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_CLUSTER_ACTIVITY),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_POOL),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_IMPORT_ERROR),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_WARNING),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_JOB),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_MY_PASSWORD),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_MY_PASSWORD),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_MY_PROFILE),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_MY_PROFILE),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_SLA_MISS),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_INSTANCE),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_LOG),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_XCOM),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_WEBSITE),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_BROWSE_MENU),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_DEPENDENCIES),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DAG_RUN),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DATASET),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CLUSTER_ACTIVITY),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DOCS),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_DOCS_MENU),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_JOB),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_SLA_MISS),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TASK_INSTANCE),
    ]

User

User users have Viewer permissions plus additional permissions:

airflow/providers/fab/auth_manager/security_manager/override.py[source]

    USER_PERMISSIONS = [
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG),
        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DAG),
        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_TASK_INSTANCE),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_TASK_INSTANCE),
        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_TASK_INSTANCE),
        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DAG_RUN),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_DAG_RUN),
        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DAG_RUN),
        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DATASET),
    ]

Op

Op users have User permissions plus additional permissions:

airflow/providers/fab/auth_manager/security_manager/override.py[source]

    OP_PERMISSIONS = [
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_CONFIG),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_ADMIN_MENU),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CONFIG),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CONNECTION),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_POOL),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_PLUGIN),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_VARIABLE),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_PROVIDER),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_XCOM),
        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_CONNECTION),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_CONNECTION),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_CONNECTION),
        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_CONNECTION),
        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_POOL),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_POOL),
        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_POOL),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_PLUGIN),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_PROVIDER),
        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_VARIABLE),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_VARIABLE),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_VARIABLE),
        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_VARIABLE),
        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_XCOM),
        (permissions.ACTION_CAN_DELETE, permissions.RESOURCE_DATASET),
        (permissions.ACTION_CAN_CREATE, permissions.RESOURCE_DATASET),
    ]

Admin

Admin users have all possible permissions, including granting or revoking permissions from other users. Admin users have Op permission plus additional permissions:

airflow/providers/fab/auth_manager/security_manager/override.py[source]

    ADMIN_PERMISSIONS = [
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_AUDIT_LOG),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_AUDIT_LOG),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_TASK_RESCHEDULE),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TASK_RESCHEDULE),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_TRIGGER),
        (permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_TRIGGER),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_PASSWORD),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_PASSWORD),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_ROLE),
        (permissions.ACTION_CAN_EDIT, permissions.RESOURCE_ROLE),
    ]

Custom Roles

DAG Level Role

Admin can create a set of roles which are only allowed to view a certain set of DAGs. This is called DAG level access. Each DAG defined in the DAG model table is treated as a View which has two permissions associated with it (can_read and can_edit. can_dag_read and can_dag_edit are deprecated since 2.0.0). There is a special view called DAGs (it was called all_dags in versions 1.10.*) which allows the role to access all the DAGs. The default Admin, Viewer, User, Op roles can all access DAGs view.

../_images/add-role.png ../_images/new-role.png

The image shows the creation of a role which can only write to example_python_operator. You can also create roles via the CLI using the airflow roles create command, e.g.:

airflow roles create Role1 Role2

And we could assign the given role to a new user using the airflow users add-role CLI command.

Permissions

Warning

Airflow allows you to define custom Roles with fine-grained RBAC permissions for users. However, not all combinations of permissions are fully consistent, and there is no mechanism to make sure that the set of permissions assigned is fully consistent. There are a number of cases where permissions for particular resources are overlapping. A good example is menu access permissions - a lack of menu access does not automatically disable access to the functionality the menu is pointing at. Another example is access to the Role view, which allows access to User information even if the user does not have “user view” access. It is simply inconsistent to add access to Roles when you have no access to users.

When you decide to use a custom set of resource-based permissions, the Deployment Manager should carefully review if the final set of permissions granted to roles is what they expect.

Resource-Based permissions

Starting with version 2.0, permissions are based on individual resources and a small subset of actions on those resources. Resources match standard Airflow concepts, such as Dag, DagRun, Task, and Connection. Actions include can_create, can_read, can_edit, and can_delete.

Permissions (each consistent of a resource + action pair) are then added to roles.

To access an endpoint, the user needs all permissions assigned to that endpoint

There are five default roles: Public, Viewer, User, Op, and Admin. Each one has the permissions of the preceding role, as well as additional permissions.

DAG-level permissions

For DAG-level permissions exclusively, access can be controlled at the level of all DAGs or individual DAG objects. This includes DAGs.can_read, DAGs.can_edit, DAGs.can_delete, DAG Runs.can_read, DAG Runs.can_create, DAG Runs.can_delete, and DAG Runs.menu_access. When these permissions are listed, access is granted to users who either have the listed permission or the same permission for the specific DAG being acted upon. For individual DAGs, the resource name is DAG: + the DAG ID, or for the DAG Runs resource the resource name is DAG Run:.

For example, if a user is trying to view DAG information for the example_dag_id, and the endpoint requires DAGs.can_read access, access will be granted if the user has either DAGs.can_read or DAG:example_dag_id.can_read access.

Stable API Permissions

Endpoint

Method

Permissions

Minimum Role

/config

GET

Configurations.can_read

Op

/connections

GET

Connections.can_read

Op

/connections

POST

Connections.can_create

Op

/connections/{connection_id}

DELETE

Connections.can_delete

Op

/connections/{connection_id}

PATCH

Connections.can_edit

Op

/connections/{connection_id}

GET

Connections.can_read

Op

/dagSources/{file_token}

GET

DAG Code.can_read

Viewer

/dags

GET

DAGs.can_read

Viewer

/dags/{dag_id}

GET

DAGs.can_read

Viewer

/dags/{dag_id}

PATCH

DAGs.can_edit

User

/dags/{dag_id}/clearTaskInstances

POST

DAGs.can_edit, DAG Runs.can_read, Task Instances.can_edit

User

/dags/{dag_id}/details

GET

DAGs.can_read

Viewer

/dags/{dag_id}/tasks

GET

DAGs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/tasks/{task_id}

GET

DAGs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/dagRuns

GET

DAGs.can_read, DAG Runs.can_read

Viewer

/dags/{dag_id}/dagRuns

POST

DAGs.can_edit, DAG Runs.can_create

User

/dags/{dag_id}/dagRuns/{dag_run_id}

DELETE

DAGs.can_edit, DAG Runs.can_delete

User

/dags/{dag_id}/dagRuns/{dag_run_id}

GET

DAGs.can_read, DAG Runs.can_read

Viewer

/dags/~/dagRuns/list

POST

DAGs.can_edit, DAG Runs.can_read

User

/datasets

GET

Datasets.can_read

Viewer

/datasets/{uri}

GET

Datasets.can_read

Viewer

/datasets/events

GET

Datasets.can_read

Viewer

/eventLogs

GET

Audit Logs.can_read

Viewer

/eventLogs/{event_log_id}

GET

Audit Logs.can_read

Viewer

/importErrors

GET

ImportError.can_read

Viewer

/importErrors/{import_error_id}

GET

ImportError.can_read

Viewer

/health

GET

None

Public

/version

GET

None

Public

/pools

GET

Pools.can_read

Op

/pools

POST

Pools.can_create

Op

/pools/{pool_name}

DELETE

Pools.can_delete

Op

/pools/{pool_name}

GET

Pools.can_read

Op

/pools/{pool_name}

PATCH

Pools.can_edit

Op

/providers

GET

Providers.can_read

Op

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/links

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/logs/{task_try_number}

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

/dags/~/dagRuns/~/taskInstances/list

POST

DAGs.can_edit, DAG Runs.can_read, Task Instances.can_read

User

/variables

GET

Variables.can_read

Op

/variables

POST

Variables.can_create

Op

/variables/{variable_key}

DELETE

Variables.can_delete

Op

/variables/{variable_key}

GET

Variables.can_read

Op

/variables/{variable_key}

PATCH

Variables.can_edit

Op

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/xcomEntries

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read, XComs.can_read

Viewer

/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/xcomEntries/{xcom_key}

GET

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read, XComs.can_read

Viewer

/users

GET

Users.can_read

Admin

/users

POST

Users.can_create

Admin

/users/{username}

GET

Users.can_read

Admin

/users/{username}

PATCH

Users.can_edit

Admin

/users/{username}

DELETE

Users.can_delete

Admin

/roles

GET

Roles.can_read

Admin

/roles

POST

Roles.can_create

Admin

/roles/{role_name}

GET

Roles.can_read

Admin

/roles/{role_name}

PATCH

Roles.can_edit

Admin

/roles/{role_name}

DELETE

Roles.can_delete

Admin

/permissions

GET

Permission Views.can_read

Admin

Website Permissions

Action

Permissions

Minimum Role

Access homepage

Website.can_read

Viewer

Show Browse menu

Browse.menu_access

Viewer

Show DAGs menu

DAGs.menu_access

Viewer

Get DAG stats

DAGs.can_read, DAG Runs.can_read

Viewer

Show Task Instances menu

Task Instances.menu_access

Viewer

Get Task stats

DAGs.can_read, DAG Runs.can_read, Task Instances.can_read

Viewer

Get last DAG runs

DAGs.can_read, DAG Runs.can_read

Viewer

Get DAG code

DAGs.can_read, DAG Code.can_read

Viewer

Get DAG details

DAGs.can_read, DAG Runs.can_read

Viewer

Show DAG Dependencies menu

DAG Dependencies.menu_access

Viewer

Get DAG Dependencies

DAG Dependencies.can_read

Viewer

Get rendered DAG

DAGs.can_read, Task Instances.can_read

Viewer

Get Logs with metadata

DAGs.can_read, Task Instances.can_read, Task Logs.can_read

Viewer

Get Log

DAGs.can_read, Task Instances.can_read, Task Logs.can_read

Viewer

Redirect to external Log

DAGs.can_read, Task Instances.can_read, Task Logs.can_read

Viewer

Get Task

DAGs.can_read, Task Instances.can_read

Viewer

Show XCom menu

XComs.menu_access

Op

Get XCom

DAGs.can_read, Task Instances.can_read, XComs.can_read

Viewer

Create XCom

XComs.can_create

Op

Delete XCom

XComs.can_delete

Op

Triggers Task Instance

DAGs.can_edit, Task Instances.can_create

User

Delete DAG

DAGs.can_delete

User

Show DAG Runs menu

DAG Runs.menu_access

Viewer

Trigger DAG run

DAGs.can_edit, DAG Runs.can_create

User

Clear DAG

DAGs.can_edit, Task Instances.can_delete

User

Clear DAG Run

DAGs.can_edit, Task Instances.can_delete

User

Mark DAG as blocked

DAGS.can_edit, DAG Runs.can_read

User

Mark DAG Run as failed

DAGS.can_edit, DAG Runs.can_edit

User

Mark DAG Run as success

DAGS.can_edit, DAG Runs.can_edit

User

Mark Task as failed

DAGs.can_edit, Task Instances.can_edit

User

Mark Task as success

DAGs.can_edit, Task Instances.can_edit

User

Get DAG as tree

DAGs.can_read, Task Instances.can_read, Task Logs.can_read

Viewer

Get DAG as graph

DAGs.can_read, Task Instances.can_read, Task Logs.can_read

Viewer

Get DAG as duration graph

DAGs.can_read, Task Instances.can_read

Viewer

Show all tries

DAGs.can_read, Task Instances.can_read

Viewer

Show landing times

DAGs.can_read, Task Instances.can_read

Viewer

Toggle DAG paused status

DAGs.can_edit

User

Show Gantt Chart

DAGs.can_read, Task Instances.can_read

Viewer

Get external links

DAGs.can_read, Task Instances.can_read

Viewer

Show Task Instances

DAGs.can_read, Task Instances.can_read

Viewer

Show Configurations menu

Configurations.menu_access

Op

Show Configs

Configurations.can_read

Viewer

Delete multiple records

DAGs.can_edit

User

Set Task Instance as running

DAGs.can_edit

User

Set Task Instance as failed

DAGs.can_edit

User

Set Task Instance as success

DAGs.can_edit

User

Set Task Instance as up_for_retry

DAGs.can_edit

User

Autocomplete

DAGs.can_read

Viewer

Show Dataset menu

Datasets.menu_access

Viewer

Show Datasets

Datasets.can_read

Viewer

Show Docs menu

Docs.menu_access

Viewer

Show Documentation menu

Documentation.menu_access

Viewer

Show Jobs menu

Jobs.menu_access

Viewer

Show Audit Log

Audit Logs.menu_access

Viewer

Reset Password

My Password.can_read, My Password.can_edit

Viewer

Show Permissions menu

Permission Views.menu_access

Admin

List Permissions

Permission Views.can_read

Admin

Get My Profile

My Profile.can_read

Viewer

Update My Profile

My Profile.can_edit

Viewer

List Logs

Audit Logs.can_read

Viewer

List Jobs

Jobs.can_read

Viewer

Show SLA Misses menu

SLA Misses.menu_access

Viewer

List SLA Misses

SLA Misses.can_read

Viewer

List Plugins

Plugins.can_read

Viewer

Show Plugins menu

Plugins.menu_access

Viewer

Show Providers menu

Providers.menu_access

Op

List Providers

Providers.can_read

Op

List Task Reschedules

Task Reschedules.can_read

Admin

Show Triggers menu

Triggers.menu_access

Admin

List Triggers

Triggers.can_read

Admin

Show Admin menu

Admin.menu_access

Viewer

Show Connections menu

Connections.menu_access

Op

Show Pools menu

Pools.menu_access

Viewer

Show Variables menu

Variables.menu_access

Op

Show Roles menu

Roles.menu_access

Admin

List Roles

Roles.can_read

Admin

Create Roles

Roles.can_create

Admin

Update Roles

Roles.can_edit

Admin

Delete Roles

Roles.can_delete

Admin

Show Users menu

Users.menu_access

Admin

Create Users

Users.can_create

Admin

Update Users

Users.can_edit

Admin

Delete Users

Users.can_delete

Admin

Reset user Passwords

Passwords.can_edit, Passwords.can_read

Admin

These DAG-level controls can be set directly through the UI / CLI, or encoded in the dags themselves through the access_control arg.

Order of precedence for DAG-level permissions

Since DAG-level access control can be configured in multiple places, conflicts are inevitable and a clear resolution strategy is required. As a result, Airflow considers the access_control argument supplied on a DAG itself to be completely authoritative if present, which has a few effects:

Setting access_control on a DAG will overwrite any previously existing DAG-level permissions if it is any value other than None:

DAG(
    dag_id="example_fine_grained_access",
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
    access_control={
        "Viewer": {"can_edit", "can_read", "can_delete"},
    },
)

It’s also possible to add DAG Runs resource permissions in a similar way, but explicit adding the resource name to identify which resource the permissions are for:

DAG(
    dag_id="example_fine_grained_access",
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
    access_control={
        "Viewer": {"DAGs": {"can_edit", "can_read", "can_delete"}, "DAG Runs": {"can_create"}},
    },
)

This also means that setting access_control={} will wipe any existing DAG-level permissions for a given DAG from the DB:

DAG(
    dag_id="example_no_fine_grained_access",
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
    access_control={},
)

Conversely, removing the access_control block from a DAG altogether (or setting it to None) won’t make any changes and can leave dangling permissions.

DAG(
    dag_id="example_indifferent_to_fine_grained_access",
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
)

In the case that there is no access_control defined on the DAG itself, Airflow will defer to existing permissions defined in the DB, which may have been set through the UI, CLI or by previous access_control args on the DAG in question.

In all cases, system-wide roles such as Can edit on DAG take precedence over dag-level access controls, such that they can be considered Can edit on DAG: *

Was this entry helpful?