建立授權的檢視表

本文件說明如何在 BigQuery 中建立授權的檢視表。

您可以透過以下方式在 BigQuery 中建立授權的檢視表:

  • 使用 Cloud Console 或 BigQuery 傳統網頁版 UI。
  • 使用指令列工具的 bq mk 指令
  • 呼叫 tables.insert API 方法
  • 提交 CREATE VIEW 資料定義語言 (DDL) 陳述式
  • 使用用戶端程式庫

總覽

為檢視表授予資料集的存取權又稱為「在 BigQuery 中建立授權的檢視表」。透過授權的檢視表,即使不將原始資料表的存取權授予特定使用者及群組,也可以和他們分享查詢結果。您也可以使用檢視表的 SQL 查詢限制使用者能夠查詢的資料欄 (欄位)。

檢視表的建立位置不能和該檢視表查詢的來源資料位置相同,因為您只能在資料集層級指派存取權控管設定,如果檢視表是建立在與來源資料相同的資料集中,您的使用者就會同時取得檢視表與資料的存取權。

如需建立授權檢視表的教學課程,請參閱在 BigQuery 中建立授權檢視表的相關說明。

所需權限

如要建立授權的檢視表,您必須具備該檢視表所屬資料集的權限,以及提供該檢視表存取權的資料集的權限。

包含檢視表的資料集

BigQuery 會將檢視表視為資料表資源,因此建立檢視表需要的權限和建立資料表相同。您至少要具備 bigquery.tables.create 權限,才能建立檢視表。以下是具有 bigquery.tables.create 權限的預先定義 Cloud IAM 角色:

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

此外,當具備 bigquery.datasets.create 權限的使用者建立資料集時,該使用者會獲得該資料集的 bigquery.dataOwner 存取權。bigquery.dataOwner 存取權可讓使用者在資料集裡建立檢視表。

如要進一步瞭解 BigQuery 中的 Cloud IAM 角色和權限,請參閱預先定義的角色和權限的相關說明。

提供檢視表存取權的資料集

您至少必須擁有 bigquery.datasets.updatebigquery.datasets.get 權限,才能更新資料集屬性。以下是包含 bigquery.datasets.updatebigquery.datasets.get 權限的預先定義 Cloud IAM 角色:

  • bigquery.dataOwner
  • bigquery.admin

此外,當具備 bigquery.datasets.create 權限的使用者建立資料集時,該使用者會獲得該資料集的 bigquery.dataOwner 存取權。bigquery.dataOwner 存取權可讓使用者更新所建立資料集中的屬性。

如要進一步瞭解 BigQuery 中的 Cloud IAM 角色和權限,請參閱存取權控管一文。

將檢視表存取權授予資料集

如何為檢視表授予資料集的存取權:

主控台

  1. 在導覽面板的「Resources」(資源) 區段,展開您的專案並選取資料集。

  2. 按一下視窗右側的 [Share dataset] (分享資料集)

  3. 在「Dataset permissions」(資料集權限) 面板中,選取 [Authorized views] (已授權視圖) 分頁標籤。

  4. 在「Share authorized view」(分享已授權檢視表) 區段中:

    • 在「Select project」(選取專案) 部分確認專案名稱。如果檢視表在其他專案中,請務必選取正確的專案。
    • 在「Select dataset」(選取資料集) 部分,選擇包含檢視表的資料集。
    • 在「Select view」(選取檢視表) 部分,選取您想要授權的檢視表。
  5. 按一下 [Add] (新增),然後按一下 [Done] (完成)。

傳統版 UI

  1. 在含有來源資料表的資料集右側,按一下下拉式箭頭,然後選擇 [Share Dataset] (分享資料集)。

  2. 在「分享資料集」對話方塊中的「新增使用者」部分,按一下欄位左側的下拉式選單,然後選擇 [授權的資料檢視]。

  3. 按一下 [Select View]

  4. 在「Select View」(選取檢視表) 對話方塊中:

    • 在「Project」(專案) 部分確認專案名稱。如果檢視表在其他專案中,請務必選取正確的專案。
    • 在「資料集」的部分選擇包含目標資料檢視的資料集。
    • 在「資料表 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 檔案。mydatasetmyotherproject 中。

    bq show --format=prettyjson \
    myotherproject:mydataset > /tmp/mydataset.json
    
  2. 將授權的檢視表新增至 JSON 檔案的「access」區段。

    舉例來說,資料集 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 的存取權控管設定。mydatasetmyotherproject 中。

     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

後續步驟