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

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

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

概要

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

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

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

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

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

始める前に

このドキュメントの各タスクを行うために必要な権限をユーザーに与える IAM ロールを付与します。

必要な権限

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

  • bigquery.datasets.update
  • bigquery.datasets.get
  • bigquery.datasets.getIamPolicy(Google Cloud Console を使用してデータセットへのアクセスを制御できます)
  • bigquery.datasets.setIamPolicy(Google Cloud Console を使用してデータセットへのアクセスを制御できます)

IAM 事前定義ロール roles/bigquery.dataOwner には、データセットへのアクセスを制御するために必要な権限が含まれています。

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

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

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

Console

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

  2. 詳細パネルで、[共有] > [権限] をクリックします。

  3. [プリンシパルを追加] をクリックします。

  4. [新しいプリンシパル] フィールドに、追加するエンティティを入力します。 次のエンティティを追加できます。

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

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

SQL

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

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    BigQuery に移動

  2. クエリエディタで次のステートメントを入力します。

    GRANT `roles/bigquery.dataViewer`
    ON SCHEMA mydataset
    TO 'user:joe@example.com';
    

  3. [ 実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリの実行をご覧ください。

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": "WRITER",
       "userByEmail": "service_account_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() 関数を呼び出してプロパティを更新します。

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

# TODO(developer): Set entity_id to the ID of the email or group from whom
# you are adding access. Alternatively, to the JSON REST API representation
# of the entity, such as a view's table reference.
entity_id = "user-or-group-to-add@example.com"

from google.cloud.bigquery.enums import EntityTypes

# TODO(developer): Set entity_type to the type of entity you are granting access to.
# Common types include:
#
# * "userByEmail" -- A single user or service account. For example "fred@example.com"
# * "groupByEmail" -- A group of users. For example "example@googlegroups.com"
# * "view" -- An authorized view. For example
#       {"projectId": "p", "datasetId": "d", "tableId": "v"}
#
# For a complete reference, see the REST API reference documentation:
# https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets#Dataset.FIELDS.access
entity_type = EntityTypes.GROUP_BY_EMAIL

# TODO(developer): Set role to a one of the "Basic roles for datasets"
# described here:
# https://cloud.google.com/bigquery/docs/access-control-basic-roles#dataset-basic-roles
role = "READER"

from google.cloud import bigquery

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

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

entries = list(dataset.access_entries)
entries.append(
    bigquery.AccessEntry(
        role=role,
        entity_type=entity_type,
        entity_id=entity_id,
    )
)
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 DCL ステートメントを使用して、データセット mydataset のユーザー joe@example.com から BigQuery データ閲覧者(roles/bigquery.dataViewer)ロールを削除します。

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    BigQuery に移動

  2. クエリエディタで次のステートメントを入力します。

    REVOKE `roles/bigquery.dataViewer`
    ON SCHEMA mydataset
    FROM 'user:joe@example.com';
    

  3. [ 実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリの実行をご覧ください。

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
}

Python

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

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

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

# TODO(developer): Set entity_id to the ID of the email or group from whom you are revoking access.
entity_id = "user-or-group-to-remove@example.com"

from google.cloud import bigquery

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

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

entries = list(dataset.access_entries)
dataset.access_entries = [
    entry for entry in entries if entry.entity_id != entity_id
]

dataset = client.update_dataset(
    dataset,
    # Update just the `access_entries` property of the dataset.
    ["access_entries"],
)  # Make an API request.

full_dataset_id = f"{dataset.project}.{dataset.dataset_id}"
print(f"Revoked dataset access for '{entity_id}' to ' dataset '{full_dataset_id}.'")

次のステップ