创建已获授权的视图

本文档介绍了如何在 BigQuery 中创建已获授权的视图。

您可以通过以下方式在 BigQuery 中创建已获授权的视图:

  • 使用 GCP Console 或经典版 BigQuery 网页界面
  • 使用命令行工具的 bq mk 命令
  • 调用 tables.insert API 方法
  • 提交 CREATE VIEW 数据定义语言 (DDL) 语句
  • 使用客户端库

概览

授予视图对数据集的访问权限也称为在 BigQuery 中创建已获授权的视图。借助已获授权的视图,您可以与特定用户和群组共享查询结果,而无需向其授予基础表的访问权限。您还可以使用视图的 SQL 查询来限制用户可查询的列(字段)。

创建视图时,必须在与视图查询的源数据不同的数据集中创建该视图。您只能在数据集级层分配访问权限控制,因此如果在与源数据相同的数据集中创建视图,您的用户就有权同时访问视图和数据。

有关如何创建已获授权的视图的教程,请参阅在 BigQuery 中创建已获授权的视图

所需权限

如需创建已获授权的视图,您需要拥有包含该视图的数据集的权限,以及提供对该视图的访问权限的数据集的权限。

包含该视图的数据集

在 BigQuery 中,视图作为表资源处理,因此创建视图所需的权限与创建表相同。如需创建视图,您至少必须获得 bigquery.tables.create 权限。以下预定义的 Cloud IAM 角色包含 bigquery.tables.create 权限:

  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

此外,如果用户具有 bigquery.datasets.create 权限,则当该用户创建数据集时,系统会为其授予该数据集的 bigquery.dataOwner 访问权限。 借助 bigquery.dataOwner 访问权限,用户可以在数据集中创建视图。

如需详细了解 BigQuery 中的 Cloud IAM 角色和权限,请参阅预定义的角色和权限

提供对该视图的访问权限的数据集

如需更新数据集属性,您至少必须获得 bigquery.datasets.updatebigquery.datasets.get 权限。以下预定义的 Cloud IAM 角色包含 bigquery.datasets.updatebigquery.datasets.get 权限:

  • bigquery.dataOwner
  • bigquery.admin

此外,如果用户具有 bigquery.datasets.create 权限,则当该用户创建数据集时,系统会为其授予该数据集的 bigquery.dataOwner 访问权限。 借助 bigquery.dataOwner 访问权限,用户可以更新其创建的数据集的属性。

如需详细了解 BigQuery 中的 Cloud IAM 角色和权限,请参阅访问权限控制

授予数据集视图访问权限

要授予数据集视图访问权限,请执行如下操作:

控制台

  1. 在导航面板的资源部分中,展开您的项目并选择数据集。

  2. 点击窗口右侧的共享数据集

  3. 数据集权限面板中,选择已获授权的视图标签页。

  4. 共享已获授权的视图部分中:

    • 对于选择项目,验证项目名称。如果视图位于不同的项目中,请务必选择该项目。
    • 对于选择数据集,请选择包含该视图的数据集。
    • 对于选择视图,选择您正在授权的视图。
  5. 点击添加,然后点击完成

经典版界面

  1. 点击包含源表的数据集右侧的下拉箭头,然后选择 Share Dataset

  2. Share Dataset 对话框中,对于 Add People,点击该字段左侧的下拉列表,然后选择 Authorized View

  3. 点击 Select View

  4. Select View 对话框中,执行以下操作:

    • 对于 Project,验证项目名称。如果视图位于不同的项目中,请务必选择该项目。
    • 对于 Dataset,选择包含该视图的数据集。
    • 对于 Table ID,输入您正在授权的视图的名称。
    • 点击 OK

      选择已获授权的视图

  5. 点击 Add,然后点击 Save changes

