使用 FAB 认证管理器进行访问控制

FAB 认证管理器的访问控制由 Flask AppBuilder (FAB) 处理。请阅读其相关的安全文档以了解其安全模型。

默认角色

FAB 认证管理器默认带有一组角色:AdminUserOpViewerPublic。默认情况下,只有 Admin 用户可以配置/修改角色的权限。然而,建议保持这些默认角色不变,如果需要更改,Admin 用户可以创建具有所需权限的新角色。

Public

Public 用户(匿名用户)没有任何权限。

Viewer

Viewer 用户拥有有限的读取权限

src/airflow/providers/fab/auth_manager/security_manager/override.py

    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_DAG_VERSION),
        (permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_WARNING),
        (permissions.ACTION_CAN_READ, RESOURCE_ASSET),
        (permissions.ACTION_CAN_READ, RESOURCE_ASSET_ALIAS),
        (permissions.ACTION_CAN_READ, RESOURCE_BACKFILL),
        (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_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, RESOURCE_ASSET),
        (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 用户拥有 Viewer 权限及额外的权限

src/airflow/providers/fab/auth_manager/security_manager/override.py

    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, RESOURCE_ASSET),
    ]

Op

Op 用户拥有 User 权限及额外的权限

src/airflow/providers/fab/auth_manager/security_manager/override.py

    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_CREATE, RESOURCE_ASSET),
        (permissions.ACTION_CAN_DELETE, RESOURCE_ASSET),
        (permissions.ACTION_CAN_CREATE, RESOURCE_BACKFILL),
        (permissions.ACTION_CAN_EDIT, RESOURCE_BACKFILL),
        (permissions.ACTION_CAN_DELETE, RESOURCE_BACKFILL),
    ]

Admin

Admin 用户拥有所有可能的权限,包括授予或撤销其他用户的权限。Admin 用户拥有 Op 权限及额外的权限。

src/airflow/providers/fab/auth_manager/security_manager/override.py

    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),
    ]

自定义角色

DAG 级别角色

Admin 可以创建一组仅允许查看特定 DAG 的角色。这称为 DAG 级别访问。在 DAG 模型表中定义的每个 DAG 都被视为一个视图(View),与之关联着两个权限(can_readcan_editcan_dag_readcan_dag_edit 自 2.0.0 版本起已弃用)。有一个特殊的视图称为 DAGs(在 1.10.* 版本中称为 all_dags),它允许该角色访问所有 DAG。默认的 AdminViewerUserOp 角色都可以访问 DAGs 视图。

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

该图显示了角色的创建过程,该角色仅允许写入 example_python_operator。您也可以使用 airflow roles create CLI 命令创建角色,例如:

airflow roles create Role1 Role2

我们可以使用 airflow users add-role CLI 命令将给定角色分配给新用户。

权限

警告

FAB 认证管理器允许您为用户定义具有细粒度 RBAC 权限的自定义角色。然而,并非所有权限组合都完全一致,并且没有机制来确保分配的权限集是完全一致的。存在一些特定资源的权限重叠的情况。一个很好的例子是菜单访问权限——缺少菜单访问权限不会自动禁用对相应功能的访问。另一个例子是对 Role 视图的访问,即使用户没有“用户视图”访问权限,也可以访问用户信息。在没有用户访问权限的情况下添加对 Roles 的访问权限本身就是不一致的。

当您决定使用自定义的基于资源的权限集时,部署管理员应仔细审查赋予角色的最终权限集是否符合他们的期望。

基于资源的权限

权限基于单个资源及其上的一小部分操作。资源与标准 Airflow 概念相匹配,例如 DagDagRunTaskConnection。操作包括 can_createcan_readcan_editcan_delete

然后将权限(每个权限由资源+操作对组成)添加到角色中。

要访问某个端点,用户需要拥有分配给该端点的所有权限

有五种默认角色:Public、Viewer、User、Op 和 Admin。每个角色都拥有前一个角色的权限,以及额外的权限。

