Snowpark Container Services: サービスのその他の考慮事項

コンテナー内部からのSnowflakeへの接続

サービス(ジョブサービスも含む)を開始すると、Snowflakeは実行中のコンテナに認証情報を提供し、コンテナコードがSnowflakeに接続して SQL を実行するためのドライバーを使用できるようにします(Snowflakeに接続するコンピューター上の他のコードと同様)。提供された認証情報は、所有者ロール(サービスを作成したロール)として認証されます。Snowflakeは、情報の一部をコンテナーの環境変数として提供します。

Snowflakeのすべてのオブジェクトには、所有者ロールがあります。サービスの所有者ロールは、Snowflakeと相互作用する際に、サービスが実行できる機能を決定します。これには SQL の実行、ステージへのアクセス、サービス間のネットワーキングが含まれます。

注釈

サービスの所有者ロールは、サービスを作成したロールを指します。また、1つ以上のサービスロールを定義して、サービスが公開するエンドポイントへのアクセスを管理することもできます。詳細については、 サービスエンドポイントへのアクセス管理 をご参照ください。

サービスを作成すると、Snowflakeはそのサービス専用の サービスユーザー も作成します。サービスがクエリを実行すると、サービスの所有者ロールを使用して、サービスユーザーとしてクエリを実行します。サービスユーザーが何を実行できるかは、この所有者ロールによって決まります。

サービスの所有者ロールは、 ACCOUNTADMIN、 SECURITYADMIN、 ORGADMIN などのいずれの権限ロールであってはなりません。これは、誤動作を起こしたサービスが実行できることを制限するためです。サービスが管理者業務を実行できるようにするためには、より意図的である必要があります。

特定のサービスユーザーが発行したクエリを表示するには、 ACCOUNTADMIN ロールを使用して、 クエリ履歴 を表示できます。サービス利用者の利用者名は以下の形式で表示されます。

  • 8.35サーバーリリース以前に作成されたサービスの場合、サービスユーザー名は SF$SERVICE$unique-id の形式です。

  • 8.35サーバーリリース以降に作成されたサービスでは、サービスユーザー名はサービス名と同じです。

Snowflakeへの接続

Snowflakeは、サービスコード内でSnowflakeクライアントを構成するために、以下の環境変数を提供します。

  • SNOWFLAKE_ACCOUNT: サービスが現在実行されているSnowflakeアカウントの アカウントロケーター を提供します。

  • SNOWFLAKE_HOST: Snowflakeへの接続に使用するホスト名を指定します。

また、Snowflakeはコンテナー内の OAuth トークンを /snowflake/session/token という名前のファイルで提供します。接続を作成する場合は、このトークンをコネクタに提供します。

コンテナーからSnowflakeへの接続を作成するときには、 SNOWFLAKE_HOST、 SNOWFLAKE_ACCOUNT、および OAuth トークンを使用する必要があります。SNOWFLAKE_HOST を使用せずに OAuth トークンを使用することはできず、 OAuth トークンをSnowpark Container Services外部で使用することはできません。詳細については、 SQL を実行するための OAuth トークンの使用 をご参照ください。

注釈

外部アクセス統合を使用してSnowflakeにアクセスすることは、潜在的にセンシティブな情報をインターネット経由で送信することを意味します。可能な限り、サービスは提供された OAuth トークンを使用して、 SNOWFLAKE_HOST ホスト名にアクセスすべきです。これにより、インターネットからSnowflakeにアクセスする必要がなくなります。

さまざまなSnowflakeドライバーを使用するサンプルコードについては、 Snowflake接続例 をご参照ください。

  • チュートリアル2main.py を参照)では、コードは以下のように環境変数を読み取ります。

    SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT')
    SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
    
    Copy

    このコードは、これらの変数を選択したSnowflakeクライアントの接続作成コードに渡します。コンテナはこれらの認証情報を使用して、所有者ロールをプライマリロールとする新しいセッションを作成し、クエリを実行します。以下のコード例は、PythonでSnowflake接続を作成するために最低限必要なものです。

    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'
    )
    
    Copy
  • デフォルトのホストを使用する場合(つまり、接続を作成するときに host 引数を含めない場合)は、他の形式の認証(ユーザー名とパスワードなど)を使用したSnowflakeへの接続がサポートされます。たとえば、以下の接続では、認証するユーザー名とパスワードを指定します。

    conn = snowflake.connector.connect(
      account = os.getenv('SNOWFLAKE_ACCOUNT'),
      user = '<user-name>',
      password = <password>
    )
    
    Copy

    デフォルトホストを使用するには、お客様のサービスからアカウントのSnowflakeホスト名へのアクセスを許可するネットワークルールと外部アクセスの統合が必要です。たとえば、アカウント名が MyAccount の場合、ホスト名は myaccount.snowflakecomputing.com になります。詳細については、 ネットワークエグレス をご参照ください。

    • アカウントのSnowflake APIホスト名に一致するネットワークルールを作成します。

      CREATE OR REPLACE NETWORK RULE snowflake_egress_access
        MODE = EGRESS
        TYPE = HOST_PORT
        VALUE_LIST = ('myaccount.snowflakecomputing.com');
      
      Copy
    • 先行するネットワークルールを使用して統合を作成します。

      CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration
        ALLOWED_NETWORK_RULES = (snowflake_egress_access)
        ENABLED = true;
      
      Copy

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 ...
    
    Copy
  • 例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 ...
    
    Copy

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')
)
Copy

