如何在 bigquery 中构建视图以实现高效的访问管理

How to structure views in bigquery for efficient access management

在 BigQuery 中,您授予 users/roles(或授权视图)数据集级别的访问权限,而不是 views/table-level。我想解决的挑战是,当我有数百个 table 和视图以及许多不同的 roles/departments 时,如何在 bigquery 中管理访问控制,这些 roles/departments 应该可以访问跨所有部门共享的视图和仅用于一个特定的 role/department?

示例:假设我有一个源数据集,其中源 tables A->D 和每个 table 的三个视图根据数据 1->3 的敏感性公开不同的字段。另外,我有三个角色(蓝色、绿色、红色)。如果我可以管理 table 级别的访问权限,它将如下所示:

查看:角色

鉴于这些要求,我无法仅基于敏感度 (1-3) 或来源 (A-D) 创建数据集并基于此管理访问权限。我能看到满足此要求的唯一解决方案是为每个角色生成一个数据集。如果角色和视图的数量很少,这可以手动完成,但是当管理 10 个以上的角色和 50 个以上的视图时,它变得更具挑战性。

我能想到的唯一解决方案是 CI/CD 设置(云构建),其中 file/s 定义数据集(即角色)、依赖项和 DDL-statement/s。让 script/program 遍历 file/s 并生成视图并授予对源的访问权限(授权视图)。 示例文件:

{"roles":["crm_analyst", "admin", "customer_service_agent"],
"ddl":"CREATE VIEW `myproject.'{role}'.newview` AS SELECT column_1, column_2, column_3 FROM myproject.mydataset.myview",
"dependencies":"myproject.mydataset.myview"}

其他公司是如何解决这个问题的?已经迁移到 bigquery 的大型银行必须有大量的部门和不同的数据集敏感性。

与群组而非角色共享数据集。每人一组"role";红色、绿色和蓝色。创建只有视图的数据集。与观点分享来源dataset.tables。

  • RED_DATASET: 共享:RED_GROUP 观点: A1-A3,B1-B3,C1-C3,D1-D3

  • BLUE_DATASET: 共享:BLUE_GROUP 观点: A1,B1

  • GREEN_DATASET: 共享:GREEN_GROUP 观点: B1-B2,C1-C2

请注意,B1 视图将拥有它的三个副本(每个 "view_dataset" 一个)并且由同一个查询定义。

这是关于视图访问控制的recommended practice

我最终编写了一个 python 脚本,该脚本从 json 文件中读取视图定义,然后生成数据集和视图并提供正确的访问权限。该解决方案有点粗糙,可以使用依赖映射(当一个视图查询另一个视图时)而不是当前的解决方案迭代视图,直到生成所有视图或脚本不能再生成视图(依赖关系中断)。该脚本每组生成两个数据集,一个带有READER(后缀'_ro')和一个带有WRITER(后缀'_rw')以确保数据团队生成的视图不能被修改并且同时给小组一个沙箱。该组应该是一个电子邮件组,数据集的名称将是电子邮件地址的本地部分。该脚本由 google 云构建执行,并通过推送到我们的 github 存储库触发。

示例视图定义(路径:views/view_test.json)

{
    "groups":["developers@datahem.org", "analysts@datahem.org"],
    "sql":"SELECT * FROM `{project}.shared_views.test_view`"
}

生成以下数据集(访问)和视图:

analysts_ro (analysts@datahem.org:READER):
- view_test

analysts_rw (analysts@datahem.org:WRITER):
(empty)

developers_ro (developers@datahem.org:READER):
- view_test

developers_rw (developers@datahem.org:WRITER):
(empty)

shared_views (analysts_ro.view_test:None, developers_ro.view_test:None):
- test_view

我制作了 python script available on github as open source as part of datahem,请随意克隆、改进和用于您自己的目的。

另一种选择是设置行级访问并将所有视图放在同一数据集中。

模拟一个 access_control table(用户、用户组)用于示例目的:

SELECT 'userA@datahem.org' as user_name, ['developer','analyst'] as user_groups
UNION ALL
SELECT 'userB@datahem.org' as user_name, ['developer'] as user_groups

并创建一个具有行级访问控制的视图,方法是添加一个包含 user_groups 数组的静态列并与 access_control "table" 连接,其中至少有一个当前用户组匹配 allowed_groups:

SELECT c.* EXCEPT(allowed_groups) FROM (
  SELECT OrderReference, Date, ['developer', 'analyst'] AS allowed_groups 
  FROM `project.dataset.orders`) as c
INNER JOIN (
  SELECT user_name, user_group 
  FROM  `project.access.access_control`, UNNEST(user_groups) as user_group 
  WHERE SESSION_USER() = user_name) g
ON g.user_group IN UNNEST(c.allowed_groups)

这是一个不错的解决方案,但它会向用户公开所有视图,即使用户无权访问它也是如此。此外,用户将能够 运行 查询视图 he/she 无权访问(产生成本)但不会得到任何结果。从可用性的角度(仅显示用户有权访问的视图)我们选择了上面标记的解决方案。