CLI

  1. 使用 show 命令将现有数据集信息(包括访问权限控制)写入 JSON 文件。如果数据集不属于默认项目,请按以下格式将相应项目 ID 添加到数据集名称中:project_id:dataset

    bq show \
    --format=prettyjson \
    project_id:dataset > path_to_file
    

    其中:

    • project_id 是您的项目 ID。
    • dataset 是数据集的名称。
    • path_to_file 是本地机器上 JSON 文件的路径。

    示例:

    输入以下命令可将 mydataset 的访问权限控制写入 JSON 文件。mydataset 属于默认项目。

    bq show --format=prettyjson mydataset > /tmp/mydataset.json
    

    输入以下命令可将 mydataset 的访问权限控制写入 JSON 文件。mydataset 属于 myotherproject

    bq show --format=prettyjson \
    myotherproject:mydataset > /tmp/mydataset.json
    
  2. 将已获授权的视图添加到 JSON 文件的“访问权限”部分。

    例如,某个数据集的 JSON 文件的“访问权限”部分可能如下所示:

    {
     "access": [
      {
       "role": "READER",
       "specialGroup": "projectReaders"
      },
      {
       "role": "WRITER",
       "specialGroup": "projectWriters"
      },
      {
       "role": "OWNER",
       "specialGroup": "projectOwners"
      }
      {
       "role": "READER",
       "specialGroup": "allAuthenticatedUsers"
      }
      {
       "role": "READER",
       "domain": "[DOMAIN_NAME]"
      }
      {
       "role": "WRITER",
       "userByEmail": "[USER_EMAIL]"
      }
      {
       "role": "READER",
       "groupByEmail": "[GROUP_EMAIL]"
      },
      {
       "view":{
       "datasetId": "[DATASET_NAME]",
       "projectId": "[PROJECT_NAME]",
       "tableId": "[VIEW_NAME]"
       }
      }
     ],
    }
    

  3. 修改完成后,使用 update 命令并使用 --source 标志包含 JSON 文件。如果数据集不属于默认项目,请按以下格式将相应项目 ID 添加到数据集名称中:project_id:dataset

    bq update \
    --source path_to_file \
    project_id:dataset
    

    其中:

    • path_to_file 是本地机器上 JSON 文件的路径。
    • project_id 是您的项目 ID。
    • dataset 是数据集的名称。

    示例:

    输入以下命令可更新 mydataset 的访问权限控制。mydataset 属于默认项目。

     bq update --source /tmp/mydataset.json mydataset
    

    输入以下命令可更新 mydataset 的访问权限控制。mydataset 属于 myotherproject

     bq update --source /tmp/mydataset.json myotherproject:mydataset
    
  4. 如需验证访问权限控制的更改,请再次输入 show 命令,但不要将信息写入文件。

    bq show --format=prettyjson [DATASET]
    

    bq show --format=prettyjson [PROJECT_ID]:[DATASET]
    

API

调用 datasets.patch 并使用 access 属性更新访问权限控制。如需了解详情,请参阅数据集

由于 datasets.update 方法会替换整个数据集资源,因此 datasets.patch 是更新访问权限控制的首选方法。

Go

试用此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Go 设置说明进行操作。如需了解详情,请参阅 BigQuery Go API 参考文档

// To run this sample, you will need to create (or reuse) a context and
// an instance of the bigquery client.  For example:
// import "cloud.google.com/go/bigquery"
// ctx := context.Background()
// client, err := bigquery.NewClient(ctx, "your-project-id")
srcDataset := client.Dataset(srcDatasetID)
viewDataset := client.Dataset(viewDatasetID)
view := viewDataset.Table(viewID)

// First, we'll add a group to the ACL for the dataset containing the view.  This will allow users within
// that group to query the view, but they must have direct access to any tables referenced by the view.
vMeta, err := viewDataset.Metadata(ctx)
if err != nil {
	return err
}
vUpdateMeta := bigquery.DatasetMetadataToUpdate{
	Access: append(vMeta.Access, &bigquery.AccessEntry{
		Role:       bigquery.ReaderRole,
		EntityType: bigquery.GroupEmailEntity,
		Entity:     "example-analyst-group@google.com",
	}),
}
if _, err := viewDataset.Update(ctx, vUpdateMeta, vMeta.ETag); err != nil {
	return err
}