チュートリアル2 では、Snowflakeに接続して SQL ステートメントを実行するSnowflakeジョブサービスを作成します。以下のステップは、チュートリアルのコードがどのように環境変数を使用するかをまとめたものです。

  1. 共通セットアップ(共通セットアップ セクションを参照)では、データベースとスキーマを含む、リソースを作成します。また、セッションの現在のデータベースとスキーマも設定します。

    USE DATABASE tutorial_db;
    ...
    USE SCHEMA data_schema;
    
    Copy
  2. (EXECUTE JOB SERVICE を実行して)ジョブサービスを作成すると、Snowflakeはコンテナを起動し、コンテナ内の以下の環境変数をセッションの現在のデータベースとスキーマに設定します。

    • SNOWFLAKE_DATABASE は「TUTORIAL_DB」に設定

    • SNOWFLAKE_SCHEMA は「DATA_SCHEMA」に設定

  3. ジョブコード(チュートリアル2の main.py を参照)はこれらの環境変数を読み取ります。

    SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE')
    SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
    
    Copy
  4. ジョブコードは SQL ステートメント(main.pyrun_job() 関数)を実行するコンテキストとしてデータベースとスキーマを設定します。

    {
       "account": SNOWFLAKE_ACCOUNT,
       "host": SNOWFLAKE_HOST,
       "authenticator": "oauth",
       "token": get_login_token(),
       "warehouse": SNOWFLAKE_WAREHOUSE,
       "database": SNOWFLAKE_DATABASE,
       "schema": SNOWFLAKE_SCHEMA
    }
    ...
    
    Copy

    注釈

    SNOWFLAKE_ACCOUNT、SNOWFLAKE_HOST、 SNOWFLAKE_DATABASE、 SNOWFLAKE_SCHEMA はSnowflakeがアプリケーションコンテナー用に生成する環境変数ですが、 SNOWFLAKE_WAREHOUSE はそうではありません(Snowflakeはウェアハウス名をコンテナーに渡さないため、チュートリアル2のアプリケーションコードがこの変数を作成しました)。

コンテナー用ウェアハウスの指定

サービスがSnowflakeに接続してSnowflakeウェアハウスでクエリを実行する場合は、ウェアハウスを指定する以下のオプションがあります。

  • アプリケーションコードでウェアハウスを指定します。 コードでクエリを実行するためにSnowflakeセッションを開始する際に、接続構成の一部としてウェアハウスを指定します。例については、 チュートリアル2 をご参照ください。

  • サービスの作成時にデフォルトのウェアハウスを指定します。 デフォルトのウェアハウスを指定するには、 CREATE SERVICE (または EXECUTE JOB SERVICE)コマンドでオプションの QUERY_WAREHOUSE パラメーターを指定します。アプリケーションコードが接続構成の一部としてウェアハウスを提供しない場合、Snowflakeはデフォルトのウェアハウスを使用します。 ALTER SERVICE コマンドを使用して、デフォルトウェアハウスを変更します。

両方の方法でウェアハウスを指定した場合は、アプリケーションコードで指定されたウェアハウスが使用されます。

SQL を実行するための OAuth トークンの使用

Snowflakeが提供するすべてのクライアントは、認証方法として OAuth をサポートしています。サービスコンテナも OAuth メカニズムを使用してSnowflakeで認証を行います。たとえば、コンテナーが SQL を実行する場合、コンテナーは他のSnowflakeクライアントと同様にSnowflakeへの接続を作成します。

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'
)
Copy

サービスを作成すると、Snowflakeはコンテナを実行し、コンテナ内の /snowflake/session/token にコンテナが使用するOauthトークンを提供します。

