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

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

Wichtig

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

Geheimnisse in Container Runtimes

Container Runtimes haben keinen Zugriff auf das _snowflake-Modul, da sie außerhalb der Umgebung der gespeicherten Prozedur ausgeführt werden. Um auf Geheimnisse in einer Container Runtime zuzugreifen, müssen Sie SQL-Funktionen erstellen, die das _snowflake-Modul verwenden, und dann diese Funktionen von Ihrer Streamlit-App aus aufrufen. Für Cortex API-Aufrufe, müssen Sie requests verwenden.

Wenn Sie eine ältere Streamlit-App auf eine Container Runtime aktualisieren, sollten die folgenden _snowflake-Funktionen durch gespeicherte Prozeduren ersetzt werden. Dies wird im nächsten Abschnitt beschrieben.

  • get_generic_secret_string

  • get_oauth_access_token

  • get_username_password

  • get_cloud_provider_token

  • get_secret_type

Außerdem sollte die folgende _snowflake-Funktion durch einen manuellen API-Aufruf ersetzt werden, authentifiziert mit einem Sitzungstoken. Dies wird im Abschnitt Aufrufen eines Cortex Agent in einer Container Runtime weiter unten beschrieben.

  • send_snow_api_request

Zugriff auf ein Geheimnis in einer Container Runtime

Um auf ein Geheimnis in einer Container Runtime zuzugreifen, führen Sie die folgenden Schritte aus:

  1. Erstellen Sie in Ihrem Snowflake-Konto ein Geheimnis. Siehe CREATE SECRET.

    CREATE OR REPLACE SECRET my_secret
      TYPE = GENERIC_STRING
      SECRET_STRING = 'my_secret_value';
    
    Copy
  2. Erstellen Sie eine Funktion, um auf Ihr Geheimnis zuzugreifen. Siehe Python-API für Zugriff auf Geheimnisse.

    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. Erstellen Sie Ihre Streamlit-App mit der Container Runtime:

    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. Rufen Sie im Code Ihrer Streamlit-App die SQL-Funktion zum Abrufen des Geheimnisses auf:

    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

Verwenden von .streamlit/secrets.toml für nicht geheime Umgebungsvariablen

Sie können zwar technisch gesehen eine Datei des Typs .streamlit/secrets.toml zum Quellverzeichnis Ihrer App hinzufügen, dies wird jedoch nicht für das Speichern tatsächlicher Geheimnisse empfohlen. Die Datei secrets.toml wird als einfacher Text in Ihren Stagingdateien gespeichert, was keine bewährte Sicherheitsmethode darstellt.

Allerdings kann secrets.toml nützlich sein, um nicht-sensible Konfigurationswerte oder umgebungsspezifische Einstellungen zu speichern, auf die Sie über st.secrets in Ihrem Code zugreifen möchten, oder die eine Abhängigkeit als Umgebungsvariable erfordert:

# .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

Sie können dann über auf diese Werte in Ihrer App über st.secrets oder als Umgebungsvariablen zugreifen:

import streamlit as st
import os

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

Bei tatsächlichen Geheimnissen wie API-Schlüsseln, Kennwörtern und Token verwenden Sie immer das in Snowflake integrierte System zur Verwaltung von Geheimnissen, wie im vorherigen Abschnitt beschrieben.

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

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

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

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
Copy