データセットへのアクセスの制御

このドキュメントでは、BigQuery 内のデータセットへのアクセスを制御する方法を説明します。

さらに、次のことも可能です。

概要

データセット レベルの権限により、特定のデータセット内のテーブル、ビュー、テーブルデータにアクセスできるユーザー、グループ、サービス アカウントが決まります。たとえば、あるユーザーに特定のデータセットに対する bigquery.dataOwner IAM ロールを付与した場合、そのユーザーはそのデータセット内のテーブルとビューを作成、更新、削除できます。

データセットの作成時にアクセス制御を適用するには、datasets.insert API メソッドを呼び出します。

Cloud Console、bq コマンドライン ツール、データ定義言語(DDL)ステートメントでデータセットを作成している間は、アクセス制御を適用できません。

データセットを作成した後、次の方法でアクセス制御を適用できます。

  • Cloud Console を使用する。
  • GRANTREVOKE DCL ステートメントを使用する。
  • bq コマンドライン ツールで bq update コマンドを使用する。
  • datasets.patch API メソッドを呼び出す。
  • クライアント ライブラリを使用する。

必要な権限とロール

このセクションでは、データセットへのアクセスを制御するために必要な Identity and Access Management(IAM)権限と、それらの権限を付与する IAM 事前定義ロールについて説明します。

権限

データセットのアクセスを制御するには、次の権限がすべて必要です。

権限 リソース
bigquery.datasets.update アクセスを制御するデータセット。
bigquery.datasets.get アクセスを制御するデータセット。

Google Cloud Console を使用してデータセットのアクセスを制御するには、次の権限も必要です。

権限 リソース
bigquery.datasets.getIamPolicy アクセスを制御するデータセット。
bigquery.datasets.setIamPolicy アクセスを制御するデータセット。

ロール

データセットのアクセスを制御するには、少なくとも次のロールが必要です。

ロール リソース
roles/bigquery.dataOwner アクセスを制御するデータセット。

BigQuery での IAM のロールと権限については、事前定義ロールと権限をご覧ください。

データセットへのアクセス権の付与

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

Console

  1. [エクスプローラ] パネルでプロジェクトを開いて、データセットを選択します。

  2. 詳細パネルで [共有データセット] をクリックします。

  3. [共有データセット] パネルの [データセットの権限] タブで、[メンバーを追加] 項目に追加するエンティティを入力します。次のエンティティを追加できます。

    • Google アカウントのメールアドレス: 個々の Google アカウントにデータセットへのアクセスを許可します。
    • Google グループ: Google グループ内のすべてのメンバーにデータセットへのアクセスを許可します。
    • Google Apps ドメイン: Google ドメイン内のすべてのユーザーとグループにデータセットへのアクセスを許可します。
    • サービス アカウント: サービス アカウントにデータセットへのアクセスを許可します。
    • 全員: 「allUsers」と入力して、一般ユーザーにアクセス権を付与します。
    • すべての Google アカウント: Google アカウントにログインしたすべてのユーザーにアクセス権を付与するには、「allAuthenticatedUsers」と入力します。
  4. [ロールを選択] で、[BigQuery] を選択し、新しいメンバーに適切な定義済みの IAM ロールを選択します。事前定義された各 BigQuery ロールに割り当てられている権限の詳細については、アクセス制御ページのロールのセクションをご覧ください。

  5. [完了] をクリックします。

SQL

次の GRANT ステートメントを使用して、データセットのユーザー joe@example.com にデータ閲覧者(roles/bigquery.dataViewer)のロールを付与します。

     GRANT `roles/bigquery.dataViewer`
     ON SCHEMA DATASET
     TO "user:joe@example.com"
 

DATASET は、リソースが含まれるデータセットの名前に置き換えます。

GRANT DCL ステートメントの詳細については、標準 SQL のデータ制御言語ステートメントをご覧ください。

bq

  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" セクションに変更を加えます。specialGroup エントリ(projectOwnersprojectWritersprojectReadersallAuthenticatedUsers)はどれも追加できます。さらに、userByEmailgroupByEmaildomain の追加や変更もできます。

    たとえば、データセットの 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"
      }
     ],
     ...
    }
    

  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.insert を呼び出します。アクセス制御を更新するには、Dataset リソースで datasets.patch を呼び出して access プロパティを使用します。

datasets.update メソッドはデータセット リソース全体を置き換えるので、アクセス制御の更新には datasets.patch メソッドのほうが適切です。

Go

このサンプルを試す前に、BigQuery クイックスタート: クライアント ライブラリの使用の Go の手順に沿って設定を行ってください。詳細については、BigQuery Go API のリファレンス ドキュメントをご覧ください。