この OAuth トークンについては、次の点に注意してください。

  • /snowflake/session/token ファイルのコンテンツは10分で期限切れとなり、Snowflakeはこのファイルを数分ごとに更新するため、コンテンツは使用する直前に読み取る必要があります。コンテナーがSnowflakeに正常に接続した後には、有効期限は接続に適用されません(ユーザーが直接作成するセッションと同様)。

  • この OAuth トークンは、特定のSnowflakeサービス内でのみ有効です。OAuth トークンをコピーしてサービス外部で使用することはできません。

  • コンテナは、 OAuth トークンを使ってサービスユーザーとしてSnowflakeに接続し、サービスの所有者ロールを使用します。

  • OAuth トークンを使用して接続すると、新しいセッションが作成されます。OAuth トークンはいずれの既存の SQL セッションとも関連付けられていません。

    注釈

    ストアドプロシージャの実行とサービスの実行の大きな違いは、ストアドプロシージャはそれを実行する SQL と同じセッションで実行されることです。しかし、コンテナーが新しい接続を確立するたびに、新しいセッションが作成されます。

ネットワーク機能の構成

以下のセクションでは、サービス(ジョブサービスを含む)のネットワーク機能(ネットワークのイングレスとエグレス)を構成する方法を説明します。

ネットワークイングレス

インターネットからサービスとのやり取りできるようにするには、サービスがリッスンしているネットワークポートを、サービス仕様ファイルのエンドポイントとして宣言します。これらのエンドポイントはイングレスを制御します。

デフォルトでは、サービスエンドポイントはプライベートです。 サービス関数サービス間通信 のみがプライベートエンドポイントにリクエストできます。エンドポイントをパブリックと宣言すると、インターネットからのエンドポイントへのリクエストを許可することができます。サービスの所有者ロールには、アカウントに対する BIND SERVICE ENDPOINT 権限が必要です。

endpoints:
- name: <endpoint name>
  port: <port number>
  protocol : < TCP / HTTP / HTTPS >
  public: true
Copy

例については、 チュートリアル1 をご参照ください。

注釈

現在、ジョブサービスではなく、サービスのみがネットワークイングレスをサポートしています。

イングレスとウェブアプリのセキュリティ

パブリックエンドポイントサポート(ネットワークイングレス)を使用して、ウェブホスティング用の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プロキシがサービスに対する受信リクエストをどのように処理し、サービスからクライアントへの送信応答をどのように変更するかを説明します。

サービスへの受信リクエスト

リクエストを受信すると、プロキシはリクエストをサービスに転送する前に以下を実行します。

  • 禁止された HTTP メソッドを持つ受信リクエスト: 受信 HTTP リクエストが以下の禁止された HTTP メソッドのいずれかを使用する場合、プロキシはそのリクエストをサービスに転送しません。

    • TRACE

    • OPTIONS

    • CONNECT

クライアントへの応答送信

Snowflakeプロキシは、クライアントに応答を転送する前に、サービスから送信された応答にこれらの修正を適用します。

  • ヘッダースクラビング: Snowflakeプロキシは、これらの応答ヘッダーを削除します(存在する場合)。

    • X-XSS-Protection

    • Server

    • X-Powered-By

    • Public-Key-Pins

  • 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';
    
    Copy

    コンテンツセキュリティポリシーの考慮点は2つあります。

    • プロキシが追加するベースラインコンテンツセキュリティポリシーに加えて、サービス自身が応答に明示的に CSP を追加することができます。サービスは、より厳格な CSP を追加して、セキュリティを強化することを選択する場合があります。たとえば、サービスは CSP を追加して、 self からのスクリプトのみを許可する場合があります。

      script-src 'self'
      
      Copy

      結果としてクライアントに送られる応答には、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';
      
      Copy

      ブラウザーは、応答で受け取ったコンテンツアクセスポリシーを尊重します。この例では、ブラウザーはアプリに example.com へのアクセスを許可しますが、他のサイトへのアクセスは許可しません。

ネットワークエグレス

アプリケーションコードは、インターネットへのアクセスを必要とする場合があります。デフォルトでは、アプリケーションコンテナーはインターネットにアクセスする権限を持っていません。 外部アクセス統合(EAIs) を使用してインターネットアクセスを有効にする必要があります。

通常、サービス(ジョブサービスを含む)から許可される外部アクセスを管理するために、アカウント管理者は EAIs を作成します。アカウント管理者は、開発者がサービスを実行するために使用する特定ロールに EAI の使用権限を付与できます。

次の例は、ネットワークルールを使用して指定された特定の宛先へのエグレストラフィックを許可する EAI を作成するステップの概要を示しています。その後、特定のインターネット宛先へのリクエストを許可するサービスを作成するときに、 EAI を参照します。

