Gérer les secrets et configurer votre application Streamlit

Les applications Streamlit ont souvent besoin d’accéder à des informations sensibles, telles que des clés d’API, des mots de passe et d’autres identifiants de connexion. La manière dont vous gérez les secrets dans votre application Streamlit dépend de l’environnement d’exécution que vous utilisez. Streamlit in Snowflake fournit des mécanismes sécurisés et intégrés pour accéder aux secrets dans les environnements d’exécution des entrepôts et des conteneurs. Pour la configuration Streamlit, chaque exécution présente également des restrictions différentes.

Dans la bibliothèque Streamlit, les applications utilisent un répertoire .streamlit/ pour stocker la configuration et les secrets :

  • .streamlit/config.toml : Personnalise les paramètres de l’application, tels que le thème, la disposition et le comportement du serveur.

  • .streamlit/secrets.toml : Stocke des informations sensibles, telles que des clés d’API et des identifiants de connexion (dans le développement local).

Streamlit in Snowflake prend en charge ces fichiers avec certaines limitations en fonction de votre environnement d’exécution. Le tableau suivant résume la prise en charge de ces fichiers dans les exécutions d’entrepôts et de conteneurs :

Fonctionnalité

Exécution d’entrepôts

Exécution de conteneurs

Prise en charge de config.toml

Sous-ensemble limité d’options de configuration

Sous-ensemble plus large d’options de configuration

Prise en charge de secrets.toml

Non pris en charge

Pris en charge, mais uniquement recommandé pour les variables d’environnement non secrètes

Pour secrets.toml, Streamlit in Snowflake fournit un système de gestion des secrets intégré plus sécurisé, qui est recommandé pour la gestion des informations sensibles. Les sections suivantes décrivent comment utiliser les secrets Snowflake dans vos applications.

Gestion de votre connexion à Snowflake

Pour gérer votre connexion à Snowflake, vous pouvez utiliser une st.connection("snowflake"). Celle-ci vous permet de vous connecter à Snowflake à partir de votre environnement de développement local et de votre application déployée.

import streamlit as st

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

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

Dans les exécutions d’entrepôts, vous pouvez également utiliser la fonction get_active_session() de Snowpark pour accéder à la session active.

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

Important

get_active_session() n’est pas sécurisé pour les threads et ne peut pas être utilisé dans les exécutions de conteneurs.

Secrets dans les exécutions de conteneurs

Vous pouvez utiliser st.secrets pour accéder aux secrets Snowflake dans les applications Streamlit in Snowflake de votre runtime de conteneur. Cela vous permet de stocker et de récupérer en toute sécurité des informations sensibles telles que les clés d’API, les identifiants de connexion et d’autres valeurs de configuration. Tout comme le fait Streamlit pour .streamlit/secrets.toml dans le développement local, Streamlit in Snowflake renseigne également les secrets dans les variables d’environnement.

Note

Les runtimes de conteneurs n’ont pas accès au module _snowflake. Si vous migrez une ancienne application de runtime d’entrepôt qui utilise des fonctions secrètes _snowflake, remplacez ces appels par st.secrets comme décrit dans cette section.

Accéder à un secret dans une exécution de conteneur

  1. Préparez le fichier Python suivant dans @my_stage/app_folder/streamlit_app.py. Pour plus d’informations sur la mise en zone de préparation des fichiers, voir Mise des fichiers en zone de préparation à l’aide de Snowsight.

    import streamlit as st
    
    secret_value = st.secrets["my_secret_name"]
    
  2. Créez un secret dans votre compte Snowflake :

    CREATE OR REPLACE SECRET my_secret
      TYPE = GENERIC_STRING
      SECRET_STRING = 'my_secret_value';
    

    Pour plus d’informations, voir CREATE SECRET.

  3. Créez une intégration d’accès externe (EAI), et attribuez-lui le secret.

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION my_eai
      ALLOWED_AUTHENTICATION_SECRETS = (my_secret)
      ENABLED = TRUE;
    
  4. Créez votre application Streamlit pour référencer le secret à l’aide du paramètre SECRETS :

    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)
      SECRETS = ('my_secret_name' = my_secret);
    
    ALTER STREAMLIT my_container_app ADD LIVE VERSION FROM LAST;
    

    Note

    Vous devez assigner à la fois le EAI et le secret de l’objet Streamlit. Vous ne pouvez pas attribuer un secret à un objet Streamlit par lui-même.

    Parce que le secret de la chaîne générique my_secret est associé à la chaîne "my_secret_name" dans le paramètre SECRETS, vous pouvez accéder au secret dans le code de votre application Streamlit en utilisant st.secrets["my_secret_name"].

