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 avec OAuth¶
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 pour mettre à jour le secret avec 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 met à 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.9 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 avec l’authentification de base¶
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.9 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;
Accéder à Amazon S3 avec AWS IAM¶
Les étapes suivantes incluent un exemple de code pour se connecter à un compartiment S3 AWS avec IAM.
Pour plus d’informations sur AWS IAM, voir la documentation sur AWS IAM.
Créez une règle de réseau,
aws_s3_network_rule
, qui représente le compartiment S3 AWS à l’emplacement spécifié par le paramètre VALUE_LIST.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 aws_s3_network_rule MODE = EGRESS TYPE = PRIVATE_HOST_PORT VALUE_LIST = ('external-access-iam-bucket.s3.us-west-2.amazonaws.com');
Créez une intégration de sécurité pour contenir les identifiants de connexion AWS IAM Amazon Resource Name (ARN) requis pour s’authentifier auprès de l’emplacement du réseau externe spécifié par la règle réseau
aws_s3_network_rule
.Pour des informations de référence sur la commande, y compris les privilèges requis, voir CREATE SECURITY INTEGRATION (authentification IAM AWS).
CREATE OR REPLACE SECURITY INTEGRATION aws_s3_security_integration TYPE = API_AUTHENTICATION AUTH_TYPE = AWS_IAM ENABLED = TRUE AWS_ROLE_ARN = 'arn:aws:iam::736112632310:role/external-access-iam-bucket';
Obtenez l’ARN et l’ID pour l’utilisateur IAM USER.
Exécutez la commande DESC sur l’intégration de sécurité que vous avez créée.
DESC SECURITY INTEGRATION aws_s3_security_integration;
À partir de la sortie affichée, copiez les valeurs des propriétés suivantes à utiliser à l’étape suivante :
API_AWS_IAM_USER_ARN
API_AWS_EXTERNAL_ID
Accordez les autorisations de l’utilisateur IAM nécessaires pour accéder au compartiment.
Utilisez les valeurs ARN et ID lors de la configuration d’une politique de confiance comme décrit à l’étape 5 de Option 1 : Configuration d’une intégration de stockage Snowflake pour accéder à Amazon S3.
Créez un secret de type CLOUD_PROVIDER_TOKEN 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 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 aws_s3_access_token TYPE = CLOUD_PROVIDER_TOKEN API_AUTHENTICATION = aws_s3_security_integration;
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 aws_s3_access_token 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 aws_s3_external_access_integration ALLOWED_NETWORK_RULES = (aws_s3_network_rule) ALLOWED_AUTHENTICATION_SECRETS = (aws_s3_access_token) ENABLED = TRUE COMMENT = 'Testing S3 connectivity';
Créez une UDF qui utilise l’intégration d’accès externe pour se connecter au compartiment S3 Amazon spécifié dans la règle réseau que vous avez créée.
Le code du gestionnaire utilise des APIs Snowflake pour récupérer un jeton du secret que vous avez créé. À partir de ce jeton, vous pouvez utiliser des APIs Snowflake pour récupérer les valeurs nécessaires à la création d’une session de connexion à Amazon S3, y compris un ID de clé d’accès, une clé d’accès secrète et un jeton de session.
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 aws_s3_python_function() RETURNS VARCHAR LANGUAGE PYTHON EXTERNAL_ACCESS_INTEGRATIONS = (aws_s3_external_access_integration) RUNTIME_VERSION = '3.9' SECRETS = ('cred' = aws_s3_access_token) PACKAGES = ('boto3') HANDLER = 'main_handler' AS $$ import boto3 import _snowflake from botocore.config import Config def main_handler(): # Get token object cloud_provider_object = _snowflake.get_cloud_provider_token('cred') # Boto3 configuration config = Config( retries=dict(total_max_attempts=9), connect_timeout=30, read_timeout=30, max_pool_connections=50 ) # Connect to S3 using boto3 s3 = boto3.client( 's3', region_name='us-west-2', aws_access_key_id=cloud_provider_object.access_key_id, aws_secret_access_key=cloud_provider_object.secret_access_key, aws_session_token=cloud_provider_object.token, config=config ) # Use S3 object to upload/download return 'Successfully connected with S3' $$;
CREATE OR REPLACE FUNCTION aws_s3_java_function() RETURNS STRING LANGUAGE JAVA EXTERNAL_ACCESS_INTEGRATIONS = (aws_s3_external_access_integration) SECRETS = ('cred' = aws_s3_access_token) HANDLER = 'AWSTokenProvider.handle' AS $$ import com.snowflake.snowpark_java.types.CloudProviderToken; import com.snowflake.snowpark_java.types.SnowflakeSecrets; public class AWSTokenProvider { public static String handle() { // Get token object SnowflakeSecrets sfSecret = SnowflakeSecrets.newInstance(); CloudProviderToken cloudProviderToken = sfSecret.getCloudProviderToken("cred"); // Create variables for AWS session credentials String accessKeyId = cloudProviderToken.getAccessKeyId(); String secretAccessKey = cloudProviderToken.getSecretAccessKey(); String token = cloudProviderToken.getToken(); // Create S3 client using AWS APIs. return "Successfully connected with S3 with temp access token: " + token; } } $$;
Accordez le privilège USAGE à l’UDF afin que les personnes ayant le rôle
user
puissent l’appeler.GRANT USAGE ON FUNCTION return_double_column(int) TO ROLE user;
Exécutez la fonction pour vous connecter au point de terminaison externe.
SELECT aws_s3_python_function();
SELECT aws_s3_java_function();