Snowflake Data Clean Rooms: PythonUDTFベースのセキュアなテンプレート

このトピックでは、クリーンルームをプログラムで設定し、コンシューマと共有し、クリーンルームにロードされたセキュアなPython UDTFsを使うことによって分析を実行するために必要なプロバイダーとコンシューマーのフローについて説明します。このフローでは、プロバイダーは、APIを使って、UDTFの安全なPythonコードをクリーンルームに読み込みます。これにより、基礎となるPythonコードをコンシューマーから完全に機密扱いとできます。プロバイダーは、コンシューマーが呼び出すためのシンプルなテンプレートを公開することで、コンシューマーがUDTFにアクセスできるようにします。これにより、コンシューマーがプロバイダーの意図した方法でのみ使用していることを確認できます。

このフローが他の例より優れている点は、以下の通りです。

  1. プロバイダー:

    a.機密Python UDTFを新しいクリーンルームに安全に読み込みます。

    b.Python UDTFを呼び出すシンプルなカスタムSQL Jinja テンプレートを作成します。

    c.コンシューマーと共有してください。

  2. コンシューマー:

    a.クリーンルーム内でプロバイダーが提供するテンプレートを調べます(注:基礎となるPythonコードは完全に機密です。SQL Jinjaテンプレートだけが表示されます)。

    b.UDTFを使用してクリーンルーム内で分析を実行します。

このトピックでは、UDTFsを使用した簡単な例について説明します。Python UDFs機械学習のためのPythonを使った、より複雑な例もあります。

前提条件

このフローを完了するには、2つの別々のSnowflakeアカウントが必要です。プロバイダーのコマンドを実行するために最初のアカウントを使用し、コンシューマーのコマンドを実行するために2番目のアカウントに切り替えます。

プロバイダー

注釈

以下のコマンドは、プロバイダーアカウントのSnowflakeワークシートで実行する必要があります。

環境の設定

開発者APIsを使用してSnowflake Data Clean Roomで作業する前に、以下のコマンドを実行してSnowflake環境をセットアップします。SAMOOHA_APP_ROLEロールを持ってない場合は、アカウント管理者にお問い合わせください。

use role samooha_app_role;
use warehouse app_wh;
Copy

クリーンルームの作成

クリーンルームの名称を作成します。既存のクリーンルーム名との衝突を避けるため、新しいクリーンルーム名を入力してください。クリーンルームの名前に使用できるのは 英数字 のみです。クリーンルーム名には、スペースとアンダースコア以外の特殊文字は使用できません。

set cleanroom_name = 'Custom Secure Python UDTF Demo Clean room';
Copy

上記で設定したクリーンルーム名で新しいクリーンルームを作成できます。上記で設定したクリーンルーム名が既にデフォルトのクリーンルームとして存在する場合、この処理は失敗します。

この手順の実行には約45秒かかります。

provider.cleanroom_init の2番目の引数は、クリーンルームのディストリビューションです。これはINTERNALまたはEXTERNALのいずれかです。テスト目的で、同じ組織内のアカウントにクリーンルームを共有する場合、INTERNALを使用して、アプリケーションパッケージがコラボレーターにリリースされる前に実施されなければならない自動セキュリティスキャンをバイパスすることができます。ただし、このクリーンルームを別の組織のアカウントと共有する場合は、EXTERNALクリーンルーム配布を使用する必要があります。

call samooha_by_snowflake_local_db.provider.cleanroom_init($cleanroom_name, 'INTERNAL');
Copy

セキュリティスキャンのステータスを表示するには、以下を使用します。

call samooha_by_snowflake_local_db.provider.view_cleanroom_scan_status($cleanroom_name);
Copy

クリーンルームを作成したら、コラボレーターと共有する前にリリースディレクティブを設定する必要があります。しかし、ディストリビューションがEXTERNALに設定されている場合は、リリースディレクティブを設定する前に、まずセキュリティスキャンが完了するのを待つ必要があります。スキャンの実行中に残りのステップを実行し続け、 provider.create_cleanroom_listing ステップの前にここに戻ることができます。