Types de secrets et variables d’environnement pris en charge

Les environnements de runtime de conteneur prennent en charge les chaînes génériques et les secrets d’authentification de base. Outre le mappage de secrets à st.secrets,|sis| mappe également les secrets aux variables d’environnement. Les noms des variables d’environnement sont sensibles à la casse. Pour les secrets d’authentification de base, deux variables d’environnement sont créées : une pour le nom d’utilisateur (suffixe _USERNAME), et une pour le mot de passe (suffixe _PASSWORD).

Type de secret

Accès st.secrets

Accès aux variables d’environnement

Chaîne générique

st.secrets["my_secret_name"]

os.environ["my_secret_name"]

Authentification de base (nom d’utilisateur)

st.secrets["my_secret_name"]["username"]

os.environ["my_secret_name_USERNAME"]

Authentification de base (mot de passe)

st.secrets["my_secret_name"]["password"]

os.environ["my_secret_name_PASSWORD"]

Note

Le fournisseur Cloud, la clé symétrique et les types de secret OAuth ne sont actuellement pas pris en charge.

Secrets de chaîne génériques

Les secrets de chaînes génériques sont stockés en tant que clés de premier niveau dans st.secrets :

ALTER STREAMLIT my_container_app
  SET SECRETS = ('my_generic_secret_name' = my_generic_secret);

Vous pouvez accéder au secret en utilisant le dictionnaire ou la notation d’attributs :

import streamlit as st

api_key = st.secrets["my_generic_secret_name"]
api_key = st.secrets.my_generic_secret_name

Secrets d’authentification de base

Les secrets d’authentification de base sont stockés sous forme d’objets de type dict avec des attributs "username" et`` »password »`` :

ALTER STREAMLIT my_container_app
  SET SECRETS = ('my_basic_auth_secret_name' = my_basic_auth_secret);

Vous pouvez accéder au secret en utilisant le dictionnaire ou la notation d’attributs :

import streamlit as st

username = st.secrets["my_basic_auth_secret_name"]["username"]
password = st.secrets["my_basic_auth_secret_name"]["password"]

username = st.secrets.my_basic_auth_secret_name.username
password = st.secrets.my_basic_auth_secret_name.password

Secrets pour les référentiels de paquets authentifiés

Les secrets sont automatiquement exposés en tant que variables d’environnement. En particulier, cela permet l’authentification avec des référentiels de paquets privés comme JFrog Artifactory.

Pour la plupart des référentiels de paquets authentifiés, utilisez un secret d’authentification de base. Le secret est automatiquement converti en variables d’environnement avec les suffixes _USERNAME et``_PASSWORD``. Si vous avez besoin d’une convention de dénomination différente, utilisez des secrets de chaîne génériques et définissez le nom de chaque variable d’environnement manuellement. Pour plus d’informations sur les variables d’environnement utilisées par uv, voir `Index de paquets<https://docs.astral.sh/uv/concepts/indexes/#providing-credentials-directly>`_ dans la documentation uv.

