Verwalten von Geheimnissen und Konfigurieren der Streamlit-App

Streamlit-Apps müssen oft auf sensible Informationen zugreifen, wie z. B. API-Schlüssel, Kennwörter und andere Anmeldeinformationen. Wie Sie Geheimnisse in Ihrer Streamlit-App verwalten, hängt von der verwendeten Laufzeitumgebung ab. Streamlit in Snowflake bietet sichere, integrierte Mechanismen für den Zugriff auf Geheimnisse sowohl zur Laufzeit von Warehouses als auch von Containern. Auch bei der Streamlit-Konfiguration gelten für jede Laufzeitumgebung unterschiedliche Einschränkungen.

In der Streamlit-Bibliothek verwenden Apps das Verzeichnis .streamlit/, um Konfiguration und Geheimnisse zu speichern:

  • .streamlit/config.toml: Passt die Einstellungen der Anwendung wie Thema, Layout und Serververhalten an.

  • .streamlit/secrets.toml: Speichert sensible Informationen wie API-Schlüssel und Anmeldeinformationen (in lokaler Entwicklung).

Streamlit in Snowflake unterstützt diese Dateien mit einigen Einschränkungen, abhängig von Ihrer Laufzeitumgebung. Die folgende Tabelle fasst die Unterstützung für diese Dateien in den Laufzeiten von Warehouses und Containern zusammen:

Feature

Warehouse-Laufzeit

Container Runtime

config.toml-Unterstützung

Begrenzte Teilmenge der Konfigurationsoptionen

Größere Teilmenge der Konfigurationsoptionen

secrets.toml-Unterstützung

Nicht unterstützt

Unterstützt, aber nur für nicht geheime Umgebungsvariablen empfohlen

Für secrets.toml bietet Streamlit in Snowflake ein sichereres, integriertes System zur Verwaltung von Geheimnissen, das für die Verwaltung sensibler Informationen empfohlen wird. In den folgenden Abschnitten wird beschrieben, wie Sie Snowflake-Geheimnisse in Ihren Apps verwenden können.

Verwalten der Verbindung zu Snowflake

Um Ihre Verbindung zu Snowflake zu verwalten, können Sie st.connection("snowflake") verwenden. So können Sie sowohl von Ihrer lokalen Entwicklungsumgebung als auch von Ihrer bereitgestellten App aus eine Verbindung zu Snowflake herstellen.

import streamlit as st

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

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

In Warehouse-Laufzeiten können Sie auch die Funktion get_active_session() von Snowpark verwenden, um die aktive Sitzung abzurufen.

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

Wichtig

get_active_session() ist nicht Thread-sicher und kann nicht in Container Runtimes verwendet werden.

Geheimnisse in Container Runtimes

Sie können st.secrets verwenden, um sicher auf Snowflake-Geheimnisse in Ihren Container-Laufzeit-Streamlit in Snowflake-Apps zuzugreifen. Auf diese Weise können Sie sensible Informationen sicher speichern und abrufen, wie z. B. API-Schlüssel, Anmeldeinformationen und andere Konfigurationswerte. Genauso wie es Streamlit für .streamlit/secrets.toml in der lokalen Entwicklung macht, füllt Streamlit in Snowflake Geheimnisse auch mit Umgebungsvariablen.

Bemerkung

Container-Laufzeitumgebungen haben keinen Zugriff auf das _snowflake-Modul. Wenn Sie eine ältere Warehouse-Laufzeit-App migrieren, die _snowflake-Geheimnisfunktionen verwendet, ersetzen Sie diese Aufrufe durch st.secrets, wie in diesem Abschnitt beschrieben.

