Gerenciamento de segredos e configuração do app Streamlit

Os apps Streamlit geralmente precisam acessar informações confidenciais, como chaves deAPI, senhas e outras credenciais. A forma como você gerencia segredos no app Streamlit depende do ambiente de tempo de execução que você usa. O Streamlit in Snowflake oferece mecanismos seguros e integrados para acessar segredos nos tempos de execução tanto de warehouse quanto de contêiner. Para configuração do Streamlit, cada tempo de execução também tem restrições diferentes.

Na biblioteca Streamlit, os apps usam um diretório .streamlit/ para armazenar configurações e segredos:

  • .streamlit/config.toml: personaliza as configurações do app, como tema, layout e comportamento do servidor.

  • .streamlit/secrets.toml: armazena informações confidenciais, como chaves de API e credenciais (em desenvolvimento local).

O Streamlit in Snowflake oferece suporte a esses arquivos com algumas limitações, dependendo do seu ambiente de tempo de execução. A tabela a seguir resume o suporte para esses arquivos nos tempos de execução de warehouse e contêiner:

Recurso

Tempo de execução de warehouse

Tempo de execução de contêiner

Suporte para config.toml

Subconjunto limitado de opções de configuração

Subconjunto mais amplo de opções de configuração

Suporte para secrets.toml

Sem suporte

Com suporte, mas recomendado somente para variáveis de ambiente não secretas

Para secrets.toml, o Streamlit in Snowflake fornece um sistema de gerenciamento de segredos integrado mais seguro, recomendado para o gerenciamento de informações confidenciais. As seções a seguir descrevem como usar os segredos do Snowflake em seus apps.

Gerenciamento da conexão com o Snowflake

Para gerenciar sua conexão com o Snowflake, você pode usar st.connection("snowflake"). Isso permite que você se conecte ao Snowflake do seu ambiente de desenvolvimento local e do seu app implantado.

import streamlit as st

conn = st.connection("snowflake")
session = conn.session()

session.sql("SELECT 1").collect()
Copy

Nos tempos de execução de warehouse, você também pode usar a função get_active_session() do Snowpark para obter a sessão ativa.

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

Importante

get_active_session() não é thread-safe e não pode ser usado em tempos de execução de contêiner.

Segredos em tempos de execução de contêiner

Os tempos de execução de contêiner não têm acesso ao módulo _snowflake porque eles são executados fora do ambiente do procedimento armazenado. Para acessar segredos em um tempo de execução de contêiner, você deve criar funções SQL que usem o módulo _snowflake e, em seguida, chamar essas funções do seu app Streamlit. Para chamadas da Cortex API, você deve usar requests.

Se você atualizar um app Streamlit mais antigo para um tempo de execução de contêiner, as funções _snowflake a seguir deverão ser substituídas por procedimentos armazenados. Esse procedimento está descrito na próxima seção.

  • get_generic_secret_string

  • get_oauth_access_token

  • get_username_password

  • get_cloud_provider_token

  • get_secret_type

Além disso, a função _snowflake a seguir deve ser substituída por uma chamada de API manual, autenticada com um token de sessão. Esse procedimento está descrito em uma seção posterior, Chamada de um Cortex Agent em tempo de execução de contêiner.

  • send_snow_api_request

Acesso a um segredo em um tempo de execução de contêiner

Para acessar um segredo em um tempo de execução de contêiner, siga as etapas abaixo:

  1. Crie um segredo em sua conta Snowflake. Consulte CREATE SECRET.

    CREATE OR REPLACE SECRET my_secret
      TYPE = GENERIC_STRING
      SECRET_STRING = 'my_secret_value';
    
    Copy
  2. Crie uma função para acessar o segredo. Consulte API de Python para acesso secreto.

    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')
    $$;
    
    Copy
  3. Crie seu app Streamlit com o seguinte tempo de execução de contêiner:

    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);
    
    Copy
  4. No código do app Streamlit, chame a função SQL para recuperar o segredo:

    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]
    
    Copy

Uso de .streamlit/secrets.toml para variáveis de ambiente não secretas

Você pode tecnicamente adicionar um arquivo .streamlit/secrets.toml ao diretório de origem do seu app, mas isso não é recomendado para armazenar segredos reais. O arquivo secrets.toml é armazenado como texto simples em seus arquivos preparados, o que não é uma prática recomendada de segurança.

Entretanto, o secrets.toml pode ser útil para armazenar valores de configuração não confidenciais ou configurações específicas do ambiente que você deseja acessar pelo st.secrets em seu código ou que uma dependência exige como variável de ambiente:

# .streamlit/secrets.toml
# ONLY USE FOR NON-SECRET CONFIGURATION VALUES
app_name = "My Streamlit App"
api_endpoint = "https://api.example.com"
max_results = 100
Copy

Em seguida, é possível acessar esses valores no app por meio do st.secrets ou como variáveis de ambiente:

import streamlit as st
import os

app_name = st.secrets["app_name"]
API_ENDPOINT = os.getenv("API_ENDPOINT")
Copy

Para segredos reais, como chaves de API, senhas e tokens, sempre use o sistema de gerenciamento de segredos integrado do Snowflake, conforme descrito na seção anterior.

Chamada de um Cortex Agent em tempo de execução de contêiner

Para chamar um Cortex Agent em um app de tempo de execução de contêiner, leia o token de sessão do contêiner Snowpark Container Services subjacente e use a biblioteca requests. Esse é o procedimento substituto recomendado para _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))
Copy

Segredos em tempos de execução de warehouse

Em tempos de execução de warehouse, você pode usar o módulo _snowflake para acessar segredos diretamente no código do app Streamlit. Os tempos de execução de warehouse herdam o acesso ao módulo _snowflake dos procedimentos armazenados, o que permite recuperar segredos referenciados no objeto Streamlit.

Para usar segredos em um tempo de execução de warehouse:

  1. Crie um objeto de segredo no Snowflake. Para obter mais informações, consulte CREATE SECRET.

    CREATE OR REPLACE SECRET my_secret
      TYPE = GENERIC_STRING
      SECRET_STRING = 'my_secret_value';
    
    Copy
  2. Crie uma integração de acesso externo e atribua o segredo a ela.

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION my_eai
      ALLOWED_AUTHENTICATION_SECRETS = (my_secret)
      ENABLED = TRUE;
    
    Copy
  3. Faça referência ao segredo em seu objeto Streamlit usando o parâmetro SECRETS:

    ALTER STREAMLIT my_warehouse_app
      SET EXTERNAL_ACCESS_INTEGRATIONS = (my_eai)
      SECRETS = ('my_secret_key' = my_secret);
    
    Copy

    Você deve atribuir a integração de acesso externo e o segredo ao objeto Streamlit. Não é possível atribuir apenas o segredo a um objeto Streamlit.

  4. No código do app Streamlit, importe o módulo _snowflake e recupere o segredo:

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

Para obter mais informações sobre como acessar segredos com o módulo _snowflake, consulte API de Python para acesso secreto.

Configuração do Streamlit

Os apps Streamlit podem incluir um arquivo de configuração (.streamlit/config.toml). Esse arquivo permite que você personalize vários aspectos do seu app, como tema, layout e comportamento. O arquivo de configuração é escrito no formato TOML. Para obter mais informações sobre as opções de configuração disponíveis, consulte a documentação do Streamlit em config.toml.

O suporte para opções de configuração varia de acordo com o ambiente de tempo de execução. Os tempos de execução de contêiner geralmente oferecem suporte mais amplo para opções de configuração do que os tempos de execução de warehouse, em especial para serviços estáticos. A tabela a seguir mostra quais seções de configuração são compatíveis com os tempos de execução de warehouse e de contêiner:

Seção de configuração

Tempo de execução de warehouse

Tempo de execução de contêiner

[global]

Sem suporte

Suporte limitado (disableWidgetStateDuplicationWarning)

[logger]

Sem suporte

Sem suporte

[client]

Sem suporte

Suporte limitado (showErrorDetails, showSidebarNavigation)

[runner]

Sem suporte

Com suporte

[server]

Sem suporte

Sem suporte

[browser]

Sem suporte

Sem suporte

[mapbox]

Sem suporte

Com suporte (obsoleto, use variáveis de ambiente em vez disso)

[theme]

Com suporte

Com suporte

[theme.sidebar]

Com suporte

Com suporte

[secrets]

Sem suporte

Com suporte (mas recomendado apenas para variáveis de ambiente não secretas)

[snowflake.sleep]

Com suporte

Não aplicável

Para obter informações sobre como usar a seção [snowflake.sleep] para configurar temporizadores de suspensão em tempos de execução de warehouse, consulte Temporizador de sono personalizado para um aplicativo Streamlit.

A estrutura de diretório a seguir mostra um exemplo de um app Streamlit com um arquivo de configuração:

source_directory/
├── .streamlit/
│   └── config.toml
├── pyproject.toml
├── streamlit_app.py
└── uv.lock
Copy