セキュアビューの使用

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

このトピックの内容:

セキュアビューの概要

セキュアビューを使用する理由

  • 非セキュアビューの場合は、内部最適化によって間接的にデータが公開される可能性があります。

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

  • 非セキュアビューの場合は、ビュー定義が他のユーザーに表示されます。

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

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

セキュアビューはいつ使用しますか?

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

セキュアビューは、ユーザーが基になるデータ表現を理解する必要のない、クエリデータを簡素化するために作成されたビューなど、クエリの利便性のためにだけに定義されたビューには使用 しないでください。セキュアビューは、非セキュアビューよりも実行速度が遅くなる可能性があります。

ちなみに

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

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

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

SELECT *
    FROM widgets_view
    WHERE 1/iff(color = 'Purple', 0, 1) = 1;

紫色のウィジェットが存在する場合、 IFF() 式は0を返します。次に、ゼロ除算エラーが原因で除算操作に失敗します。これにより、ユーザーは少なくとも1つの紫色のウィジェットが存在すると推測できます。

セキュアビューの作成

セキュアビューは、ビューの標準 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';

Account Usage:

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

(INFORMATION_SCHEMA ビューと ACCOUNT_USAGE ビューの違いに関する一般的な情報については、 Account UsageとInformation Schemaの違い をご参照ください。)

または、 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)を使用して、どのロールがデータテーブルのどの行にアクセスできるかを追跡します。

CREATE TABLE widgets (
    id NUMBER(38,0) DEFAULT widget_id_sequence.nextval, 
    name VARCHAR,
    color VARCHAR,
    price NUMBER(38,0),
    created_on TIMESTAMP_LTZ(9));
CREATE TABLE widget_access_rules (
    widget_id NUMBER(38,0),
    role_name VARCHAR);
CREATE OR REPLACE SECURE VIEW widgets_view AS
    SELECT w.*
        FROM widgets AS w
        WHERE w.id IN (SELECT widget_id
                           FROM widget_access_rules AS a
                           WHERE upper(role_name) = CURRENT_ROLE()
                      )
    ;

WHERE 句は、各ロールが表示できるウィジェットを制限します。

赤色のウィジェットにのみアクセスできるユーザーが、前に示したクエリを実行するとします。

SELECT *
    FROM widgets_view
    WHERE 1/iff(color = 'Purple', 0, 1) = 1;

セキュアビューの WHERE 句は、ユーザーのクエリにある WHERE 句の前に実行されます。紫色のウィジェットはビューによって除外されるため、ユーザーのクエリでゼロ除算エラーが生成されることはありません。

セキュアビューではない場合、Snowflakeオプティマイザーは WHERE句の述語を並べ替えることができます。これにより、ユーザーのクエリの述語が最初に実行され、ゼロ除算エラーが発生する可能性があります。

セキュアビューを使用するためのベストプラクティス

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

これらの落とし穴を説明するために、このセクションでは、このトピックの前の例で定義されたサンプル 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 関数を使用する場合、Snowflakeはこれらの関数に対して NULL 値を返します。なぜなら、共有されるデータの所有者は通常、ビューが共有されるアカウントのユーザーまたはロールを制御しないためです。

最上部に戻る