Exemples d’accès au réseau externe¶
Cette rubrique fournit des exemples d’accès à des emplacements réseau externes à partir de fonctions et de procédures définies par l’utilisateur.
Accès à l’API Google Translate¶
Les étapes suivantes comprennent le code permettant de créer une intégration d’accès externe pour l’accès à l’API Google Translation. Les étapes ajoutent l’intégration de la sécurité et les autorisations nécessaires à l’exécution des instructions.
Créez une règle réseau représentant l’emplacement externe.
Pour plus d’informations sur le rôle d’une règle de réseau dans l’accès externe, y compris les privilèges requis, voir Création d’une règle de réseau pour représenter l’emplacement réseau externe.
CREATE OR REPLACE NETWORK RULE google_apis_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('translation.googleapis.com');
Créez une intégration de sécurité pour contenir les identifiants de connexion OAuth requis pour s’authentifier auprès de l’emplacement du réseau externe spécifié par la règle réseau
google_apis_network_rule
.Pour des informations de référence sur la commande, y compris les privilèges requis, voir CREATE SECURITY INTEGRATION (authentification API externe).
CREATE OR REPLACE SECURITY INTEGRATION google_translate_oauth TYPE = API_AUTHENTICATION AUTH_TYPE = OAUTH2 OAUTH_CLIENT_ID = 'my-client-id' OAUTH_CLIENT_SECRET = 'my-client-secret' OAUTH_TOKEN_ENDPOINT = 'https://oauth2.googleapis.com/token' OAUTH_AUTHORIZATION_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth' OAUTH_ALLOWED_SCOPES = ('https://www.googleapis.com/auth/cloud-platform') ENABLED = TRUE;
Créer un secret pour représenter les identifiants de connexion contenus dans l’intégration de sécurité
google_translate_oauth
.Pour plus d’informations sur le rôle du secret dans l’accès externe, y compris les privilèges requis, voir Création d’un secret pour représenter les identifiants de connexion.
Le secret doit spécifier un jeton d’actualisation avec son paramètre OAUTH_REFRESH_TOKEN. Pour obtenir un jeton d’actualisation auprès du fournisseur de services (dans ce cas, auprès du service de l’API Google Cloud Translation), vous pouvez utiliser un moyen proposé par le fournisseur ou utiliser les fonctions système Snowflake.
Pour créer un secret avec un jeton d’actualisation, utilisez soit Google OAuth Playground, soit les fonctions système Snowflake, comme décrit ci-dessous :
Fonctions système Snowflake
Exécutez CREATE SECRET pour créer un secret. Vous le mettrez à jour avec le jeton d’actualisation à une étape ultérieure.
USE DATABASE my_db; USE SCHEMA secret_schema; CREATE OR REPLACE SECRET oauth_token TYPE = oauth2 API_AUTHENTICATION = google_translate_oauth;
Exécutez la fonction SYSTEM$START_OAUTH_FLOW pour récupérer une URL avec laquelle vous pouvez obtenir un jeton d’actualisation, en spécifiant comme argument le nom du secret que vous avez précédemment créé.
CALL SYSTEM$START_OAUTH_FLOW( 'my_db.secret_schema.oauth_token' );
La fonction génère une URL que vous pouvez utiliser pour compléter le processus de consentement OAuth.
Dans un navigateur, accédez à l’URL générée et effectuez le processus de consentement OAuth2. Lorsque vous avez terminé, laissez le navigateur ouvert à la dernière page du processus.
Dans la barre d’adresse du navigateur, copiez l’ensemble du texte après le point d’interrogation dans l’URL de la dernière page du processus de consentement.
Exécutez la fonction SYSTEM$FINISH_OAUTH_FLOW, en spécifiant comme argument les paramètres que vous venez de copier depuis la barre d’adresse du navigateur.
Cette opération permet de mettre à jour le secret à l’aide d’un jeton d’actualisation.
Assurez-vous d’exécuter SYSTEM$FINISH_OAUTH_FLOW dans la même session que SYSTEM$START_OAUTH_FLOW. SYSTEM$FINISH_OAUTH_FLOW mettra à jour le secret que vous avez spécifié dans SYSTEM$START_OAUTH_FLOW via le jeton d’accès et le jeton d’actualisation obtenus auprès du serveur OAuth.
CALL SYSTEM$FINISH_OAUTH_FLOW( 'state=<remaining_url_text>' );
Google OAuth Playground
Dans Google OAuth Playground, sélectionnez et autorisez l’API Cloud Translation comme spécifié à l’étape 1.
A l’étape 2, cliquez sur exchange authorization code for tokens, puis copiez la valeur du jeton refresh token.
Exécutez CREATE SECRET pour créer un secret qui spécifie la valeur du jeton d’actualisation que vous avez copiée.
Pour plus d’informations sur le rôle d’un secret dans l’accès externe, y compris les privilèges requis, voir Création d’un secret pour représenter les identifiants de connexion.
CREATE OR REPLACE SECRET oauth_token TYPE = oauth2 API_AUTHENTICATION = google_translate_oauth OAUTH_REFRESH_TOKEN = 'my-refresh-token';
Créez une intégration d’accès externe à l’aide de la règle de réseau et du secret.
Pour plus d’informations sur le rôle d’une intégration d’accès externe, y compris les privilèges requis, voir Création d’une intégration d’accès externe.
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION google_apis_access_integration ALLOWED_NETWORK_RULES = (google_apis_network_rule) ALLOWED_AUTHENTICATION_SECRETS = (oauth_token) ENABLED = TRUE;
Créez un rôle
developer
qui sera attribué aux utilisateurs qui doivent créer une UDF ou une procédure utilisant l’intégration.CREATE OR REPLACE ROLE developer; CREATE OR REPLACE ROLE user;
Accordez au rôle
developer
les privilèges nécessaires pour créer une UDF qui utilise les objets pour l’accès externe. Cela comprend les éléments suivants :Le privilège READ sur le secret.
Le privilège USAGE sur le schéma qui contient le secret.
Le privilège USAGE sur l’intégration.
GRANT READ ON SECRET oauth_token TO ROLE developer; GRANT USAGE ON SCHEMA secret_schema TO ROLE developer; GRANT USAGE ON INTEGRATION google_apis_access_integration TO ROLE developer;
Créez une UDF
google_translate_python
qui traduit le texte spécifié en une phrase dans la langue spécifiée. Pour plus d’informations, voir Utilisation de l’intégration de l’accès externe dans une fonction ou une procédure.USE ROLE developer; CREATE OR REPLACE FUNCTION google_translate_python(sentence STRING, language STRING) RETURNS STRING LANGUAGE PYTHON RUNTIME_VERSION = 3.8 HANDLER = 'get_translation' EXTERNAL_ACCESS_INTEGRATIONS = (google_apis_access_integration) PACKAGES = ('snowflake-snowpark-python','requests') SECRETS = ('cred' = oauth_token ) AS $$ import _snowflake import requests import json session = requests.Session() def get_translation(sentence, language): token = _snowflake.get_oauth_access_token('cred') url = "https://translation.googleapis.com/language/translate/v2" data = {'q': sentence,'target': language} response = session.post(url, json = data, headers = {"Authorization": "Bearer " + token}) return response.json()['data']['translations'][0]['translatedText'] $$;
Accordez le privilège USAGE à la fonction
google_translate_python
afin que les personnes ayant le rôleuser
puissent l’appeler.GRANT USAGE ON FUNCTION google_translate_python(string, string) TO ROLE user;
Exécutez la fonction
google_translate_python
pour traduire une phrase.USE ROLE user; SELECT google_translate_python('Happy Thursday!', 'zh-CN');
Cette opération génère la sortie suivante.
------------------------------------------------------- | GOOGLE_TRANSLATE_PYTHON('HAPPY THURSDAY!', 'ZH-CN') | ------------------------------------------------------- | 快乐星期四! | -------------------------------------------------------
Accès à une fonction lambda externe¶
Les étapes suivantes comprennent un exemple de code pour créer une intégration d’accès externe pour l’accès à une fonction lambda externe à Snowflake. L’exemple utilise un espace réservé pour le point de terminaison externe lui-même, mais il pourrait s’agir d’une fonction disponible sur un point de terminaison de service REST, par exemple.
L’accès externe est utilisé dans une UDF vectorisée Python qui reçoit un Pandas DataFrame contenant les données.
Créez une règle réseau
lambda_network_rule
représentant l’emplacement externemy_external_service
(ici, une valeur d’espace réservé pour l’emplacement d’un point de terminaison externe).Pour plus d’informations sur le rôle d’une règle réseau dans l’accès externe, voir Création d’une règle de réseau pour représenter l’emplacement réseau externe.
CREATE OR REPLACE NETWORK RULE lambda_network_rule MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('my_external_service');
Créez un secret pour représenter les identifiants de connexion requis par le service externe.
Le code du gestionnaire, plus loin dans cet exemple, récupère les identifiants de connexion du secret à l’aide d’une API Snowflake pour Python.
Pour plus d’informations sur le rôle du secret dans l’accès externe, voir Création d’un secret pour représenter les identifiants de connexion.
CREATE OR REPLACE SECRET secret_password TYPE = PASSWORD USERNAME = 'my_user_name' PASSWORD = 'my_password';
Créez un rôle
developer
et accordez-lui des privilèges READ sur le secret. Ce rôle sera attribué aux utilisateurs qui doivent créer une UDF ou une procédure utilisant le secret.Créez également le rôle que les utilisateurs utiliseront pour appeler la fonction.
CREATE OR REPLACE ROLE developer; CREATE OR REPLACE ROLE user;
Accordez au rôle
developer
les privilèges nécessaires pour créer une UDF qui utilise les objets pour l’accès externe. Cela comprend les éléments suivants :Le privilège READ sur le secret.
Le privilège USAGE sur le schéma qui contient le secret.
GRANT READ ON SECRET secret_password TO ROLE developer; GRANT USAGE ON SCHEMA secret_schema TO ROLE developer;
Créez une intégration d’accès externe pour spécifier le point de terminaison externe et les identifiants de connexion par le biais de la règle réseau et du secret que vous avez créés.
Pour plus d’informations sur le rôle d’une intégration d’accès externe, y compris les privilèges requis, voir Création d’une intégration d’accès externe.
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION lambda_external_access_integration ALLOWED_NETWORK_RULES = (lambda_network_rule) ALLOWED_AUTHENTICATION_SECRETS = (secret_password) ENABLED = TRUE;
Créez une UDF vectorisée Python
return_double_column
qui accède à un emplacement réseau externe pour traiter les données reçues en tant que Pandas DataFrame.Pour plus d’informations sur l’utilisation de l’accès externe dans une UDF, voir Utilisation de l’intégration de l’accès externe dans une fonction ou une procédure.
CREATE OR REPLACE FUNCTION return_double_column(x int) RETURNS INT LANGUAGE PYTHON EXTERNAL_ACCESS_INTEGRATIONS = (lambda_external_access_integration) SECRETS = ('cred' = secret_password) RUNTIME_VERSION = 3.8 HANDLER = 'return_first_column' PACKAGES = ('pandas', 'requests') AS $$ import pandas import numpy as np import json import requests import base64 import _snowflake from _snowflake import vectorized from requests.auth import HTTPBasicAuth from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry session = requests.Session() retries = Retry(total=10, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504], allowed_methods = None) session.mount('https://', HTTPAdapter(max_retries=retries)) @vectorized(input=pandas.DataFrame) def return_first_column(df): request_rows = [] df.iloc[:,0] = df.iloc[:,0].astype(int) request_rows = np.column_stack([df.index, df.iloc[:,0]]).tolist() request_payload = {"data" : request_rows} username_password_object = _snowflake.get_username_password('cred'); basic = HTTPBasicAuth(username_password_object.username, username_password_object.password) url = 'my_external_service' response = session.post(url, json=request_payload, auth=basic) response.raise_for_status() response_payload = json.loads(response.text) response_rows = response_payload["data"] return pandas.DataFrame(response_rows)[1] $$;
Accordez le privilège USAGE à la fonction
return_double_column
afin que les personnes ayant le rôleuser
puissent l’appeler.GRANT USAGE ON FUNCTION return_double_column(int) TO ROLE user;
Exécutez la fonction
return_double_column
, en adressant une demande au point de terminaison externe.Le code de l’exemple suivant crée une table à deux colonnes et insère 100 000 000 lignes contenant des entiers de 4 octets. Le code exécute ensuite la fonction
return_double_column
, transmettant les valeurs de la colonnea
pour un traitement par le point de terminaison externe.CREATE OR REPLACE TABLE t1 (a INT, b INT); INSERT INTO t1 SELECT SEQ4(), SEQ4() FROM TABLE(GENERATOR(ROWCOUNT => 100000000)); SELECT return_double_column(a) AS retval FROM t1 ORDER BY retval;