アプリ間通信

このトピックでは、アプリ間通信(IAC)を使って1つの Snowflake Native App が別の Snowflake Native App と通信する方法を説明します。

アプリ間通信:概要

アプリ間通信(IAC)は、他のアプリが呼び出すことができる関数やプロシージャへのアクセスを提供することにより、 Snowflake Native App が同じコンシューマーアカウントの他の Snowflake Native Apps に追加の機能を提供することを可能にします。

たとえば、カスタマーIDsを解決する Snowflake Native App は、異なるベンダーのデータセットを結合して、他の Snowflake Native Apps がカスタマーデータを強化することをサポートできます。

IACは、2つ以上の独立したアプリが相互に通信するためのインフラストラクチャを提供し、管理とセキュリティのニーズを尊重します。アプリ開発者は、次を実行することでアプリのIACを有効にします。

  • インターフェースの作成

  • アプリロールを使用してインターフェースへのアクセスを制御します。

  • 同期または非同期インタラクションの選択。同期インタラクションは、他のアプリが直接呼び出すことができるストアドプロシージャや関数を使用します。一方、非同期インタラクションは、他のアプリが結果をチェックするためにポーリングできる、テーブルやビューに格納されているリクエスト結果へのアクセスを提供します。

用語

IACは次の用語を使用します。

クライアント

接続リクエストを開始し、サーバーアプリの関数とプロシージャを呼び出すアプリ。

サーバー

アプリロールを使用して、関数やプロシージャへのアクセスを提供するアプリ。

コンシューマー

クライアントおよびサーバーアプリをインストールするユーザー。

アプリケーション構成

またはクライアントアプリがサーバーアプリの名前をリクエストするために使用するSQLオブジェクト。IACは、``APPLICATION_NAME``型のアプリケーション構成を使用して、サーバーアプリ名を保存する。

アプリケーション仕様

クライアントアプリがサーバーアプリへの接続をリクエストするために作成するSQLオブジェクト。IACは、 CONNECTION 型のアプリケーション仕様を使用します。アプリの仕様の詳細については、 アプリ仕様の概要 をご参照ください。

アプリ間通信のワークフロー

接続を確立して使用するには、クライアントアプリとサーバーアプリ間のハンドシェイクプロセスが含まれます。

  1. サーバーアプリプロバイダーからアプリロール名を取得します。クライアントアプリプロバイダーは、Snowflake外部のサーバーアプリプロバイダーと連携し、接続仕様でリクエストするサーバーアプリロールを決定します。

  2. ターゲットアプリを特定 :クライアントアプリは、サーバーアプリの名前をリクエストする構成定義オブジェクトを作成します。コンシューマーは受信リクエストを検出し、構成オブジェクトを通じてサーバーアプリ名をクライアントアプリに提供します。

  3. 接続のリクエストと承認 :クライアントアプリは、サーバーアプリへの接続をリクエストするアプリケーション仕様を作成し、コンシューマーは接続リクエストを承認します。

  4. サーバーアプリとの通信 :クライアントアプリは、サーバーアプリのプロシージャや関数を呼び出します。

ターゲットアプリを特定

クライアントアプリがサーバーアプリと通信する前に、最初にアプリの正確な名前を特定する必要があります。コンシューマーはインストール時にアプリのカスタム名を選択できるため、クライアントアプリはまずサーバーアプリの正確な名前を識別する必要があります。

クライアントアプリのセットアップスクリプトは、 CONFIGURATION DEFINITION オブジェクトを作成してこの情報をリクエストします。

次の例は、クライアントアプリのセットアップスクリプトが CONFIGURATION DEFINITION オブジェクトを作成して、サーバーアプリの名前をリクエストする方法を示しています。

ALTER APPLICATION
  SET CONFIGURATION DEFINITION my_server_app_name_configuration
    TYPE = APPLICATION_NAME
    LABEL = 'Server App'
    DESCRIPTION = 'Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.'
    APPLICATION_ROLES = (my_server_app_role);
Copy

次の例は、コンシューマーが受信構成定義リクエストをどのようにチェックするかを示しています。

SHOW CONFIGURATIONS IN APPLICATION my_server_app_name;
Copy

このコマンドは以下のような結果を返します。

name                             | created_on              | updated_on              | type               | ...
my_server_app_name_configuration | 2026-02-09 10:00:00.000 | 2026-02-09 10:00:00.000 | APPLICATION_NAME   | ...