リリースディレクティブを設定するには、次のようにします。

call samooha_by_snowflake_local_db.provider.set_default_release_directive($cleanroom_name, 'V1_0', '0');
Copy

クロスリージョンの共有

顧客のアカウントと異なる地域にアカウントを持つSnowflakeの顧客とクリーンルームを共有するには、Cross-Cloud Auto-Fulfillmentを有効にする必要があります。他地域のコンシューマーとの協業に関連する追加コストについては、Cross-Cloud Auto-Fulfillment costsをご参照ください。

開発者APIsを使用する場合、クロスリージョン共有を有効にするには2つのステップがあります。

  1. ACCOUNTADMINロールを持つSnowflake管理者は、Snowflake アカウントのクロスクラウド自動複製を有効にします。手順については、異なるリージョンのアカウントと連携するをご参照ください。

  2. プロバイダーは、 provider.enable_laf_for_cleanroom コマンドを実行して、クリーンルームのクロスクラウド自動複製を有効にします。例:

    call samooha_by_snowflake_local_db.provider.enable_laf_for_cleanroom($cleanroom_name);
    
    Copy

クリーンルームのクロスクラウド自動複製を有効にした後、 provider.create_cleanroom_listing コマンドを使用して、通常通りリストにコンシューマーを追加できます。リストは、必要に応じて自動的にリモートクラウドやリージョンに複製されます。

カスタムPythonコードをUDFsとしてクリーンルームに秘密裏にロードする

このセクションでは、顧客の年齢と活動日数を取り込み、年齢を10年に、日数を年に変換する単純なPython UDTFを読み込みます。

次のAPIを使うことにより、Python関数をインライン関数としてクリーンルームに直接定義することができます。あるいは、クリーンルームステージにアップロードしたステージングされたファイルからPythonをロードすることもできます。例については[API リファレンスガイド](../provider)をご参照ください。

call samooha_by_snowflake_local_db.provider.load_python_into_cleanroom(
    $cleanroom_name,
    'mod_days_and_age',                     -- Name of the UDF
    ['age integer', 'days integer'],        -- Arguments of the UDF, specified as (variable name, variable type)
    ['pandas', 'numpy'],                    -- Packages UDF will use
    'table(decade integer, years float)',   -- Return type of UDF
    'ModifyAgeAndDays',                     -- Handler
    $$
import pandas as pd
import numpy as np

class ModifyAgeAndDays:
    def __init__(self):
        self.year = 365

    def process(self, age, days):
        rounded_age = int(np.floor(age / 10)) * 10
        years = np.round(days / self.year)
        yield (rounded_age, years)
    $$
);
Copy

注釈

Pythonをクリーンルームにロードすると、クリーンルーム用の新しいパッチが作成されます。クリーンルームのディストリビューションがEXTERNALに設定されている場合は、セキュリ ティスキャンが完了するのを待ってから、デフォルトのリリースディレクティブを更新する必要があります。

-- See the versions available inside the clean room
show versions in application package samooha_cleanroom_Custom_Secure_Python_UDTF_Demo_clean_room;

-- Once the security scan is approved, update the release directive to the latest version
call samooha_by_snowflake_local_db.provider.set_default_release_directive($cleanroom_name, 'V1_0', '1');
Copy

UDTFsを使用してカスタムテンプレートを追加する

クリーンルームにカスタム分析テンプレートを追加するには、プロバイダー側とコンシューマー側の両方でテーブル名のプレースホルダーとプロバイダー側の結合列が必要です。SQL Jinjaテンプレートでは、これらのプレースホルダーは次のものである必要があります。

  • source_table:プロバイダーのテーブル名の 配列

  • my_table:コンシューマーのテーブル名の 配列

