シークレットを管理し、Streamlitアプリを設定する¶
Streamlitアプリは、しばしば API キー、パスワード、およびその他の認証情報などの機密情報にアクセスする必要があります。Streamlitアプリでシークレットをどのように管理するかは、使用しているランタイム環境によって異なります。 Streamlit in Snowflake は、ウェアハウスとコンテナランタイムの両方でシークレットにアクセスするための安全な組み込みメカニズムを提供します。Streamlitの構成では、各ランタイムにも異なる制限があります。
Streamlitライブラリでは、アプリは .streamlit/ ディレクトリを使用して構成とシークレットを保存します。
.streamlit/config.toml:テーマ、レイアウト、サーバーの動作などのアプリの設定をカスタマイズします。.streamlit/secrets.toml:API キーや認証情報などの機密情報を保管します(ローカル開発の場合)
Streamlit in Snowflake はこれらのファイルをサポートしていますが、ランタイム環境に応じていくつかの制限があります。次のテーブルは、ウェアハウスとコンテナランタイムにおけるこれらのファイルのサポートをまとめたものです。
機能 |
ウェアハウスランタイム |
コンテナランタイム |
|---|---|---|
|
構成オプションの限られたサブセット |
構成オプションのより広範なサブセット |
|
サポート対象外 |
サポートされていますが、非シークレットの環境変数に対してのみ推奨されます。 |
secrets.toml の場合、 Streamlit in Snowflake は、機密情報の管理に推奨される、より安全な組み込みのシークレット管理システムを提供します。次のセクションでは、アプリでSnowflakeのシークレットを使用する方法について説明します。
Snowflakeへの接続の管理¶
Snowflakeへの接続を管理するには、 st.connection("snowflake") を使用します。これにより、ローカルの開発環境とデプロイされたアプリの両方からSnowflakeに接続できます。
import streamlit as st
conn = st.connection("snowflake")
session = conn.session()
session.sql("SELECT 1").collect()
ウェアハウスのランタイムでは、Snowparkのアクティブなセッションを取得する get_active_session() 関数を使用できます。
import streamlit as st
from snowflake.snowpark.context import get_active_session
# ONLY IN WAREHOUSE RUNTIMES
session = get_active_session()
session.sql("SELECT 1").collect()
重要
get_active_session() はスレッドセーフではなく、コンテナランタイムでは使用できません。
コンテナランタイムのシークレット¶
コンテナランタイムはストアドプロシージャ環境の外部で実行されるため、 _snowflake モジュールにアクセスできません。コンテナランタイムでシークレットにアクセスするには、 _snowflake モジュールを使用する SQL 関数を作成する必要があり、Streamlitアプリからこれらの関数を呼び出します。Cortex用 API 呼び出しの場合は、 requests を使用する必要があります。
古いStreamlitアプリをコンテナランタイムにアップグレードした場合、次の _snowflake 関数はストアドプロシージャに置き換える必要があります。これについては次のセクションで説明します。
get_generic_secret_stringget_oauth_access_tokenget_username_passwordget_cloud_provider_tokenget_secret_type
さらに、次の _snowflake 関数は、セッショントークンで認証された手動 API 呼び出しに置き換える必要があります。これは後のセクション コンテナランタイム内でのCortex Agentの呼び出し で説明します。
send_snow_api_request
コンテナランタイムでシークレットにアクセスする¶
コンテナランタイムでシークレットにアクセスするには、以下の手順を実行します。
Snowflakeアカウントにシークレットを作成します。CREATE SECRET をご参照ください。
CREATE OR REPLACE SECRET my_secret TYPE = GENERIC_STRING SECRET_STRING = 'my_secret_value';
シークレットにアクセスする関数を作成します。シークレットアクセスのためのPython API をご参照ください。
CREATE OR REPLACE FUNCTION get_my_secret() RETURNS STRING LANGUAGE PYTHON RUNTIME_VERSION = 3.12 HANDLER = 'get_my_secret' EXTERNAL_ACCESS_INTEGRATIONS = (my_eai) SECRETS = ('my_secret' = my_secret) AS $$ import _snowflake def get_my_secret(): return _snowflake.get_generic_secret_string('my_secret') $$;
コンテナランタイムでStreamlitアプリを作成します。
CREATE STREAMLIT my_container_app FROM '@my_stage/app_folder' MAIN_FILE = 'streamlit_app.py' RUNTIME_NAME = 'SYSTEM$ST_CONTAINER_RUNTIME_PY3_11' COMPUTE_POOL = my_compute_pool QUERY_WAREHOUSE = my_warehouse EXTERNAL_ACCESS_INTEGRATIONS = (my_eai);
Streamlitアプリのコードで、 SQL 関数を呼び出してシークレットを取得します。
import streamlit as st # Get the Snowflake connection conn = st.connection("snowflake") session = conn.session() # Call the function to retrieve the secret secret = session.sql("SELECT get_my_secret()").collect()[0][0]
非シークレット環境変数に .streamlit/secrets.toml を使用する¶
技術的には .streamlit/secrets.toml ファイルをアプリのソースディレクトリに追加できますが、 実際のシークレットを保存するためには推奨されていません。secrets.toml ファイルはステージングされたファイルにプレーンテキストとして保存されますが、これはセキュリティのベストプラクティスではありません。
ただし secrets.toml は、コード内で st.secrets 経由でアクセスする、または依存関係で環境変数として必要な、機密性のない構成値や環境固有の設定を保存するのに役立ちます。
# .streamlit/secrets.toml
# ONLY USE FOR NON-SECRET CONFIGURATION VALUES
app_name = "My Streamlit App"
api_endpoint = "https://api.example.com"
max_results = 100
その後、st.secrets または環境変数を通じてアプリ内でこれらの値にアクセスできるようになります。
import streamlit as st
import os
app_name = st.secrets["app_name"]
API_ENDPOINT = os.getenv("API_ENDPOINT")
API キー、パスワード、トークンのような実際のシークレットの場合、前のセクションで説明したように、常にSnowflakeの組み込みシークレット管理システムを使用します。
コンテナランタイム内でのCortex Agentの呼び出し¶
コンテナランタイムアプリでCortex Agentを呼び出すには、基になる Snowpark Container Services コンテナからセッショントークンを読み取り、 requests ライブラリを使用します。これは、 _snowflake.send_snow_api_request() に推奨される交換です。
import requests
import json
import os
SNOWFLAKE_HOST = os.getenv("SNOWFLAKE_HOST")
SNOWFLAKE_ACCOUNT = os.getenv("SNOWFLAKE_ACCOUNT")
ANALYST_ENDPOINT = "/api/v2/cortex/analyst/message"
URL = "https://" + SNOWFLAKE_HOST + ANALYST_ENDPOINT
def get_token() -> str:
"""Read the oauth token embedded into SPCS container"""
return open("/snowflake/session/token", "r").read()
def send_request(semantic_model_file, prompt):
"""Sends the prompt using the semantic model file """
headers = {
"Content-Type": "application/json",
"accept": "application/json",
"Authorization": f"Bearer {get_token()}",
"X-Snowflake-Authorization-Token-Type": "OAUTH"
}
request_body = {
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": prompt}],
}
],
"semantic_model_file": semantic_model_file,
}
return requests.post(URL, headers=headers, data=json.dumps(request_body))
ウェアハウスランタイムのシークレット¶
ウェアハウスのランタイムでは、 _snowflake モジュールを使用して、Streamlitアプリコード内のシークレットに直接アクセスできます。ウェアハウスランタイムは、ストアドプロシージャから _snowflake モジュールへのアクセスを継承し、これによりStreamlitオブジェクトで参照されるシークレットを取得できるようになります。
ウェアハウスランタイムでシークレットを使用するには次のようにします。
Snowflakeでシークレットオブジェクトを作成します。詳細については、 CREATE SECRET をご参照ください。
CREATE OR REPLACE SECRET my_secret TYPE = GENERIC_STRING SECRET_STRING = 'my_secret_value';
外部アクセス統合を作成し、それにシークレットを割り当てます。
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION my_eai ALLOWED_AUTHENTICATION_SECRETS = (my_secret) ENABLED = TRUE;
SECRETS パラメーターを使用して、Streamlitオブジェクト内のシークレットを参照します。
ALTER STREAMLIT my_warehouse_app SET EXTERNAL_ACCESS_INTEGRATIONS = (my_eai) SECRETS = ('my_secret_key' = my_secret);
外部アクセス統合とシークレットの両方をStreamlitオブジェクトに割り当てる必要があります。Streamlitオブジェクトに単独でシークレットを割り当てることはできません。
Streamlitアプリのコードで、
_snowflakeモジュールをインポートしてシークレットを取得します。import streamlit as st import _snowflake # Retrieve an API key from a generic string secret my_secret = _snowflake.get_generic_secret_string('my_secret_key')
_snowflake モジュールを使用したシークレットへのアクセスの詳細については、 シークレットアクセスのためのPython API をご参照ください。
Streamlit構成¶
Streamlitアプリには、構成ファイル(.streamlit/config.toml)を含めることができます。このファイルを使うと、テーマ、レイアウト、動作など、アプリの様々な側面をカスタマイズできます。構成ファイルは TOML 形式で書き込まれます。使用可能な構成オプションの詳細については、Streamlitドキュメントの config.toml をご参照ください。
構成オプションのサポートは、ランタイム環境によって異なります。コンテナランタイムは通常、特に静的サービングのために、ウェアハウスランタイムよりも広範な構成オプションのサポートを提供します。次のテーブルは、ウェアハウスとコンテナランタイムでサポートされている構成セクションを示しています。
構成セクション |
ウェアハウスランタイム |
コンテナランタイム |
|---|---|---|
|
サポート対象外 |
限定サポート( |
|
サポート対象外 |
サポート対象外 |
|
サポート対象外 |
限定サポート( |
|
サポート対象外 |
サポート対象 |
|
サポート対象外 |
サポート対象外 |
|
サポート対象外 |
サポート対象外 |
|
サポート対象外 |
サポート対象(非推奨、代わりに環境変数を使用) |
|
サポート対象 |
サポート対象 |
|
サポート対象 |
サポート対象 |
|
サポート対象外 |
サポート対象(ただし、非シークレット環境変数の場合のみ推奨) |
|
サポート対象 |
該当なし |
[snowflake.sleep] セクションを使用してウェアハウスランタイムでスリープタイマーを構成する方法については、 Streamlitアプリのカスタムスリープタイマー を参照してください。
次のディレクトリ構造は、構成ファイルを使用したStreamlitアプリの例です。
source_directory/
├── .streamlit/
│ └── config.toml
├── pyproject.toml
├── streamlit_app.py
└── uv.lock