DAG 级别权限

对于仅限 DAG 级别的权限,访问权限可以在所有 DAG 或单个 DAG 对象级别进行控制。这包括 DAGs.can_readDAGs.can_editDAGs.can_deleteDAG Runs.can_readDAG Runs.can_createDAG Runs.can_deleteDAG Runs.menu_access。当列出这些权限时,访问权限会授予拥有所列权限的用户,或者拥有正在操作的特定 DAG 的相同权限的用户。对于单个 DAG,资源名称是 DAG: + DAG ID;对于 DAG Runs 资源,资源名称是 DAG Run:

例如,如果用户尝试查看 example_dag_id 的 DAG 信息,并且该端点需要 DAGs.can_read 访问权限,则如果用户拥有 DAGs.can_readDAG:example_dag_id.can_read 权限,则将授予访问权限。

稳定版 API 权限

端点

方法

权限

最低所需角色

/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

PUT

DAGs.can_edit, DAG Runs.can_edit, 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, Task Instances.can_read

User

/assets

GET

Assets.can_read

Viewer

/assets/{uri}

GET

Assets.can_read

Viewer

/assets/events

GET

Assets.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.can_read

Viewer

显示 Browse 菜单

Browse.menu_access

Viewer

显示 DAGs 菜单

DAGs.menu_access

Viewer

获取 DAG 统计信息

DAGs.can_read, DAG Runs.can_read

Viewer

显示 Task Instances 菜单

Task Instances.menu_access

Viewer

获取 Task 统计信息

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

Viewer

获取最近的 DAG 运行

DAGs.can_read, DAG Runs.can_read

Viewer

获取 DAG 代码

DAGs.can_read, DAG Code.can_read

Viewer

获取 DAG 详情

DAGs.can_read, DAG Runs.can_read

Viewer

显示 DAG Dependencies 菜单

DAG Dependencies.menu_access

Viewer

获取 DAG 依赖关系

DAG Dependencies.can_read

Viewer

获取渲染后的 DAG

DAGs.can_read, Task Instances.can_read

Viewer

获取包含元数据的日志

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

Viewer

获取日志

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

Viewer

重定向到外部日志

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

Viewer

获取 Task

DAGs.can_read, Task Instances.can_read

Viewer

显示 XCom 菜单

XComs.menu_access

Op

获取 XCom

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

Viewer

创建 XCom

XComs.can_create

Op

删除 XCom

XComs.can_delete

Op

触发 Task 实例

DAGs.can_edit, Task Instances.can_create

User

删除 DAG

DAGs.can_delete

User

显示 DAG Runs 菜单

DAG Runs.menu_access

Viewer

触发 DAG 运行

DAGs.can_edit, DAG Runs.can_create

User

清除 DAG

DAGs.can_edit, Task Instances.can_delete

User

清除 DAG Run

DAGs.can_edit, Task Instances.can_delete

User

标记 DAG 为阻塞

DAGS.can_edit, DAG Runs.can_read

User

标记 DAG Run 为失败

DAGS.can_edit, DAG Runs.can_edit

User

标记 DAG Run 为成功

DAGS.can_edit, DAG Runs.can_edit

User

标记 Task 为失败

DAGs.can_edit, Task Instances.can_edit

User

标记 Task 为成功

DAGs.can_edit, Task Instances.can_edit

User

获取树状视图的 DAG

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

Viewer

获取图状视图的 DAG

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

Viewer

获取持续时间图的 DAG

DAGs.can_read, Task Instances.can_read

Viewer

显示所有尝试

DAGs.can_read, Task Instances.can_read

Viewer

显示到达时间

DAGs.can_read, Task Instances.can_read

Viewer

切换 DAG 暂停状态

DAGs.can_edit

User

显示甘特图

DAGs.can_read, Task Instances.can_read

Viewer

获取外部链接

DAGs.can_read, Task Instances.can_read

Viewer

显示 Task 实例