次に、コンシューマーは次のコマンドを使用してサーバーアプリ名を提供します。

ALTER APPLICATION my_client_app_name
  SET CONFIGURATION my_server_app_name_configuration
  VALUE = MY_SERVER_APP_NAME;
Copy

接続のリクエストと承認

クライアントアプリがサーバーアプリの名前を取得すると、クライアントアプリはサーバーアプリへの接続をリクエストするために:code:`APPLICATION SPECIFICATION`を作成します。アプリケーションロール名は、Snowflakeの外部でのオフライン通信を通じて取得されることに注意してください。

次の例は、 my_server_app_name という名前のサーバーアプリへの接続用に APPLICATION SPECIFICATION を作成する方法を示しています。

ALTER APPLICATION SET SPECIFICATION my_server_app_name_connection_specification
  TYPE = CONNECTION
  LABEL = 'Server App'
  DESCRIPTION = 'Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.'
  SERVER_APPLICATION = MY_SERVER_APP_NAME -- server name obtained from Step 1
  SERVER_APPLICATION_ROLES = (my_server_app_role);
Copy

アプリケーション仕様を作成することにより、クライアントアプリはアプリ仕様で指定されたサーバーアプリロールの付与をリクエストします。

注釈

アプリ仕様の LABEL および DESCRIPTION の値は、ステップ1で作成した CONFIGURATION DEFINITION オブジェクト内の LABEL および DESCRIPTION の値に一致する必要があります。値が一致しない場合、接続は Snowsight に正しく表示されません

効率的な接続ワークフローを作成するには、クライアントアプリにより、before_configuration_change <label-native_apps_configuration_callbacks_before_configuration_change>`同期コールバックでアプリケーション仕様を作成することをお勧めします。このコールバックは、 :code:`ALTER APPLICATION SET CONFIGURATION VALUE コマンドが実行されているときに実行されます。コールバックの詳細については、 コールバック をご参照ください。:ref:`before_configuration_change <label-native_apps_configuration_callbacks_before_configuration_change>`同期コールバック内でアプリケーション仕様を作成するセットアップスクリプトの例については、:ref:`label-native_apps_iac_examples`をご参照ください。

クライアントアプリがアプリ仕様を作成すると、コンシューマーは接続リクエストを確認し、承認または拒否できます。

SQLを使用した接続リクエストの承認

次の例は、SQLを使用してコンシューマーが接続リクエストを承認する方法を示しています。

ALTER APPLICATION my_server_app_name
  APPROVE SPECIFICATION my_server_app_name_connection_specification
  SEQUENCE_NUMBER = 1;
Copy

|sf-web-interface|を使用した接続リクエストの承認

Snowsight で接続リクエストを表示し、承認するには、次の操作を実行します。

  1. Snowsight にサインインします。

  2. アプリを選択します。Configurations`に、:ui:`Application connections`というタイトルのセクションが表示されます。保留中の各接続には、接続の名前またはラベル、接続の簡単な説明、 :ui:`Review ボタンが表示されます。

  3. Review ボタンをクリックします。接続リクエストの詳細が表示されます。

  4. ターゲットアプリを Select from your apps から選択します。

  5. Next をクリックします。次の情報が表示されます。

    • クライアントアプリがサーバーアプリに接続することと、アプリが使用するロールを示す図。

    • 接続の詳細。

    • クライアントアプリに付与されるサーバー権限のサブセット。IACのセキュリティに関する考慮事項については、:ref:`label-native_apps_iac_security_considerations`をご参照ください。

    • Approve Connection のトグルスイッチ。スイッチは On に設定されています。

  6. 接続を承認するには、トグルスイッチを On に設定したままにし、 Save をクリックします。更新された接続リストが表示され、接続のステータスが表示されます。

  7. 接続を拒否するには、トグルスイッチを:ui:`Off`に切り替えます。

  8. 接続を承認または却下せずにレビューページを終了するには、:ui:`Cancel`ボタンをクリックします。

承認後

コンシューマーが接続リクエストを承認すると、 Snowflake Native App Framework は、リクエストされたサーバーアプリのロールをクライアントアプリに付与します。承認はクライアントアプリからサーバーアプリへの USAGE も付与します。これにより、サーバーアプリは、どのクライアントアプリが接続されているかを認識できます。

