BigQueryの列レベル・行レベルのセキュリティを解説

記事タイトルとURLをコピーする

G-genの杉村です。 BigQueryでは 列レベル および 行レベル でアクセスポリシーを設定し、アクセス制限を行うことができます。この機能について解説します。

BigQuery

列レベルのセキュリティ

列レベルのセキュリティとは

BigQuery の 列レベルのセキュリティ (column-level security) 機能は、列に事前定義した ポリシータグ を付与することで、特定の Google アカウントやグループだけが列にアクセスできるようにする仕組みです。
当機能は「列レベルのアクセス制御 (column-level access control) 」 とも呼称されます。

例として、 BigQuery テーブルの個人情報を含む列に security-level : high のようなタグを付与し、このタグがついている列には manager@example.com グループのメンバーしかアクセスできないようにする、といったことが可能です。

アクセスポリシーは SQL を実行する際に評価され、許可されていないメンバーからのクエリは Access Denied として拒否されます。

列レベルのセキュリティ

分類 (Taxonomy) とポリシータグ

列レベルのセキュリティ機能では事前に Data Catalog サービスで 分類 (Taxonomy) を作成します。

分類の中には複数のポリシータグを収容可能です。

作成したポリシータグには IAM ロールを紐づけることができます。
ポリシータグに対して、アカウントやグループと Fine-Grained Reader (きめ細かい読み取り) ロール等を紐づけることで、そのポリシータグがアタッチされた列へのアクセスを許可することが可能です。

分類とポリシータグ

このポリシータグをテーブルの列ヘアタッチすることで、適切な IAM ロールと紐付けられたアカウントやグループのみが列へアクセスできるようになります。

列へポリシータグをアタッチ

なお、ポリシータグには「子タグ」を作ることができ、5段階までネストできます。
親のタグへのアクセス権限を持っていれば、子タグへのアクセス権限を持っているのと同じになります (IAM 権限の 継承)。

制限

列レベルセキュリティには以下のような制限があります。

  • 列にはポリシータグを 1 つしかアタッチできない
  • 1 テーブルにアタッチ可能なポリシータグの種類は最大 1,000 まで
  • ポリシータグが一つでもついているとそのテーブルには Legacy SQL が使えなくなる

特に1つ目の「ある列にはポリシータグを 1 つしかアタッチできない」という制限があるため、アクセス制御が複雑になりすぎないように分類とポリシータグ作成には工夫が必要です。

行レベルのセキュリティ

行レベルのセキュリティとは

行レベルのセキュリティ (row-level security) 機能は、テーブルに 行レベルアクセスポリシー を作成することで、アカウントやグループに対して 特定の値を持った列にだけアクセスできるように制限する 機能です。

例として、顧客情報のうち地域情報を含む region 列の値が Kanto なら関東地域担当のセールスチームにだけ行が見えるようにし、関西担当チームからは見えないようにする、といったことが可能です。

アクセスポリシーは SQL を実行する際に評価され、許可されていない行はクエリ結果から取り除かれます。

行レベルのセキュリティ

行レベルアクセスポリシー

行レベルアクセスポリシーDDL で作成します。
(権限付与なので DCL と呼ぶのでは、とも一瞬思われますが、 CREATE 文なので DDL 扱い)

以下のようになります。

CREATE ROW ACCESS POLICY region
ON `myproject.mydataset.user_table`
GRANT TO ("group:team-kanto@example.com")
FILTER USING (region = "Kanto");

FILTER 句の部分に WHERE 句に相当する文を入れることで、許可対象の行が持つ値を指定できます。

また以下のような指定も可能です。

CREATE ROW ACCESS POLICY region
ON `myproject.mydataset.employee_table`
GRANT TO ("domain:example.com")
FILTER USING ( emp_email = SESSION_USER() );

上の例では FILTER 句で指定する emp_email 列の値を SESSION_USER() としています。
これは BigQuery の SESSION_USER 関数 です。
上記の例は従業員が自分のデータだけを社員一覧テーブルから抜き出せるようなことを想定しています。

このように BigQuery の組み込み関数を利用することも可能です。

制限

行レベルセキュリティを使用すると、クエリの際に特定の行しか見えなくなることから主にパフォーマンス面の弊害があることに注意が必要です。

  • パーティショニングやクラスタリング による高速化が期待できなくなり、フルスキャンになってしまう
  • マテリアライズド・ビューへのクエリでも、ソーステーブルに行レベルセキュリティが使われていると、ソーステーブルへのクエリになる
  • BigQuery BI Engine のキャッシュが効かなくなる
  • クエリパフォーマンスが若干低下する

列レベルセキュリティ vs 行レベルセキュリティ

列レベルセキュリティ機能と行レベルセキュリティ機能は一見よく似ていますが、ユースケースの違いは明白です。

特定のアカウント・グループに列ごと見せたくないときには列レベルセキュリティ機能を使います。
個人情報が入っている列、見せたくない情報が入っている列などです。

一方で、列全体ではなく、列の値によって見せる行を分けたいときに行レベルセキュリティ機能を使います。
ただし、行レベルセキュリティ機能を使うとパーティショニングやクラスタリングによるフルスキャン回避が効かなくなりパフォーマンス低下が起きることに十分留意しなくてはいけません。
場合によってはアクセスユースケースによってテーブル自体を分け、テーブルへの読み取り権限を IAM で制限するなど工夫する必要があるかもしれません。

杉村 勇馬 (記事一覧)

執行役員 CTO / クラウドソリューション部 部長

元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 12資格、Google Cloud認定資格11資格。X (旧 Twitter) では Google Cloud や AWS のアップデート情報をつぶやいています。