安全なビューの使用

このトピックでは、ビューおよびマテリアライズドビューを安全なものとして定義するための概念と構文について説明します。

このトピックの内容:

安全なビューの概要

安全なビューを使用する理由

一部のビューの内部最適化では、ビューのベーステーブルの基になるデータへのアクセスが必要です。このアクセスにより、ビューのユーザーから隠されたデータが、ユーザー定義関数や他のプログラムによるメソッドなどのユーザーコードを通じて公開される可能性があります。安全なビューはこれらの最適化を利用せず、ユーザーが基礎となるデータにアクセスできないようにします。

さらに、デフォルトでは、ビュー定義またはテキストとも呼ばれる標準ビューの作成に使用されるクエリ式は、さまざまなコマンドとインターフェイスでユーザーに表示されます。詳細については、 安全なビューとの対話 (このトピック内)をご参照ください。

セキュリティまたはプライバシー上の理由から、ビューの基礎となるテーブルや内部構造の詳細を公開したくない場合があります。保護されたビューでは、ビューの定義と詳細は承認されたユーザー(つまり、ビューを所有するロールを付与されたユーザー)にのみ表示されます。

安全なビューはいつ使用しますか?

ビューは、データプライバシーのために特に指定されている場合に、安全であると定義される必要があります(つまり、基になるテーブルのすべてのユーザーに公開されるべきではない機密データへのアクセスを制限するため)。

安全なビューは、ユーザーが基礎となるデータ表現を理解する必要のない、クエリデータを簡素化するために作成されたビューなど、クエリの利便性のために定義されたビューには使用 しないでください。これは、Snowflakeクエリオプティマイザーが安全なビューを評価するときに、通常のビューに使用される特定の最適化をバイパスするからです。これにより、安全なビューのクエリパフォーマンスに何らかの影響が生じる可能性があります。

ちなみに

安全なビューを使用するかどうかを決定するときは、ビューの目的を考慮し、データのプライバシー/セキュリティとクエリパフォーマンスのトレードオフを検討する必要があります。

安全でないビューでは、データがどのように公開される可能性がありますか?

次のウィジェットの例を使用して、ごく一部のウィジェットのみにアクセスできるユーザーを考えてみましょう。これらのウィジェットはすべて赤です。ユーザーが紫色のウィジェットが存在するかどうか疑問に思い、次のクエリを発行するとします。

select *
from widgets_view
where 1/iff(color = 'Purple', 0, 1) = 1;

widgets_view が安全なビューでない場合、現在のユーザーがそのウィジェットにアクセスできない場合でも、紫色のウィジェットが存在する場合、このクエリはエラーを生成する可能性があります。エラー生成は、クエリオプティマイザーが承認述語( IN サブクエリ内)の前または後にユーザーのフィルターを評価するかどうかに依存します。 widgets_view が安全なビューである場合、クエリオプティマイザーは承認述語の前にユーザーのフィルターを評価しません。

安全なビューの作成

安全なビューは、ビューの標準 DDL で SECURE キーワードを使用して定義されます。

  • 安全なビューを作成するには、 CREATE VIEW または CREATE MATERIALIZED VIEW コマンドで SECURE キーワードを指定します。

  • 既存のビューを安全なビューに変換して通常のビューに戻すには、 ALTER VIEW または ALTER MATERIALIZED VIEW コマンドで SECURE キーワードを設定/設定解除します。

安全なビューとの対話

安全なビューの定義の表示

安全なビューの定義は、許可されたユーザー(つまり、ビューを所有するロールを付与されたユーザー)にのみ公開されます。権限のないユーザーが次のコマンドまたはインターフェイスを使用する場合、ビュー定義は表示されません。

ビューが安全かどうかを判断する

非マテリアライズドビューの場合、情報スキーマビューおよびアカウント使用状況ビューの IS_SECURE 列は、ビューが安全かどうかを識別します。例えば、 mydb データベースの MYVIEW という名前のビューの場合:

select table_catalog, table_schema, table_name, is_secure from mydb.information_schema.views where table_name = 'MYVIEW';

select table_catalog, table_schema, table_name, is_secure from snowflake.account_usage.views where table_name = 'MYVIEW';

または、 SHOW VIEWS コマンドを使用して同様の情報を表示できます(ビュー名では大文字と小文字が区別されないことに注意)。

SHOW VIEWS LIKE 'myview';

マテリアライズドビューの場合は、 SHOW MATERIALIZED VIEWS コマンドを使用して、ビューが安全かどうかを識別します。例:

SHOW MATERIALIZED VIEWS LIKE 'my_mv';

クエリプロファイルでのセキュリティビューの詳細の表示

安全なビューの内部は、 クエリプロファイル (ウェブインターフェイス内)で公開されません。非所有者は所有者のクエリプロファイルにアクセスできるため、これは安全なビューの所有者にも当てはまります。

Snowflakeアクセス制御で安全なビューを使用する

ビューセキュリティは、 CURRENT_ROLE および CURRENT_USER コンテキスト関数を使用してSnowflakeユーザーおよびロールと統合できます。次の例は、ロールを使用してテーブルの行へのアクセスを制御する方法を示しています。この例では、データ(widgets)を含むテーブルに加えて、アクセステーブル(widget_access_rules)を使用して、どのロールがデータテーブルのどの行にアクセスできるかを追跡します。