テーブル名は、これらの変数を使用して動的にすることができますが、クリーンルームにリンクされた表示名を使用して、必要に応じてテンプレートにハードコード化することもできます。列名はテンプレートにハードコード化することも、パラメーターで動的に設定することもできます。パラメーターを使用して設定する場合は、列ポリシーと照合するために、パラメーターの dimensions または measure_column を配列として呼び出す必要があることにご留意ください。これらを SQL Jinjaパラメーターとしてテンプレートに追加します。これらは後でクエリ時にコンシューマーから渡されます。結合ポリシーは、許可された列以外の列でコンシューマーにより結合できないようにします。

また、SQL Jinjaテンプレートのカスタム引数は、以下のフィルターを使用して、結合および列のポリシーに準拠しているかどうかを確認することができます。

  • join_policy: 文字列値またはフィルター句が結合ポリシーに準拠しているかどうかを確認します。

  • column_policy: 文字列値またはフィルター句が列ポリシーに準拠しているかどうかを確認します。

  • join_and_column_policy: フィルター句で結合に使用される列が結合ポリシーに準拠しているか、また、フィルターとして使用される列が列ポリシーに準拠しているかを確認します。

たとえば、 {{provider_id | sqlsafe | join_policy }} 句では、 p.HEM の入力が解析され、 p.HEM が結合ポリシーにあるかどうかが確認されます。注意: sqlsafe フィルターでは、コラボレーターが純粋な SQL をテンプレートに入れることができるため、使用には注意してください。

注釈

クリーンルームに実際にリンクされているセキュアビューの名前はテーブル名と異なるため、すべてのプロバイダー/コンシューマーテーブルは、これらの引数を使用して参照する必要があります。重要なのは、プロバイダーテーブルのエイリアスはp(またはp1)、p2、p3、p4などにする 必要 があり、コンシューマーテーブルのエイリアスはc(またはc1)、c2、c3などにする 必要 があるということです。これは、クリーンルームでセキュリティポリシーを実施するために必要です。

この関数は、同じ名前の既存のテンプレートを上書きすることに注意してください。既存のテンプレートを更新したい場合は、更新されたテンプレートでこの関数を再度呼び出します。

このテンプレートは単に顧客のテーブルをスキャンし、数十年単位で年齢を、年単位でアクティブな日数を返します。

call samooha_by_snowflake_local_db.provider.add_custom_sql_template(
    $cleanroom_name,
    'prod_custom_udtf_age_days',
$$
    select decade, years from identifier({{ source_table[0] }}) p, table(cleanroom.mod_days_and_age(identifier({{ dimensions[0] | column_policy }}), identifier({{ dimensions[1] | column_policy }})));
$$
);
Copy

OPTIONAL:UDTFを使用した、より複雑なカスタムテンプレート。

このテンプレートは、UDTFを内部結合に適用し、オーバーラップから追加データを取得する前に、まずコンシューマテーブルとプロバイダーテーブルのオーバーラップを行います。

call samooha_by_snowflake_local_db.provider.add_custom_sql_template(
    $cleanroom_name,
    'prod_custom_udtf_age_days_with_overlap',
$$
    select 
        c.status,
        decade, 
        avg(years) as years,
        sum(c.days_active) as days_active_c
    from 
        identifier({{ source_table[0] }}) p 
        inner join 
        identifier({{ my_table[0] }}) c
        on p.hem = c.hem,
        table(cleanroom.mod_days_and_age(identifier({{ dimensions[0] | column_policy }}), identifier({{ dimensions[1] | column_policy }})))
    group by c.status, decade
    order by c.status, decade
$$
);
Copy

追加されたテンプレートの表示

クリーンルームで現在有効なテンプレートを表示したい場合は、以下の手順を呼び出します。

call samooha_by_snowflake_local_db.provider.view_added_templates($cleanroom_name);
Copy