Zugriff auf ein Geheimnis in einer Container Runtime

  1. Stellen Sie die folgende Python-Datei in @my_stage/app_folder/streamlit_app.py bereit. Weitere Informationen zum Bereitstellen von Dateien finden Sie unter Bereitstellen von Dateien im Stagingbereich mit Snowsight.

    import streamlit as st
    
    secret_value = st.secrets["my_secret_name"]
    
  2. Erstellen Sie in Ihrem Snowflake-Konto ein Geheimnis:

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

    Weitere Informationen dazu finden Sie unter CREATE SECRET.

  3. Erstellen Sie eine Integration für den externen Zugriff (EAI), und weisen Sie ihr das Geheimnis zu:

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION my_eai
      ALLOWED_AUTHENTICATION_SECRETS = (my_secret)
      ENABLED = TRUE;
    
  4. Erstellen Sie Ihre Streamlit-App, um mithilfe des Parameters SECRETS auf das Geheimnis zu verweisen:

    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;
    

    Bemerkung

    Sie müssen sowohl die EAI als auch das Geheimnis dem Streamlit-Objekt zuweisen. Sie können einem Streamlit-Objekt selbst kein Geheimnis zuweisen.

    Weil das Geheimnis der generischen Zeichenfolge my_secret der Zeichenfolge "my_secret_name" im Parameter SECRETS zugeordnet ist, können Sie mithilfe von st.secrets["my_secret_name"] auf das Geheimnis im Code Ihrer Streamlit-App zugreifen.

Unterstützte Geheimnistypen und Umgebungsvariablen

Container-Laufzeitumgebungen unterstützen Geheimnisse der generischen Zeichenfolge und der Basisauthentifizierung. Zusätzlich zur Zuordnung von Geheimnissen zu st.secrets, ordnet Streamlit in Snowflake auch Geheimnisse den Umgebungsvariablen zu. Bei den Namen von Umgebungsvariablen wird zwischen Groß- und Kleinschreibung unterschieden. Für Geheimnisse der Basisauthentifizierung werden zwei Umgebungsvariablen erstellt: eine für den Benutzernamen (_USERNAME-Suffix) und eine für das Kennwort (_PASSWORD-Suffix).

Typ des Geheimnisses

Zugriff auf st.secrets

Zugriff auf Umgebungsvariablen

Generische Zeichenfolge

st.secrets["my_secret_name"]

os.environ["my_secret_name"]

Basisauthentifizierung (Benutzername)

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

os.environ["my_secret_name_USERNAME"]

Basisauthentifizierung (Kennwort)

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

os.environ["my_secret_name_PASSWORD"]

Bemerkung

Cloudanbieter, symmetrischer Schlüssel und OAuth-Geheimnistypen werden derzeit nicht unterstützt.

Geheimnisse der generischen Zeichenfolge

Geheimnisse der generischen Zeichenfolge werden als Schlüssel der obersten Ebene in st.secrets gespeichert:

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

Sie können auf das Geheimnis mit einer Wörterbuch- oder einer Attributnotation zugreifen:

import streamlit as st

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

Geheimnisse der Basisauthentifizierung

Geheimnisse der Basisauthentifizierung werden als dict-ähnliche Objekte mit den Attributen "username" und "password" gespeichert:

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

Sie können auf das Geheimnis mit einer Wörterbuch- oder einer Attributnotation zugreifen:

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

Geheimnisse für authentifizierte Paket-Repositorys

Geheimnisse werden automatisch als Umgebungsvariablen angezeigt. Insbesondere ermöglicht dies die Authentifizierung mit privaten Paket-Repositorys wie JFrog Artifactory.

Verwenden Sie für die meisten authentifizierten Paket-Repositorys ein Geheimnis der Basisauthentifizierung. Das Geheimnis wird mit den Suffixen _USERNAME und _PASSWORD automatisch in Umgebungsvariablen umgewandelt. Wenn Sie eine andere Namenskonvention benötigen, verwenden Sie Geheimnisse der generischen Zeichenfolge, und legen Sie den Namen jeder Umgebungsvariablen manuell fest. Weitere Informationen zu den Umgebungsvariablen, die von uv verwendet werden, finden Sie unter Paketindizes in der uv-Dokumentation.

