外部アクセス統合の作成と使用¶
特定の外部ネットワークロケーションへのアクセスを有効にするには、外部ロケーションを指定するネットワークルールのリストと使用を許可されるシークレットのリストを指定する外部アクセス統合を作成します。UDF の作成時、あるいは CREATEFUNCTION または CREATEPROCEDURE でプロシージャを作成する際に、 EXTERNAL_ACCESS_INTEGRATIONS 句を使用してこの統合を参照することで、ハンドラーコードが外部ロケーションとの認証コードにシークレットを使用できるようになります。
管理者は EXTERNAL_ACCESS_HISTORY ビューを使うことで、外部ネットワークロケーションへのリクエストをモニターできます。
外部アクセスの設定と使用に使用するコード例のエンドツーエンドシークエンスについては、 外部ネットワークアクセスの例 をご参照ください。
以下のステップを使用して、 UDF から、またはプロシージャから外部ネットワークロケーションへのアクセスを設定します。
外部ネットワークロケーションを表すネットワークルール を作成します。
認証情報を保持するためにシークレット を作成します。
外部アクセス統合 を作成し、シークレットとネットワークルールを集約して、ハンドラーが外部ロケーションにアクセスする際に使用できるようにします。
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')
アクセス制御¶
セキュリティのため、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');
認証情報を表すシークレットの作成¶
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';
Tip
このプレビューでは、 TYPE
を GENERIC_STRING
として指定することで、 API キーだけを認証情報として使用することができます。
CREATE OR REPLACE SECRET bp_maps_api
TYPE = GENERIC_STRING
SECRET_STRING = 'replace-with-your-api-key';
外部アクセス統合の作成¶
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;
関数またはプロシージャでの外部アクセス統合の使用¶
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']
$$;