import (
	"context"
	"fmt"

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

// updateDatasetAccessControl demonstrates how the access control policy of a dataset
// can be amended by adding an additional entry corresponding to a specific user identity.
func updateDatasetAccessControl(projectID, datasetID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	ds := client.Dataset(datasetID)
	meta, err := ds.Metadata(ctx)
	if err != nil {
		return err
	}
	// Append a new access control entry to the existing access list.
	update := bigquery.DatasetMetadataToUpdate{
		Access: append(meta.Access, &bigquery.AccessEntry{
			Role:       bigquery.ReaderRole,
			EntityType: bigquery.UserEmailEntity,
			Entity:     "sample.bigquery.dev@gmail.com"},
		),
	}

	// Leverage the ETag for the update to assert there's been no modifications to the
	// dataset since the metadata was originally read.
	if _, err := ds.Update(ctx, update, meta.ETag); err != nil {
		return err
	}
	return nil
}

Java

このサンプルを試す前に、BigQuery クイックスタート: クライアント ライブラリの使用にある Java の設定手順を行ってください。詳細については、BigQuery Java API のリファレンス ドキュメントをご覧ください。

import com.google.cloud.bigquery.Acl;
import com.google.cloud.bigquery.Acl.Role;
import com.google.cloud.bigquery.Acl.User;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Dataset;
import java.util.ArrayList;

public class UpdateDatasetAccess {

  public static void main(String[] args) {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    // Create a new ACL granting the READER role to "sample.bigquery.dev@gmail.com"
    // For more information on the types of ACLs available see:
    // https://cloud.google.com/storage/docs/access-control/lists
    Acl newEntry = Acl.of(new User("sample.bigquery.dev@gmail.com"), Role.READER);

    updateDatasetAccess(datasetName, newEntry);
  }

  public static void updateDatasetAccess(String datasetName, Acl newEntry) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      Dataset dataset = bigquery.getDataset(datasetName);

      // Get a copy of the ACLs list from the dataset and append the new entry
      ArrayList<Acl> acls = new ArrayList<>(dataset.getAcl());
      acls.add(newEntry);

      bigquery.update(dataset.toBuilder().setAcl(acls).build());
      System.out.println("Dataset Access Control updated successfully");
    } catch (BigQueryException e) {
      System.out.println("Dataset Access control was not updated \n" + e.toString());
    }
  }
}

Python

このサンプルを試す前に、BigQuery クイックスタート: クライアント ライブラリの使用にある Python の設定手順を行ってください。詳細については、BigQuery Python API のリファレンス ドキュメントをご覧ください。

dataset.access_entries プロパティを使用してデータセットのアクセス制御を設定します。次に、client.update_dataset() 関数を呼び出してプロパティを更新します。
from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

# TODO(developer): Set dataset_id to the ID of the dataset to fetch.
# dataset_id = 'your-project.your_dataset'

dataset = client.get_dataset(dataset_id)  # Make an API request.

entry = bigquery.AccessEntry(
    role="READER",
    entity_type="userByEmail",
    entity_id="sample.bigquery.dev@gmail.com",
)

entries = list(dataset.access_entries)
entries.append(entry)
dataset.access_entries = entries

dataset = client.update_dataset(dataset, ["access_entries"])  # Make an API request.

full_dataset_id = "{}.{}".format(dataset.project, dataset.dataset_id)
print(
    "Updated dataset '{}' with modified user permissions.".format(full_dataset_id)
)

データセットへのアクセス権の取消

データセットへのアクセスを取り消すには:

Console

  1. [エクスプローラ] パネルでプロジェクトを開いて、データセットを選択します。

  2. 詳細パネルで [共有データセット] をクリックします。

  3. [共有データセット] パネルの [データセットの権限] タブで、メンバーを変更するロールを展開します。

  4. 削除するユーザー アカウントの [削除] アイコン をクリックします。

  5. [メンバーを削除しますか?] ダイアログで [削除] をクリックします。

  6. [完了] をクリックします。

SQL

次の REVOKE ステートメントを使用して、データセットのユーザー joe@example.com からデータ閲覧者(roles/bigquery.dataViewer)のロールを削除します。

  REVOKE `roles/bigquery.dataViewer`
  ON SCHEMA DATASET
  FROM "user:joe@example.com"
 

DATASET は、リソースが含まれるデータセットの名前に置き換えます。

REVOKE DCL ステートメントの詳細については、標準 SQL のデータ制御言語ステートメントをご覧ください。

bq

  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" セクションに変更を加えます。specialGroup のエントリ(projectOwnersprojectWritersprojectReadersallAuthenticatedUsers)は削除できます。さらに、userByEmailgroupByEmaildomain の削除もできます。

    たとえば、データセットの 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"
      }
     ],
     ...
    }
    

  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

アクセス制御を更新するには、Dataset リソースで datasets.patch を呼び出して access プロパティを使用します。

datasets.update メソッドはデータセット リソース全体を置き換えるので、アクセス制御の更新には datasets.patch メソッドのほうが適切です。

Go

このサンプルを試す前に、BigQuery クイックスタート: クライアント ライブラリの使用の Go の手順に沿って設定を行ってください。詳細については、BigQuery Go API のリファレンス ドキュメントをご覧ください。

import (
	"context"
	"fmt"

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

// revokeDatasetAccess updates the access control on a dataset to remove all
// access entries that reference a specific entity.
func revokeDatasetAccess(projectID, datasetID, entity string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// entity := "user@mydomain.com"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	ds := client.Dataset(datasetID)
	meta, err := ds.Metadata(ctx)
	if err != nil {
		return err
	}

	var newAccessList []*bigquery.AccessEntry
	for _, entry := range meta.Access {
		if entry.Entity != entity {
			newAccessList = append(newAccessList, entry)
		}
	}

	// Only proceed with update if something in the access list was removed.
	// Additionally, we use the ETag from the initial metadata to ensure no
	// other changes were made to the access list in the interim.
	if len(newAccessList) < len(meta.Access) {

		update := bigquery.DatasetMetadataToUpdate{
			Access: newAccessList,
		}
		if _, err := ds.Update(ctx, update, meta.ETag); err != nil {
			return err
		}
	}
	return nil
}

次のステップ