BigQueryのデータセットへのアクセスをタグで制御してみる

2024.04.02

Google Cloudデータエンジニアのはんざわです。
先日、BigQueryのデータセットへのアクセス権限を改めて考え直す機会があり、その際にタグで制御する方法もあることを思い出しました。
この記事では、実際にその方法を試してみたいと思います。
また、検証には以下のドキュメントを参考にしています。

前準備

今回の検証では、以下のような状況を仮定します

  • データアナリストチームと機械学習エンジニアチームの2つのチームが存在する

  • それぞれのチームに必要なデータセットのみ表示する

    • データアナリストチームが必要なデータセット: da_dataset
    • 機械学習エンジニアチームが必要なデータセット: ml_dataset
  • 不要なデータセットの表示を制限するためにチーム毎にタグを作成し、IAM Conditionsの設定をする

これらの仮定を踏まえた上で検証に必要なリソースを作成します。

サービスアカウントを発行

各チーム向けにサービスアカウントを発行します。
以下のようにデータアナリストチーム向けにdata-analyst、機械学習エンジニアチーム向けにmachine-learningと名付けたサービスアカウントを作成しました。

それぞれのサービスアカウントにプロジェクトレベルでBigQuery ジョブユーザーBigQuery データ閲覧者の権限を付与します。

それぞれの権限を簡単に振り返っておきましょう

  • BigQuery ジョブユーザー
    • ジョブを実行する権限。SELECT 1 + 1のようなクエリを実行することができるようになる
    • この権限単体ではテーブルへのアクセスは不可能
  • BigQuery データ閲覧者
    • テーブルを参照するための権限。プロジェクト単位、データセット単位、テーブル単位で権限を付与することが可能
    • BigQuery ジョブユーザーの権限と一緒に付与することでテーブルにクエリを実行することが可能になる

データセットを作成

次に各チームが参照するテーブルを配置するデータセットを作成します。
以下のようにda_datasetml_datasetの2つ作成しました。

続いて、サンプル用のテーブルを以下のクエリで作成します。

CREATE TABLE ml_dataset.sample AS
SELECT
  1 AS id,
  100 AS sales;

CREATE TABLE da_dataset.sample AS
SELECT
  1 AS id,
  100 AS sales;

タグを作成

IAM Conditionで制限をかけるためのタグを作成します。
タグと似たものにラベルが存在しますが、ラベルではIAM Conditionで制限をかけることができません。
タグとラベルの違いについては以下のリンクを確認してください。

IAM と 管理からタグを選択します。

タグキーの作成を選択します。

タグキーをteamでタグの値をdamlで登録します。

作成したタグは以下のとおりです。
タグキーIDタグ値IDはあとで使用するため別途控えておきましょう。

データセットにタグを付与する

次に作成したダグをデータセットに付与します。
付与したいデータセットの開き、右上の詳細を編集を選択します。

次にタグの欄のスコープの選択から現在のプロジェクトを選択を選択します。

前準備で作成したタグキーと値を選択します。
以下の例では対象のデータセットがml_datasetでしたのでタグの値をmlで登録しています。
同様にデータアナリストのデータセットにもタグを付与しておきます。

IAM Conditionの設定

IAM と 管理からIAMを選択し、先ほど作成したサービスアカウントの右側のペンマークを選択します。

次にBigQuery データ閲覧者の横にあるIAMの条件を追加を選択します。

適当にタイトルを入力し、条件タイプにタグ、演算子に値IDがある、キーIDと値IDに先ほど控えたIDを入力します。

もう一方のサービスアカウントにも同様の設定をします。

これで全ての前準備が終わりました。
今度は実際に各サービスアカウントでデータセットが表示されるか、クエリが実行できるかを確認してみたいと思います。

検証

まずは機械学習チームのサービスアカウントで挙動を確認してみます。

$ bq ls

datasetId   
------------ 
ml_dataset

想定通り、ml_datasetのみ表示されました。
クエリも実行してみます。

$ bq query --nouse_legacy_sql \
'SELECT
   *
 FROM
   ml_dataset.sample'

+----+-------+
| id | sales |
+----+-------+
|  1 |   100 |
+----+-------+

こちらも想定通りの結果が返ってきました。
次は試しにデータアナリストチームのテーブルにクエリを投げてみます。

$ bq query --nouse_legacy_sql \
'SELECT
   *
 FROM
   da_dataset.sample'

> Access Denied: Table <PROJECT_ID>:da_dataset.sample: User does not have permission to query table <PROJECT_ID>:da_dataset.sample, or perhaps it does not exist in location asia-northeast1.

こちらも想定通り、エラーが返ってきました。

全く逆のことをデータアナリストチームのサービスアカウントでの実行してみましたが、同じ結果が返ってきました。

気になった点

今回は1つのキーに対し、複数の値を設定する方法でダグを作成しました。
しかし、この方法だと **ひとつのデータセットに対し、複数のチームの参照許可(= 複数のチームのダグを付与)することが出来ないと判明しました。

先ほどの例だと、あるデータセットにDAMLの2つのタグを付与することで双方のチームから参照を許可するようにしたいと思いましたが、以下のように同じキーを付与することは不可能です。

解決策として、キーを分けることも現実的には可能だと思いますが、キーの管理が大変になりそうだなと思いました。

まとめ

今回はタグを利用したデータセットへのアクセスを制限する方法を紹介しました。
まだプレビュー機能ですが、似たような方法でテーブルへのアクセス制限もできるようになってますので併せて確認してみてください。