注釈

この例では、 widgets および widget_access_rules テーブルが既に存在することを前提としています。テーブルを作成したり、テーブルにデータを入力したりするための構文は提供しません。

desc table widgets;

------------+-------------------+--------+-------+---------+-------------+------------+--------+------------+---------+
    name    |       type        |  kind  | null? | default | primary key | unique key | check  | expression | comment |
------------+-------------------+--------+-------+---------+-------------+------------+--------+------------+---------+
 ID         | NUMBER(38,0)      | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
 NAME       | VARCHAR(16777216) | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
 COLOR      | VARCHAR(16777216) | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
 PRICE      | NUMBER(38,0)      | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
 CREATED_ON | TIMESTAMP_LTZ(9)  | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
------------+-------------------+--------+-------+---------+-------------+------------+--------+------------+---------+

desc table widget_access_rules;

-----------+-------------------+--------+-------+---------+-------------+------------+--------+------------+---------+
   name    |       type        |  kind  | null? | default | primary key | unique key | check  | expression | comment |
-----------+-------------------+--------+-------+---------+-------------+------------+--------+------------+---------+
 WIDGET_ID | NUMBER(38,0)      | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
 ROLE_NAME | VARCHAR(16777216) | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
-----------+-------------------+--------+-------+---------+-------------+------------+--------+------------+---------+

create or replace secure view widgets_view as
select w.*
from widgets w
where w.id in (select widget_id
               from widget_access_rules a
               where upper(role_name) = CURRENT_ROLE());

安全なビューを使用するためのベストプラクティス

安全なビューは、ビューによってフィルタリングされたテーブルの行のデータがユーザーに表示される可能性を防ぎます。ただし、ビューを慎重に構築しないと、データ所有者が基礎となるデータに関する情報を誤って公開してしまう可能性はまだあります。このセクションでは、回避すべき潜在的な落とし穴について説明します。

これらの落とし穴を説明するために、このセクションでは、このトピックの前の例で定義されたサンプル widgets テーブルとビューを使用します。

シーケンス生成列

代理キーを生成する一般的な方法は、シーケンス列または自動インクリメント列を使用することです。これらのキーが、基礎となるデータのすべてにアクセスできないユーザーに公開されている場合、ユーザーは基礎となるデータ分布の詳細を推測できる可能性があります。たとえば、 widgets_view は ID 列を公開します。シーケンスから ID が生成される場合、 widgets_view のユーザーは、ユーザーがアクセスできる2つのウィジェットの作成タイムスタンプ間に作成されたウィジェットの総数を推測できます。次のクエリと結果について考慮しましょう。

select * from widgets_view order by created_on;

------+-----------------------+-------+-------+-------------------------------+
  ID  |         NAME          | COLOR | PRICE |          CREATED_ON           |
------+-----------------------+-------+-------+-------------------------------+
...
 315  | Small round widget    | Red   | 1     | 2017-01-07 15:22:14.810 -0700 |
 1455 | Small cylinder widget | Blue  | 2     | 2017-01-15 03:00:12.106 -0700 |
...

結果に基づいて、ユーザーは1139ウィジェット(1455 - 315)が1月7日から1月15日の間に作成されたと疑う可能性があります。この情報が機密性が高すぎてビューのユーザーに公開できない場合、次のいずれかの方法を使用できます:

  • シーケンス生成列をビューの一部として公開しない。

  • シーケンスによって生成された値の代わりに、ランダム化された識別子( UUID_STRING によって生成など)を使用する。

  • プログラムで識別子を難読化する。

スキャンデータサイズ

安全なビューを含むクエリの場合、Snowflakeはスキャンされたデータの量(バイトまたはマイクロパーティションのいずれか)またはデータの合計量を公開しません。これは、データのサブセットにのみアクセスできるユーザーから情報を保護するためです。ただし、ユーザーはクエリのパフォーマンス特性に基づいて、基礎となるデータの量について観察することができます。例えば、2倍の長さで実行されるクエリは、2倍のデータを処理する可能性があります。そのような観察結果は良くても概算程度ですが、場合によっては、このレベルの情報でさえ公開されることは望ましくありません。

このような場合、ベースデータのビューをユーザーに公開するのではなく、ユーザー/ロールごとにデータを具体化するのが最適です。 widgets テーブルの場合、ウィジェットにアクセスできる各ロールに対してテーブルが作成され、そのロールからアクセス可能なウィジェットのみが含まれ、ロールにはそのテーブルへのアクセスが許可されます。これは、単一のビューを使用するよりもはるかに複雑ですが、非常に高いセキュリティの状況では、これが必要になる場合があります。

安全なビューおよびデータ共有

Snowflakeでのデータの安全な共有 で安全なビューを使用する場合は、 CURRENT_ACCOUNT 関数を使用して、特定のアカウントのユーザーにベーステーブルの行へのアクセスを許可できます。

注釈

共有されるデータの所有者は通常、共有されているアカウントのロールとユーザーを制御しないため、Snowflakeは、他のアカウントと共有される安全なビューで CURRENT_ROLE または CURRENT_USER を使用することを許可しません。