Exemple : S’authentifier auprès d’un référentiel JFrog Artifactory privé

  1. Mettez en zone de préparation les fichiers sources de votre application dans @my_stage/app_folder. Les fichiers sources de votre appli doivent inclure un fichier:file:pyproject.toml qui configure l’index des paquets privés dans la table [[tool.uv.index]] :

    [[tool.uv.index]]
    name = "my_jfrog_repo"
    url = "https://my-org.jfrog.io/artifactory/api/pypi/pypi-local/simple"
    

    Pour plus d’informations sur la déclaration des dépendances de votre appli dans un fichier pyproject.toml, voir:doc:/developer-guide/streamlit/app-development/dependency-management.

  2. Créez un secret d’authentification de base avec vos identifiants de connexion JFrog :

    CREATE OR REPLACE SECRET jfrog_creds
      TYPE = PASSWORD
      USERNAME = 'my_username'
      PASSWORD = 'my_api_token';
    
  3. Créez une intégration d’accès externe pour votre référentiel privé :

    CREATE OR REPLACE NETWORK RULE jfrog_network_rule
      TYPE = HOST_PORT
      MODE = EGRESS
      VALUE_LIST = ('my-org.jfrog.io');
    
    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION jfrog_eai
      ALLOWED_NETWORK_RULES = (jfrog_network_rule)
      ALLOWED_AUTHENTICATION_SECRETS = (jfrog_creds)
      ENABLED = TRUE;
    

    Note

    Pour éviter une erreur DNS, vous devrez peut-être inclure le fournisseur Cloud de votre référentiel dans la liste de valeurs de la règle réseau. Par exemple, si votre référentiel se trouve sur AWS, vous pouvez avoir besoin de la liste de valeurs suivante dans votre règle réseau :

    VALUE_LIST = ('my-org.jfrog.io', '<jfrog-server-name>.s3.amazonaws.com');
    
  4. Joignez l’EAI et le secret à votre application Streamlit :

    CREATE STREAMLIT my_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 = (jfrog_eai)
      SECRETS = ('UV_INDEX_MY_JFROG_REPO' = jfrog_creds);
    
    ALTER STREAMLIT my_app ADD LIVE VERSION FROM LAST;
    

    Parce que le secret d’authentification de base jfrog_creds est associé à la chaîne "UV_INDEX_MY_JFROG_REPO" dans le paramètre SECRETS, le runtime injecte automatiquement les variables d’environnement UV_INDEX_MY_JFROG_REPO_USERNAME et``UV_INDEX_MY_JFROG_REPO_PASSWORD`` selon les exigences de uv.

Ordre de précédence d’un fichier .streamlit/secrets.toml local

Vous pouvez combiner des secrets gérés par Snowflake avec un fichier .streamlit/secrets.toml local dans le répertoire source de votre application. Lorsque les deux sont présents, la bibliothèque Streamlit les fusionne. Le fichier .streamlit/secrets.toml défini localement a la priorité sur les secrets gérés par Snowflake.

Parce que .streamlit/secrets.toml est stocké sous forme de texte brut dans vos fichiers en zone de préparation, il n’est pas recommandé d’y stocker des secrets réels. Utilisez la gestion des secrets intégrée de Snowflake pour les identifiants de connexion sensibles. Utilisez le fichier .streamlit/secrets.toml défini localement pour stocker des valeurs de configuration non sensibles ou des paramètres spécifiques à l’environnement.

Supprimer ou modifier les secrets de votre application Streamlit

  • Pour supprimer tous les secrets d’une application Streamlit in Snowflake, utilisez la clause UNSETSECRETS avec:doc:/sql-reference/sql/alter-streamlit :

    ALTER STREAMLIT my_database.my_schema.my_app
      UNSET SECRETS;
    

    Ceci supprime toutes les associations de secrets de l’application Streamlit in Snowflake. Les objets secrets sous-jacents restent dans votre compte Snowflake et peuvent être réattribués ultérieurement. Pour supprimer également toute association EAI, annulez également la définition de la propriété EXTERNAL_ACCESS_INTEGRATIONS.

  • Pour mettre à jour ou modifier les secrets joints, utilisez ALTER STREAMLIT avec SETSECRETS :

    ALTER STREAMLIT my_database.my_schema.my_app
      SET SECRETS = ('new_secret' = my_new_secret);
    

Exemple : Créer une application Streamlit de runtime de conteneur avec une API externe authentifiée

Cet exemple illustre la création d’une application Streamlit in Snowflake qui appelle une API externe utilisant une clé d’API secrète.

  1. Préparez le fichier Python suivant dans @my_stage/weather_app/streamlit_app.py :

    import streamlit as st
    import requests
    
    api_key = st.secrets["weather_api_name"]
    
    response = requests.get(
        "https://api.weather.com/v1/current",
        headers={"Authorization": f"Bearer {api_key}"}
    )
    
    st.write(response.json())
    

    Parce que requests est une dépendance de streamlit, elle est incluse dans l’image de base du runtime d’exécution. Par conséquent, le runtime l’installe automatiquement, même si vous n’incluez pas de fichier de dépendances ou si vous ne configurez pas d’index de paquets.

  2. Créez le secret, la règle réseau et l’EAI :

    CREATE OR REPLACE SECRET weather_api_key
      TYPE = GENERIC_STRING
      SECRET_STRING = 'secret_value';
    
    CREATE OR REPLACE NETWORK RULE weather_api_rule
      TYPE = HOST_PORT
      MODE = EGRESS
      VALUE_LIST = ('api.weather.com');
    
    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION weather_eai
      ALLOWED_NETWORK_RULES = (weather_api_rule)
      ALLOWED_AUTHENTICATION_SECRETS = (weather_api_key)
      ENABLED = TRUE;
    
  3. Créez l’objet Streamlit :

    CREATE STREAMLIT weather_app
      FROM '@my_stage/weather_app'
      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 = (weather_eai)
      SECRETS = ('weather_api_name' = weather_api_key);
    
    ALTER STREAMLIT weather_app ADD LIVE VERSION FROM LAST;
    