各テーブルに列ポリシーを設定する

テーブル内の列を確認するためにリンクされたデータを表示します。上位10行を表示するには、以下のプロシージャを呼び出します。

select * from SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS limit 10;
Copy

コンシューマーがグループ化、集計(例:SUM/AVG)、および一般的に分析で使用できる列を、テーブルとテンプレートの組み合わせごとに設定します。これにより柔軟性が生まれ、同じテーブルでも基礎となるテンプレートによって異なる列選択が可能になります。これはテンプレートを追加した後にのみ呼び出されるべきです。

列ポリシーは 置換のみ であることに注意してください。したがって、この関数が再度呼び出された場合、以前に設定された列ポリシーは新しいものに完全に置き換えられます。

列ポリシーは、email、HEM、RampIDなどのID列では使用しないでください。コンシューマーがこれらの列でグループ化できないようにするためです。実稼働環境では、システムはインテリジェントにPII列を推測し、この操作をブロックしますが、この機能はサンドボックス環境では利用できません。これは、Status、Age Band、Channel、Days Activeなどのように、コンシューマーに集計やグループ化してもらう列にのみ使用してください。

「column_policy」と「join_policy」がコンシューマー分析リクエストのチェックを実行するために、SQL Jinjaテンプレートでは、すべての列名が dimensions または measure_columns として参照される必要があることに注意してください。カスタムSQL Jinjaテンプレートでチェックする列を参照するには、必ずこれらのタグを使用してください。

call samooha_by_snowflake_local_db.provider.set_column_policy($cleanroom_name, [
    'prod_custom_udtf_age_days:SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS:AGE_BAND', 
    'prod_custom_udtf_age_days:SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS:DAYS_ACTIVE',
    'prod_custom_udtf_age_days_with_overlap:SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS:AGE_BAND', 
    'prod_custom_udtf_age_days_with_overlap:SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS:DAYS_ACTIVE'
]);
Copy

テンプレートの追加された列ポリシーを表示するには、以下のプロシージャを呼び出します。

call samooha_by_snowflake_local_db.provider.view_column_policy($cleanroom_name);
Copy

コンシューマーと共有する

最後に、以下のようにSnowflakeアカウントロケータとアカウント名を追加して、データコンシューマーをクリーンルームに追加します。Snowflakeアカウント名は<ORGANIZATION>.<ACCOUNT_NAME>の形式である必要があります。

注釈

以下のプロシージャを呼び出すには、最初に provider.set_default_release_directive を使用してリリースディレクティブを設定していることを確認してください。次を使用した最新のバージョンとパッチが表示されます。

show versions in application package samooha_cleanroom_Custom_Secure_Python_UDTF_Demo_clean_room;
Copy
call samooha_by_snowflake_local_db.provider.add_consumers($cleanroom_name, '<CONSMUMER_ACCOUNT_LOCATOR>');
Copy

複数のコンシューマーアカウントロケーターを、カンマ区切りの文字列として provider.add_consumers 関数に渡すことも、 provider.add_consumers を個別に呼び出すこともできます。

このクリーンルームに追加されたコンシューマーを表示したい場合は、次の手順を呼び出します。

call samooha_by_snowflake_local_db.provider.view_consumers($cleanroom_name);
Copy

以下の手順で最近作成されたクリーンルームを表示します。

call samooha_by_snowflake_local_db.provider.view_cleanrooms();
Copy

最近作られたクリーンルームの詳細を、以下の手順で表示します。

call samooha_by_snowflake_local_db.provider.describe_cleanroom($cleanroom_name);
Copy

作成されたクリーンルームは削除することもできます。次のコマンドはクリーンルームを完全に削除するので、以前クリーンルームにアクセスしていたコンシューマーはもうクリーンルームを使用することができません。将来、同じ名前のクリーンルームが必要な場合は、上記のフローを使用して再初期化する必要があります。