Beispiel: Authentifizieren bei einem privaten JFrog Artifactory-Repository

  1. Stellen Sie die Quelldateien Ihrer App in @my_stage/app_folder bereit. Die Quelldateien Ihrer App müssen eine pyproject.toml-Datei enthalten, die den privaten Paketindex in der Tabelle [[tool.uv.index]] konfiguriert:

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

    Weitere Informationen zum Deklarieren der Abhängigkeiten Ihrer App in einer pyproject.toml-Datei finden Sie unter Verwalten von Abhängigkeiten für Ihre Streamlit-App.

  2. Erstellen Sie ein Geheimnis der Basisauthentifizierung mit Ihren JFrog-Anmeldeinformationen:

    CREATE OR REPLACE SECRET jfrog_creds
      TYPE = PASSWORD
      USERNAME = 'my_username'
      PASSWORD = 'my_api_token';
    
  3. Erstellen Sie eine Integration für den externen Zugriff für Ihr privates Repository:

    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;
    

    Bemerkung

    Um einen DNS-Fehler zu vermeiden, müssen Sie möglicherweise den Cloudanbieter für Ihr Repository in die Werteliste der Netzwerkregel aufnehmen. Beispiel: Wenn sich Ihr Repository in AWS befindet, benötigen Sie möglicherweise die folgende Werteliste in Ihrer Netzwerkregel:

    VALUE_LIST = ('my-org.jfrog.io', '<jfrog-server-name>.s3.amazonaws.com');
    
  4. Verknüpfen Sie die EAI und das Geheimnis mit Ihrer Streamlit-App:

    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;
    

    Weil das Geheimnis der Basisauthentifizierung jfrog_creds der Zeichenfolge "UV_INDEX_MY_JFROG_REPO" im Parameter SECRETS zugeordnet ist, fügt die Laufzeitumgebung automatisch die Umgebungsvariablen UV_INDEX_MY_JFROG_REPO_USERNAME und UV_INDEX_MY_JFROG_REPO_PASSWORD ein, wie von uv gefordert.

Rangfolge einer lokalen .streamlit/secrets.toml-Datei

Sie können von Snowflake verwaltete Geheimnisse mit einer lokalen .streamlit/secrets.toml-Datei im Quellverzeichnis Ihrer App kombinieren. Wenn beide vorhanden sind, führt die Streamlit-Bibliothek sie zusammen. Die lokal definierte .streamlit/secrets.toml-Datei hat Vorrang vor den von Snowflake verwalteten Geheimnissen.

Da .streamlit/secrets.toml als einfacher Text in Ihren Stagingdateien gespeichert wird, ist es keine bewährte Sicherheitsmethode, die tatsächlichen Geheimnisse darin zu speichern. Verwenden Sie die in Snowflake integrierte Geheimnisverwaltung für sensible Anmeldeinformationen. Verwenden Sie die lokal definierte .streamlit/secrets.toml-Datei, um nicht-sensible Konfigurationswerte oder umgebungsspezifische Einstellungen zu speichern.

Geheimnisse aus Ihrer Streamlit-App entfernen oder ändern

  • Um alle Geheimnisse aus einer Streamlit in Snowflake-App zu entfernen, verwenden Sie die UNSET SECRETS-Klausel mit ALTER STREAMLIT:

    ALTER STREAMLIT my_database.my_schema.my_app
      UNSET SECRETS;
    

    Auf diese Weise werden alle Geheimniszuordnungen aus der Streamlit in Snowflake-App entfernt. Die zugrunde liegenden Geheimnisobjekte verbleiben in Ihrem Snowflake-Konto und können später neu zugewiesen werden. Um auch alle EAI-Zuordnungen zu entfernen, deaktivieren Sie ebenfalls die Eigenschaft EXTERNAL_ACCESS_INTEGRATIONS.

  • Um die damit verbundenen Geheimnisse zu aktualisieren oder zu ändern, verwenden Sie ALTER STREAMLIT mit SET SECRETS:

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

Beispiel: Erstellen einer Streamlit-App mit Container-Laufzeit mithilfe einer authentifizierten externen API

In diesem Beispiel wird das Erstellen einer Streamlit in Snowflake-App gezeigt, die eine externe API unter Verwendung eines geheimen API-Schlüssels aufruft.

  1. Stellen Sie die folgende Python-Datei in @my_stage/weather_app/streamlit_app.py bereit:

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

    Weil requests eine Abhängigkeit von streamlit ist, ist es im Laufzeit-Basisbild enthalten. Daher installiert die Laufzeitumgebung es automatisch, auch wenn Sie keine Datei mit Abhängigkeiten hinzufügen oder einen Paketindex konfigurieren.

  2. Erstellen Sie das Geheimnis, die Netzwerkregel und die 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. Erstellen Sie das Streamlit-Objekt:

    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;
    

Aufrufen eines Cortex Agent in einer Container Runtime