Appel d’un Agent Cortex dans une exécution de conteneur

Pour appeler un Agent Cortex dans une application d’exécution de conteneurs, lisez le jeton de session à partir du conteneur Snowpark Container Services sous-jacent, puis utilisez la bibliothèque requests. Il s’agit du remplacement recommandé pour _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))

Secrets dans les exécutions d’entrepôts

Dans les exécutions d’entrepôts, vous pouvez utiliser le module _snowflake pour accéder aux secrets directement dans le code de votre application Streamlit. Les exécutions d’entrepôts héritent de l’accès au module _snowflake à partir de procédures stockées, ce qui vous permet de récupérer les secrets qui sont référencés dans l’objet Streamlit.

Pour utiliser des secrets dans une exécution d’entrepôts, procédez comme suit :

  1. Créez un objet secret dans Snowflake. Pour plus d’informations, voir CREATE SECRET.

    CREATE OR REPLACE SECRET my_secret
      TYPE = GENERIC_STRING
      SECRET_STRING = 'my_secret_value';
    
  2. Créez une intégration d’accès externe et attribuez-lui le secret.

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION my_eai
      ALLOWED_AUTHENTICATION_SECRETS = (my_secret)
      ENABLED = TRUE;
    
  3. Référencez le secret dans votre objet Streamlit à l’aide du paramètre SECRETS :

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

    Vous devez attribuer à l’objet Streamlit à la fois l’intégration d’accès externe et le secret. Vous ne pouvez pas attribuer un secret à un objet Streamlit par lui-même.

  4. Dans le code de votre application Streamlit, importez le module _snowflake et récupérez le secret :

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

Pour plus d’informations sur l’accès aux secrets avec le module _snowflake, consultez API Python pour l’accès aux secrets.

Configuration de Streamlit

Les applications Streamlit peuvent inclure un fichier de configuration (.streamlit/config.toml). Ce fichier vous permet de personnaliser divers aspects de votre application, tels que le thème, la disposition et le comportement. Le fichier de configuration est écrit au format TOML. Pour plus d’informations sur les options de configuration disponibles, consultez la documentation Streamlit sur config.toml.

La prise en charge des options de configuration varie selon l’environnement d’exécution. Les exécutions de conteneurs offrent généralement une prise en charge plus large des options de configuration que les exécutions d’entrepôts, en particulier pour le service statique. Le tableau suivant montre les sections de configuration prises en charge dans les exécutions d’entrepôts et de conteneurs :

Section de configuration

Exécution d’entrepôts

Exécution de conteneurs

[global]

Non pris en charge

Prise en charge limitée (disableWidgetStateDuplicationWarning)

[logger]

Non pris en charge

Non pris en charge

[client]

Non pris en charge

Prise en charge limitée (showErrorDetails, showSidebarNavigation)

[runner]

Non pris en charge

Pris en charge

[server]

Non pris en charge

Non pris en charge

[browser]

Non pris en charge

Non pris en charge

[mapbox]

Non pris en charge

Prise en charge (obsolète, utilisez des variables d’environnement à la place)

[theme]

Pris en charge

Pris en charge

[theme.sidebar]

Pris en charge

Pris en charge

[secrets]

Non pris en charge

Prise en charge (mais uniquement recommandée pour les variables d’environnement non secrètes)

[snowflake.sleep]

Pris en charge

Non applicable

Pour plus d’informations sur l’utilisation de la section [snowflake.sleep] pour configurer les minuteurs de mise en veille dans les exécutions d’entrepôts, consultez Minuterie de mise en veille personnalisée pour une application Streamlit.

La structure des répertoires suivante montre un exemple d‘application Streamlit avec un fichier de configuration :

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