// Now, we'll authorize a specific view against a source dataset, delegating access enforcement.
// Once this has been completed, members of the group previously added to the view dataset's ACL
// no longer require access to the source dataset to successfully query the view.
srcMeta, err := srcDataset.Metadata(ctx)
if err != nil {
	return err
}
srcUpdateMeta := bigquery.DatasetMetadataToUpdate{
	Access: append(srcMeta.Access, &bigquery.AccessEntry{
		EntityType: bigquery.ViewEntity,
		View:       view,
	}),
}
if _, err := srcDataset.Update(ctx, srcUpdateMeta, srcMeta.ETag); err != nil {
	return err
}

Python

试用此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Python 设置说明进行操作。如需了解详情,请参阅 BigQuery Python API 参考文档

# from google.cloud import bigquery
# client = bigquery.Client()

# Assign access controls to the dataset containing the view
# shared_dataset_id = 'my_shared_dataset'
# analyst_group_email = 'data_analysts@example.com'
shared_dataset = client.get_dataset(
    client.dataset(shared_dataset_id)
)  # API request
access_entries = shared_dataset.access_entries
access_entries.append(
    bigquery.AccessEntry("READER", "groupByEmail", analyst_group_email)
)
shared_dataset.access_entries = access_entries
shared_dataset = client.update_dataset(
    shared_dataset, ["access_entries"]
)  # API request

# Authorize the view to access the source dataset
# project = 'my-project'
# source_dataset_id = 'my_source_dataset'
source_dataset = client.get_dataset(
    client.dataset(source_dataset_id)
)  # API request
view_reference = {
    "projectId": project,
    "datasetId": shared_dataset_id,
    "tableId": "my_shared_view",
}
access_entries = source_dataset.access_entries
access_entries.append(bigquery.AccessEntry(None, "view", view_reference))
source_dataset.access_entries = access_entries
source_dataset = client.update_dataset(
    source_dataset, ["access_entries"]
)  # API request

使用视图强制实施行级访问

视图可用于限制对特定列(字段)的访问。如果要限制对表中个别行的访问权限,则不需要为每个用户或群组创建单独的视图。相反,您可以使用 SESSION_USER() 函数返回当前用户的电子邮件地址。

要向不同的用户显示不同的行,请向包含允许查看该行的用户的表再添加一个字段。然后,创建一个使用 SESSION_USER() 函数的视图。在以下示例中,用户名称存储在 allowed_viewer 字段中:

SELECT
  COLUMN_1,
  COLUMN_2
FROM
  `dataset.view`
WHERE
  allowed_viewer = SESSION_USER()

这种方法的局限性在于,每次只能为一名用户授予访问权限。您可以将 allowed_viewer 设为重复字段,从而突破这个限制。这种方法允许您为每行提供用户列表,但即便使用了重复字段,在表中存储用户名仍然需要手动跟踪有权限访问各行的各用户。

此时应改为使用群组名称填充 allowed_viewer 字段,并创建一个将群组映射到用户的单独的表。将群组映射到用户的表具有存储群组名称和用户名的架构。例如:{group:string, user_name:string}。这种方法让您可以分别管理包含数据的表中的用户和群组信息。

如果映射表名为 private.access_control,则用于创建已获授权的视图的 SQL 查询如下所示:

SELECT
  c.customer,
  c.id
FROM
  `private.customers` c
INNER JOIN (
  SELECT
    group
  FROM
    `private.access_control`
  WHERE
    SESSION_USER() = user_name) g
ON
  c.allowed_group = g.group

后续步骤

此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面