管理密钥并配置 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") (https://docs.streamlit.io/develop/api-reference/connections/st.connections.snowflakeconnection)。这允许您从本地开发环境和部署的应用程序连接到 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 格式编写。有关可用配置选项的更多信息,请参阅 config.toml (https://docs.streamlit.io/develop/api-reference/configuration/config.toml) 上的 Streamlit 文档。
对配置选项的支持因运行时环境而异。与仓库运行时相比,容器运行时通常为配置选项提供更广泛的支持,特别是在静态服务方面。下表显示了仓库和容器运行时支持哪些配置部分:
配置部分 |
仓库运行时 |
容器运行时 |
|---|---|---|
|
不支持 |
有限支持 ( |
|
不支持 |
不支持 |
|
不支持 |
有限支持( |
|
不支持 |
支持 |
|
不支持 |
不支持 |
|
不支持 |
不支持 |
|
不支持 |
支持(已弃用,请改用环境变量) |
|
支持 |
支持 |
|
支持 |
支持 |
|
不支持 |
支持(但仅建议用于非密钥环境变量) |
|
支持 |
不适用 |
有关使用 [snowflake.sleep] 部分在仓库运行时配置睡眠计时器的信息,请参阅 为 Streamlit 应用程序自定义睡眠计时器。
以下目录结构显示了带有配置文件的 Streamlit 应用程序示例:
source_directory/
├── .streamlit/
│ └── config.toml
├── pyproject.toml
├── streamlit_app.py
└── uv.lock