Snowpark Container Services: Zusätzliche Hinweise zu Diensten¶
Verbinden mit Snowflake aus einem Container heraus¶
Wenn Sie einen Dienst (einschließlich Jobdienste) starten, stellt Snowflake den aktiven Containern Anmeldeinformationen zur Verfügung, damit Ihr Containercode Treiber für die Verbindung zu Snowflake und das Ausführen von SQL verwenden kann (ähnlich wie jeder andere Code auf Ihrem Computer, der sich mit Snowflake verbindet). Die bereitgestellten Anmeldeinformationen authentifizieren als Eigentümerrolle (die Rolle, die den Dienst erstellt hat). Snowflake stellt einige der Informationen als Umgebungsvariablen in Ihren Containern bereit.
Jedes Objekt in Snowflake hat eine Eigentümerrolle. Die Eigentümerrolle des Dienstes bestimmt, welche Funktionen Ihr Dienst bei der Interaktion mit Snowflake ausführen darf. Dazu gehören das Ausführen von SQL, der Zugriff auf Stagingbereiche und die Vernetzung zwischen Diensten.
Bemerkung
Die Eigentümerrolle eines Dienstes bezieht sich auf die Rolle, die den Dienst erstellt hat. Sie können auch eine oder mehrere Dienstrollen definieren, um den Zugriff auf die Endpunkte zu verwalten, die der Dienst bereitstellt. Weitere Informationen dazu finden Sie unter Verwalten des Zugriffs auf Dienstendpunkte.
Wenn Sie einen Dienst erstellen, erstellt Snowflake auch einen Dienstbenutzer speziell für diesen Dienst. Wenn der Dienst eine Abfrage ausführt, führt er die Abfrage als der Dienstbenutzer aus und verwendet die Eigentümerrolle des Dienstes. Was der Dienstbenutzer tun kann, wird durch die Eigentümerrolle bestimmt.
Die Eigentümerrolle des Dienstes darf keine der privilegierten Rollen sein, wie ACCOUNTADMIN und SECURITYADMIN. Dies soll die Möglichkeiten eines fehlerhaften Dienstes einschränken und verlangt von den Kunden ein größeres Maß an Aufmerksamkeit, wenn einem Dienst die Ausführung von administrativen Operationen ermöglicht wird.
Um die von einem bestimmten Dienstbenutzer erstellten Abfragen einzusehen, können Sie die Rolle ACCOUNTADMIN verwenden und den Abfrageverlauf anzeigen. Der Benutzername des Dienstbenutzers wird in den folgenden Formen angezeigt:
Bei einem Service, der vor dem Release 8.35 des Servers erstellt wurde, hat der Dienstbenutzer das Format
SF$SERVICE$unique-id
.Bei einem Service, der nach dem Release 8.35 des Servers erstellt wurde, ist der Dienstbenutzer derselbe wie der Name des Services.
Verbinden mit Snowflake¶
Snowflake stellt die folgenden Umgebungsvariablen zur Verfügung, mit denen Sie einen Snowflake-Client in Ihrem Dienstcode konfigurieren können:
SNOWFLAKE_ACCOUNT: Liefert den Konto-Locator für das Snowflake-Konto, unter dem der Service derzeit läuft.
SNOWFLAKE_HOST: Gibt den Hostnamen an, der für die Verbindung zu Snowflake verwendet wird.
Snowflake stellt auch ein OAuth-Token im Container in einer Datei namens /snowflake/session/token
bereit. Wenn Sie eine Verbindung herstellen, geben Sie dieses Token an den Konnektor weiter.
Wenn Sie eine Verbindung zu Snowflake von einem Container aus erstellen, müssen Sie SNOWFLAKE_HOST, SNOWFLAKE_ACCOUNT und das OAuth-Token verwenden. Sie können das OAuth-Token nur verwenden, wenn Sie auch SNOWFLAKE_HOST verwenden, und Sie können das OAuth-Token nicht außerhalb von Snowpark Container Services verwenden. Weitere Informationen dazu finden Sie unter Verwenden eines OAuth-Tokens zum Ausführen von SQL.
Bemerkung
Die Verwendung externer Integrationen für den Zugriff auf Snowflake kann bedeuten, dass potenziell sensible Informationen über das Internet gesendet werden. Wann immer möglich, sollten Services das bereitgestellte OAuth-Token verwenden, um auf den SNOWFLAKE_HOST-Hostnamen zuzugreifen. Dadurch müssen Sie nicht mehr über das Internet auf Snowflake zugreifen.
Beispielcode für die Verwendung verschiedener Snowflake-Treiber finden Sie unter Snowflake Connection Samples.
Beispiele
In Tutorial 2 (siehe
main.py
) liest der Code die Umgebungsvariablen wie folgt:SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT') SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
Der Code übergibt diese Variablen an einen Verbindungserstellungscode für den Snowflake-Client Ihrer Wahl. Der Container verwendet diese Anmeldeinformationen, um eine neue Sitzung mit der Eigentümerrolle als Primärrolle zu erstellen, um Abfragen auszuführen. Der folgende Beispielcode zeigt, was mindestens zum Erstellen einer Snowflake-Verbindung in Python erforderlich ist:
def get_login_token(): with open('/snowflake/session/token', 'r') as f: return f.read() conn = snowflake.connector.connect( host = os.getenv('SNOWFLAKE_HOST'), account = os.getenv('SNOWFLAKE_ACCOUNT'), token = get_login_token(), authenticator = 'oauth' )
Wenn Sie den Standard-Host verwenden (d. h. Sie geben das Argument
host
beim Erstellen einer Verbindung nicht an), wird die Verbindung zu Snowflake mit anderen Formen der Authentifizierung (z. B. Benutzername und Kennwort) unterstützt. Bei der folgenden Verbindung werden zur Authentifizierung beispielsweise Benutzername und Kennwort angegeben:conn = snowflake.connector.connect( account = os.getenv('SNOWFLAKE_ACCOUNT'), user = '<user-name>', password = <password> )
Die Verwendung eines Standard-Hosts erfordert eine Integration für den externen Zugriff mit einer Netzwerkregel, die den Zugriff von Ihrem Dienst auf den Snowflake-Hostnamen Ihres Kontos erlaubt. Wenn Ihr Kontoname beispielsweise MyAccount ist, lautet der Hostname myaccount.snowflakecomputing.com. Weitere Informationen dazu finden Sie unter Konfigurieren des Netzwerkausgangs.
Erstellen Sie eine Netzwerkregel, die einen Abgleich mit Snowflake-API-Hostnamen Ihres Kontos vornimmt:
CREATE OR REPLACE NETWORK RULE snowflake_egress_access MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('myaccount.snowflakecomputing.com');
Erstellen Sie eine Integration unter Verwendung der obigen Netzwerkregel:
CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration ALLOWED_NETWORK_RULES = (snowflake_egress_access) ENABLED = true;
Konfigurieren des Datenbank- und Schemakontextes für das Ausführen von SQL¶
In diesem Abschnitt werden zwei Konzepte erläutert:
Die Logik, mit der Snowflake Datenbank und Schema bestimmt, in dem Ihr Dienst erstellt werden soll.
Die Methode, mit der Snowflake diese Informationen an Ihre Container weitergibt, sodass der Containercode SQL im gleichen Datenbank- und Schemakontext ausführen kann.
Snowflake verwendet den Dienstnamen, um die Datenbank und das Schema zu bestimmen, in denen ein Dienst erstellt werden soll:
Beispiel 1: In den folgenden Befehlen CREATE SERVICE und EXECUTE JOB SERVICE gibt der Dienstname nicht explizit einen Datenbank- und Schemanamen an. Snowflake erstellt den Dienst und den Jobdienst in der aktuellen Datenbank und dem aktuellen Schema.
-- Create a service. CREATE SERVICE test_service IN COMPUTE POOL ... -- Execute a job service. EXECUTE JOB SERVICE IN COMPUTE POOL tutorial_compute_pool NAME = example_job_service ...
Beispiel 2: In den folgenden Befehlen CREATE SERVICE und EXECUTE JOB SERVICE enthält der Dienstname einen Datenbank- und einen Schemanamen. Snowflake erstellt den Dienst und den Jobdienst in der angegebenen Datenbank (
test_db
) und dem angegebenen Schema (test_schema
), unabhängig vom aktuellen Schema.-- Create a service. CREATE SERVICE test_db.test_schema.test_service IN COMPUTE POOL ... -- Execute a job service. EXECUTE JOB SERVICE IN COMPUTE POOL tutorial_compute_pool NAME = test_db.test_schema.example_job_service ...
Wenn Snowflake einen Dienst startet, werden den ausgeführten Containern die Datenbank- und Schemainformationen über die folgenden Umgebungsvariablen zur Verfügung gestellt:
SNOWFLAKE_DATABASE
SNOWFLAKE_SCHEMA
Ihr Containercode kann Umgebungsvariablen im Verbindungscode verwenden, um die zu verwendende Datenbank und das Schema zu bestimmen, wie im folgenden Beispiel gezeigt:
conn = snowflake.connector.connect(
host = os.getenv('SNOWFLAKE_HOST'),
account = os.getenv('SNOWFLAKE_ACCOUNT'),
token = get_login_token(),
authenticator = 'oauth',
database = os.getenv('SNOWFLAKE_DATABASE'),
schema = os.getenv('SNOWFLAKE_SCHEMA')
)
Beispiel
In Tutorial 2 erstellen Sie einen Snowflake-Jobdienst, der sich mit Snowflake verbindet und SQL-Anweisungen ausführt. Die folgenden Schritte fassen zusammen, wie der Tutorial-Code die Umgebungsvariablen verwendet:
Bei der grundlegenden Einrichtung (siehe Abschnitt Grundlegende Einrichtung) erstellen Sie Ressourcen, einschließlich einer Datenbank und eines Schemas. Sie legen auch die aktuelle Datenbank und das aktuelle Schema für die Sitzung fest:
USE DATABASE tutorial_db; ... USE SCHEMA data_schema;
Nachdem Sie einen Jobdienst erstellt haben (durch Ausführen von EXECUTE JOB SERVICE), startet Snowflake den Container und setzt die folgenden Umgebungsvariablen im Container auf die aktuelle Datenbank und das aktuelle Schema der Sitzung:
SNOWFLAKE_DATABASE ist auf „TUTORIAL_DB“ gesetzt.
SNOWFLAKE_SCHEMA ist auf „DATA_SCHEMA“ gesetzt.
Der Jobcode (siehe
main.py
in Tutorial 2) liest diese Umgebungsvariablen aus:SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE') SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
Der Jobcode legt die Datenbank und das Schema als Kontext fest, in dem die SQL-Anweisungen ausgeführt werden (Funktion
run_job()
inmain.py
):{ "account": SNOWFLAKE_ACCOUNT, "host": SNOWFLAKE_HOST, "authenticator": "oauth", "token": get_login_token(), "warehouse": SNOWFLAKE_WAREHOUSE, "database": SNOWFLAKE_DATABASE, "schema": SNOWFLAKE_SCHEMA } ...
Bemerkung
SNOWFLAKE_ACCOUNT SNOWFLAKE_HOST, SNOWFLAKE_DATABASE, SNOWFLAKE_SCHEMA sind Umgebungsvariablen, die Snowflake für den Anwendungscontainer generiert, allerdings nicht SNOWFLAKE_WAREHOUSE (der Anwendungscode von Tutorial 2 erstellt diese Variable, da Snowflake keinen Warehouse-Namen an einen Container übergibt).
Angeben des Warehouses für Ihren Container¶
Wenn Ihr Dienst eine Verbindung zu Snowflake herstellt, um eine Abfrage in einem Snowflake-Warehouse auszuführen, haben Sie die folgenden Optionen für die Angabe des Warehouses:
Warehouse in Ihrem Anwendungscode angeben. Geben Sie ein Warehouse als Teil der Verbindungskonfiguration an, wenn Sie eine Snowflake-Sitzung zum Ausführen von Abfragen in Ihrem Code starten. Ein Beispiel dazu finden Sie unter Tutorial 2.
Standard-Warehouse beim Erstellen eines Dienstes angeben. Geben Sie den optionalen Parameter QUERY_WAREHOUSE im Befehl CREATE SERVICE (oder EXECUTE JOB SERVICE) an, um ein Standard-Warehouse bereitzustellen. Wenn Ihr Anwendungscode kein Warehouse als Teil der Verbindungskonfiguration bereitstellt, verwendet Snowflake das Standard-Warehouse. Verwenden Sie den Befehl ALTER SERVICE, um das Standard-Warehouse zu ändern.
Wenn Sie ein Warehouse mit beiden Methoden angeben, wird das im Anwendungscode angegebene Warehouse verwendet.
Verwenden eines OAuth-Tokens zum Ausführen von SQL¶
Alle von Snowflake bereitgestellten Clients unterstützen OAuth als Authentifizierungsoption. Auch Dienstcontainer verwenden den OAuth-Mechanismus zur Authentifizierung bei Snowflake. Wenn ein Container zum Beispiel SQL ausführen möchte, stellt er eine Verbindung zu Snowflake her, ähnlich wie jeder andere Snowflake-Client:
def get_login_token():
with open('/snowflake/session/token', 'r') as f:
return f.read()
conn = snowflake.connector.connect(
host = os.getenv('SNOWFLAKE_HOST'),
account = os.getenv('SNOWFLAKE_ACCOUNT'),
token = get_login_token(),
authenticator = 'oauth'
)
Wenn Sie einen Dienst erstellen, führt Snowflake die Container aus und stellt den Containern ein OAuth-Token zur Verfügung, das an der folgendem Speicherort innerhalb des Containers verwendet wird: /snowflake/session/token
.
Beachten Sie die folgenden Details zu diesem OAuth-Token:
Sie müssen den Inhalt der Datei
/snowflake/session/token
unmittelbar vor der Verwendung lesen, da der Inhalt innerhalb von 10 Minuten abläuft, und Snowflake diese Datei alle paar Minuten aktualisiert. Nachdem sich ein Container erfolgreich mit Snowflake verbunden hat, gilt die Ablaufzeit nicht mehr für die Verbindung (wie bei allen Sitzungen, die Benutzer direkt erstellen).Dieses OAuth-Token ist nur innerhalb des jeweiligen Snowflake-Dienstes gültig. Sie können das OAuth-Token nicht kopieren und außerhalb des Dienstes verwenden.
Unter Verwendung des OAuth-Tokens verbinden sich die Container mit Snowflake als Dienstbenutzer und verwenden die Eigentümerrolle des Dienstes.
Die Verwendung des OAuth-Tokens zum Herstellen einer Verbindung führt zu einer neuen Sitzung. Das OAuth-Token ist mit keiner bestehenden SQL-Sitzung verbunden.
Bemerkung
Ein wesentlicher Unterschied zwischen dem Ausführen von gespeicherten Prozeduren und dem Ausführen eines Dienstes besteht darin, dass gespeicherte Prozeduren in der gleichen Sitzung ausgeführt werden wie der SQL-Code, der sie ausführt. Aber jedes Mal, wenn ein Container eine neue Verbindung aufbaut, wird eine neue Sitzung erstellt.
Konnektivität mit Snowflake aus einem Container heraus unter Verwendung Aufruferrechte¶
Container führen Abfragen aus, indem sie sich als Dienstbenutzer mit Snowflake verbinden und die Eigentümerrolle des Dienstes verwenden, die dem Dienst Berechtigungen gewährt. In bestimmten Anwendungsszenarien kann es erforderlich sein, dass Sie Abfragen im Kontext des Endbenutzers und nicht des Dienstbenutzers ausführen müssen. In diesem Kontext wird das Aufruferrechte-Feature verwendet.
Nehmen wir zum Beispiel an, Sie erstellen einen Dienst, der einen öffentlichen Endpunkt für eine Webanwendung bereitstellt, die ein Dashboard mit in Snowflake gespeicherten Daten anzeigt. Sie gewähren anderen Benutzern in Ihrem Snowflake-Konto Zugriff auf das Dashboard (indem Sie diesen Benutzern die Dienstrolle zuweisen). Wenn sich einer dieser Endbenutzer beim Dashboard anmeldet, soll das Dashboard nur die Daten anzeigen, auf die der Benutzer Zugriff hat.
Da Container jedoch standardmäßig Abfragen unter Verwendung des Dienstbenutzers und der Eigentümerrolle des Dienstes ausführen, zeigt das Dashboard die Daten an, auf die die Eigentümerrolle des Dienstes Zugriff hat, unabhängig davon, welcher Endbenutzer mit dem Endpunkt verbunden ist. Daher sind die Daten im Dashboard des Benutzers nicht auf die Daten beschränkt, auf die der Benutzer Zugriff hat, so dass der Benutzer auf Daten zugreifen kann, auf die er keinen Zugriff hat.
Um das Dashboard so einzuschränken, dass nur Daten angezeigt werden, auf die der angemeldete Benutzer Zugriff hat, müssen die Anwendungscontainer SQL mit den Berechtigungen des Endbenutzers ausführen. Sie können dies aktivieren, indem Sie die Aufruferrechte in der Anwendung verwenden.
Bemerkung
Das Aufruferrechte-Feature wird nur unterstützt, wenn der Zugriff auf einen Dienst über den Netzwerkeingang erfolgt. Das Feature ist nicht verfügbar, wenn Sie eine Dienstfunktion für den Zugriff auf den Dienst verwenden.
Das Aufruferrechte-Feature wird derzeit in Snowflake Native App (Apps mit Containern nicht) unterstützt.
Konfigurieren der Aufruferrechte für Ihren Dienst¶
Die Konfiguration der Aufruferrechte für Ihre Anwendung ist ein zweistufiger Prozess.
Setzen Sie
executeAsCaller
in der Dienstspezifikation auftrue
, wie im folgenden Spezifikationsfragment gezeigt:spec: containers: ... capabilities: securityContext: executeAsCaller: true
Dies teilt Snowflake ausdrücklich mit, dass die Anwendung beabsichtigt, die Aufruferrechte zu verwenden und veranlasst Snowflake, den
Sf-Context-Current-User-Token
-Header in jede eingehende Anfrage einzufügen, bevor die Anfrage an den Anwendungscontainer gesendet wird. Dieses Benutzer-Token erleichtert die Ausführung der Abfrage als aufrufender Benutzer. Wenn nichts angegeben wird, istexecuteAsCaller
standardmäßig auffalse
eingestellt.Die Angabe der Option
executeAsCaller
wirkt sich nicht auf die Möglichkeit des Dienstes aus, Abfragen in der Dienstbenutzerrolle und der Eigentümerrolle des Dienstes auszuführen. WennexecuteAsCaller
aktiviert ist, hat der Dienst die Möglichkeit, sich sowohl als aufrufender Benutzer als auch als Dienstbenutzer mit Snowflake zu verbinden.Aktualisieren Sie Ihren Anwendungscode. Um eine Snowflake-Verbindung im Namen des aufrufenden Benutzers herzustellen, aktualisieren Sie Ihren Code, um ein Anmeldetoken zu erstellen, das sowohl das OAuth-Token, das Snowflake dem Dienst bereitgestellt hat, als auch das Benutzer-Token aus dem
Sf-Context-Current-User-Token
-Header enthält. Das Anmeldetoken sollte diesem Format entsprechen:<service-oauth-token>.<Sf-Context-Current-User-Token>
.Dies wird in dem folgenden Python-Codefragment veranschaulicht:
# Environment variables below will be automatically populated by Snowflake. SNOWFLAKE_ACCOUNT = os.getenv("SNOWFLAKE_ACCOUNT") SNOWFLAKE_HOST = os.getenv("SNOWFLAKE_HOST") def get_login_token(): with open("/snowflake/session/token", "r") as f: return f.read() def get_connection_params(ingress_user_token = None): # start a Snowflake session as ingress user # (if user token header provided) if ingress_user_token: logger.info("Creating a session on behalf of the current user.") token = get_login_token() + "." + ingress_user_token else: logger.info("Creating a session as the service user.") token = get_login_token() return { "account": SNOWFLAKE_ACCOUNT, "host": SNOWFLAKE_HOST, "authenticator": "oauth", "token": token } def run_query(request, query): ingress_user_token = request.headers.get('Sf-Context-Current-User-Token') # ingress_user_token is None if header not present connection_params = get_connection_params(ingress_user_token) with Session.builder.configs(connection_params).create() as session: # use the session to execute a query.
Im obigen Beispiel:
Die Funktion
get_login_token
liest die Datei, in die Snowflake das OAuth-Token für den zu verwendenden Container kopiert hat.Die Funktion
get_connection_params
konstruiert ein Token durch Verkettung des OAuth-Tokens und des Benutzertokens aus demSf-Context-Current-User-Token
-Header. Die Funktion nimmt dieses Token in ein Verzeichnis von Parametern auf, die die Anwendung für die Verbindung mit Snowflake verwendet.
Ein Beispiel mit einer Schritt-für-Schritt-Anleitung finden Sie unter Erstellen eines Dienstes mit aktivierten Aufruferrechten.
Zugriff auf einen Dienst mit konfigurierten Aufruferrechten¶
Bei der Konfiguration der Aufruferrechte geht es darum, dass Ihr Dienst im Namen des Aufrufers eine Snowflake-Verbindung aufbaut. Die Art und Weise, wie Sie sich bei den Eingangsendpunkten des Dienstes anmelden (programmgesteuert oder über einen Browser), bleibt unverändert. Nach der Anmeldung gilt Folgendes:
Zugriff auf einen öffentlichen Endpunkt über einen Browser: Nachdem Sie sich bei einem Endpunkt angemeldet haben, stellt der Dienst im Namen des anrufenden Benutzers mit der Standardrolle des Benutzers eine Verbindung zu Snowflake her. Wenn keine Standardrolle für den Benutzer konfiguriert ist, wird die Rolle PUBLIC verwendet.
Programmgesteuerter Zugriff auf einen öffentlichen Endpunkt: Bei der programmgesteuerten Anmeldung bei einem Endpunkt mit dem JWT-Token können Sie optional den Parameter
scope
setzen, um die zu aktivierende Rolle anzugeben
Nachdem ein Dienst die Verbindung zu Snowflake mit Aufruferrechten im Namen des Aufrufers hergestellt hat, wird ein Umschalten zwischen den Rollen derzeit nicht unterstützt. Wenn Ihre Anwendung verschiedene Rollen für den Zugriff auf verschiedene Objekte benötigt, richten Sie den Benutzer so ein, dass alle sekundären Rollen standardmäßig aktiv sind. Verwenden Sie dazu den Befehl ALTER USER, um die Eigenschaft DEFAULT_SECONDARY_ROLES des Benutzers auf (‚ALL‘) einzustellen:
ALTER USER my_user SET DEFAULT_SECONDARY_ROLES = ( 'ALL' );
Verwalten von Aufruferberechtigungen für einen Dienst¶
Wenn ein Dienst eine Sitzung mit Aufruferrechten erstellt, arbeitet die Sitzung als aufrufender Benutzer (nicht als Dienstbenutzer). Wenn eine Operation über diese Sitzung durchgeführt wird, wendet Snowflake zwei Berechtigungsprüfungen an:
Die erste Berechtigungsprüfung erfolgt so, als hätte der Benutzer die Sitzung direkt erstellt. Dies sind die normalen Berechtigungsprüfungen, die Snowflake für den Benutzer durchführt.
Die zweite Berechtigungsprüfung verifiziert, dass der Dienst die Operation im Namen eines Benutzers durchführen darf. Snowflake überprüft dies, indem sichergestellt wird, dass der Rolle des Diensteigentümers die erforderlichen Aufruferberechtigungen gewährt wurden.
In einer Sitzung mit Aufruferrechten müssen sowohl die normale Berechtigungsprüfung als auch die Prüfung der Aufruferrechte der Rolle des Diensteigentümers die Operation erlauben. Dies wird als eingeschränkte Aufruferrechte bezeichnet. Standardmäßig hat der Dienst keine Berechtigung, etwas im Namen eines Benutzers zu tun. Sie müssen dem Dienst explizit Aufruferrechte gewähren, damit er mit den Berechtigungen des Aufrufers ausgeführt werden kann.
Nehmen wir zum Beispiel an, dass ein Benutzer U1
eine Rolle R1
verwendet, die die Berechtigung SELECT für die Tabelle T1
hat. Wenn sich U1
bei dem öffentlichen Endpunkt Ihres Dienstes (example_service
) anmeldet, der so konfiguriert ist, dass er die Aufruferrechte verwendet, stellt der Dienst dann im Namen von U1
eine Verbindung zu Snowflake her.
Damit der Dienst die Tabelle T1
im Namen von U1
abfragen kann, müssen Sie der Rolle des Diensteigentümers die folgenden Berechtigungen erteilen:
Berechtigungen zur Auflösung des Tabellennamens, indem einem Aufrufer eine Berechtigung gewährt wird, die es dem Dienst ermöglicht, mit der USAGE-Berechtigung auf der Datenbank und dem Schema für diese Tabelle zu arbeiten.
Berechtigung zur Verwendung eines Warehouse, um Abfragen auszuführen, indem einem Aufrufer eine Berechtigung gewährt wird, die es dem Dienst ermöglicht, mit der entsprechende USAGE-Berechtigung auf dem Warehouse zu arbeiten.
Berechtigungen zur Abfrage der Tabelle, indem einem Aufrufer eine Berechtigung gewährt wird, die es dem Dienst ermöglicht, mit der SELECT-Berechtigung auf der Tabelle
T1
ausgeführt zu werden.
-- Permissions to resolve the table's name.
GRANT CALLER USAGE ON DATABASE <db_name> TO ROLE <service_owner_role>;
GRANT CALLER USAGE ON SCHEMA <schema_name> TO ROLE <service_owner_role>;
-- Permissions to use a warehouse
GRANT CALLER USAGE ON WAREHOUSE <warehouse_name> TO ROLE <service_owner_role>;
-- Permissions to query the table.
GRANT CALLER SELECT ON TABLE T1 TO ROLE <service_owner_role>;
Jede Rolle in Ihrem Konto, die über die globale Berechtigung MANAGE CALLER GRANT verfügt, kann Aufruferberechtigungen gewähren. Weitere Informationen über Aufruferrechte finden Sie unter GRANT CALLER und Eingeschränkte Aufruferrechte.
Beispiel¶
Hier finden Sie ein Beispiel für einen Dienst, der bei der Ausführung von SQL-Abfragen im Namen der Benutzer das Aufruferrechte-Feature verwendet. Weitere Informationen finden Sie unter Erstellen eines Dienstes mit aktivierten Aufruferrechten.
Konfigurieren des Netzwerkeingangs¶
Um eine Interaktion mit Ihrem Dienst vom Internet aus zu ermöglichen, deklarieren Sie die Netzwerkports, die von Ihrem Dienst überwacht werden, als Endpunkte in der Dienstspezifikationsdatei. Diese Endpunkte kontrollieren den eingehenden Datenverkehr.
Standardmäßig sind die Dienstendpunkte privat. Nur Dienstfunktionen und die Dienst-zu-Dienst-Kommunikation können Anforderungen an die privaten Endpunkte senden. Sie können einen Endpunkt als öffentlich deklarieren, um Anforderungen an einen Endpunkt aus dem Internet zuzulassen. Die Eigentümerrolle des Dienstes muss über die Berechtigung BIND SERVICE ENDPOINT für das Konto verfügen.
endpoints:
- name: <endpoint name>
port: <port number>
protocol : < TCP / HTTP / HTTPS >
public: true
Ein Beispiel dazu finden Sie unter Tutorial 1.
Bemerkung
Derzeit unterstützen nur Dienste, nicht aber Jobdienste, den Netzwerkzugang (eingehende Daten).
Sicherheit von Eingangsdatenverkehr und Webanwendungen¶
Sie können einen Snowpark Container Services-Dienst für das Webhosting erstellen, indem Sie die Unterstützung für öffentliche Endpunkte (Netzwerkeingang) nutzen. Für zusätzliche Sicherheit setzt Snowflake einen Proxydienst ein, um eingehende Anforderungen von Clients an Ihren Dienst und ausgehende Antworten von Ihrem Dienst an die Clients zu überwachen. In diesem Abschnitt wird erklärt, was der Proxy tut und wie er sich auf einen Dienst auswirkt, der in Snowpark Container Services bereitgestellt wird.
Bemerkung
Wenn Sie einen Dienst lokal testen, verwenden Sie nicht den Snowflake-Proxy. Daher wird es Unterschiede zwischen der lokalen Ausführung eines Dienstes und der Bereitstellung in Snowpark Container Services geben. Lesen Sie diesen Abschnitt, und aktualisieren Sie Ihre lokalen Einstellungen, um das Testen zu optimieren.
Beispiel:
Der Proxy leitet eine eingehende HTTP-Anforderung nicht weiter, wenn die Anforderung eine nicht zulässige HTTP-Methode verwendet.
Der Proxy sendet eine 403-Antwort an den Client, wenn der Content-Type-Header in der Antwort angibt, dass die Antwort eine ausführbare Datei enthält.
Darüber hinaus kann der Proxy auch neue Kopfzeilen einfügen und bestehende Kopfzeilen in der Anforderung und der Antwort ändern, wobei Ihr Container und Ihre Datensicherheit berücksichtigt werden.
Beispielsweise könnte Ihr Dienst nach Erhalt einer Anforderung in der Antwort HTML-, JavaScript-, CSS- und andere Inhalte für eine Webseite an den Client-Browser senden. Die Webseite im Browser ist Teil Ihres Dienstes und dient als Benutzerschnittstelle. Wenn Ihr Dienst aus Sicherheitsgründen Einschränkungen unterliegt (z. B. bezüglich des Herstellens von Netzwerkverbindungen zu anderen Standorten), möchten Sie vielleicht auch, dass die Webseite Ihres Dienstes denselben Einschränkungen unterliegt.
Standardmäßig haben Dienste nur begeschränkte Berechtigungen für den Zugriff auf das Internet. Der Browser sollte auch verhindern, dass die Clientanwendung auf das Internet zugreift und möglicherweise in den meisten Fällen Daten freigibt. Wenn Sie eine Integration des externen Zugriffs (EAI) eingerichtet haben, um Ihrem Dienst den Zugriff auf example.com
zu ermöglichen (siehe Konfigurieren des Netzwerkausgangs), sollte die Webseite für Ihren Dienst auch über Ihren Browser auf example.com
zugreifen können.
Der Snowflake-Proxy wendet dieselben Netzwerkbeschränkungen auf den Dienst und die Webseite an, indem er einen CSP-Header (Content-Security-Policy
) in die Antwort einfügt. Standardmäßig fügt der Proxy eine Baseline-CSP in die Antwort ein, um Schutz vor allgemeinen Sicherheitsbedrohungen zu bieten. Bei der Browser-Sicherheit geht es darum, ein Gleichgewicht zwischen Funktionalität und Sicherheit zu finden. Es liegt in der gemeinsamen Verantwortung sicherzustellen, dass diese Basis für Ihren Anwendungsfall geeignet ist. Wenn Ihr Dienst so konfiguriert ist, dass eine EAI verwendet wird, wendet der Proxy außerdem dieselben Netzwerkregeln von der EAI auf die CSP der Webseite an. Diese CSP ermöglicht der Webseite im Browser auf dieselben Standorte zuzugreifen, auf die auch der Dienst zugreifen kann.
In den folgenden Abschnitten wird erläutert, wie der Snowflake-Proxy eingehende Anforderungen für Ihren Dienst verarbeitet und die ausgehenden Antworten Ihres Dienstes an die Clients modifiziert.
Beim Dienst eingehende Anforderungen¶
Wenn eine Anforderung eintrifft, führt der Proxy folgende Schritte aus, bevor er die Anforderung an den Dienst weiterleitet:
Eingehende Anforderungen mit nicht zulässigen HTTP-Methoden: Wenn eine eingehende HTTP-Anforderung eine der folgenden nicht zulässigen HTTP-Methoden verwendet, leitet der Proxy die Anforderung nicht an Ihren Dienst weiter:
TRACE
OPTIONS
CONNECT
An die Clients ausgehende Antworten¶
Der Snowflake-Proxy wendet diese Änderungen auf die von Ihrem Dienst gesendete Antwort an, bevor er die Antwort an den Client weiterleitet.
Header Scrubbing: Der Snowflake-Proxy entfernt diese Antwort-Header, falls vorhanden:
X-XSS-Protection
Server
X-Powered-By
Public-Key-Pins
Antwort-Header „Content-Type“: Wenn die Antwort Ihres Dienstes den „Content-Type“-Header mit einem der folgenden Werte des MIME-Typs (der auf eine ausführbare Datei hinweist) enthält, leitet der Snowflake-Proxy diese Antwort nicht an den Client weiter. Stattdessen sendet der Proxy eine
403 Forbidden
-Antwort.application/x-msdownload
: ausführbare Microsoft-Datei.application/exe
: allgemeine ausführbare Datei.application/x-exe
: eine weitere allgemeine ausführbare Datei.application/dos-exe
: ausführbare DOS-Datei.application/x-winexe
: ausführbare Windows-Datei.application/msdos-windows
: ausführbare MS-DOS-Windows-Datei.application/x-msdos-program
: ausführbare MS-DOS-Datei.application/x-sh
: Unix-Shell-Skript.application/x-bsh
: Bourne-Shell-Skript.application/x-csh
: C-Shell-Skript.application/x-tcsh
: Tcsh-Shell-Skript.application/batch
: Windows-Batch-Datei.
Antwort-Header „X-Frame-Options“: Um Clickjacking-Angriffe zu verhindern, setzt der Snowflake-Proxy diesen Antwort-Header auf
DENY
und verhindert so, dass andere Webseiten einen iFrame zur Webseite für Ihren Dienst verwenden.Antwort-Header „Cross-Origin-Opener-Policy“ (COOP): Snowflake setzt den COOP-Antwort-Header auf
same-origin
, um zu verhindern, dass verweisende Cross-Origin-Fenster auf Ihre Dienst-Registerkarte zugreifen.Antwort-Header „Cross-Origin-Resource-Policy“ (CORP): Snowflake setzt den CORP-Header auf
same-origin
, um zu verhindern, dass externe Websites Ressourcen laden, die vom Eingangsendpunkt bereitgestellt werden (z. B. in einem iFrame).Antwort-Header „X-Content-Type-Options“: Snowflake-Proxy setzt diesen Header auf
nosniff
, um sicherzustellen, dass die Clients den von Ihrem Dienst in der Antwort angegebenen MIME-Typ nicht ändern.Antwort-Header „Cross-Origin-Embedder-Policy“ (COEP): Snowflake-Proxy setzt den COEP-Antwort-Header auf
credentialless
, was bedeutet, dass Snowflake beim Laden eines Cross-Origin-Objekts, z. B. eines Images oder eines Skripts, die Anmeldeinformationen nicht sendet, wenn das Remoteobjekt das „Cross-Origin Resource Sharing“ (CORS)-Protokoll nicht unterstützt.Antwort-Header „Content-Security-Policy-Report-Only“: Snowflake-Proxy ersetzt diesen Antwort-Header durch einen neuen Wert, der den Client anweist, die CSP-Berichte an Snowflake zu senden.
Antwort-Header „Content-Security-Policy“ (CSP): Standardmäßig fügt der Snowflake-Proxy die folgende Baseline-CSP hinzu, um sich gegen gängige Webangriffe zu schützen.
default-src 'self' 'unsafe-inline' 'unsafe-eval' blob: data:; object-src 'none'; connect-src 'self'; frame-ancestors 'self';
Es gibt zwei Überlegungen zur Inhaltssicherheitsrichtlinie:
Zusätzlich zur Baseline-Sicherheitsrichtlinie für Inhalte, die der Proxy hinzufügt, kann der Dienst selbst explizit eine CSP in der Antwort hinzufügen. Ein Dienst könnte sich dafür entscheiden, die Sicherheit durch Hinzufügen einer strengeren CSP zu erhöhen. Ein Dienst könnte zum Beispiel folgendes CSP hinzufügen, um nur Skripte von
self
zuzulassen.script-src 'self'
In der Antwort, die an den Client gesendet wird, sind zwei CSP-Header enthalten. Nach Erhalt der Antwort wenden die Client-Browser dann die strengste Inhaltssicherheitsrichtlinie an, die die in den einzelnen Richtlinien angegebenen zusätzlichen Einschränkungen enthält.
Wenn Sie eine Integration für den externen Zugriff (EAI) konfigurieren, um Ihrem Dienst den Zugriff auf eine externe Website (Konfigurieren des Netzwerkausgangs) zu ermöglichen, erstellt der Snowflake-Proxy eine CSP, die Ihrer Webseite den Zugriff auf diese Site ermöglicht. Angenommen, eine mit einer EAI verknüpfte Netzwerkregel erlaubt Ihrem Dienst den Ausgangsdatenzugriff auf
example.com
. Dann fügt der Snowflake-Proxy diesen CSP-Antwort-Header hinzu:default-src 'self' 'unsafe-inline' 'unsafe-eval' http://example.com https://example.com blob: data:; object-src 'none'; connect-src 'self' http://example.com https://example.com wss://example.com; frame-ancestors 'self';
Die Browser halten sich an die in der Antwort enthaltene Inhaltszugriffsrichtlinie. In diesem Beispiel erlauben die Browser der App den Zugriff auf
example.com
, aber nicht auf andere Websites.
Überlegungen zum Zugriff und SSO¶
Wenn Sie vom Internet aus auf den öffentlichen Endpunkt zugreifen, kann es sein, dass die Authentifizierung mit Benutzername und Kennwort funktioniert, aber SSO zu einer leeren Seite oder dem Fehler führt: „OAuth Clientintegration mit der angegebenen Client-ID wurde nicht gefunden.“
Dies passiert, wenn Sie die alte Methode der föderierten Authentifizierung (SSO) mit Snowflake anstelle der neueren Version der Sicherheitsintegration verwenden, wie unter Konfigurieren von Snowflake für die Verwendung der Verbundauthentifizierung beschrieben. Gehen Sie wie folgt vor, um dies zu überprüfen:
Führen Sie die folgende Abfrage aus:
SHOW PARAMETERS LIKE 'SAML_IDENTITY_PROVIDER' IN ACCOUNT;
Wenn Sie diesen Parameter gesetzt haben, haben Sie zu irgendeinem Zeitpunkt die alte föderierte Authentifizierung verwendet.
Wenn der obige Parameter gesetzt wurde, führen Sie die folgenden Abfragen aus, um festzustellen, ob Sie über eine SAML-Sicherheitsintegration verfügen:
SHOW INTEGRATIONS; SELECT * FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) WHERE "type" = 'SAML2';
Wenn Sie keine Integrationen des Typs SAML2 haben, dann verwenden Sie die alte Methode der föderierten Authentifizierung.
In diesem Fall besteht die Lösung darin, von der alten Methode der föderierten Authentifizierung auf die neue, integrative Methode der föderierten Authentifizierung umzusteigen. Weitere Informationen dazu finden Sie unter Migration zu einer SAML2-Sicherheitsintegration.
Konfigurieren des Netzwerkausgangs¶
Der Code Ihrer Anwendung erfordert möglicherweise einen Zugang zum Internet. Standardmäßig haben Anwendungscontainer keine Berechtigung für den Zugriff auf das Internet. Sie müssen daher den Internetzugang über Integrationen für den externen Zugriff (External Access Integrations, EAIs) aktivieren.
In der Regel werden EAIs von einem Kontoadministrator erstellt, um den von Diensten (einschließlich Jobdiensten) erlaubten externen Zugriff zu verwalten. Kontoadministratoren können dann die Berechtigung zur EAI-Nutzung bestimmten Rollen zuweisen, die Entwickler zum Ausführen von Diensten verwenden.
Im folgenden Beispiel werden die Schritte zum Erstellen einer EAI beschrieben, die ausgehenden Datenverkehr zu bestimmten Zielen zulässt, die mithilfe von Netzwerkregeln spezifiziert werden. Sie können sich dann auf diese EAI beziehen, wenn Sie einen Dienst erstellen, um Anforderungen an bestimmte Internetziele zuzulassen.
Beispiel
Angenommen, Sie möchten, dass Ihr Anwendungscode Anforderungen an die folgenden Ziele sendet:
HTTPS-Anforderung an translation.googleapis.com
HTTP- und HTTPS-Anforderung an google.com
Führen Sie die folgenden Schritte aus, damit Ihr Dienst auf diese Domänen im Internet zugreifen kann:
Erstellen Sie eine Integration für den externen Zugriff (EAI). Dafür sind die entsprechenden Berechtigungen erforderlich. Sie können zum Beispiel die Rolle ACCOUNTADMIN verwenden, um eine EAI zu erstellen. Dies ist ein zweistufiger Prozess:
Verwenden Sie den Befehl CREATE NETWORK RULE, um eine oder mehrere Netzwerkregeln für den ausgehenden Datenverkehr zu erstellen, wobei in den Regeln die externen Ziele aufgeführt sind, für die Sie den Zugriff erlauben möchten. Sie können benötigen für dieses Beispiel normalerweise nur eine Netzwerkregel, aber zur Veranschaulichung erstellen wir hier zwei Netzwerkregeln:
Erstellen Sie eine Netzwerkregel namens
translate_network_rule
.CREATE OR REPLACE NETWORK RULE translate_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('translation.googleapis.com');
Diese Regel erlaubt TCP-Verbindungen zum Ziel
translation.googleapis.com
. Die Domäne in der Eigenschaft VALUE_LIST gibt keine optionale Portnummer an, sodass der Standardport 443 (HTTPS) angenommen wird. Dadurch kann Ihre Anwendung eine Verbindung zu jeder URL herstellen, die mithttps://translation.googleapis.com/
beginnt.Erstellen Sie eine Netzwerkregel namens
google_network_rule
.CREATE OR REPLACE NETWORK RULE google_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('google.com:80', 'google.com:443');
Dadurch kann Ihre Anwendung eine Verbindung zu jeder URL herstellen, die mit
http://google.com/
oderhttps://google.com/
beginnt.
Bemerkung
Für den Parameter
VALUE_LIST
müssen Sie einen vollständigen Hostnamen angeben. Platzhalter (z. B.*.googleapis.com
) werden nicht unterstützt.Snowpark Container Services unterstützt nur die Netzwerkregeln, die die Ports 22, 80, 443 und 1024+ erlauben. Wenn eine referenzierte Netzwerkregel den Zugriff auf andere Ports zulässt, schlägt das Erstellen des Dienstes fehl. Wenden Sie sich an Ihren Kundenbetreuer, wenn Sie zusätzliche Ports benötigen.
Bemerkung
Damit Ihr Dienst HTTP- oder HTTPS-Anforderungen an ein beliebiges Ziel im Internet senden kann, geben Sie in der VALUE_LIST-Eigenschaft „0.0.0.0“ als Domäne an. Die folgende Netzwerkregel erlaubt es, sowohl „HTTP“- als auch „HTTPS“-Anforderungen an beliebige Ziele im Internet zu senden. Mit „0.0.0.0“ werden nur die Ports 80 oder 443 unterstützt.
CREATE NETWORK RULE allow_all_rule TYPE = 'HOST_PORT' MODE= 'EGRESS' VALUE_LIST = ('0.0.0.0:443','0.0.0.0:80');
Erstellen Sie eine Integration für den externe Zugriff (EAI), die festlegt, dass die beiden obigen Netzwerkregeln für ausgehenden Datenverkehr zulässig sind:
CREATE EXTERNAL ACCESS INTEGRATION google_apis_access_integration ALLOWED_NETWORK_RULES = (translate_network_rule, google_network_rule) ENABLED = true;
Nun kann der Kontoadministrator Entwicklern die Nutzung (USAGE) der Integration gestatten, damit diese einen Dienst ausführen können, der auf bestimmte Ziele im Internet zugreifen kann.
GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE test_role;
Erstellen Sie den Dienst durch Angabe der EAI wie in den folgenden Beispielen gezeigt. Die Eigentümerrolle, die den Dienst erstellt, benötigt die Berechtigung USAGE für die EAI und die Berechtigung READ für die referenzierten Geheimnisse. Beachten Sie, dass Sie mit der Rolle ACCOUNTADMIN keine Dienste erstellen können.
Erstellen Sie einen Dienst:
USE ROLE test_role; CREATE SERVICE eai_service IN COMPUTE POOL MYPOOL EXTERNAL_ACCESS_INTEGRATIONS = (GOOGLE_APIS_ACCESS_INTEGRATION) FROM SPECIFICATION $$ spec: containers: - name: main image: /db/data_schema/tutorial_repository/my_echo_service_image:tutorial env: TEST_FILE_STAGE: source_stage/test_file args: - read_secret.py endpoints: - name: read port: 8080 $$;
Diese CREATE SERVICE-Beispielanforderung verwendet eine Inline-Dienstspezifikation und gibt die optionale Eigenschaft EXTERNAL_ACCESS_INTEGRATIONS an, um die EAI einzuschließen. Die EAI gibt die Netzwerkregeln an, die den ausgehenden Datenverkehr vom Dienst zu den spezifischen Zielen erlauben.
Führen Sie einen Jobdienst aus:
EXECUTE JOB SERVICE IN COMPUTE POOL tt_cp NAME = example_job_service EXTERNAL_ACCESS_INTEGRATIONS = (GOOGLE_APIS_ACCESS_INTEGRATION) FROM SPECIFICATION $$ spec: container: - name: curl image: /tutorial_db/data_schema/tutorial_repo/alpine-curl:latest command: - "curl" - "http://google.com/" $$;
Dieser EXECUTE JOB SERVICE-Beispielbefehl gibt die Inline-Spezifikation und die optionale Eigenschaft EXTERNAL_ACCESS_INTEGRATIONS an, um die EAI einzuschließen. Dadurch wird der ausgehende Datenverkehr vom Job zu den in den Netzwerkregeln angegebenen Zielen zugelassen, die die EAI zulässt.
Netzwerkausgang über private Konnektivität¶
Anstatt den Netzwerkausgag über das öffentliche Internet zu routen, können Sie sich dafür entscheiden, den Ausgangverkehr Ihres Dienstes über einen privaten Konnektivitätsendpunkt zu leiten.
Zunächst müssen Sie den privaten Konnektivitätsendpunkt in Ihrem Snowflake-Konto erstellen. Konfigurieren Sie dann eine Netzwerkregel, um den ausgehenden Datenverkehr über die private Konnektivität zuzulassen. Der Prozess zur Einrichtung einer External Access Integration (EAI) bleibt derselbe wie im vorangegangenen Abschnitt beschrieben.
Bemerkung
Private Kommunikation erfordert, dass sowohl Snowflake als auch das Cloud-Konto des Kunden denselben Cloudanbieter und dieselbe Region verwenden.
Wenn Sie zum Beispiel den ausgehenden Internetzugang Ihres Dienstes zu einem Amazon S3-Bucket über private Konnektivität aktivieren möchten, gehen Sie wie folgt vor:
Aktivieren Sie die private Link-Konnektivität für den selbstverwalteten Endpunktdienst (Amazon S3). Eine Schritt-für-Schritt-Anleitung finden Sie unter AWS Private Link for Amazon S3.
Rufen Sie die Systemfunktion SYSTEM$PROVISION_PRIVATELINK_ENDPOINT auf, um einen privaten Konnektivitätsendpunkt in Ihrem Snowflake-VNet bereitzustellen. Dadurch kann Snowflake über private Konnektivität eine Verbindung zum externen Dienst (in diesem Beispiel Amazon S3) herstellen.
USE ROLE ACCOUNTADMIN; SELECT SYSTEM$PROVISION_PRIVATELINK_ENDPOINT( 'com.amazonaws.us-west-2.s3', '*.s3.us-west-2.amazonaws.com' );
Genehmigen Sie den Endpunkt im Konto des Cloudanbieters. In diesem Beispiel für Amazon AWS, siehe Verbindungsanfragen annehmen oder ablehnen in der AWS-Dokumentation. Um den Endpunkt in Azure zu genehmigen, lesen Sie auch die Azure-Dokumentation.
Verwenden Sie den Befehl CREATE NETWORK RULE, um eine Netzwerkegel für den ausgehenden Datenverkehr zu erstellen, in der Sie die externen Ziele angeben, für die Sie den Zugriff erlauben möchten.
CREATE OR REPLACE NETWORK RULE private_link_network_rule MODE = EGRESS TYPE = PRIVATE_HOST_PORT VALUE_LIST = ('<bucket-name>.s3.us-west-2.amazonaws.com');
Der Parameters TYPE ist auf PRIVATE_HOST_PORT eingestellt. Er zeigt an, dass die Netzwerkregel den ausgehenden Datenverkehr über die private Konnektivität zulässt.
Die übrigen Schritte zur Erstellung eines EAI und dessen Verwendung zur Erstellung eines Dienstes sind die gleichen wie im vorangegangenen Abschnitt (siehe Konfigurieren des Netzwerkausgangs) erklärt.
Weitere Informationen zur Arbeit mit privaten Konnektivitätsendpunkten finden Sie unter:
Konfigurieren der Netzwerkkommunikation zwischen Containern¶
Es gibt zwei Konzepte:
Kommunikation zwischen Containern einer Dienstinstanz: Wenn eine Dienstinstanz mehrere Container ausführt, können diese Container über „localhost“ miteinander kommunizieren (es ist nicht erforderlich, in der Dienstspezifikation Endpunkte zu definieren).
Kommunikation zwischen Containern verschiedener Dienste oder mehrerer Dienstinstanzen: Container, die zu verschiedenen Diensten (oder verschiedenen Instanzen desselben Dienstes) gehören, können über Endpunkte kommunizieren, die in Spezifikationsdateien definiert sind. Weitere Informationen dazu finden Sie unter Dienst-zu-Dienst-Kommunikation.
Übergabe von Anmeldeinformationen an einen Container mit Snowflake-Geheimnissen¶
Es gibt viele Gründe, warum Sie von Snowflake verwaltete Anmeldeinformationen an Ihren Container weitergeben möchten. Ihr Dienst könnte zum Beispiel mit externen Endpunkten (außerhalb von Snowflake) kommunizieren. In diesem Fall müssen Sie in Ihrem Container Anmeldeinformationen bereitstellen, die Ihr Anwendungscode verwenden kann.
Um Anmeldeinformationen bereitzustellen, speichern Sie diese zunächst in Snowflake-Geheimnis-Objekten. In der Service-Spezifikation geben Sie dann unter containers.secrets
an, welche Geheimnisobjekte verwendet werden sollen und wo sie im Container platziert werden sollen. Sie können diese Anmeldeinformationen entweder an Umgebungsvariablen in den Containern übergeben oder sie in lokalen Dateien in den Containern verfügbar machen.
Snowflake-Geheimnisse angeben¶
Geben Sie ein Snowflake-Geheimnis durch Name oder Referenz an (die Referenz ist nur im Native Application-Szenario anwendbar):
Snowflake-Geheimnis per Name übergeben: Sie können einen Geheimnamen als
snowflakeSecret
-Feldwert übergeben.... secrets: - snowflakeSecret: objectName: '<secret-name>' <other info about where in the container to copy the secret> ...
Beachten Sie, dass Sie optional
<secret-name>
direkt als WertsnowflakeSecret
angeben können.Snowflake-Geheimnis per Referenz weitergeben: Wenn Sie Snowpark Container Services verwenden, um eine Native App (eine App mit Containern) zu erstellen, verwenden der App-Produzent und die Verbraucher unterschiedliche Snowflake-Konten. In bestimmten Kontexten muss eine installierte Snowflake Native App auf bestehende Geheimnisobjekte im Verbraucherkonto zugreifen, die außerhalb des APPLICATION-Objekts existieren. In diesem Fall können Entwickler die Syntax der Spezifikation „secrets by reference“ (Geheimnisse per Referenz) verwenden, um Anmeldeinformationen wie gezeigt zu behandeln:
containers: - name: main image: <url> secrets: - snowflakeSecret: objectReference: '<reference-name>' <other info about where in the container to copy the secret>
Beachten Sie, dass die Spezifikation
objectReference
anstelle vonobjectName
verwendet, um einen geheimen Referenznamen anzugeben.
Festlegen der Platzierung von Geheimnissen innerhalb des Containers¶
Sie können Snowflake anweisen, die Geheimnisse entweder als Umgebungsvariablen in den Containern zu platzieren oder sie in lokale Dateien der Container zu schreiben.
Übergeben Sie Geheimnisse als Variablen der Umgebung¶
Um Snowflake-Geheimnisse als Umgebungsvariablen an Container zu übergeben, fügen Sie envVarName
in das containers.secrets
-Feld ein.
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: <secret-name>
secretKeyRef: username | password | secret_string | 'access_token'
envVarName: '<env-variable-name>'
Der secretKeyRef
-Wert hängt von der Art des Snowflake-Geheimnisses ab. Mögliche Werte sind die folgenden:
username
oderpassword
, wenn das Snowflake-Geheimnis vom Typpassword
ist.secret_string
, wenn das Snowflake-Geheimnis vom Typgeneric_string
ist.
Beachten Sie, dass Snowflake die als Umgebungsvariablen übergebenen Geheimnisse nicht aktualisiert, nachdem ein Dienst erstellt wurde.
Beispiel 1: Übergeben von Geheimnissen des Typs password als Umgebungsvariable¶
In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ password
:
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
Um dieses Snowflake-Geheimnisobjekt den Umgebungsvariablen (z. B. LOGIN_USER
und LOGIN_PASSWORD
) in Ihrem Container zur Verfügung zu stellen, fügen Sie das folgende Feld containers.secrets
in die Spezifikationsdatei ein:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret_object
secretKeyRef: username
envVarName: LOGIN_USER
- snowflakeSecret: testdb.testschema.my_secret_object
secretKeyRef: password
envVarName: LOGIN_PASSWORD
In diesem Beispiel ist der Wert snowflakeSecret
ein vollständig qualifizierter Objektname, da Geheimnisse in einem anderen Schema als der zu erstellende Dienst gespeichert sein können.
Das Feld containers.secrets
in diesem Beispiel ist eine Liste mit zwei snowflakeSecret
-Objekten:
Mit dem ersten Objekt wird
username
im Snowflake-Geheimnisobjekt der UmgebungsvariablenLOGIN_USER
in Ihrem Container zugeordnet.Mit dem zweiten Objekt wird
password
im Snowflake-Geheimnisobjekt der UmgebungsvariablenLOGIN_PASSWORD
in Ihrem Container zugeordnet.
Beispiel 2: Übergeben von Geheimnissen vom Typ generic_string als Umgebungsvariable¶
In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ generic_string
:
CREATE SECRET testdb.testschema.my_secret
TYPE=generic_string
SECRET_STRING='
some_magic: config
';
Um dieses Snowflake-Geheimnisobjekt den Umgebungsvariablen (z. B. GENERIC_SECRET) in Ihrem Container zur Verfügung zu stellen, fügen Sie das folgende Feld containers.secrets
in die Spezifikationsdatei ein:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret
secretKeyRef: secret_string
envVarName: GENERIC_SECRET
Geheimnisse in lokale Containerdateien schreiben¶
Um Snowflake-Geheimnisse für Ihren Anwendungscontainer in lokalen Containerdateien verfügbar zu machen, fügen Sie ein containers.secrets
-Feld ein: Um Snowflake-Geheimnisse für Ihren Anwendungscontainer in lokalen Containerdateien verfügbar zu machen, fügen Sie directoryPath
in die Datei containers.secrets
ein:
containers:
- name: <name>
image: <url>
...
secrets:
- snowflakeSecret: <snowflake-secret-name>
directoryPath: '<local directory path in the container>'
Snowflake füllt die notwendigen Dateien für das Geheimnis in diesem angegebenen directoryPath
auf; die Angabe von secretKeyRef
ist nicht erforderlich. Je nach Geheimnistyp erstellt Snowflake die folgenden Dateien im Container unter dem von Ihnen angegebenen Verzeichnispfad:
username
undpassword
, wenn das Snowflake-Geheimnis vom Typpassword
ist.secret_string
, wenn das Snowflake-Geheimnis vom Typgeneric_string
ist.access_token
, wenn das Snowflake-Geheimnis vom Typoauth2
ist.
Bemerkung
Wenn nach dem Erstellen eines Dienstes das Snowflake-Geheimnisobjekt aktualisiert wird, aktualisiert Snowflake die entsprechenden Geheimnisdateien in den aktiven Containern.
Beispiel 1: Übergeben von Geheimnissen des Typs password mithilfe von lokalen Containerdateien¶
In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ password
:
CREATE SECRET testdb.testschema.my_secret_object
TYPE = password
USERNAME = 'snowman'
PASSWORD = '1234abc';
Um diese Anmeldeinformationen in lokalen Containerdateien zur Verfügung zu stellen, fügen Sie das folgende containers.secrets
-Feld in die Spezifikationsdatei ein:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret_object
directoryPath: '/usr/local/creds'
Wenn Sie Ihren Dienst starten, erstellt Snowflake zwei Dateien innerhalb des Containers: /usr/local/creds/username
und /usr/local/creds/password
. Ihr Anwendungscode kann dann diese Dateien lesen.
Beispiel 2: Übergabe von Geheimnissen vom Typ generic_string in lokalen Containerdateien¶
In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ generic_string
:
CREATE SECRET testdb.testschema.my_secret
TYPE=generic_string
SECRET_STRING='
some_magic: config
';
Um dieses geheime Snowflake-Objekt in lokalen Containerdateien bereitzustellen, fügen Sie das folgende containers.secrets
-Feld in die Datei mit den Spezifikationen ein:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.my_secret
directoryPath: '/usr/local/creds'
Wenn Sie Ihren Dienst starten, erstellt Snowflake diese Datei in den Containern: /usr/local/creds/secret_string
.
Beispiel 3: Übergeben von Geheimnissen des Typs oauth2 mithilfe von lokalen Containerdateien¶
In diesem Beispiel erstellen Sie das folgende Snowflake-Geheimnisobjekt vom Typ oauth2
:
CREATE SECRET testdb.testschema.oauth_secret
TYPE = OAUTH2
OAUTH_REFRESH_TOKEN = '34n;vods4nQsdg09wee4qnfvadH'
OAUTH_REFRESH_TOKEN_EXPIRY_TIME = '2023-12-31 20:00:00'
API_AUTHENTICATION = my_integration;
Um diese Anmeldeinformationen in lokalen Containerdateien zur Verfügung zu stellen, fügen Sie das folgende containers.secrets
-Feld in die Spezifikationsdatei ein:
containers:
- name: main
image: <url>
secrets:
- snowflakeSecret: testdb.testschema.oauth_secret
directoryPath: '/usr/local/creds'
Snowflake ruft das Zugriffstoken aus dem OAuth-Geheimnisobjekt ab und erstellt /usr/local/creds/access_token
in den Containern.
Wenn ein Dienst Geheimnisse des „oauth2“-Typs verwendet, wird erwartet, dass der Dienst dieses Geheimnis für den Zugriff auf ein Internetziel verwendet. Ein OAuth-Geheimnis muss von einer Integration für den externen Zugriff (EAI) erlaubt werden, da sonst CREATE SERVICE und EXECUTE JOB SERVICE fehlschlagen. Diese zusätzliche EAI-Anforderung gilt nur für Geheimnisse des „oauth2“-Typs und nicht für andere Typen von Geheimnissen.
Zusammenfassend sind folgende allgemeine Schritte zum Erstellen eines solchen Dienstes erforderlich:
Erstellen Sie ein Geheimnis vom Typ „oauth2“ (siehe oben).
Erstellen Sie eine EAI, um die Verwendung des Geheimnisses durch einen Dienst zu erlauben. Beispiel:
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION example_eai ALLOWED_NETWORK_RULES = (<name>) ALLOWED_AUTHENTICATION_SECRETS = (testdb.testschema.oauth_secret) ENABLED = true;
Erstellen Sie einen Dienst, der ein
containers.secrets
-Feld in der Spezifikation enthält. Darin wird auch die optionale Eigenschaft EXTERNAL_ACCESS_INTEGRATIONS mit einer EAI angegeben, um die Verwendung des OAuth2-Geheimnisses zuzulassen.Beispiel für einen CREATE SERVICE-Befehl (mit Inline-Spezifikation):
CREATE SERVICE eai_service IN COMPUTE POOL MYPOOL EXTERNAL_ACCESS_INTEGRATIONS = (example_eai) FROM SPECIFICATION $$ spec: containers: - name: main image: <url> secrets: - snowflakeSecret: testdb.testschema.oauth_secret directoryPath: '/usr/local/creds' endpoints: - name: api port: 8080 $$;
Weitere Informationen zu ausgehendem Datenverkehr finden Sie unter Konfigurieren des Netzwerkausgangs.
Richtlinien und Einschränkungen¶
Allgemeine Beschränkungen: Sollten Sie Probleme mit diesen Beschränkungen haben, wenden Sie sich bitte an Ihren Kontobeauftragten.
Sie können bis zu 200 Dienste in Ihrem Snowflake-Konto erstellen.
Jeder Service kann bis zu 100 Endpunkte bereitstellen.
Die folgenden Beschränkungen gelten, wenn Sie den Internetzugang (siehe Konfigurieren des Netzwerkausgangs) unter Verwendung von Integrationen für den externen Zugang (EAIs) aktivieren.
Jeder Service kann bis zu 10 EAIs unterstützen (siehe CREATE SERVICE und ALTER SERVICE).
Jedes EAI kann bis zu 100 Hostnamen haben.
Snowpark Container Services unterstützt ausgehende private Konnektivität sowohl auf AWS als auch auf Azure. Eingehende private Konnektivität ist in der Vorschau für AWS. Wenden Sie sich an Ihren Kundenbetreuer, wenn Sie eine eingehende private Konnektivität zu Azure benötigen.
Wenn Sie vom Internet aus auf den öffentlichen Endpunkt zugreifen, kann es sein, dass die Authentifizierung mit Benutzername und Kennwort funktioniert, aber SSO zu einer leeren Seite oder dem Fehler führt: „OAuth Clientintegration mit der angegebenen Client-ID wurde nicht gefunden.“ Informationen zum Umgang mit diesem Problem finden Sie unter Überlegungen zum Zugriff und SSO.
Anforderungen an Plattformimages: Snowpark Container Services benötigt derzeit Images der linux/amd64-Plattform.
Dienstcontainer haben keine Berechtigungen: Dienstcontainer werden derzeit ohne weitreichende Berechtigungen ausgeführt, d. h. sie können die Konfiguration der Hardware auf dem Host nicht ändern und können BS-Konfigurationen nur begrenzt ändern. Dienstcontainer können nur Betriebssystemkonfigurationen ausführen, die auch ein normaler Benutzer (d. h. ein Benutzer, der keine Root-Berechtigung benötigt) ausführen kann.
Umbenennen von Datenbank und Schema:
Benennen Sie keine Datenbanken und Schemas um, für die Sie bereits einen Dienst erstellt haben. Das Umbenennen bedeutet im Grunde, dass ein Dienst in eine andere Datenbank und ein anderes Schema verschoben wird, was nicht unterstützt wird. Beispiel:
Der DNS-Name des Dienstes wird weiterhin den alten Datenbank- und Schemanamen verwenden.
Datenbank- und Schemainformationen, die Snowflake den aktiven Dienstcontainern zur Verfügung stellt, beziehen sich weiterhin auf die alten Namen.
Neue Protokolleinträge, die von Diensten in die Ereignistabelle aufgenommen werden, beziehen sich weiterhin auf die alten Datenbank- und Schemanamen.
Die Dienstfunktion wird weiterhin auf den Dienst in der alten Datenbank und dem alten Schema verweisen, und wenn Sie die Dienstfunktion aufrufen, wird sie fehlschlagen.
Eine Dienstspezifikation kann auf Objekte wie Snowflake-Stagingbereiche und Image-Repositorys verweisen. Wenn Sie den Namen von Datenbank oder Schema umbenennen, in denen sich diese Objekte befinden, müssen Sie die Datenbank- und Schemanamen der referenzierten Objekte in der Dienstspezifikation manuell aktualisieren.
Löschen und Wiederherstellen von Datenbank und Schema:
Wenn Sie die übergeordnete Datenbank oder das übergeordnete Schema löschen, werden die Dienste asynchron gelöscht. Das bedeutet, dass ein Dienst noch einige Zeit weiter ausgeführt wird, bevor er durch interne Prozesse entfernt wird.
Wenn Sie versuchen, eine zuvor gelöschte Datenbank oder ein Schema wiederherzustellen, gibt es keine Garantie, dass die Dienste wiederhergestellt werden.
Übertragen der Eigentümerschaft: Das Übertragen der Eigentümerschaft von Diensten (einschließlich Jobdiensten) wird nicht unterstützt.
Replikation: Bei der Replikation in Snowflake ist Folgendes zu beachten:
Snowpark Container Services-Objekte wie Dienste, Computepools und Repositorys können nicht repliziert werden.
Wenn Sie ein Repository innerhalb einer Datenbank erstellen, kann nicht die gesamte Datenbank repliziert werden. In Fällen, in denen die Datenbank andere Ressourcen enthält, wie z. B. Dienste oder Computepools, wird der Replikationsprozess der Datenbank erfolgreich sein, aber diese einzelnen Objekte innerhalb der Datenbank werden nicht repliziert.
Timeout von Jobdiensten: Snowpark Container Services-Jobdienste werden synchron ausgeführt. Wenn eine Anweisung ein Zeitlimit überschreitet, wird der Jobdienst abgebrochen. Das Standard-Timeout für Anweisungen beträgt zwei Tage. Kunden können den Timeout-Wert ändern, indem sie den Parameter STATEMENT_TIMEOUT_IN_SECONDS mit ALTER SESSION einstellen.
ALTER SESSION SET statement_timeout_in_seconds=<time>
Stellen Sie ihn ein, bevor Sie den Befehl EXECUTE JOB SERVICE ausführen.