call samooha_by_snowflake_local_db.provider.drop_cleanroom($cleanroom_name);
Copy

注釈

これでプロバイダーフローは終了です。コンシューマーアカウントに切り替えて、コンシューマーフローを継続してください。

コンシューマー

注釈

以下のコマンドは、コンシューマーアカウントのSnowflakeワークシートで実行する必要があります。

環境の設定

開発者APIsを使用してSnowflake Data Clean Roomで作業する前に、以下のコマンドを実行してSnowflake環境をセットアップします。SAMOOHA_APP_ROLEロールを持ってない場合は、アカウント管理者にお問い合わせください。

use role samooha_app_role;
use warehouse app_wh;
Copy

クリーンルームをインストールする

クリーンルーム共有がインストールされると、利用可能なクリーンルームのリストは、以下のコマンドを使用して表示することができます。

call samooha_by_snowflake_local_db.consumer.view_cleanrooms();
Copy

プロバイダーが共有したクリーンルームの名前を割り当てます。

set cleanroom_name = 'Custom Secure Python UDTF Demo Clean room';
Copy

以下のコマンドは、関連するプロバイダーと選択されたクリーンルームを持つコンシューマーアカウントにクリーンルームをインストールします。

この手順の実行には約45秒かかります。

call samooha_by_snowflake_local_db.consumer.install_cleanroom($cleanroom_name, '<PROVIDER_ACCOUNT_LOCATOR>');
Copy

クリーンルームが設置されると、プロバイダーはクリーンルームの使用を可能にする前に、プロバイダー側でクリーンルームの設定を完了しなければなりません。以下の関数でクリーンルームのステータスを確認できます。有効化されると、以下のRun Analysisコマンドを実行できるようになります。クリーンルームが有効になるまで、通常約1分かかります。

call samooha_by_snowflake_local_db.consumer.is_enabled($cleanroom_name);
Copy

分析を実行する

クリーンルームがインストールされたので、プロバイダーがクリーンルームに追加した分析テ ンプレートを"run_analysis "コマンドを使って実行できます。各フィールドがどのように決定されるかについては、以下のセクションをご参照ください。

通過可能なデータセットの数は、プロバイダーが実装したテンプレートによって制限されます。テンプレートによっては、特定のテーブル数を必要とする場合があります。テンプレート作成者は、サポートしたい要件を課すことができます。

注釈

分析を実行する前に、ウェアハウスサイズを変更したり、テーブルが大きい場合は新しい大きなウェアハウスサイズを使用することができます。

call samooha_by_snowflake_local_db.consumer.run_analysis(
    $cleanroom_name,
    'prod_custom_udtf_age_days',
    [],                                         -- The consumer tables go here
    ['SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS'], -- The provider tables go here
    object_construct(
        'dimensions', ['p.age_band', 'p.days_active']  -- Any parameters the template needs will go here
    )
);
Copy

データセットのフィルタリング"where_clause"、ディメンションまたはmeasure_columnsのいずれかを参照する必要がある各列について、プロバイダーテーブルのフィールドを参照するにはp.を、コンシューマーテーブルのフィールドを参照するにはc.を使用できます。複数のプロバイダーテーブルにはp2、p3などを、複数のコンシューマーテーブルにはc2、c3などを使用してください。

OPTIONAL:分析の実行

次のrun_analysis呼び出しは、最初にオーバーラップを実行するオプションの例の結果を取得します。まず、以下の手順でデータセットをクリーンルームにリンクする必要があります。

call samooha_by_snowflake_local_db.consumer.link_datasets($cleanroom_name, ['SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS']);
Copy

注釈

テーブルが存在するにもかかわらずこの手順がうまくいかない場合、SAMOOHA_APP_ROLEロールにまだアクセス権が与えられていない可能性があります。もしそうであれば、ACCOUNTADMINロールに切り替え、データベース上で以下のプロシージャを呼び出します。