アプリケーションコードが、以下の宛先にリクエストを送信するとします。

  • HTTPS が、translation.googleapis.comにリクエストする

  • HTTP と HTTPS が、google.comにリクエストする

以下のステップに従って、サービスがインターネット上のこれらのドメインにアクセスできるようにします。

  1. 外部アクセス統合(EAI)を作成するこれには適切な権限が必要です。たとえば、 ACCOUNTADMIN ロールを使用して EAI を作成することができます。これは2段階のプロセスです。

    1. CREATE NETWORK RULE コマンドを使用して、アクセスを許可する外部宛先をリストした1つ以上のエグレスネットワークルールを作成します。この例は1つのネットワークルールで実現できますが、説明のために2つのネットワークルールを作成します。

      1. translate_network_rule という名前のネットワークルールを作成します。

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

        このルールは、 translation.googleapis.com の宛先への TCP 接続を許可します。VALUE_LIST プロパティのドメインは、オプションのポート番号を指定しないため、デフォルトのポート443(HTTPS)が想定されます。これにより、アプリケーションは https://translation.googleapis.com/ で始まる任意の URL に接続できます。

      2. google_network_rule という名前のネットワークルールを作成します。

        CREATE OR REPLACE NETWORK RULE google_network_rule
          MODE = EGRESS
          TYPE = HOST_PORT
          VALUE_LIST = ('google.com:80', 'google.com:443');
        
        Copy

        これにより、アプリケーションは 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');
      
      Copy
    2. 外部アクセス統合(EAI) を作成し、先行する2つのエグレスネットワークルールが許可されることを指定します。

      CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration
        ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule)
        ENABLED = true;
      
      Copy

      これで、アカウント管理者は、開発者に統合の使用権限を付与して、インターネット上の特定の宛先にアクセスできるサービスを実行できるようにすることができます。

      GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
      
      Copy
  2. 以下の例に示すように、 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
        $$;
      
      Copy

      この例の 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/"
        $$;
      
      Copy

      この例の EXECUTE JOB SERVICE コマンドは、インライン仕様と、 EAI を含めるためのオプション EXTERNAL_ACCESS_INTEGRATIONS プロパティを指定します。これは、ジョブから 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>
      ...
    
    Copy

    なお、 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>
    
    Copy

    この仕様では、シークレットの参照名を提供するために、 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>'
Copy

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';
Copy