Um einen Cortex Agent in einer Container Runtime-App aufzurufen, lesen Sie das Sitzungstoken aus dem zugrunde liegenden Snowpark Container Services-Container und verwenden Sie dann die requests-Bibliothek. Dies ist der empfohlene Ersatz für _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))

Geheimnisse in Warehouse-Laufzeiten

In Warehouse-Laufzeiten können Sie das _snowflake-Modul verwenden, um direkt auf Geheimnisse im Code Ihrer Streamlit-App zuzugreifen. Warehouse-Laufzeiten erben Zugriff auf das _snowflake-Modul aus gespeicherten Prozeduren, mit dem Sie Geheimnisse abrufen können, die im Streamlit-Objekt referenziert werden.

So verwenden Sie Geheimnisse in einer Warehouse-Laufzeit:

  1. Erstellen Sie in Snowflake ein Geheimnisobjekt. Weitere Informationen dazu finden Sie unter CREATE SECRET.

    CREATE OR REPLACE SECRET my_secret
      TYPE = GENERIC_STRING
      SECRET_STRING = 'my_secret_value';
    
  2. Erstellen Sie eine Integration für den externen Zugriff und weisen Sie ihr das Geheimnis zu.

    CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION my_eai
      ALLOWED_AUTHENTICATION_SECRETS = (my_secret)
      ENABLED = TRUE;
    
  3. Referenzieren Sie das Geheimnis in Ihrem Streamlit-Objekt mit demSECRETS-Parameter:

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

    Sie müssen dem Streamlit-Objekt sowohl die Integration für den externen Zugriff als auch das Geheimnis zuweisen. Sie können einem Streamlit-Objekt selbst kein Geheimnis zuweisen.

  4. Importieren Sie im Code Ihrer Streamlit-App das _snowflake-Modul und rufen Sie das Geheimnis ab:

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

Weitere Informationen zum Zugriff auf Geheimnisse mit dem _snowflake-Modul finden Sie unter Python-API für Zugriff auf Geheimnisse.

Streamlit-Konfiguration

Streamlit-Apps können eine Konfigurationsdatei (.streamlit/config.toml) enthalten. Mit dieser Datei können Sie verschiedene Aspekte Ihrer App anpassen, wie z. B. das Thema, das Layout und das Verhalten. Die Konfigurationsdatei ist im TOML-Format geschrieben. Weitere Informationen zu den verfügbaren Konfigurationsoptionen finden Sie in der Streamlit-Dokumentation zu config.toml.

Die Unterstützung für die Konfigurationsoptionen variiert je nach Laufzeitumgebung. Container Runtimes bieten im Allgemeinen eine größere Unterstützung für Konfigurationsoptionen als Warehouse-Laufzeiten, insbesondere für die statische Bereitstellung. Die folgende Tabelle zeigt, welche Konfigurationsabschnitte für Laufzeiten von Warehouses und Containern unterstützt werden:

Konfigurationsabschnitt

Warehouse-Laufzeit

Container Runtime

[global]

Nicht unterstützt

Eingeschränkte Unterstützung (disableWidgetStateDuplicationWarning)

[logger]

Nicht unterstützt

Nicht unterstützt

[client]

Nicht unterstützt

Eingeschränkte Unterstützung (showErrorDetails, showSidebarNavigation)

[runner]

Nicht unterstützt

Unterstützt

[server]

Nicht unterstützt

Nicht unterstützt

[browser]

Nicht unterstützt

Nicht unterstützt

[mapbox]

Nicht unterstützt

Unterstützt (veraltet, verwenden Sie stattdessen Umgebungsvariablen)

[theme]

Unterstützt

Unterstützt

[theme.sidebar]

Unterstützt

Unterstützt

[secrets]

Nicht unterstützt

Unterstützt (aber nur für nicht geheime Umgebungsvariablen empfohlen)

[snowflake.sleep]

Unterstützt

Nicht anwendbar

Weitere Informationen zur Verwendung des Abschnitts [snowflake.sleep] zum Konfigurieren von Sleep-Timern in Warehouse-Laufzeiten finden Sie unter Benutzerdefinierter Sleep-Timer für eine Streamlit-App.

Die folgende Verzeichnisstruktur zeigt ein Beispiel für eine Streamlit-App mit einer Konfigurationsdatei:

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