コンシューマーが接続リクエストを承認すると、クライアントアプリとサーバーアプリで以下のコールバックがそれぞれトリガーされます。

  • :ref:`after_server_connection_change <label-native_apps_connection_callbacks_after_server_connection_change>`がクライアントアプリでトリガーされる

  • :ref:`after_client_connection_change <label-native_apps_connection_callbacks_after_client_connection_change>`がサーバーアプリでトリガーされる

これらのコールバックにより、接続が確立されたときに、サーバーアプリとクライアントアプリは追加のアクションを実行できます。

アプリケーション仕様の承認に関する詳細については、次のトピックをご参照ください。

サーバーアプリとの通信

接続が確立され、クライアントアプリにリクエストされたサーバーアプリのロールが付与されると、クライアントアプリはサーバーアプリと通信できるようになります。

注釈

サーバーアプリのメソッドを呼び出す前に、クライアントアプリは承認されたアプリケーション仕様から実行時にサーバーアプリの名前を取得し、サーバーアプリの名前が変更された場合に正しい名前が使用されるようにする必要があります。次の例は、実行時にサーバーアプリの名前を取得する方法を示しています。

SHOW APPROVED SPECIFICATIONS ->>
  SELECT PARSE_JSON("definition"):"SERVER_APPLICATION"::STRING
  FROM $1
  WHERE "name" = 'MY_SERVER_APP_NAME_CONNECTION_SPECIFICATION';
Copy

クライアントアプリは、サーバーアプリと同期的または非同期的に通信できます。

  • 同期通信では、サーバーアプリのプロシージャや関数を直接呼び出します。

  • 非同期通信では、テーブルなどのデータオブジェクトに格納されているキューを使用します。たとえば、サーバーアプリは、リクエストとしてテーブルに記録を挿入するプロシージャを提供でき、サーバーアプリはこれを定期的に処理します。その後、クライアントアプリは、サーバーが提供する別のプロシージャを使用して、テーブルの結果を確認できます。

次の同期操作の例は、Pythonを使用してサーバーアプリのプロシージャを呼び出すクライアントアプリを示しています。

session.call("server_app_name.customer_schema.get_customer_data", customer_id);
Copy

次の非同期操作の例は、Pythonを使用してサーバーアプリのプロシージャを呼び出すクライアントアプリを示しています。クライアントアプリはサーバーアプリのプロシージャを呼び出し、テーブルにリクエストを作成し、サーバーアプリが処理します。クライアントアプリは、テーブルをポーリングして、結果の更新された記録をチェックすることができます。

session.call("server_app_name.customer_schema.request_customer_data_async", customer_id);
Copy

次に、クライアントアプリはテーブルをポーリングして、結果の更新されたレコードを確認できます。

session.call("server_app_name.customer_schema.check_customer_data_requests_async", customer_id);
Copy

接続の管理

Snowsight で既存の接続を表示するにはの場合は、次の操作を実行します。

  1. Snowsight にサインインします。

  2. ナビゲーションメニューで Catalog » Apps を選択します。

  3. アプリを選択します。すべてのアプリ接続は、 Configurations というタイトルのセクションに表示されます。そのセクションの下には、 Application connections というタイトルのサブセクションがあります。

  4. 接続を変更するには、接続の鉛筆アイコンをクリックします。以下を変更できます。

    • アプリに接続されているアプリ

    • 接続の承認ステータス

  5. 接続済みアプリを表示するには、 View app ボタンをクリックします。

  6. 接続のセキュリティ設定を変更するには、歯車アイコンをクリックします。

セキュリティに関する考慮事項

仕様リクエストを承認する場合、コンシューマーはクライアントアプリにサーバーアプリアクセスを付与すると、クライアントアプリが持つ権限を昇格させる可能性があることに注意する必要があります。たとえば、サーバーアプリに外部アクセスがある場合、クライアントアプリはサーバーアプリを通じてインターネットやその他の外部リソースに間接的にアクセスする可能性があります。サーバーアプリが別のサーバーアプリのクライアントアプリである場合、クライアントアプリは最初のサーバーアプリを通じて他のサーバーアプリのリソースにアクセスできる場合があります。

コンシューマーは接続を承認する前に、サーバーアプリの機能と権限を検査する必要があります。サーバーの機能を検査するには、管理者ロール(例:ACCOUNTADMIN)を使用します。権限の低いロールでサーバーを検査しても、サーバーのすべての機能と権限が明らかになることはありません。コンシューマーは、サーバーアプリのコードがコンシューマーからは見えないこと、そしてコンシューマーが接続を承認した後にサーバーアプリの権限と機能が変更される可能性があることに注意する必要があります。