use role accountadmin;
call samooha_by_snowflake_local_db.consumer.register_db('<DATABASE_NAME>');
use role samooha_app_role;
Copy

これで分析を実行できます。

call samooha_by_snowflake_local_db.consumer.run_analysis(
    $cleanroom_name,
    'prod_custom_udtf_age_days_with_overlap',
    ['SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS'],  -- The consumer tables go here
    ['SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS'], -- The provider tables go here
    object_construct(
        'dimensions', ['p.age_band', 'p.days_active']  -- Any parameters the template needs will go here
    )
);
Copy

データセットのフィルタリング"where_clause"、ディメンションまたはmeasure_columnsのいずれかを参照する必要がある各列について、プロバイダーテーブルのフィールドを参照するにはp.を、コンシューマーテーブルのフィールドを参照するにはc.を使用できます。複数のプロバイダーテーブルにはp2、p3などを、複数のコンシューマーテーブルにはc2、c3などを使用してください。

run_analysisの入力を決定する方法

分析を実行するには、run_analysis関数にいくつかのパラメータを渡す必要があります。このセクションでは、どのようなパラメータを渡すかを決定する方法を説明します。

テンプレート名

まず、以下のプロシージャを呼び出すことで、サポートされている分析テンプレートを確認できます。

call samooha_by_snowflake_local_db.consumer.view_added_templates($cleanroom_name);
Copy

テンプレートを使って分析を実行する前に、どのような引数を指定し、どのような型が期待されるかを知っておく必要があります。カスタムテンプレートについては、以下のように実行できます。

call samooha_by_snowflake_local_db.consumer.view_template_definition($cleanroom_name, 'prod_custom_udtf_age_days');
Copy

これには、異なるSQL Jinjaのパラメータが大量に含まれることもあります。以下の機能は、SQL Jinjaテンプレートを解析し、run_analysisで指定する必要がある引数をリストに抽出します。

call samooha_by_snowflake_local_db.consumer.get_arguments_from_template($cleanroom_name, 'prod_custom_udtf_age_days');
Copy

データセット名

プロバイダーによってクリーンルームに追加されたデータセット名を表示したい場合は、次の手順を呼び出します。クリーンルームのセキュリティ特性上、プロバイダーがクリーンルームに追加したデータセットは表示できません。

call samooha_by_snowflake_local_db.consumer.view_provider_datasets($cleanroom_name);
Copy

また、クリーンルームにリンクしたテーブルは、以下の呼び出しで確認することができます。

call samooha_by_snowflake_local_db.consumer.view_consumer_datasets($cleanroom_name);
Copy

列のディメンションと測定

分析を実行する際、特定の列でフィルタリング、グループ化、集計を行いたい場合があります。プロバイダーによってクリーンルームに追加された列ポリシーを表示したい場合は、次の手順を呼び出します。

call samooha_by_snowflake_local_db.consumer.view_provider_column_policy($cleanroom_name);
Copy

よくあるエラー

実行分析の結果、 Not approved: unauthorized columns used エラーが表示される場合は、プロバイダーが設定した結合ポリシーと列ポリシーを再度表示することが推奨されます。

call samooha_by_snowflake_local_db.consumer.view_provider_join_policy($cleanroom_name);
call samooha_by_snowflake_local_db.consumer.view_provider_column_policy($cleanroom_name);
Copy

また、プライバシーの予算を使い果たしたため、これ以上クエリを実行できなくなる可能性もあります。残りのプライバシー予算は以下のコマンドで表示できます。毎日リセットされますが、クリーンルームのプロバイダーが希望すればリセットすることもできます。

call samooha_by_snowflake_local_db.consumer.view_remaining_privacy_budget($cleanroom_name);
Copy

差分プライバシーがクリーンルームで有効になっているかどうかは、次のAPIで確認できます。

call samooha_by_snowflake_local_db.consumer.is_dp_enabled($cleanroom_name);
Copy