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.

  1. 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');
    
    Copy
  2. 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;
    
    Copy
  3. 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

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

        La fonction génère une URL que vous pouvez utiliser pour compléter le processus de consentement OAuth.

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

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

      5. 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>' );
        
        Copy
    • Google OAuth Playground

      1. Dans Google OAuth Playground, sélectionnez et autorisez l’API Cloud Translation comme spécifié à l’étape 1.

      2. A l’étape 2, cliquez sur exchange authorization code for tokens, puis copiez la valeur du jeton refresh token.

      3. 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';
        
        Copy
  4. 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;
    
    Copy
  5. 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;
    
    Copy
  6. 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;
      
      Copy
  7. 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']
    $$;
    
    Copy
  8. Accordez le privilège USAGE à la fonction google_translate_python afin que les personnes ayant le rôle user puissent l’appeler.

    GRANT USAGE ON FUNCTION google_translate_python(string, string) TO ROLE user;
    
    Copy
  9. Exécutez la fonction google_translate_python pour traduire une phrase.

    USE ROLE user;
    
    SELECT google_translate_python('Happy Thursday!', 'zh-CN');
    
    Copy

    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.

  1. Créez une règle réseau lambda_network_rule représentant l’emplacement externe my_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');
    
    Copy
  2. 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';
    
    Copy
  3. 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;
    
    Copy
  4. 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;
    
    Copy
  5. 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;
    
    Copy
  6. 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]
    $$;
    
    Copy
  7. Accordez le privilège USAGE à la fonction return_double_column afin que les personnes ayant le rôle user puissent l’appeler.

    GRANT USAGE ON FUNCTION return_double_column(int) TO ROLE user;
    
    Copy
  8. 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 colonne a 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;
    
    Copy