サーバーアプリの機能と権限を検査するSQLコマンドには以下が含まれますが、これらに限定されません。

  • SHOW GRANTS TO APPLICATION :このコマンドは、クライアントアプリのサーバーアプリに付与された権限を一覧表示します。

  • SHOW PRIVILEGES IN APPLICATION :このコマンドは、クライアントアプリに付与できる潜在的なアカウントレベルの権限をリストします。

  • SHOW REFERENCES IN APPLICATION :このコマンドは、クライアントアプリが付与を使用せずに使用する可能性のある参照をリストします。

  • SHOW SPECIFICATIONS IN APPLICATION :このコマンドは、外部アクセス統合(EAIs)、セキュリティ統合、共有、リスト、接続など、コンシューマーが承認したアプリケーション仕様をリストします。

SQL 参照情報

次のSQLコマンドは、アプリ間の通信を管理するために使用されます。

コールバック

|naf|は、アプリ間の通信ワークフロー管理をしえんするために、ライフサイクルコールバックを提供しています。これらのコールバックにより、アプリは構成、接続、仕様の変更に対応することができます。コールバックを使用するには、アプリのマニフェストファイルの:code:`lifecycle_callbacks`セクションにそれらを登録します。

コールバックに関する一般的な情報については、:doc:`callbacks`をご参照ください。

構成コールバック

これらのコールバックは、構成値が設定または設定解除されたときにトリガーされます。一般的なユースケースとしては、コンシューマーがサーバーアプリ名を提供した際に、:ref:`before_configuration_change <label-native_apps_configuration_callbacks_before_configuration_change>`コールバックを使用して接続仕様を自動的に作成することです。

validate_configuration_change

:code:`ALTER APPLICATION SET CONFIGURATION VALUE`コマンドの一部として呼び出される同期コールバック。アプリが指定された値に対してカスタム検証を実行できるようにします。コールバックがエラーを返す場合、コマンドは失敗し、新しい値は設定されません。

before_configuration_change

:code:`ALTER APPLICATION SET CONFIGURATION VALUE`および:code:`ALTER APPLICATION UNSET CONFIGURATION`コマンドの一部として呼び出される同期コールバック。構成値が保存される前に、アプリが構成値に基づいて操作を実行できるようにします。

after_configuration_change

:code:`ALTER APPLICATION SET CONFIGURATION VALUE`または:code:`ALTER APPLICATION UNSET CONFIGURATION`コマンドの完了後に呼び出される非同期コールバック。通知や追跡などの目的で、アプリが変更に対応できるようにします。

接続コールバック

これらのコールバックは、接続が確立された場合、拒否された場合、接続がドロップされた場合、接続されたアプリが削除された場合など、接続のステータスが変更されたときにトリガーされます。

after_server_connection_change

仕様の承認、却下、またはサーバーアプリの削除など、接続状態に影響する操作によりクライアントアプリでトリガーされる非同期コールバック。

after_client_connection_change

仕様の承認、却下、削除、クライアントアプリの削除など、接続状態に影響する操作によってサーバーアプリでトリガーされる非同期コールバック。

after_server_version_change

サーバーアプリのバージョンまたはパッチ番号が変更された後、クライアントアプリで呼び出される非同期コールバック。これにより、クライアントアプリはアップグレードまたはダウングレードに対応することができます。

次の例は、アプリ間通信を使用するためのアプリの構成方法を示しています。

例:セットアップスクリプトとマニフェストファイル

次の例は、クライアントアプリのセットアップスクリプト( setup.sql )を示しています。

CREATE OR ALTER VERSIONED SCHEMA app_schema;

-- create a callback that creates the connection request before the config value of the server name is saved
CREATE OR REPLACE PROCEDURE app_schema.before_config_change_callback(config_name STRING, config_value STRING)
RETURNS STRING
LANGUAGE SQL
AS
$$
DECLARE
    spec_name VARCHAR;
    existing_target VARCHAR;
