承認済みのビューの作成

このドキュメントでは、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.update および bigquery.datasets.get 権限が付与されている必要があります。bigquery.datasets.update 権限と bigquery.datasets.get 権限は、事前定義された以下の Cloud IAM の役割に含まれています。

  • bigquery.dataOwner
  • bigquery.admin

また、bigquery.datasets.create 権限を持つユーザーがデータセットを作成すると、そのデータセットに対する bigquery.dataOwner アクセス権がユーザーに付与されます。bigquery.dataOwner アクセス権により、自身が作成したデータセット プロパティの更新が許可されます。

BigQuery での Cloud IAM 役割と権限については、アクセス制御をご覧ください。

データセットに表示アクセス権を付与する

データセットへの表示アクセス権を付与するには:

Console

  1. ナビゲーション パネルの [リソース] セクションでプロジェクトを展開し、データセットを選択します。

  2. ウィンドウの右側にある [共有データセット] をクリックします。

  3. [データセットの権限] パネルで、[承認済みのビュー] タブを選択します。

  4. [承認済みビューの共有] セクションで、次の操作を行います。

    • [プロジェクトの選択] で、プロジェクト名を確認します。ビューが異なるプロジェクトにある場合には、そのプロジェクトを選択します。
    • [データセットを選択] で、ビューを含むデータセットを選択します。
    • [ビューを選択] で、承認するビューを選択します。
  5. [追加] をクリックしてから [完了] をクリックします。

従来の UI

  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 ファイルに書き込みます。データセットがデフォルト プロジェクト以外のプロジェクトにある場合は、project_id:dataset の形式でプロジェクト ID をデータセット名に追加します。

        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 セクションは次のようになります。

        {
         "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 ファイルを指定します。データセットがデフォルト プロジェクト以外のプロジェクトにある場合は、project_id:dataset の形式でプロジェクト ID をデータセット名に追加します。

        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 のリファレンス ドキュメントをご覧ください。

import (
    	"context"
    	"fmt"

    	"cloud.google.com/go/bigquery"
    )

    // updateViewDelegated demonstrates the setup of an authorized view, which allows access to a view's results
    // without the caller having direct access to the underlying source data.
    func updateViewDelegated(projectID, srcDatasetID, viewDatasetID, viewID string) error {
    	// projectID := "my-project-id"
    	// srcDatasetID := "sourcedata"
    	// viewDatasetID := "views"
    	// viewID := "myview"
    	ctx := context.Background()
    	client, err := bigquery.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("bigquery.NewClient: %v", err)
    	}
    	defer client.Close()

    	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
    	}
    	return nil
    }
    

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
    

次のステップ