ブログ

Blog

絞り込んで表示する

2020.12.17 - 

BigQueryのデータのアクセス権限

この記事は BigQuery Advent Calendar 11日目の投稿となります。

みなさん、こんにちは。グルーヴノーツのなかむらと申します。
BigQueryが好き過ぎて、なんだかんだやっていたらGoogle Developers Expertというになっております。

そんなこんなでBigQueryのおかげで毎日楽しいデータ生活を送っているのですが、データを扱うところでは楽しいだけではやっていけません。個人であれば公開するのも良いでしょうが、企業となればやはり厳重に管理するものとなっております。

そこでBigQueryではどのようにデータを守ることができるのか?そのあたりを書いていきたいと思います。

※注:執筆当時はまだ新しいUIが降ってきていないので、旧UIで解説となります。ご容赦ください。ほんとごめんなさいごめんなさいごめんなさい。おれだって早く欲しいのですよ。ほん(ry

1.BigQueryでの機能

BigQueryではデータを守るために以下のような機能が備わっています。
これらを順に解説していきます。

  • アクセス権の設定
    以下の単位できめ細やかにアクセス権を設定することができます。
    • データセット
    • テーブル
    • 行(AuthorizedViewで解説します)

  • 制御しながらデータを見せる
    アクセス権とは違い、クエリの結果しか見せない、暗号化してしまうということもできます。
    • AuthorizedView
    • 暗号化関数

  • 監査ログ
    誰がいつ、どこで、何をしたかの監査ログを取ることができます。
    • Cloud Logging(今回はこちらはお話ししませんが、大事です!)

2.アクセス権の設定

様々な単位でアクセス権を設定できますが、実際の企業では人のアカウントごとに設定していては大変です。
そんなときはGoogle GroupやGoogle Workspaceのドメインなど、グループごとに割り当てるのが良いと思います。

データのアクセス権とジョブ(クエリ)の設定について

そうそう。アクセス権の設定の前にこれを先に話しておかねば。
BigQueryでは、データにアクセスする権限と、ジョブ(クエリ)を発行する権限が明確に分かれています。前者はBigQueryでデータセットやテーブルに対して付与します。後者はIAMでプロジェクトに対して付与します。

最初のうちは、この点を理解しきれず、「アクセスできない」とか「クエリできない」と悩んだものです。しかし、一度わかると非常に理にかなった機能の分離だと思います。

とても理解しやすいのは、Googleが当初から用意している bigquery-public-data です。GCPを契約した人、全員のアクセス権を登録しているわけではないです。誰でもアクセスできる = 公開しているというわけです。では、ここでのクエリ課金はどういう仕組みになっているでしょうか? もちろん、自分が権限を与えられたプロジェクト(複数指定可)に課金されるわけです。

つまり、一部のデータだけを社外の取引先に公開して、『みたいだけ見るがよい。でもクエリ課金はあなたのプロジェクトでよろしくね!』っていうことができるのです。CSVでダウンロード? APIでデータ取得? 古い!! BigQueryでデータ共有したからそこ見てね! あとはクエリであろうが、データポータルであろうが煮るなり焼くなりコロ助なり。でいいんじゃないですか? (他のサービスでこんなことできるのかしら?)

わたしもお国のデータがBigQueryにあればなぁってことで、個人的にこんなデータを公開しています(そろそろ更新したり、追加したりしないとなぁ)。

ロールについて

では、本題に戻って。
ユーザーに対してプロジェクトとBigQueryにロールというものを割り当てていきます。ロールとは色々な権限がまとまってセットされているものです。GCPコンソールの"IAMと管理 → ロール"で確認してみてください。様々な権限が割り当てられています。
デフォルトでパターンがいくつか用意されています。もちろん自分でも作ることができます。

プロジェクト(IAM)でユーザーに割り当てるもの

  • BigQueryジョブユーザー
    設定されたプロジェクトのBigQueryでジョブ(クエリ)を発行することができます。つまり、どこのデータを見ようが、ここで設定されたプロジェクトに課金されます。クエリを発行する人には設定してあげましょう。

  • BigQueryユーザー
    上記に加え、設定されたプロジェクトのBigQueryのデータセットやテーブルの一覧、データは見れませんが設定されている情報を見ることができます。しかし、BigQuery Storage API経由ではデータを取得することができます(ちょっと疑問、なんでだろ?)。 正直、あんまり使ったことないです...。

  • BigQuery管理者
    BigQueryに対して何でもできます。読んで字の如し管理者にだけ割り当てましょう。

 

BigQuery(データセット・テーブル)でユーザーに割り当てるもの

  • BigQueryデータ閲覧者
    設定されたデータセットやテーブルのデータ・メタデータを閲覧することができます。スケジュールされたクエリも見れます。データセットに付与されている場合は、その中のテーブルの一覧も閲覧することができます。
    データを見る人にはこれだけで十分だと思います。

  • BigQueryデータ編集者
    上記に加えて、テーブルやデータの作成・更新・削除、タグ付けなどが行えます。スケジュールされたクエリも作成できます。
    データを入れ込んだり、編集したり、スケジュールクエリをセットしたりする人にはこれが必要です。

  • BigQueryデータオーナー
    上記に加えて共有設定やデータセットの削除が行えます。データの管理者に対して付与します。

 

その他(カスタムロール)

ロールを自分で作ることも可能です。例えばデータをロードするだけのバッチをサービスアカウントで運用したとします。それに対してBigQueryデータ編集者を割り当ててしまうと、データの読み込み権限まで与えられているので、そのサービスアカウントを使っていたずらされる可能性がありますよね?
じゃ、どうすれば良いかというとデータをロードするだけの最小限の権限をロールで設定し、付与すればデータを見られる心配はありません。
このようにきめ細かに設定することも可能です。

データセットとテーブル

ユーザーに対してデータセットへ権限を付与した場合は、その配下のテーブルへも同様の権限が継承されます。
しかし、その中でもあるテーブルだけは編集権限を持たせたいといった場合は、そのテーブルだけに対してBigQueryデータ編集者を付与すれば実現できます。
テーブルだけに付与すれば、そのテーブルしか見ることができません。データセットすら見れないし、その中のテーブル一覧も見えません。

データセットに対して付与した場合

こんな感じで見えます(当たり前なんですけどね)。

テーブルに付与した場合

では、データセットに対する権限を外してこのうちのproduct_masterだけに権限を付与してみましょう。

はい、何も見えません。データセットすら見えませんね。しかし、共有されたテーブルにクエリを発行するときちんと結果が表示されます。

データセットには閲覧権限を、テーブルには編集権限を

では、データセットには閲覧権限を付与しますが、product_masterだけに編集権限を付与してみましょう。
まずはproduct_masterにupdateが実行できるか確認してみましょう。

大丈夫っぽいですね。

では、product_receiptにupdateが実行できるか確認してみましょう。

はい。残念ながら権限がないと言われてupdateすることができませんでしたね。

このように、あるテーブルのみ編集権限を付与するなど柔軟に設定することができます。どんなときに使うの?ってよく聞かれますが、あるキャンペーンの商品一覧(5千点あるとか)だけを抽出したいなどという場合に、自由にテーブルの中のデータを操れるようにするために使ったりします。

列について

列ごとに権限を付与することができます。例えば、テーブル内の仕入れ情報は見せたくない、個人情報は見せたくないなど様々にあると思います。
これはData Catalogのポリシータグを利用して設定することが可能です。こちらは手順を交えて説明します。

 

ポリシータグの一覧画面

GCPのコンソールからData Catalogの画面に遷移して、ポリシータグの一覧を表示します。

ポリシータグの作成

一覧画面から作成をクリックします。

分類名や説明、ポリシータグ(分類について複数設定可)を入力して保存をクリック。

作成した分類の内容が表示されます。
アクセス制御の適用をオンにすると、BigQueryでこのタグを設定した列はアクセスすることができなくなります。
とりあえずオンにしてみましょう。

BigQueryの列に適用

テーブルのスキーマ編集画面で適用したいフィールド名(列名)を選択して、ポリシータグを追加をクリックします。

先ほどData Catalogで設定したポリシータグが表示されますので、設定したいものを選んで、ページ下部の選択ボタンをクリックします。

スキーマ編集画面に戻るので保存をクリックしてください。(コレ忘れがち!
するとポリシータグに追加されているのがわかります。ちなみに設定した本人(管理者でも)もいきなり見れなくなりますので注意してください。

テーブルのプレビューでも表示されません。

見れるようにするには?

Data Catalogのポリシータグで権限を付与するユーザーを設定します。
まずは付与するタグにチェックを入れます。するとユーザーを追加するメニューが表示されますので、メンバーを追加をクリック。

新しいメンバーに閲覧を許可するユーザーのメールアドレスを入力します。

ロールの設定でデータカタログ→きめ細かい読み取りを設定、保存をクリックします。(ここよく忘れるので注意)。

すると、設定したユーザーはアラートなど出ずにデータを見ることができます。

制御しながらデータを見せる

合計はOKだけど生データは見せたくない、そもそも持っているデータ自体を暗号化したいなどあると思います。
ここではそのあたりを解説していきます。

AuthorizedView

Viewとはあらかじめ設定したクエリの結果をテーブルのように見せる仕組みです。
AuthorizedViewでは、そのViewに対してデータの閲覧権限を設定します。よって、そのViewの閲覧権限をユーザーに付与すればデータも見れるということになります。
例えば商品ごとに集計した下記のようなクエリをViewにして、view_datasetという違うデータセットに保存します。

SELECT
re.product_code ,
ma.product_name ,
ma.company_name ,
sum(re.qty),
sum(re.price * qty)
FROM
`project-data-share.acl_data.product_receipt` as re
JOIN
`project-data-share.acl_data.product_master` as ma
ON
re.product_code = ma.product_code
JOIN
`project-data-share.acl_data.company_master` as com
ON
ma.company_name = com.company_name
WHERE
SESSION_USER() = com.email
GROUP BY
re.product_code,
ma.product_name ,
ma.company_name

そして、このもとのデータが入っているデータセットの「承認済みビューの共有」で、このViewを選択して追加をクリック。下の完了ボタンをクリックします。

では、データセットに権限をセットしてきましたが、削除してみて生データが入っているテーブルにクエリを発行してみましょう。

はい。エラーになりました。当たり前ですね。権限ないのですから。
では、Viewを保存した方のデータセットに閲覧権限を付与して、そのViewに対してクエリを発行してみましょう。

できましたね!
このようにある一定の期間だけ見せたいとか、見せるデータを絞りたいとか、色々な使い方ができると思います。
部門ごとに見せるデータを分けるためにわざわざ新しいテーブルを作るよりも、こちらの方が効率的じゃないかな?って思います。

行レベルでの権限

このAuthorizedViewを利用してクエリを発行したユーザー(emailアドレス)によって行レベルでデータを見せる、見せないの設定ができます。
先ほどはすべての商品の合計を見ることができました。次は、ユーザーが持っている商品の合計のみを見せてみようと思います。

商品マスタはこんな感じのテーブルです。会社名が入っていますね。

で、会社のマスタにアクセスするユーザーの情報(emailアドレス)を付与したテーブルを準備します。(今回は柔軟にできるようにスプレッドシートを外部テーブルとして使っています。)

で、Viewに設定するクエリはこんな感じです。

SELECT
re.product_code ,
ma.product_name ,
ma.company_name ,
sum(re.qty),
sum(re.price * qty)
FROM
`project-data-share.acl_data.product_receipt` as re
JOIN
`project-data-share.acl_data.product_master` as ma
ON
re.product_code = ma.product_code
JOIN
`project-data-share.acl_data.company_master` as com
ON
ma.company_name = com.company_name
WHERE
SESSION_USER() = com.email
GROUP BY
re.product_code,
ma.product_name ,
ma.company_name

クエリ自体は長々となっていますが、何も難しいことはやっていません。ポイントは SESSION_USER() = com.email これです。
これがいまアクセスしているユーザーの情報を取得して、そのemailでフィルタしているというものになります。

では、やってみましょう。

bq.acl.test@gmail.comはyy野菜に設定されていたので、そこのデータしかみれていませんね。素晴らしい。
ちなみにさっき、会社のアドレスも設定していたので、それもやっておきましょう。

ちゃんとxx商事がでました。大丈夫ですね。

このような感じで、ある特定のデータしか見せたくないなどの場合に便利に使えると思います。
でも、あくまでフィルタしているだけなので課金は全部のデータに対してかかりますよ。そのあたりはclustered tableなどを上手く使ってくださいね。

暗号化関数

BigQueryには暗号化関数が用意されています。それを用いて、データの暗号化と復号をやっていきましょう。
まずはproduct_codeとそれに対応したkeyのデータを生成したテーブルを作成します。

CREATE OR REPLACE TABLE
`project-data-share.acl_data.product_key` AS
SELECT
product_code,
KEYS.NEW_KEYSET('AEAD_AES_GCM_256') AS keyset
FROM
`project-data-share.acl_data.product_master`

ここで作成したkeyを使って、そこからproduct_masterのcompany_nameを暗号化したテーブルを作成します。

CREATE OR REPLACE TABLE
`project-data-share.acl_data.enc_product_master` AS
SELECT
product_code,
product_name,
AEAD.ENCRYPT( (
SELECT
keyset
FROM
`project-data-share.acl_data.product_key` AS key
WHERE
key.product_code = ma.product_code),
ma.company_name,
ma.product_code) AS enc_com_name,
cost
FROM
`project-data-share.acl_data.product_master` AS ma

company_nameが暗号化されましたね。
では、これを復号してみましょう。暗号化したものと似ていますね。

SELECT
product_code,
product_name,
AEAD.DECRYPT_STRING( (
SELECT
keyset
FROM
`project-data-share.acl_data.product_key` AS key
WHERE
key.product_code = ma.product_code),
ma.enc_com_name,
ma.product_code) AS dec_com_name,
cost
FROM
`project-data-share.acl_data.enc_product_master` AS ma

このようにデータとしては暗号化して持っているが、keyを使うことで復号できるというものです。
どのようなところで使うかというと、例えば個人の住所などもレコードで持っている場合、データは暗号化して保持しておく、必要なときに復号する、ある一定の期間後はkeyのレコードを削除して復号できないようにする、こうすることでレコード全体を削除やデータのアップデートをすることなく必要なデータだけを残しておくことができます。


3.最後に

どうだったでしょうか?色んなデータアクセスの権限があります。
要件や場面によって、使い分けたり組み合わせたりすることでデータを守ることができるかな?と思います。もちろん、これだけでは万全というわけではありません。

データのダウンロードは?エクスポートは?監査は?など、他のもの(Cloud LoggingやCloud Data Loss Prevention, Google Vault)と組み合わせることで強固にできると思います。

まぁ、最終的には人なんですけどね。

と、いうことで楽しく安心できるデータライフを!
(おそくなってごめんなさい。)