DAGs.can_read, Task Instances.can_read

Viewer

显示 Configurations 菜单

Configurations.menu_access

Op

显示配置

Configurations.can_read

Viewer

删除多条记录

DAGs.can_edit

User

将 Task 实例设置为运行中

DAGs.can_edit

User

将 Task 实例设置为失败

DAGs.can_edit

User

将 Task 实例设置为成功

DAGs.can_edit

User

将 Task 实例设置为待重试

DAGs.can_edit

User

自动完成

DAGs.can_read

Viewer

显示 Asset 菜单

Assets.menu_access

Viewer

显示 Assets

Assets.can_read

Viewer

显示 Docs 菜单

Docs.menu_access

Viewer

显示 Documentation 菜单

Documentation.menu_access

Viewer

显示 Jobs 菜单

Jobs.menu_access

Viewer

显示审计日志

Audit Logs.menu_access

Viewer

重置密码

My Password.can_read, My Password.can_edit

Viewer

显示 Permissions 菜单

Permission Views.menu_access

Admin

列出权限

Permission Views.can_read

Admin

获取我的资料

My Profile.can_read

Viewer

更新我的资料

My Profile.can_edit

Viewer

列出日志

Audit Logs.can_read

Viewer

列出 Jobs

Jobs.can_read

Viewer

显示 SLA Misses 菜单

SLA Misses.menu_access

Viewer

列出 SLA 未达标项

SLA Misses.can_read

Viewer

列出插件

Plugins.can_read

Viewer

显示 Plugins 菜单

Plugins.menu_access

Viewer

显示 Providers 菜单

Providers.menu_access

Op

列出 Provider

Providers.can_read

Op

列出 Task 重新调度项

Task Reschedules.can_read

Admin

显示 Triggers 菜单

Triggers.menu_access

Admin

列出 Triggers

Triggers.can_read

Admin

显示 Admin 菜单

Admin.menu_access

Viewer

显示 Connections 菜单

Connections.menu_access

Op

显示 Pools 菜单

Pools.menu_access

Viewer

显示 Variables 菜单

Variables.menu_access

Op

显示 Roles 菜单

Roles.menu_access

Admin

列出角色

Roles.can_read

Admin

创建角色

Roles.can_create

Admin

更新角色

Roles.can_edit

Admin

删除角色

Roles.can_delete

Admin

显示 Users 菜单

Users.menu_access

Admin

创建用户

Users.can_create

Admin

更新用户

Users.can_edit

Admin

删除用户

Users.can_delete

Admin

重置用户密码

Passwords.can_edit, Passwords.can_read

Admin

这些 DAG 级别控制可以直接通过 UI / CLI 设置,或者通过 DAG 本身中的 access_control 参数进行编码。

DAG 级别权限的优先级顺序

由于 DAG 级别访问控制可以在多个地方配置,冲突是不可避免的,因此需要明确的解决方案策略。因此,如果存在 DAG 本身的 access_control 参数,Airflow 会认为它是完全权威的,这会产生一些影响:

如果在 DAG 上设置 access_control 且其值不为 None,它将覆盖之前存在的任何 DAG 级别权限。

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"},
    },
)

也可以以类似的方式添加 DAG Runs 资源的权限,但需要明确添加资源名称以标识权限所属的资源。

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"}},
    },
)

这也意味着设置 access_control={} 将从数据库中清除给定 DAG 的所有现有 DAG 级别权限。

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

相反,完全从 DAG 中移除 access_control 块(或将其设置为 None)不会进行任何更改,并且可能会留下悬空权限。

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

在 DAG 本身未定义 access_control 的情况下,Airflow 将遵循数据库中定义的现有权限,这些权限可能通过 UI、CLI 或该 DAG 先前的 access_control 参数设置。

在所有情况下,系统范围的角色(如 Can edit on DAG)优先于 DAG 级别访问控制,以至于它们可以被视为 Can edit on DAG: *

这篇文章有帮助吗?