外部アクセス統合の作成と使用

特定の外部ネットワークロケーションへのアクセスを有効にするには、外部ロケーションを指定するネットワークルールのリストと使用を許可されるシークレットのリストを指定する外部アクセス統合を作成します。UDF の作成時、あるいは CREATEFUNCTION または CREATEPROCEDURE でプロシージャを作成する際に、 EXTERNAL_ACCESS_INTEGRATIONS 句を使用してこの統合を参照することで、ハンドラーコードが外部ロケーションとの認証コードにシークレットを使用できるようになります。

管理者は EXTERNAL_ACCESS_HISTORY ビューを使うことで、外部ネットワークロケーションへのリクエストをモニターできます。

外部アクセスの設定と使用に使用するコード例のエンドツーエンドシークエンスについては、 外部ネットワークアクセスの例 をご参照ください。

以下のステップを使用して、 UDF から、またはプロシージャから外部ネットワークロケーションへのアクセスを設定します。

  1. 外部ネットワークロケーションを表すネットワークルール を作成します。

  2. 認証情報を保持するためにシークレット を作成します。

  3. 外部アクセス統合 を作成し、シークレットとネットワークルールを集約して、ハンドラーが外部ロケーションにアクセスする際に使用できるようにします。

  4. UDF またはプロシージャを値として統合名に設定された EXTERNAL_ACCESS_INTEGRATIONS パラメーターセットで作成します。これにより、関数またはプロシージャに、外部のネットワークロケーションにアクセスし、統合のネットワークルールとシークレットで指定された認証情報を使用する許可が与えられます。

    ハンドラーコードからシークレットのコンテンツにアクセスできるように、 SECRET パラメーターに統合に含まれるシークレットの名前を別途設定します。

    関数またはプロシージャのハンドラーコードで、統合に含まれるネットワークルールで指定された外部ネットワークロケーションにアクセスします。許可されたネットワークルールで指定されていないネットワークロケーションへのアクセスは拒否されます。

外部ネットワークロケーションを表すネットワークルールの作成

CREATE NETWORK RULE コマンドを使って、外部ネットワークロケーションとアクセス制限を表すネットワークルールを作成することができます。例えば、ネットワークルールで、ホスト名などのネットワーク識別子や、ネットワークとの通信方向(イングレスまたはエグレス)を指定します。

外部ネットワークへのアクセスをサポートするために、管理者は 外部アクセス統合 を作成する際にこのルールを含めます。統合に含まれる各ルールは、関数またはプロシージャがアクセスを許可される外部ネットワークロケーションを指定します。

外部アクセス統合で使用するネットワークルールを作成する際は、以下を指定します。

  • MODE パラメーター値としての EGRESS。

  • TYPE パラメーター値としての HOST_PORT。

  • VALUE_LIST パラメーターの外部ロケーションのエンドポイント。

  • (オプション)外部ロケーションのエンドポイント名があるポート番号。ポート番号を省略すると、Snowflakeは外部アクセス用のデフォルトのポート番号443を使用します。

    例えば、エンドポイントがポート80を必要とする場合、VALUE_LIST パラメーターは以下のようになります。

    VALUE_LIST = ('example.com:80')
    
    Copy

アクセス制御

セキュリティのため、Snowflakeではネットワークルールを作成する際に、以下の権限を持つロールを使用する必要があります。

  • ルールを保持するスキーマに対する CREATE NETWORK RULE 権限。

次の例のコードは、Google翻訳 API へのアウトバウンドリクエスト用に google_apis_network_rule というネットワークルールを作成します。

CREATE OR REPLACE NETWORK RULE google_apis_network_rule
  MODE = EGRESS
  TYPE = HOST_PORT
  VALUE_LIST = ('translation.googleapis.com');
Copy

認証情報を表すシークレットの作成

CREATE SECRET を使用して、外部ネットワークロケーションとの認証に必要な認証情報を表すシークレットを作成することができます。例えば、シークレットにはユーザー名やパスワードなどの認証情報を含めることができます。

OAuth をサポートする外部ネットワークロケーションにアクセスする場合のベストプラクティスは、クライアント ID、クライアントシークレット、トークンエンドポイントなどの OAuth フローに必要な値を含む セキュリティ統合 への参照をシークレットに含めることです。

このシークレットは以下のような目的で使用されます。

  • 管理者が 外部アクセス統合 を作成する場合。

    統合を作成する場合、管理者は、開発者が統合を使用する関数やプロシージャを作成する際に、ハンドラーコードで使用できるシークレットを指定します。

  • 開発者が UDF またはプロシージャハンドラーを作成する場合。

    開発者は、外部ロケーションに対するリクエストを行う際にハンドラーコードが認証に使うことができる認証情報を含む、許可されたシークレットを指定します。ハンドラーを記述する際、開発者はハンドラーコードにリテラル値として認証情報を含めるのではなく、Snowflake API を使用してシークレットに含まれる認証情報を取得することができます。

注釈

リフレッシュトークンを必要とする OAuth シークレットについては、Snowflakeで利用可能なシステム関数など、複数の方法でトークンを取得できます。例については、 Google翻訳 API へのアクセス をご参照ください。

アクセス制御

セキュリティのため、Snowflakeではシークレットを作成する際、以下の権限を持つロールを使用する必要があります。

  • シークレットを保持するスキーマに対する CREATE SECRET 権限。

次の例のコードでは、 oauth_token というシークレットを作成し、 OAuth を使った認証に必要な値を含むセキュリティ統合(google_translate_oauth で表される)を指定します。

セキュリティ統合を作成するコードを含む、より完全な例については、 外部ネットワークアクセスの例 をご参照ください。

