Snowpark Container Services: サービスのその他の考慮事項¶
SQL 実行¶
アプリケーションコンテナがSnowflakeに接続して SQL を実行できます。このトピックでは、コンテナコードが、認証情報、サービスのデータベースとスキーマコンテキスト、 SQL ステートメントの実行に使用されるウェアハウスなど、Snowflakeに接続するために必要な情報を取得する方法について説明します。
認証情報構成オプション¶
Snowflakeは、 SQL を実行するときに、アプリケーションコンテナがSnowflake提供の認証情報を使用してSnowflakeに対して認証することを推奨します。外部アクセス統合(EAI)を介して接続することで、他の認証情報を使用することは可能ですが、 EAI を介して接続する場合、Snowflakeの外部で実行され、インターネット経由でSnowflakeに接続しているかのようにサービスを扱います。
You have three options to connect to Snowflake from a service container:
**Snowflakeが提供するサービスユーザー認証情報を使用する: ** Snowflakeが提供するすべてのサービスに、サービス認証情報と呼ばれる認証情報があります。サービスはこれらの認証情報を使用して、サービスユーザーとしてSnowflakeに接続します。
**Snowflakeが提供する呼び出し元認証情報(呼び出し元権限)を使用する: ** 呼び出し元権限でサービスを構成すると、Snowflakeは呼び出しユーザーとしてSnowflakeに接続するための、サービスの認証情報も提供します。
Use other credentials: In this case, you use an external access integration (EAI) that allows your service to connect to Snowflake's internet endpoint by using valid authentication credentials. This option requires an administrator to create the EAI, and then grant the USAGE privilege on the integration to the service owner role.
注釈
外部アクセス統合を使用してSnowflakeにアクセスすることは、潜在的にセンシティブな情報をインターネット経由で送信することを意味します。
Snowflakeに接続するためにさまざまなSnowflakeドライバーを使用するコードの例については、 Snowflake接続サンプル をご参照ください。
Snowflakeが提供するサービスユーザー認証情報の使用¶
Snowflakeが提供するサービス認証情報を使用する場合は、以下のような影響に注意してください。
Every object in Snowflake has an owner role, which is the role that is used to create the object. A service's owner role determines the capabilities that the service is allowed when it interacts with Snowflake. These capabilities include executing SQL, accessing stages, and performing service-to-service networking.
When you create a service, Snowflake also creates a service user that is specific to that service. That service user has access to only two roles: the service owner role and the 'PUBLIC' role. The default role for the service user is the service owner role.
When you start a service, including job services, Snowflake performs several actions. In each of your application containers, Snowflake enables the container code to use drivers for connecting to Snowflake and executing SQL, which is similar to any other code on your computer connecting to Snowflake. The following list shows the actions that Snowflake performs when you start a service:
Provides credentials (an OAuth token) in the container in a file that is named
/snowflake/session/token. The container code uses these credentials to authenticate as the service user. This OAuth token can't be used outside Snowpark Container ServicesSets the following environment variables for you to configure a Snowflake client in your service code:
SNOWFLAKE_ACCOUNT: This variable is set to the account locator for the Snowflake account that the service is currently running under.
SNOWFLAKE_HOST: This variable provides the hostname that is used to connect to Snowflake.
サービスユーザーとしてSnowflakeへの接続を作成する場合、コンテナコードは SNOWFLAKE_HOST、 SNOWFLAKE_ACCOUNT、および OAuth トークンを使用する必要があります。OAuth トークンは SNOWFLAKE_HOST を使用しないと使用できません。
例
チュートリアル2 (main.py を参照)で、コードは次の例に示すように環境変数を読み取ります。
SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT')
SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
The code passes these variables to a connection creation code for the Snowflake client of choice. The container uses these credentials to create a new session, with the service's owner role as the session's primary role, to run queries. The following example shows the minimum code that you need to create a Snowflake connection in Python:
def get_login_token():
with open('/snowflake/session/token', 'r') as f:
return f.read()
conn = snowflake.connector.connect(
host = os.getenv('SNOWFLAKE_HOST'),
account = os.getenv('SNOWFLAKE_ACCOUNT'),
token = get_login_token(),
authenticator = 'oauth'
)
Be aware of the following details about this OAuth token:
Snowflake refreshes the content of the
/snowflake/session/tokenfile every few minutes. Every token is valid for up to one hour. After a container connects to Snowflake successfully, the expiration time doesn't apply to the connection, as is the case with any sessions that users create directly.This OAuth token is valid only within the specific Snowflake service. You can't copy the OAuth token and use it outside the service.
If you use the OAuth token to connect, it creates a new session. The OAuth token is not associated with any existing SQL session.
注釈
A significant difference between executing stored procedures and executing a service is that stored procedures run in the same session as the SQL that runs the procedures. But every time a container establishes a new connection, you create a new session.
特定のサービスユーザーが発行したクエリを表示するには、 ACCOUNTADMIN ロールを使用して、 クエリ履歴 を表示できます。サービス利用者の利用者名は以下の形式で表示されます。
8.35サーバーリリース以前に作成されたサービスの場合、サービスユーザー名は
SF$SERVICE$unique-idの形式です。8.35サーバーリリース以降に作成されたサービスでは、サービスユーザー名はサービス名と同じです。
注釈
A service's owner role is the role that created the service. You can define one or more service roles to manage access to the endpoints that the service exposes. For more information, see サービス関連権限の管理.
Snowflakeが提供する呼び出し元認証情報(呼び出し元権限)の使用について¶
In certain application scenarios, you might need to execute queries by using the context of the end user rather than the service user as explained in the preceding section. The caller's rights feature is used in this context.
For example, suppose that you create a service that exposes a public endpoint for a web application that displays a dashboard that uses data stored in Snowflake. You grant other users in your Snowflake account access to the dashboard by granting them the service role. When a user signs in, the dashboard displays only the data that user is authorized to access.
However, because containers by default execute queries by using the service user and the service's owner role, the dashboard shows the data that the service's owner role has access to, regardless of which end user connected to the endpoint. As a result, the dashboard isn't limited to the data the end user is authorized to access, allowing the signed-in user to see data they shouldn't have access to.
To limit the dashboard to show only data that is accessible to the signed in user, the application containers must execute SQL by using privileges granted to the end user. You can enable this by using caller's rights in the application.
注釈
The caller's rights feature is supported only when accessing a service using network ingress. The feature isn't available when using a service function to access the service.
呼び出し元権限の機能は現在、 Snowflake Native App (コンテナー付きアプリ)ではサポートされていません。
Configure caller's rights for your service¶
Configuring caller's rights for your application is a two-step procedure.
In the service specification, set the
executeAsCallertotrue, in as shown in the following specification fragment:spec: containers: ... capabilities: securityContext: executeAsCaller: true
This setting tells Snowflake that the application intends to use caller's rights and causes Snowflake to insert the
Sf-Context-Current-User-Tokenheader in every incoming request before sending the request to the application container. This user token facilitates query execution as the calling user. If not specified,executeAsCallerdefaults tofalse.Specifying the
executeAsCalleroption doesn't affect the service's ability to execute queries as the service user and service's owner role. WithexecuteAsCallerenabled, the service has the option to connect to Snowflake both as a calling user and as a service user.To establish a Snowflake connection on behalf of the calling user, update your application code to create a login token that includes both the OAuth token that Snowflake provided to the service and the user token from the
Sf-Context-Current-User-Tokenheader.ログイントークンはこの形式(
<service-oauth-token>.<Sf-Context-Current-User-Token>)に従う必要があります。This update is demonstrated in the following Python code fragment:
# Environment variables below will be automatically populated by Snowflake. SNOWFLAKE_ACCOUNT = os.getenv("SNOWFLAKE_ACCOUNT") SNOWFLAKE_HOST = os.getenv("SNOWFLAKE_HOST") def get_login_token(): with open("/snowflake/session/token", "r") as f: return f.read() def get_connection_params(ingress_user_token = None): # start a Snowflake session as ingress user # (if user token header provided) if ingress_user_token: logger.info("Creating a session on behalf of the current user.") token = get_login_token() + "." + ingress_user_token else: logger.info("Creating a session as the service user.") token = get_login_token() return { "account": SNOWFLAKE_ACCOUNT, "host": SNOWFLAKE_HOST, "authenticator": "oauth", "token": token } def run_query(request, query): ingress_user_token = request.headers.get('Sf-Context-Current-User-Token') # ingress_user_token is None if header not present connection_params = get_connection_params(ingress_user_token) with Session.builder.configs(connection_params).create() as session: # use the session to execute a query.
上記の例では、
get_login_token関数は、コンテナーが使用する OAuth トークンを Snowflake がコピーしたファイルを読み込みます。The
get_connection_paramsfunction constructs a token by concatenating the OAuth token and the user token from theSf-Context-Current-User-Tokenheader. The function includes this token in a dictionary of parameters that the application uses to connect to Snowflake.
注釈
When a service uses caller's rights, it can connect to Snowflake as multiple users. You are responsible for managing access to resources that arn't managed by Snowflake.
For example, in Streamlit apps, the st.connection object automatically caches the connection by using st.cache_resource in the global state, making it accessible across Streamlit sessions that are started by different users. When you use caller's rights, consider using st.session_state to store connections on a per-session basis to avoid sharing connections between users.
For an example with step-by-step instructions, see Create a service with caller's rights enabled.
呼び出し元権限が構成されたサービスへのアクセス¶
Configuring caller's rights means that your service is establishing a Snowflake connection on behalf of the caller. How you log in to the service's ingress endpoints, either programmatically or by using a browser, remains the same. After log in, the following behaviors and optionsapply:
Accessing a public endpoint using a browser: After you log into an endpoint, the service establishes a connection to** Snowflake on behalf of the calling user using the default role of the user. If there is no default role configured for the user, the PUBLIC role is used.
Accessing a public endpoint programmatically: When logging into an endpoint programmatically using JWT token, you can optionally set the
scopeparameter to specify the role to activate
Currently, after a service establishes a caller's right connection to Snowflake on behalf of the caller, switching roles is not supported. If your application needs to use different roles to access different objects, you must change the user's default secondary roles property.
To set up the user to have all secondary roles active by default, use the ALTER USER command to set the DEFAULT_SECONDARY_ROLES property of the user to ('ALL'), as shown in the following example:
ALTER USER my_user SET DEFAULT_SECONDARY_ROLES = ( 'ALL' );
サービスへの呼び出し元グラントの管理¶
When a service creates a caller's rights session, the session operates as the calling user, not as the service user. When an operation is performed by using this session, Snowflake applies a sequence oftwo permissions checks:
The first permissions check is performed as if the user created the session directly. This check is part of thenormal permission checks that Snowflake performs for the user.
The second permissions check verifies that the service is allowed to perform the operation on behalf of a user. Snowflake verifies this by ensuring that the service's owner role was granted the necessary caller grants.
呼び出し元権限セッションにおいて、通常の権限チェックとサービス所有者ロールの 呼び出し元権限 チェックの両方が、その操作を許可しなければなりません。これは、 制限された呼び出し元権限 と呼ばれます。デフォルトでは、サービスはユーザーに代わって何かをする権限を持っていません。サービスが呼び出し元権限で実行できるように、呼び出し元権限を明示的に付与する必要があります。
For example, suppose a user U1 uses a role R1 that has the SELECT privilege on the table T1. When U1 logs into the public endpoint of your
service (example_service), which is configured to use the caller's rights, the service then establishes a connection with Snowflake on
behalf of U1.
サービスが U1 に代わってテーブル T1 をクエリできるようにするには、サービスの所有者ロールに以下の権限を付与する必要があります。
そのテーブルのデータベースとスキーマに対して、 USAGE 権限でサービスを実行することを許可する呼び出し元グラントを付与することで、テーブル名を解決する権限です。
サービスをウェアハウス上で USAGE 権限で実行できるようにする呼び出し元グラントを付与することで、クエリを実行するためにウェアハウスを使用する権限です。
テーブル
T1の SELECT 権限でサービスを実行できる呼び出し元グラントを付与することで、テーブルにクエリを実行できる権限です。
以下の例は、これらの権限を持つサービスの所有者ロールを付与する方法を示しています。
-- Permissions to resolve the table's name.
GRANT CALLER USAGE ON DATABASE <db_name> TO ROLE <service_owner_role>;
GRANT CALLER USAGE ON SCHEMA <schema_name> TO ROLE <service_owner_role>;
-- Permissions to use a warehouse
GRANT CALLER USAGE ON WAREHOUSE <warehouse_name> TO ROLE <service_owner_role>;
-- Permissions to query the table.
GRANT CALLER SELECT ON TABLE T1 TO ROLE <service_owner_role>;
あなたのアカウントでグローバル権限(MANAGE CALLER GRANT)を持つロールであれば、呼び出し元グラントを付与することができます。呼び出し元権限の詳細については、 GRANT CALLER および 制限された呼び出し元権限 をご参照ください。
例¶
For an example of a service that uses the caller's rights feature when executing SQL queries on behalf of the users is provided. For more information, see Create a service with caller's rights enabled.
Connect to Snowflake by using other credentials¶
Snowflakeが提供する OAuth トークンだけでなく、他の形式の認証を使用してSnowflakeに接続できます。そのためには、コンテナがSnowflakeの外部で実行され、インターネットを介して接続しているかのように、コンテナがSnowflakeに接続できるようにする外部アクセス統合(EAI)を作成します。 この方法で接続する場合は、クライアントが使用するホストを構成する必要はありません。
注釈
これらの接続は EAI を通過するため、Snowflake認証もネットワークポリシーを強制します。ビジネスでネットワークポリシーが必要な場合は、他の認証情報との接続はサポートされません。
たとえば、以下の接続では、認証するユーザー名とパスワードを指定します。
conn = snowflake.connector.connect(
account = '<acct-name>',
user = '<user-name>',
password = '<password>'
)
To use a default hostname, you need external access integration with a network rule that allows access from your service to the
Snowflake internet hostname for your account. For example, if your account name is MYACCOUNT in the organization MYORG, the hostname is
myorg-myaccount.snowflakecomputing.com. For more information, see ネットワークエグレスの構成. Privatelink hostnames are not supported
アカウントのSnowflake APIホスト名に一致するネットワークルールを作成します。
CREATE OR REPLACE NETWORK RULE snowflake_egress_access MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('myorg-myaccount.snowflakecomputing.com');
先行するネットワークルールを使用する統合を作成します。
CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration ALLOWED_NETWORK_RULES = (snowflake_egress_access) ENABLED = TRUE;
Configuration of the database and schema context for executing SQL¶
Snowflakeは、認証情報を提供するだけでなく、サービスが作成されるデータベースとスキーマコンテキストも提供します。コンテナコードはこの情報を使用して、サービスと同じデータベースとスキーマコンテキスト内で SQL を実行できます。
このセクションでは、2つの概念について説明します。
サービスを作成するデータベースとスキーマを決定するためにSnowflakeが使用するロジック。
Snowflakeがこの情報をコンテナーに伝え、コンテナーコードが同じデータベースとスキーマコンテキストで SQL を実行できるようにするためのメソッド。
Snowflakeはサービス名を使用して、サービスを作成するデータベースとスキーマを決定します。
例1: 以下の CREATE SERVICE および EXECUTE JOB SERVICE コマンドでは、サービス名が明示的にデータベース名とスキーマ名を指定していません。Snowflakeは、現在のデータベースとスキーマでサービスとジョブサービスを作成します。
-- Create a service. CREATE SERVICE test_service IN COMPUTE POOL ... -- Execute a job service. EXECUTE JOB SERVICE IN COMPUTE POOL tutorial_compute_pool NAME = example_job_service ...
例2: 以下の CREATE SERVICE と EXECUTE JOB SERVICE コマンドでは、サービス名にデータベース名とスキーマ名が含まれています。Snowflakeは、現在のスキーマに関係なく、指定されたデータベース(
test_db)とスキーマ(test_schema)にサービスとジョブサービスを作成します。-- Create a service. CREATE SERVICE test_db.test_schema.test_service IN COMPUTE POOL ... -- Execute a job service. EXECUTE JOB SERVICE IN COMPUTE POOL tutorial_compute_pool NAME = test_db.test_schema.example_job_service ...
Snowflakeがサービスを開始する際は、以下の環境変数を使用して、実行中のコンテナにデータベースとスキーマ情報が提供されます。
SNOWFLAKE_DATABASE
SNOWFLAKE_SCHEMA
コンテナーコードでは、この例に示すように、接続コードで環境変数を使用して、使用するデータベースとスキーマを決定することができます。
conn = snowflake.connector.connect(
host = os.getenv('SNOWFLAKE_HOST'),
account = os.getenv('SNOWFLAKE_ACCOUNT'),
token = get_login_token(),
authenticator = 'oauth',
database = os.getenv('SNOWFLAKE_DATABASE'),
schema = os.getenv('SNOWFLAKE_SCHEMA')
)
例
チュートリアル2 では、Snowflakeに接続して SQL ステートメントを実行するSnowflakeジョブサービスを作成します。以下のステップは、チュートリアルのコードがどのように環境変数を使用するかをまとめたものです。
共通セットアップ(共通セットアップ セクションを参照)では、データベースとスキーマを含む、リソースを作成します。また、セッションの現在のデータベースとスキーマも設定します。
USE DATABASE tutorial_db; ... USE SCHEMA data_schema;
(EXECUTE JOB SERVICE を実行して)ジョブサービスを作成すると、Snowflakeはコンテナを起動し、コンテナ内の以下の環境変数をセッションの現在のデータベースとスキーマに設定します。
SNOWFLAKE_DATABASE は「TUTORIAL_DB」に設定
SNOWFLAKE_SCHEMA は「DATA_SCHEMA」に設定
ジョブコード(チュートリアル2の
main.pyを参照)はこれらの環境変数を読み取ります。SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE') SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
ジョブコードは SQL ステートメント(
main.pyのrun_job()関数)を実行するコンテキストとしてデータベースとスキーマを設定します。{ "account": SNOWFLAKE_ACCOUNT, "host": SNOWFLAKE_HOST, "authenticator": "oauth", "token": get_login_token(), "warehouse": SNOWFLAKE_WAREHOUSE, "database": SNOWFLAKE_DATABASE, "schema": SNOWFLAKE_SCHEMA } ...
注釈
SNOWFLAKE_ACCOUNT、SNOWFLAKE_HOST、 SNOWFLAKE_DATABASE、 SNOWFLAKE_SCHEMA はSnowflakeがアプリケーションコンテナー用に生成する環境変数ですが、 SNOWFLAKE_WAREHOUSE はそうではありません(Snowflakeはウェアハウス名をコンテナーに渡さないため、チュートリアル2のアプリケーションコードがこの変数を作成しました)。
コンテナー用ウェアハウスの指定¶
サービスがSnowflakeに接続してSnowflakeウェアハウスでクエリを実行する場合は、ウェアハウスを指定する以下のオプションがあります。
アプリケーションコードでウェアハウスを指定します。 コードでクエリを実行するためにSnowflakeセッションを開始する際に、接続構成の一部としてウェアハウスを指定します。例については、 チュートリアル2 をご参照ください。
Specify a default warehouse when creating a service. Specify the optional QUERY_WAREHOUSE parameter in the CREATE SERVICE or EXECUTE JOB SERVICE command to provide a default warehouse. If your application code doesn't provide a warehouse as part of connection configuration, Snowflake uses the default warehouse. Use the ALTER SERVICE command to change the default warehouse.
注釈
QUERY_WAREHOUSE パラメーターを使用して指定されたウェアハウスは サービスユーザー のみのデフォルトです。サービスが他のユーザーに代わってSnowflakeに接続するとき、呼び出し元権限のシナリオ のコンテキストにおいて、Snowflakeはユーザーのデフォルトのウェアハウスを使用します。
If you specify a warehouse by using both methods, the warehouse that is specified in the application code is used.
Access service user query history¶
You can find queries executed by your service as the service user by filtering the QUERY_HISTORY ビュー or QUERY_HISTORY function where user_type is SNOWFLAKE_SERVICE.
例1: サービスによって実行されるフェッチクエリ。
SELECT *
FROM snowflake.account_usage.query_history
WHERE user_type = 'SNOWFLAKE_SERVICE'
AND user_name = '<service_name>'
AND user_database_name = '<service_db_name>'
AND user_schema_name = '<service_schema_name>'
order by start_time;
WHERE 句で、
user_name = '<service_name>': サービスは サービスユーザー としてクエリを実行し、サービスユーザーの名前はサービス名と同じであるため、ユーザー名としてサービス名を指定します。user_type = 'SNOWFLAKE_SERVICE'およびuser_name = '<service_name>': これはクエリ結果を、あるサービスによって実行されたクエリのみを取得するように制限します。user_database_nameおよびuser_schema_name: サービスユーザーにとって、これらはサービスのデータベースとスキーマです。
QUERY_HISTORY 関数を呼び出しても同じ結果が得られます。
SELECT *
FROM TABLE(<service_db_name>.information_schema.query_history())
WHERE user_database_name = '<service_db_name>'
AND user_schema_name = '<service_schema_name>'
AND user_type = 'SNOWFLAKE_SERVICE'
AND user_name = '<service_name>'
order by start_time;
WHERE 句で、
user_type = 'SNOWFLAKE_SERVICE'およびuser_name = '<service_name>'は、あるサービスによって実行されたクエリのみを取得するようにクエリ結果を制限します。user_database_nameとuser_schema_nameの名前は、サービスユーザーの場合、サービスのデータベースとスキーマです。
例2: サービスによって実行されたクエリと対応するサービス情報を取得します。
SELECT query_history.*, services.*
FROM snowflake.account_usage.query_history
JOIN snowflake.account_usage.services
ON query_history.user_name = services.service_name
AND query_history.user_schema_id = services.service_schema_id
AND query_history.user_type = 'SNOWFLAKE_SERVICE'
このクエリは、 QUERY_HISTORY と SERVICES ビューを結合し、クエリとクエリを実行したサービスに関する情報を取得します。次の点に注意してください。
サービスによって実行されるクエリの場合、
query_history.user_nameは、サービスユーザー名です。これは、サービス名と同じです。クエリは、スキーマ IDs (スキーマ名ではない)を使用してビューを結合し、同じスキーマを参照していることを確認します。スキーマをドロップして再作成すると、スキーマ ID は変更されますが、名前は同じままだからです。
クエリにオプションのフィルターを追加することができます。例:
特定のクエリを実行したサービスのみを取得するためのフィルター
query_history。特定のサービスによって実行されたクエリのみを取得するためのフィルター
services。
例3: すべてのサービスについて、サービスユーザー情報をフェッチします。
SELECT services.*, users.*
FROM snowflake.account_usage.users
JOIN snowflake.account_usage.services
ON users.name = services.service_name
AND users.schema_id = services.service_schema_id
AND users.type = 'SNOWFLAKE_SERVICE'
このクエリは、 ACCOUNT_USAGE スキーマの SERVICES と USERS ビューを結合し、サービスとサービスユーザー情報を取得します。次の点に注意してください。
サービスがクエリを実行すると、サービスユーザーとしてクエリを実行します。サービスユーザーの名前はサービス名と同じです。したがって、結合条件
users.name = services.service_nameを指定します。サービス名はスキーマ内でのみ一意です。したがって、クエリは、各サービスユーザーが所属する固有のサービス(そして、異なるスキーマで実行されている他の同じ名前のサービスではない)に対して一致することを確実にするために、結合条件(
users.schema_id = services.service_schema_id)を指定します。
ネットワークイングレスの構成¶
インターネットからサービスとのやり取りできるようにするには、サービスがリッスンしているネットワークポートを、サービス仕様ファイルのエンドポイントとして宣言します。これらのエンドポイントはイングレスを制御します。
デフォルトでは、サービスエンドポイントはプライベートです。サービス関数 と サービス間通信 のみがプライベートエンドポイントにリクエストできます。エンドポイントをパブリックと宣言すると、インターネットからエンドポイントへのリクエストを許可することができます。パブリックエンドポイントの作成は権限操作であり、サービスの所有者ロールはアカウントで BIND SERVICE ENDPOINT 権限を持っている必要があります。
endpoints:
- name: <endpoint name>
port: <port number>
protocol : < TCP / HTTP >
public: true
corsSettings: # optional CORS configuration
Access-Control-Allow-Origin: # required list of allowed origins
- <origin> # for example, "http://example.com"
- <origin>
...
Access-Control-Allow-Methods: # optional list of HTTP methods
- <method>
- <method>
...
Access-Control-Allow-Headers: # optional list of HTTP headers
- <header-name>
- <header-name>
...
Access-Control-Expose-Headers: # optional list of HTTP headers
- <header-name>
- <header-name>
...
例については、 チュートリアル1 をご参照ください。
イングレス接続のタイムアウト¶
イングレスエンドポイントのタイムアウトは90秒です。イングレスエンドポイントへの接続に90秒間アクティビティがない場合、Snowflakeは接続を終了します。アプリケーションでもっと長く接続する必要がある場合は、ポーリングまたは WebSockets を使用します。
イングレスウェブブラウザー認証ログアウト¶
サービスとして動作するウェブアプリを構築している場合、ユーザーを /sfc-endpoint/logout に誘導してアプリからログアウトできるようにするオプションがあります。
ログアウト後、ユーザーはサービスのパブリックエンドポイントにアクセスするためにSnowflakeへの再認証が必要となります。
イングレスとウェブアプリのセキュリティ¶
パブリックエンドポイントサポート(ネットワークイングレス)を使用して、ウェブホスティング用のSnowpark Container Servicesサービスを作成できます。セキュリティを強化するために、Snowflakeはプロキシサービスを採用して、クライアントからサービスへの受信リクエストと、サービスからクライアントへの送信応答をモニターします。このセクションでは、プロキシが何を行い、Snowpark Container Servicesに展開されたサービスにどのような影響を与えるかを説明します。
注釈
ローカルでサービスをテストする場合はSnowflakeプロキシを使用しないため、Snowpark Container Servicesに展開した場合とローカルでサービスを実行した場合のエクスペリエンスに違いが生じます。このセクションを確認し、より良いテストのためにローカル設定を更新してください。
例:
禁止されている HTTP メソッドをリクエストが使用する場合、プロキシは受信 HTTP リクエストを転送しません。
プロキシは、応答のContent-Typeヘッダーが実行可能ファイルを含むことを示す場合は、403応答をクライアントに送信します。
さらに、プロキシはリクエストと応答に新しいヘッダーを注入したり、既存のヘッダーを変更したりすることもできます。
たとえば、リクエストを受信すると、サービスは応答で HTML、 JavaScript、 CSS などのウェブページのコンテンツをクライアントのブラウザーに送信する可能性があります。ブラウザー上のウェブページはサービスの一部であり、ユーザーインターフェイスとして機能します。セキュリティ上の理由から、サービスに制限がある場合(他サイトへのネットワーク接続の制限など)に、サービスのウェブページにも同じ制限を設けたい場合があります。
デフォルトでは、サービスはインターネットにアクセスする権限が制限されている。ブラウザーでも、クライアントアプリがインターネットにアクセスし、データを共有する可能性を制限する必要があります。外部アクセス統合(EAI)を設定してサービスが example.com (ネットワークエグレスの構成 を参照)にアクセスできるようにすると、サービスのウェブページもブラウザーを通して example.com にアクセスできるようになります。
Snowflakeプロキシは、応答に Content-Security-Policy (CSP)ヘッダーを追加して、サービスとウェブページに同じネットワーク制限を適用します。デフォルトでは、プロキシは一般的なセキュリティの脅威から守るために、応答にベースライン CSP を追加します。ブラウザーのセキュリティは、機能性とセキュリティのバランスをとるためのベストエフォートであり、このベースラインがあなたのユースケースに適切であることを確認することは、共有された責任です。さらに、サービスが EAI を使用するように設定されている場合、プロキシはウェブページに対して EAI から CSP まで同じネットワークルールを適用します。この CSP により、ブラウザーのウェブページは、サービスがアクセスできるのと同じサイトにアクセスできるようになります。
Snowflakeは、サービス仕様で構成する CORS サポートを提供します。
Snowflakeプロキシは、サービス仕様で定義されている CORS 設定を返します。プロキシはサービスによって返された CORS ヘッダーをすべて削除することに注意してください。
以下の CORS ヘッダーはデフォルトでセットされています。
Access-Control-Expose-Headersヘッダーは、エンドポイントのサービス仕様で構成されたヘッダーに加えて、常に以下のヘッダー名を報告します。X-Frame-OptionsCross-Origin-Opener-PolicyCross-Origin-Resource-PolicyX-Content-Type-OptionsCross-Origin-Embedder-PolicyContent-Security-Policy-Report-OnlyContent-Security-Policy
Access-Control-Max-Ageは2時間にセットされます。Access-Control-Allow-Credentialsはtrueにセットされます。
さらに、Snowflakeは、 Origin の値に基づいて、 Access-Control-Allow-Origin の値が異なる可能性があることをブラウザーに示すために、 Origin の値で Vary ヘッダーをセットします。
CORS リクエストを実行するには、 Authorization ヘッダーが必要です。このヘッダー(Authorization: "Snowflake Token=\"${patToken}\"")にプログラムによるアクセストークン(PAT)を指定できます。プログラムのアクセストークンを生成する方法については、 認証のためのプログラム アクセス トークンの使用 をご参照ください。
以下のセクションでは、Snowflakeプロキシがサービスに対する受信リクエストをどのように処理し、サービスからクライアントへの送信応答をどのように変更するかを説明します。
サービスへの受信リクエスト¶
リクエストを受信すると、プロキシはリクエストをサービスに転送する前に以下を実行します。
禁止された HTTP メソッドを持つ受信リクエスト: 受信 HTTP リクエストが以下の禁止された HTTP メソッドのいずれかを使用する場合、プロキシはそのリクエストをサービスに転送しません。
TRACECONNECT
受信リクエストヘッダーのスクラブ: Snowflakeプロキシは、以下のリクエストヘッダーが存在する場合は削除します。
X-SF-SPCS-AuthorizationAuthorization:Snowflakeトークンが含まれている場合のみ削除され、含まれていない場合はサービスに渡されます。
クライアントへの応答送信¶
Snowflakeプロキシは、クライアントに応答を転送する前に、サービスから送信された応答にこれらの修正を適用します。
ヘッダースクラビング: Snowflakeプロキシは、これらの応答ヘッダーを削除します(存在する場合)。
X-XSS-ProtectionServerX-Powered-ByPublic-Key-Pins
CORS ヘッダー操作: 進入と CORS への配慮 を参照してください。
Content-Type応答ヘッダー: サービス応答でContent-Typeヘッダーに次の MIME 型の値(実行可能ファイルを示す)が含まれる場合、Snowflakeプロキシはその応答をクライアントに転送しません。代わりに、プロキシは
403 Forbidden応答を送信します。application/x-msdownload:Microsoftの実行可能ファイル。application/exe: 汎用実行可能ファイル。application/x-exe: 別の汎用実行可能ファイル。application/dos-exe: DOS の実行可能ファイル。application/x-winexe:Windowsの実行可能ファイル。application/msdos-windows: MS-DOS Windows実行可能ファイル。application/x-msdos-program: MS-DOS 実行可能ファイル。application/x-sh:Unixシェルスクリプト。application/x-bsh:Bourneシェルスクリプト。application/x-csh:Cシェルスクリプト。application/x-tcsh:Tcshシェルスクリプト。application/batch:Windowsバッチファイル。
X-Frame-Options応答ヘッダー: クリックジャッキング攻撃を防ぐために、Snowflakeプロキシはこの応答ヘッダーを
DENYに設定し、他のウェブページがサービスのウェブページにiframeを使用できないようにします。Cross-Origin-Opener-Policy(COOP)応答ヘッダー: Snowflakeは COOP 応答ヘッダーを
same-originに設定し、参照元のクロスオリジンウィンドウがサービスタブにアクセスできないようにします。Cross-Origin-Resource-Policy(CORP)応答ヘッダー: Snowflakeは CORP ヘッダーを
same-originに設定し、外部サイトが(iframeなどで)イングレスエンドポイントによって公開されたリソースをロードできないようにします。X-Content-Type-Options応答ヘッダー: Snowflakeプロキシはこのヘッダーを
nosniffに設定し、クライアントがサービスによって応答に記載された MIME 型を変更できないようにします。Cross-Origin-Embedder-Policy(COEP)応答ヘッダー: Snowflakeプロキシは COEP 応答ヘッダーを
credentiallessに設定します。これは、画像やスクリプトなどのクロスオリジンオブジェクトをロードするときに、リモートオブジェクトがCross-Origin Resource Sharing(CORS)プロトコルをサポートしていない場合、Snowflakeはそれをロードするときに認証情報を送信しないことを意味します。Content-Security-Policy-Report-Only応答ヘッダー: Snowflakeプロキシは、クライアントに CSP レポートをSnowflakeに送信するよう指示する新しい値で、この応答ヘッダーを置き換えます。
Content-Security-Policy(CSP)応答ヘッダー: デフォルトでは、Snowflakeプロキシは、一般的なウェブ攻撃から保護するために、以下のベースライン CSP を追加します。
default-src 'self' 'unsafe-inline' 'unsafe-eval' blob: data:; object-src 'none'; connect-src 'self'; frame-ancestors 'self';
コンテンツセキュリティポリシーの考慮点は2つあります。
プロキシが追加するベースラインコンテンツセキュリティポリシーに加えて、サービス自身が応答に明示的に CSP を追加することができます。サービスは、より厳格な CSP を追加して、セキュリティを強化することを選択する場合があります。たとえば、サービスは CSP を追加して、
selfからのスクリプトのみを許可する場合があります。script-src 'self'
結果としてクライアントに送られる応答には、2つの CSP ヘッダーがあります。応答を受信すると、クライアントブラウザーは、各ポリシーによって指定された追加制限を含む、最も厳格なコンテンツセキュリティポリシーを適用します。
サービスが外部サイト(ネットワークエグレスの構成)にアクセスできるように外部アクセス統合(EAI)を構成すると、Snowflakeプロキシは、ウェブページがそのサイトにアクセスできるようにする CSP を作成します。たとえば、 EAI に関連付けられているネットワークルールが、サービスに
example.comへのエグレスアクセスを許可しているとします。次に、Snowflakeプロキシは以下の CSP 応答ヘッダーを追加します。default-src 'self' 'unsafe-inline' 'unsafe-eval' http://example.com https://example.com blob: data:; object-src 'none'; connect-src 'self' http://example.com https://example.com wss://example.com; frame-ancestors 'self';
ブラウザーは、応答で受け取ったコンテンツアクセスポリシーを尊重します。この例では、ブラウザーはアプリに
example.comへのアクセスを許可しますが、他のサイトへのアクセスは許可しません。
進入と CORS への配慮¶
デフォルトでは、ブラウザーは、あるサーバーでホストされているウェブアプリが、ホスト名の異なる別のサーバーにリクエストを送信するのをブロックします。例えば、Snowpark Container Services内にデプロイされたバックエンドサービスとやり取りする必要があるウェブアプリをSnowpark Container Servicesの外でホストする場合、この制限が適用されます。
CORS (Cross-Origin Resource Sharing)により、Snowpark Container Servicesサービスは、その環境外でホストされているウェブアプリからのリクエストを許可するよう、ブラウザーに指示することができます。各パブリックエンドポイントを構成して、 CORS プリフライトリクエストと標準リクエストの両方への応答方法を指定できます。
Snowflakeプロキシは常に以下のレスポンスヘッダーを上書きします。
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Expose-HeadersAccess-Control-Max-AgeAccess-Control-Allow-Credentials
Snowflakeプロキシは、以下のいずれかが真である場合、レスポンスにこれらの CORS ヘッダーを含めません。
CORS はサービスエンドポイントに構成されていません。つまり、サービス仕様に
corsSettingsはありませんCORS がサービスエンドポイントに構成されていますが、リクエストの
Originヘッダーがサービス仕様の指定されたAccess-Control-Allow-Originフィールドと一致しません
サービス仕様では、各パブリックエンドポイントに対して CORS の設定を行うことができます。リクエストの origin ヘッダーが、仕様でエンドポイントに指定されている Access-Control-Allow-Origin フィールドにマッチするとき、プロキシは以下の調整を加えて、仕様で定義されている CORS ヘッダーをレスポンスに含めます。
Access-Control-Allow-Origin: リクエストからOriginヘッダーを返します。Access-Control-Expose-Headers: 構成した許可ヘッダーのリストを、これらの常時公開ヘッダーとマージします:X-Frame-Options、Cross-Origin-Opener-Policy、Cross-Origin-Resource-Policy、X-Content-Type-Options、Cross-Origin-Embedder-Policy、Content-Security-Policy-Report-Only、Content-Security-Policy。Access-Control-Max-Age:2時間にセットされます。Access-Control-Allow-Credentials: trueにセットされます。
進入と SSO への配慮¶
インターネットからパブリックエンドポイントにアクセスすると、ユーザー名/パスワード認証コードは機能しますが、 SSO では、空白のページが表示されるか、以下のエラーが表示されることがあります。「指定されたOAuth クライアントとの統合 ID が見つかりません。」
この現象は、 フェデレーション認証を使用するためのSnowflakeの構成 で説明されている新しいセキュリティ統合バージョンではなく、Snowflake で古いスタイルの統合認証 (SSO) を使用している場合に発生します。次のことを確認してください。
以下のクエリを実行します。
SHOW PARAMETERS LIKE 'SAML_IDENTITY_PROVIDER' IN ACCOUNT;
このパラメーターがセットされている場合は、ある時点で旧式の認証コードを使用していたことになります。
前述のパラメーターがセットされている場合、以下のクエリを実行して、 SAML セキュリティ統合があるかどうかを確認します。
SHOW INTEGRATIONS ->> SELECT * FROM $1 WHERE "type" = 'SAML2';
SAML2 タイプの統合がない場合は、旧式の認証コードを使用していることになります。
この大文字と小文字の場合、解決策は、旧式の統合認証から新しい統合形式の統合認証に移行することです。詳細については、 SAML2 セキュリティ統合への移行 をご参照ください。
ネットワークエグレスの構成¶
アプリケーションコードは、インターネットへのアクセスを必要とする場合があります。デフォルトでは、アプリケーションコンテナーはインターネットにアクセスする権限を持っていません。外部アクセス統合(EAIs) を使用してインターネットアクセスを有効にする必要があります。
通常、サービス(ジョブサービスを含む)から許可される外部アクセスを管理するために、アカウント管理者は EAIs を作成します。アカウント管理者は、開発者がサービスを実行するために使用する特定ロールに EAI の使用権限を付与できます。
次の例は、ネットワークルールを使用して指定された特定の宛先へのエグレストラフィックを許可する EAI を作成するステップの概要を示しています。その後、特定のインターネット宛先へのリクエストを許可するサービスを作成するときに、 EAI を参照します。
例
アプリケーションコードが、以下の宛先にリクエストを送信するとします。
HTTPS が、translation.googleapis.comにリクエストする
HTTP と HTTPS が、google.comにリクエストする
以下のステップに従って、サービスがインターネット上のこれらのドメインにアクセスできるようにします。
外部アクセス統合(EAI)を作成するこれには適切な権限が必要です。たとえば、 ACCOUNTADMIN ロールを使用して EAI を作成することができます。これは2段階のプロセスです。
CREATE NETWORK RULE コマンドを使用して、アクセスを許可する外部宛先をリストした1つ以上のエグレスネットワークルールを作成します。この例は1つのネットワークルールで実現できますが、説明のために2つのネットワークルールを作成します。
translate_network_ruleという名前のネットワークルールを作成します。CREATE OR REPLACE NETWORK RULE translate_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('translation.googleapis.com');
このルールは、
translation.googleapis.comの宛先への TCP 接続を許可します。VALUE_LIST プロパティのドメインは、オプションのポート番号を指定しないため、デフォルトのポート443(HTTPS)が想定されます。これにより、アプリケーションはhttps://translation.googleapis.com/で始まる任意の URL に接続できます。google_network_ruleという名前のネットワークルールを作成します。CREATE OR REPLACE NETWORK RULE google_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('google.com:80', 'google.com:443');
これにより、アプリケーションは
http://google.com/またはhttps://google.com/で始まる任意の URL に接続できます。
注釈
VALUE_LISTパラメーターには、完全なホスト名を指定する必要があります。ワイルドカード(例:*.googleapis.com)はサポートされていません。Snowpark Container Servicesは、ポート22、80、443、1024+を許可するネットワークルールのみをサポートします。参照されているネットワークルールが他のポートへのアクセスを許可している場合、サービスの作成は失敗します。追加のポートが必要な場合は、担当者にお問い合わせください。
注釈
サービスが HTTP または HTTPS リクエストをインターネット上の任意の宛先に送信できるようにするには、 VALUE_LIST プロパティでドメインとして「0.0.0.0」を指定します。以下のネットワークルールは、インターネット上の任意の宛先に「HTTP」と「HTTPS」の両方のリクエストを送信することを許可します。「0.0.0.0」をサポートしているのは、ポート80または443のみです。
CREATE NETWORK RULE allow_all_rule TYPE = 'HOST_PORT' MODE= 'EGRESS' VALUE_LIST = ('0.0.0.0:443','0.0.0.0:80');
外部アクセス統合(EAI) を作成し、先行する2つのエグレスネットワークルールが許可されることを指定します。
CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule) ENABLED = true;
これで、アカウント管理者は、開発者に統合の使用権限を付与して、インターネット上の特定の宛先にアクセスできるサービスを実行できるようにすることができます。
GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
以下の例に示すように、 EAI を指定してサービスを作成します。サービスを作成する所有者ロールは、 EAI の USAGE 権限と、参照されるシークレットの READ 権限が必要です。ACCOUNTADMIN ロールを使用してサービスを作成することはできません。
サービスを作成します。
USE ROLE test_role; CREATE SERVICE eai_service IN COMPUTE POOL MYPOOL EXTERNAL_ACCESS_INTEGRATIONS = (GOOGLE_APIS_ACCESS_INTEGRATION) FROM SPECIFICATION $$ spec: containers: - name: main image: /db/data_schema/tutorial_repository/my_echo_service_image:tutorial env: TEST_FILE_STAGE: source_stage/test_file args: - read_secret.py endpoints: - name: read port: 8080 $$;
この例の CREATE SERVICE リクエストは、インラインサービス仕様を使用し、 EAI を含むようにオプションの EXTERNAL_ACCESS_INTEGRATIONS プロパティを指定します。EAI は、サービスから特定の宛先へのエグレストラフィックを許可するネットワークルールを指定します。
ジョブサービスを実行します。
EXECUTE JOB SERVICE IN COMPUTE POOL tt_cp NAME = example_job_service EXTERNAL_ACCESS_INTEGRATIONS = (GOOGLE_APIS_ACCESS_INTEGRATION) FROM SPECIFICATION $$ spec: container: - name: curl image: /tutorial_db/data_schema/tutorial_repo/alpine-curl:latest command: - "curl" - "http://google.com/" $$;
この例の EXECUTE JOB SERVICE コマンドは、インライン仕様と、 EAI を含めるためのオプション EXTERNAL_ACCESS_INTEGRATIONS プロパティを指定します。これは、ジョブから EAI が許可するネットワークルールで指定された宛先への、エグレストラフィックを許可します。
プライベート接続を使用したネットワークエグレス¶
公衆インターネット経由でネットワークのイグレスをルーティングする代わりに、 プライベート接続エンドポイント を介してサービスのイグレス・トラフィックを誘導することを選択することもできます。
まず、Snowflakeアカウントでプライベート接続エンドポイントを作成する必要があります。次に、 プライベート接続 を使用する発信トラフィックを許可するネットワークルールを構成します。外部アクセス統合(EAI)のセットアップ手順は、前のセクションと同じです。
注釈
プライベート通信では、Snowflakeとお客様のクラウドアカウントの両方が同じクラウドプロバイダーと同じリージョンを使用する必要があります。
例えば、プライベート接続を介してAmazon S3バケットへのサービスのアウトバウンドインターネットアクセスを有効にしたい場合、次のようにします。
自営エンドポイントサービス(Amazon S3)のプライベートリンク接続を有効にします。ステップバイステップの手順については、 AWS Private Link for Amazon S3 をご参照ください。
SYSTEM$PROVISION_PRIVATELINK_ENDPOINT システム関数を呼び出して、Snowflake VNet にプライベート接続エンドポイントをプロビジョニングします。これにより、Snowflakeはプライベート接続を使用して外部サービス(この例ではAmazon S3)に接続できるようになります。
USE ROLE ACCOUNTADMIN; SELECT SYSTEM$PROVISION_PRIVATELINK_ENDPOINT( 'com.amazonaws.us-west-2.s3', '*.s3.us-west-2.amazonaws.com' );
クラウドプロバイダーのアカウントで、エンドポイントを承認します。この例では、Amazon AWS の場合、 接続リクエストを受け入れるか拒否するか AWS ドキュメントの を参照してください。 また、Azure でエンドポイントを承認するには、 Azure ドキュメント をご参照ください。
CREATE NETWORK RULE コマンドを使用して、アクセスを許可する外部宛先を指定するエグレスネットワークルールを作成します。
CREATE OR REPLACE NETWORK RULE private_link_network_rule MODE = EGRESS TYPE = PRIVATE_HOST_PORT VALUE_LIST = ('<bucket-name>.s3.us-west-2.amazonaws.com');
TYPE パラメーターの値は PRIVATE_HOST_PORT にセットされます。このネットワークルールは、発信ネットワークトラフィックが プライベート接続 を使用することを許可することを示します。
EAI を作成し、それを使用してサービスを作成する残りの手順は、前のセクションで説明したのと同様です(ネットワークエグレスの構成 を参照)。
プライベート接続エンドポイントの操作については、以下を参照してください。
コンテナー間のネットワーク通信構成¶
次の2つを考慮します。
Snowflakeシークレットを使用してコンテナーに認証情報を引き渡す¶
Snowflake が管理する認証情報をコンテナーに渡したい理由は多数あります。サービスが外部エンドポイント(Snowflakeの外部)と通信する場合は、アプリケーションコードが使用できるように、コンテナー内に認証情報を提供する必要があります。
認証情報を提供するには、まず認証情報を Snowflake secret オブジェクトに格納します。次に、サービス仕様の中で、 containers.secrets 、どのシークレットオブジェクトを使用し、コンテナー内のどこに配置するかを指定します。これらの認証情報をコンテナー内の環境変数に渡すか、コンテナー内のローカルファイルで利用できるようにします。
Snowflakeのシークレットを指定する¶
Snowflakeのシークレットを名前または参照で指定します(参照はNative Applicationシナリオでのみ適用可能です)。
Snowflake のシークレットを名前で渡す:
snowflakeSecretフィールドの値としてシークレット名を渡すことができます。... secrets: - snowflakeSecret: objectName: '<secret-name>' <other info about where in the container to copy the secret> ...
なお、
snowflakeSecretの値として、<secret-name>を直接指定することもできます。Snowflakeシークレットをリファレンスで渡す: Snowpark Container Services を使用してNative App(コンテナー付きアプリ)を作成する場合、アプリのプロデューサーとコンシューマーは異なる Snowflake アカウントを使用します。場合によっては、インストールされた Snowflake Native Appは、 APPLICATION オブジェクトの外部に存在するコンシューマーカウントの既存のオブジェクトにアクセスする必要があります。この場合、開発者は「secrets by reference(参照によるシークレット)」指定構文を使用して、図のように認証情報を扱うことができます。
containers: - name: main image: <url> secrets: - snowflakeSecret: objectReference: '<reference-name>' <other info about where in the container to copy the secret>
この仕様では、シークレットの参照名を提供するために、
objectNameの代わりにobjectReferenceを使用していることに注意してください。
コンテナー内のシークレットの配置を指定する¶
Snowflakeには、シークレットを環境変数としてコンテナーに配置するか、ローカルコンテナーファイルに書き込むように指示することができます。
シークレットを環境変数として引き渡し¶
Snowflakeのシークレットを環境変数としてコンテナーに渡すには、 containers.secrets フィールドに envVarName を含めます。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: <secret-name>
secretKeyRef: username | password | secret_string | 'access_token'
envVarName: '<env-variable-name>'
secretKeyRef: この値はSnowflakeシークレットの型によって異なります。設定可能な値は以下の通りです。
username、またはSnowflakeシークレットがpassword型の場合はpassword。Snowflakeシークレットが
generic_string型の場合はsecret_string。
サービスが作成された後、Snowflakeは環境変数として渡されたシークレットを更新しないことに注意してください。
例1: パスワード 型のシークレットを環境変数として引き渡し¶
この例では、 password 型の以下のSnowflakeシークレットオブジェクトを作成します。
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
このSnowflakeシークレットオブジェクトをコンテナー内の環境変数(例: LOGIN_USER や LOGIN_PASSWORD)に提供するには、仕様ファイルに以下の containers.secrets フィールドを追加します。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret_object
secretKeyRef: username
envVarName: LOGIN_USER
- snowflakeSecret: testdb.testschema.my_secret_object
secretKeyRef: password
envVarName: LOGIN_PASSWORD
この例では、 snowflakeSecret の値は完全修飾オブジェクト名です。これは、シークレットは作成されるサービスとは異なるスキーマに格納できるためです。
この例の containers.secrets フィールドは、2つの snowflakeSecret オブジェクトのリストです。
最初のオブジェクトは、Snowflakeシークレットオブジェクトの
usernameをコンテナーの環境変数LOGIN_USERにマップします。2番目のオブジェクトは、Snowflakeシークレットオブジェクトの
passwordをコンテナーの環境変数LOGIN_PASSWORDにマップします。
例¶
この例では、 generic_string 型の以下のSnowflakeシークレットオブジェクトを作成します。
CREATE SECRET testdb.testschema.my_secret
TYPE=generic_string
SECRET_STRING='
some_magic: config
';
このSnowflakeシークレットオブジェクトをコンテナー内の環境変数(例: GENERIC_SECRET)に提供するには、仕様ファイルに以下の containers.secrets フィールドを追加します。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret
secretKeyRef: secret_string
envVarName: GENERIC_SECRET
ローカルコンテナーファイルでのシークレットを記述する¶
ローカルコンテナーファイル内のアプリケーションコンテナーで Snowflake シークレットを利用できるようにするには、 containers.secrets フィールドを含めます。ローカルコンテナーファイル内のアプリケーションコンテナーでSnowflake のシークレットを利用できるようにするには、 containers.secrets に directoryPath を含めます。
containers:
- name: <name>
image: <url>
...
secrets:
- snowflakeSecret: <snowflake-secret-name>
directoryPath: '<local directory path in the container>'
Snowflakeは、この指定された directoryPath; secretKeyRef を指定する必要はありません。シークレットタイプに応じて、Snowflakeは指定したディレクトリパスの下のコンテナー内に以下のファイルを作成します。
Snowflakeシークレットが
password型の場合、usernameとpasswordです。Snowflakeシークレットが
generic_string型の場合はsecret_string。Snowflakeシークレットが
oauth2型の場合はaccess_token。
注釈
サービスが作成された後、Snowflakeのシークレットオブジェクトが更新されると、Snowflakeは実行中のコンテナ内の対応するシークレットファイルを更新します。
例1: ローカルコンテナーファイルにおける password 型のシークレットの引き渡し¶
この例では、 password 型の以下のSnowflakeシークレットオブジェクトを作成します。
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
これらの認証情報をローカルコンテナーファイルで利用できるようにするには、仕様ファイルに以下の containers.secrets フィールドを追加します。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret_object
directoryPath: '/usr/local/creds'
サービスを開始すると、Snowflakeはコンテナー内に /usr/local/creds/username と /usr/local/creds/password の2つのファイルを作成します。そうすると、アプリケーションコードはこれらのファイルを読み取ることができます。
例2: ローカルコンテナーファイルにおける oauth2 型のシークレットを引き渡す¶
この例では、 generic_string 型の以下のSnowflakeシークレットオブジェクトを作成します。
CREATE SECRET testdb.testschema.my_secret
TYPE=generic_string
SECRET_STRING='
some_magic: config
';
このSnowflakeシークレットオブジェクトをローカルコンテナーファイルで提供するには、仕様ファイルに以下の containers.secrets フィールドを追加します。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret
directoryPath: '/usr/local/creds'
サービスを開始すると、Snowflakeはコンテナー内に /usr/local/creds/secret_string のファイルを作成します。
例3: ローカルコンテナーファイルにおける oauth2 型のシークレットを引き渡す¶
この例では、 oauth2 型の以下のSnowflakeシークレットオブジェクトを作成します。
CREATE SECRET testdb.testschema.oauth_secret
TYPE = OAUTH2
OAUTH_REFRESH_TOKEN = '34n;vods4nQsdg09wee4qnfvadH'
OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2023-12-31 20:00:00'
API_AUTHENTICATION = my_integration;
これらの認証情報をローカルコンテナーファイルで利用できるようにするには、仕様ファイルに以下の containers.secrets フィールドを追加します。
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.oauth_secret
directoryPath: '/usr/local/creds'
Snowflakeは OAuth シークレットオブジェクトからアクセストークンをフェッチし、コンテナーに /usr/local/creds/access_token を作成します。
サービスがoauth2型のシークレットを使用する場合、サービスはインターネット宛先にアクセスするためにそのシークレットを使用することが求められます。oauthシークレットは 外部アクセス統合(EAI) によって許可される必要があります。それ以外の場合、 CREATE SERVICE または EXECUTE JOB SERVICE は失敗します。この追加の EAI 要件は、oauth2型のシークレットにのみ適用され、他の型のシークレットには適用されません。
要約すると、このようなサービスを作る際の典型的なステップは以下のとおりです。
oauth2型のシークレットを作成します(前述のとおり)。
サービスによるシークレットの使用を許可する EAI を作成します。例:
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION example_eai ALLOWED_NETWORK_RULES = (<name>) ALLOWED_AUTHENTICATION_SECRETS = (testdb.testschema.oauth_secret) ENABLED = true;
仕様に
containers.secretsフィールドを含むサービスを作成します。また、oauth2シークレットの使用を許可するために、 EXTERNAL_ACCESS_INTEGRATIONS プロパティに EAI を含めるようにオプションで指定します。CREATE SERVICE (インライン仕様を使用)コマンドの例:
CREATE SERVICE eai_service IN COMPUTE POOL MYPOOL EXTERNAL_ACCESS_INTEGRATIONS = (example_eai) FROM SPECIFICATION $$ spec: containers: - name: main image: <url> secrets: - snowflakeSecret: testdb.testschema.oauth_secret directoryPath: '/usr/local/creds' endpoints: - name: api port: 8080 $$;
エグレスの詳細については、 ネットワークエグレスの構成 をご参照ください。
ガイドラインと制約¶
一般的な制限: これらの制限に関する問題が発生した場合は、アカウント担当者にお問い合わせください。
Snowflakeアカウントには最大200のサービスを作成できます。
各サービスは最大100のエンドポイントを持つことができます(spec.endpoints を参照)。
各サービスは最大20のコンテナーを持つことができます(spec.containers を参照)。
各サービスは最大50のシークレットを持つことができます(containers.secrets を参照)。
各サービスは最大20のボリュームを持つことができます(spec.volumes を参照)。
外部アクセス統合(EAIs)を使用してインターネットアクセス(ネットワークエグレスの構成)を有効にすると、以下の制限が適用されます。
各サービスは最大10個の EAIs (CREATE SERVICE および ALTER SERVICE を参照)をサポートすることができます。
各 EAI は最大100のホスト名を持つことができます。
インターネットからパブリックエンドポイントにアクセスすると、ユーザー名/パスワード認証コードは機能しますが、 SSO では、空白のページが表示されるか、以下のエラーが表示されることがあります。" 指定された OAuth クライアントとの統合 ID が見つかりません。"この問題への対処情報については、 進入と SSO への配慮 をご覧ください。
画像プラットフォームの要件: 現在、Snowpark Container Servicesにはlinux/amd64プラットフォーム画像が必要です。
サービスコンテナの権限なし: サービスコンテナは権限として実行されないため、ホスト上のハードウェアの構成を変更できず、限られた OS 構成のみを変更できます。サービスコンテナは、通常のユーザー(つまり、ルートを必要としないユーザー)ができるオペレーティングシステム構成のみを実行できます。
データベースおよびスキーマの名前変更:
すでにサービスを作成したデータベースやスキーマの名前は変更しないでください。名前変更は事実上、サービスを別のデータベースとスキーマに移動することになりますが、これはサポートされていません。例:
Snowflakeが実行中のサービスコンテナーに提供したデータベースとスキーマの情報は、引き続き従来の名前を参照します。
サービスがイベントテーブルにインジェストする新しいログは、従来のデータベース名とスキーマ名を参照し続けます。
サービス関数は従来のデータベースとスキーマのサービスを参照し続け、サービス関数を呼び出すと失敗します。
サービス仕様は、Snowflakeステージやイメージリポジトリなどのオブジェクトを参照することができます。これらのオブジェクトが存在するデータベース名やスキーマ名を変更した場合は、サービス仕様の参照オブジェクトのデータベース名やスキーマ名を手動で更新する必要があります。
Ownership transferof the parent schema or database:
You can transfer the ownership of the parent schema or database to a different role. But the ownership of services inside the schema or database isn't transferred to the new role because services run as service's owner roles and that doesn't change. As a result, the services could lose permissions on objects inside the schema, such as image repositories and Snowflake stages in the same schema.
If you must transfer the ownership of the parent schema or database, consider re-creating the services.
データベースおよびスキーマのドロップおよびドロップ解除:
親データベースまたはスキーマをドロップすると、サービスは非同期に削除されます。つまり、内部プロセスでサービスが削除されるまで、しばらくの間サービスが実行され続ける可能性があります。
以前に削除されたデータベースやスキーマのドロップ解除を試行しても、サービスが復元される保証はありません。
Ownership transfer of services: Ownership transfer or future ownership transfer for services, including job services, isn't supported.
サービス関数の所有権移転:
サービス関数の所有権は、異なるロールに移転することができます。新しい所有者ロールがサービスの USAGE 権限を持っていない場合、関数の呼び出しは失敗します。新しい関数所有者ロールに USAGE 権限を与える必要があります。
複製: Snowflakeで複製を扱う場合、以下の点に注意してください。
サービス、コンピューティングプール、リポジトリなどのSnowpark Container Servicesオブジェクトを複製することはできません。
データベース内にリポジトリを作成した場合は、データベース全体を複製することはできません。データベースにサービス、コンピューティングプールなどの他のリソースが含まれている場合、データベースの複製プロセスは成功しますが、データベース内の個々のオブジェクトは複製されません。
Job services timeout: Snowpark Container Services job services runs synchronously by default. If a statement times out, the job service is canceled. The default statement timeout is two days. Customers can change the timeout by setting the parameter STATEMENT_TIMEOUT_IN_SECONDS using ALTER SESSION.
ALTER SESSION SET statement_timeout_in_seconds=<time>
EXECUTE JOB SERVICE コマンドを実行する前に設定します。
ASYNC=trueを指定してジョブサービスを非同期的に実行し、ステートメントのタイムアウトによってジョブサービスが中断されるのを回避できます。File staging commands support in Google Cloud: To use the PUT, GET, LIST, or REMOVE command with Snowflake client libraries on Google Cloud, update your clients to at least the following versions.
クライアント
バージョン
Go Snowflakeドライバー
1.14.1
Python用Snowflake Connector
3.16.0
.NET ドライバー
4.6.0
Node.jsドライバー
2.1.3
JDBCドライバー
3.25.1
ODBCドライバー
3.10.0