このSnowflakeシークレットオブジェクトをコンテナー内の環境変数(例: LOGIN_USERLOGIN_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
Copy

この例では、 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
  ';
Copy

このSnowflakeシークレットオブジェクトをコンテナー内の環境変数(例: GENERIC_SECRET)に提供するには、仕様ファイルに以下の containers.secrets フィールドを追加します。

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret
    secretKeyRef: secret_string
    envVarName: GENERIC_SECRET
Copy

ローカルコンテナーファイルでのシークレットを記述する

ローカルコンテナーファイル内のアプリケーションコンテナーで Snowflake シークレットを利用できるようにするには、 containers.secrets フィールドを含めます。ローカルコンテナーファイル内のアプリケーションコンテナーでSnowflake のシークレットを利用できるようにするには、 containers.secretsdirectoryPath を含めます。

containers:
- name: <name>
  image: <url>
  ...
  secrets:
  - snowflakeSecret: <snowflake-secret-name>
    directoryPath: '<local directory path in the container>'
Copy

Snowflakeは、この指定された directoryPath; secretKeyRef を指定する必要はありません。シークレットタイプに応じて、Snowflakeは指定したディレクトリパスの下のコンテナー内に以下のファイルを作成します。

  • Snowflakeシークレットが password 型の場合、 usernamepassword です。

  • 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';
Copy

これらの認証情報をローカルコンテナーファイルで利用できるようにするには、仕様ファイルに以下の containers.secrets フィールドを追加します。

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret_object
    directoryPath: '/usr/local/creds'
Copy

サービスを開始すると、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
  ';
Copy

このSnowflakeシークレットオブジェクトをローカルコンテナーファイルで提供するには、仕様ファイルに以下の containers.secrets フィールドを追加します。

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.my_secret
    directoryPath: '/usr/local/creds'
Copy

サービスを開始すると、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;
Copy

これらの認証情報をローカルコンテナーファイルで利用できるようにするには、仕様ファイルに以下の containers.secrets フィールドを追加します。

containers:
- name: main
  image: <url>
  secrets:
  - snowflakeSecret: testdb.testschema.oauth_secret
    directoryPath: '/usr/local/creds'
Copy

Snowflakeは OAuth シークレットオブジェクトからアクセストークンをフェッチし、コンテナーに /usr/local/creds/access_token を作成します。

サービスがoauth2型のシークレットを使用する場合、サービスはインターネット宛先にアクセスするためにそのシークレットを使用することが求められます。oauthシークレットは 外部アクセス統合(EAI) によって許可される必要があります。それ以外の場合、 CREATE SERVICE または EXECUTE JOB SERVICE は失敗します。この追加の EAI 要件は、oauth2型のシークレットにのみ適用され、他の型のシークレットには適用されません。

要約すると、このようなサービスを作る際の典型的なステップは以下のとおりです。

  1. oauth2型のシークレットを作成します(前述のとおり)。

  2. サービスによるシークレットの使用を許可する EAI を作成します。例:

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION example_eai
      ALLOWED_NETWORK_RULES = (<name>)
      ALLOWED_AUTHENTICATION_SECRETS = (testdb.testschema.oauth_secret)
      ENABLED = true;
    
    Copy
  3. 仕様に 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
      $$;
    
    Copy

エグレスの詳細については、 ネットワークエグレス をご参照ください。

ガイドラインと制約

  • 一般的な制限: これらの制限に関する問題が発生した場合は、アカウント担当者にお問い合わせください。

    • Snowflakeアカウントには最大200のサービスを作成できます。

    • 各サービスは最大100のエンドポイントを公開できます。

    • 外部アクセス統合(EAIs)を使用してインターネットアクセス(ネットワークエグレス)を有効にすると、以下の制限が適用されます。

      • 各サービスは最大10個の EAIs (CREATE SERVICE および ALTER SERVICE を参照)をサポートすることができます。

      • 各 EAI は最大100のホスト名を持つことができます。

  • イメージプラットフォームの要件: 現在、Snowpark Container Servicesにはlinux/amd64プラットフォームイメージが必要です。

  • サービスコンテナの権限なし: サービスコンテナは権限として実行されないため、ホスト上のハードウェアの構成を変更できず、限られた OS 構成のみを変更できます。サービスコンテナは、通常のユーザー(つまり、ルートを必要としないユーザー)ができるオペレーティングシステム構成のみを実行できます。

  • データベースおよびスキーマの名前変更:

    • すでにサービスを作成したデータベースやスキーマの名前は変更しないでください。名前変更は事実上、サービスを別のデータベースとスキーマに移動することになりますが、これはサポートされていません。例:

      • サービス DNS 名は従来のデータベース名とスキーマ名を反映し続けます。

      • Snowflakeが実行中のサービスコンテナーに提供したデータベースとスキーマの情報は、引き続き従来の名前を参照します。

      • サービスがイベントテーブルにインジェストする新しいログは、従来のデータベース名とスキーマ名を参照し続けます。

      • サービス関数は従来のデータベースとスキーマのサービスを参照し続け、サービス関数を呼び出すと失敗します。

    • サービス仕様は、Snowflakeステージやイメージリポジトリなどのオブジェクトを参照することができます。これらのオブジェクトが存在するデータベース名やスキーマ名を変更した場合は、サービス仕様の参照オブジェクトのデータベース名やスキーマ名を手動で更新する必要があります。

  • データベースおよびスキーマのドロップおよびドロップ解除:

    • 親データベースまたはスキーマをドロップすると、サービスは非同期に削除されます。つまり、内部プロセスでサービスが削除されるまで、しばらくの間サービスが実行され続ける可能性があります。

    • 以前に削除されたデータベースやスキーマのドロップ解除を試行しても、サービスが復元される保証はありません。

  • 所有者譲渡: サービス(ジョブサービスを含む)の所有権譲渡はサポートされていません。

  • 複製: Snowflakeで複製を扱う場合、以下の点に注意してください。

    • サービス、コンピューティングプール、リポジトリなどのSnowpark Container Servicesオブジェクトを複製することはできません。

    • データベース内にリポジトリを作成した場合は、データベース全体を複製することはできません。データベースにサービス、コンピューティングプールなどの他のリソースが含まれている場合、データベースの複製プロセスは成功しますが、データベース内の個々のオブジェクトは複製されません。

  • ジョブサービスのタイムアウト: Snowparkコンテナサービスのジョブサービスは同期的に実行されます。ステートメントがタイムアウトすると、ジョブサービスはキャンセルされます。デフォルトのステートメントタイムアウトは2日間。お客様は、ALTER SESSION を使用してパラメーター STATEMENT_TIMEOUT_IN_SECONDS を設定することにより、タイムアウトを変更できます。

    ALTER SESSION SET statement_timeout_in_seconds=<time>
    
    Copy

    EXECUTE JOB SERVICE コマンドを実行する前に設定します。