CREATE OR REPLACE SECRET oauth_token
  TYPE = OAUTH2
  API_AUTHENTICATION = google_translate_oauth
  OAUTH_REFRESH_TOKEN = 'my-refresh-token';
Copy

ちなみに

このプレビューでは、 TYPEGENERIC_STRING として指定することで、 API キーだけを認証情報として使用することができます。

CREATE OR REPLACE SECRET bp_maps_api
  TYPE = GENERIC_STRING
  SECRET_STRING = 'replace-with-your-api-key';
Copy

外部アクセス統合の作成

CREATE EXTERNAL ACCESS INTEGRATION コマンドを使用すると、 UDFs とプロシージャで使用するために、許可されたネットワークルール(外部ネットワークロケーションを表す)と許可されたシークレット(認証用の認証情報を表す)を集約した外部アクセス統合を作成できます。

特に、外部アクセス統合は、 UDFs とその統合を参照するプロシージャが使用できるネットワークルールとシークレットを指定します。

外部アクセス統合は、管理者が UDFs とプロシージャから外部ネットワークロケーションへのアクセスを管理するために使用します。統合は、 UDFs と統合を参照するプロシージャによって使用が許可されるロケーションと認証情報のみを指定します。管理者は、外部ロケーションへのアクセスを管理するために、統合を有効にしたり無効にしたりすることもできます。

アクセス制御

セキュリティのため、Snowflakeでは外部アクセス統合を作成する際に、以下の権限を持つロールを使用する必要があります。

  • アカウントに対する CREATE INTEGRATION 権限。

  • 統合が使用するシークレットに対する USAGE 権限と、シークレットのスキーマに対する USAGE 権限。

以下の例のコードは、 google_apis_access_integration という外部アクセス統合を作成します。統合は google_apis_network_rule ネットワークルール(ネットワークロケーションを表す)と oauth_token シークレット(認証情報を表す)を指定します。

このルールとシークレットの詳細については、 外部ネットワークロケーションを表すネットワークルールの作成認証情報を表すシークレットの作成 をご参照ください。

CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION google_apis_access_integration
  ALLOWED_NETWORK_RULES = (google_apis_network_rule)
  ALLOWED_AUTHENTICATION_SECRETS = (oauth_token)
  ENABLED = true;
Copy

関数またはプロシージャでの外部アクセス統合の使用

CREATE FUNCTION または CREATE PROCEDURE コマンドを使用して UDF またはプロシージャを作成する場合、以下のように外部ネットワークロケーションへのアクセスを有効にすることができます。

  • EXTERNAL_ACCESS_INTEGRATIONS パラメーターを含め、その値を1つ以上の統合に設定します。

    指定した各統合は、統合が指定した外部ネットワークロケーションとシークレットへのアクセスを許可します。

  • SECRETS パラメーターを含め、その値に1つ以上のシークレットと、ハンドラーコードからそれらにアクセスするために使う名前を設定します。

    値として指定するシークレットは、外部アクセス統合でも指定する必要があります。

  • ハンドラーコードで、シークレットにアクセスし、外部ネットワークロケーションで認証するための認証情報を取得します。

注釈

認証情報をコード内のリテラル値として含めるのではなく、常にSnowflakeシークレットを使用して認証情報を表します。認証情報の保護に加え、シークレットを使用することで、認証情報の使用を監査および管理することが可能になります。これは、シークレットの READ 権限を付与された人物だけが、 UDF またはプロシージャでそれを含む統合を加えて使用できるからです。

Snowflakeでは、特定の UDF から行うことができる接続の総数を制限しています。リソースの枯渇の問題を避けるために、接続はできるだけ再利用してください。これは、 TCP クライアントまたはセッションを UDF 初期化中に一度だけ作成し、 UDF ハンドラーで残りのクエリに使用することで達成できます。

アクセス制御

セキュリティのため、Snowflakeでは UDF またはプロシージャを作成する際に、以下の権限を持つロールを使用する必要があります。

  • 参照するシークレットに対する READ 権限と、シークレットのスキーマに対する USAGE 権限。

  • 参照する統合に対する USAGE 権限。

これらの権限を要求することで、管理者は外部アクセスを有効にできるユーザーのセットを管理することができます。詳細については、 GRANT <権限>アクセス制御権限 をご参照ください。

次の例のコードは、 UDF を google_translate_python という名前で作成し、 google_apis_access_integration という外部アクセス統合を指定します(詳細については、 外部アクセス統合の作成 をご参照ください)。統合は、統合を参照する UDF が使用を許可されるネットワークルール(外部ネットワークロケーションを表す)とシークレット(認証情報を表す)を指定します。このルールとシークレットの詳細については、 外部ネットワークロケーションを表すネットワークルールの作成認証情報を表すシークレットの作成 をご参照ください。

Pythonのハンドラーコードは _snowflake.get_oauth_access_token 関数を使用して OAuth トークンをシークレットから取得し、トークンを使用して外部ロケーションで認証を行います。URL のホストが統合で指定されたネットワークルールに記載されているため、ハンドラーコードは指定された URL にリクエストを行う可能性があります。

CREATE OR REPLACE FUNCTION google_translate_python(sentence STRING, language STRING)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = 3.8
HANDLER = 'get_translation'
EXTERNAL_ACCESS_INTEGRATIONS = (google_apis_access_integration)
PACKAGES = ('snowflake-snowpark-python','requests')
SECRETS = ('cred' = oauth_token )
AS
$$
import _snowflake
import requests
import json
session = requests.Session()
def get_translation(sentence, language):
  token = _snowflake.get_oauth_access_token('cred')
  url = "https://translation.googleapis.com/language/translate/v2"
  data = {'q': sentence,'target': language}
  response = session.post(url, json = data, headers = {"Authorization": "Bearer " + token})
  return response.json()['data']['translations'][0]['translatedText']
$$;
Copy