BEGIN
    IF (config_value IS NOT NULL AND config_name = 'MY_SERVER_APP_NAME_CONFIGURATION') THEN
        SHOW SPECIFICATIONS;
        SELECT PARSE_JSON("definition"):SERVER_APPLICATION::STRING
            INTO existing_target
            FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));

        IF(existing_target IS NOT NULL AND UPPER(existing_target) != UPPER(config_value)) THEN
            EXECUTE IMMEDIATE 'ALTER APPLICATION DROP SPECIFICATION CONNECTION_' || UPPER(existing_target);
        END IF;

        spec_name := 'CONNECTION_' || UPPER(config_value);
        EXECUTE IMMEDIATE
        'ALTER APPLICATION SET SPECIFICATION ' || spec_name || '
            TYPE = CONNECTION
            LABEL = ''Server App''
            DESCRIPTION = ''Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.''
            SERVER_APPLICATION = ' || config_value || '
            SERVER_APPLICATION_ROLES = (my_server_app_role)';
    END IF;
RETURN 'success';
END;
$$;

CREATE APPLICATION ROLE IF NOT EXISTS client_app_user;
GRANT USAGE ON SCHEMA app_schema TO APPLICATION ROLE client_app_user;
ALTER APPLICATION SET CONFIGURATION DEFINITION my_server_app_name_configuration
    TYPE = APPLICATION_NAME
    LABEL = 'Server App'
    DESCRIPTION = 'Request for an application that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2'
    APPLICATION_ROLES = (client_app_user);
Copy

次の例は、クライアントアプリのマニフェストファイル( manifest.yml )を示しています。

manifest_version: 2

artifacts:
  setup_script: setup.sql

lifecycle_callbacks:
    before_configuration_change: app_schema.before_config_change_callback
Copy

前述のコード例については、次の点に注意してください。

  • :ref:`before_configuration_change <label-native_apps_configuration_callbacks_before_configuration_change>`コールバック内で、アプリは構成の以前の値に一致する既存の接続仕様をチェックし、存在する場合はドロップします。次に、コールバックは、新しく指定されたサーバーアプリ名の新しい接続仕様を作成します。サーバー名が設定されているときに新しい接続を作成すると、接続仕様が重複して作成されなくなります。

例:アプリ間非同期通信

次の例は、サーバーアプリのセットアップスクリプト(setup.sql)を使用して、非同期通信のためのプロシージャを作成する方法を示しています。サーバーアプリは処理待ちキューのテーブルを作成し、アプリロールを通じてクライアントアプリに2つのプロシージャ(キューにリクエストを追加するための``submit_request``、完了したリクエストの結果を取得するための``fetch_response``)を提供します。サーバーアプリは定期的に``process_requests``プロシージャを実行して、保留中のリクエストをすべて処理します。

CREATE TABLE IF NOT EXISTS app_schema.processing_queue (
  request_id NUMBER AUTOINCREMENT,
  operation STRING,
  input STRING,
  status STRING DEFAULT 'PENDING',
  response STRING DEFAULT ''
);

CREATE OR REPLACE PROCEDURE app_schema.submit_request(operation STRING, input STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
BEGIN
    INSERT INTO app_schema.processing_queue (operation, input) VALUES (:operation, :input);
    RETURN 'Request submitted successfully';
END;
$$;

CREATE OR REPLACE PROCEDURE app_schema.process_requests()
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
DECLARE
    -- Cursor to find all PENDING requests
    c1 CURSOR FOR SELECT * FROM app_schema.processing_queue WHERE status = 'PENDING';
    result STRING;
BEGIN
    FOR request IN c1 DO

        IF (request.operation = 'OPERATION_X') THEN
            -- assuming there is a UDF func_x(input) to perform operation_x
            result := (SELECT func_x(:request.input));
        END IF;

        -- update the processing queue with the result
        LET stmt STRING :=
            'UPDATE app_schema.processing_queue SET status = 'DONE', response = ' ||
            result ||
            ' WHERE request_id = ' ||
            request.request_id;
        EXECUTE IMMEDIATE (:stmt);

    END FOR;

    RETURN 'Processed pending requests.';
END;
$$;

CREATE OR REPLACE PROCEDURE app_schema.fetch_response(operation STRING, input STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
BEGIN
    LET res STRING := (SELECT response FROM app_schema.processing_queue WHERE operation = :operation AND input = :input);
    RETURN res;
END;
$$;

CREATE APPLICATION ROLE IF NOT EXISTS my_server_app_role;
GRANT USAGE ON SCHEMA app_schema TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.submit_request(string, string) TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.process_requests() TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.fetch_response(string, string) TO APPLICATION ROLE my_server_app_role;
Copy