Authentification auprès du serveur

Cette rubrique décrit comment s’authentifier auprès du serveur lors de l’utilisation de l’API SQL de Snowflake.

Lorsque vous envoyez une requête, celle-ci doit inclure des informations d’authentification. Les sections suivantes expliquent comment ajouter ces informations à la requête :

Dans ce chapitre :

Utilisation de OAuth

Pour utiliser OAuth, suivez les étapes suivantes :

  1. Configurez OAuth pour l’authentification.

    Voir Introduction à OAuth pour plus de détails sur la façon de configurer OAuth et d’obtenir un jeton OAuth.

  2. Utilisez SnowSQL pour vérifier que vous pouvez utiliser un jeton OAuth généré pour vous connecter à Snowflake :

    • Pour les systèmes Linux et MacOS

    $ snowsql -a <account_identifier> -u <user> --authenticator=oauth --token=<oauth_token>
    
    Copy
    • Pour les systèmes Windows

    $ snowsql -a <account_identifier> -u <user> --authenticator=oauth --token="<oauth_token>"
    
    Copy
  3. Dans chaque requête d’API que vous envoyez, définissez les en-têtes suivants :

    • Authorization: Bearer oauth_token

      oauth_token est le jeton OAuth généré.

    • X-Snowflake-Authorization-Token-Type: OAUTH

      Notez que vous pouvez également choisir d’omettre l’en-tête X-Snowflake-Authorization-Token-Type. Si cet en-tête n’est pas présent, Snowflake suppose que le jeton dans l’en-tête Authorization est un jeton OAuth.

Utilisation de l’authentification par paire de clés

Pour utiliser l’authentification par paire de clés, suivez ces étapes :

  1. Configurez l’authentification par paire de clés.

    Dans le cadre de ce processus, vous devez :

    1. Générer une paire de clés publique-privée. La clé privée générée doit se trouver dans un fichier (par exemple, nommé rsa_key.p8).

    2. Attribuez la clé publique à votre utilisateur Snowflake. Après avoir attribué la clé à l’utilisateur, exécutez la commande DESCRIBE USER. Dans la sortie, la propriété RSA_PUBLIC_KEY_FP doit être définie comme l’empreinte de la clé publique attribuée à l’utilisateur.

    Pour des instructions sur la façon de générer la paire de clés et d’attribuer une clé à un utilisateur, voir Authentification par paire de clés et rotation de paires de clés. Pour des exemples de création d’une empreinte et de la génération d’un jeton JWT spécifiques à un langage, voir ce qui suit :

  2. Utilisez SnowSQL pour vérifier que vous pouvez utiliser la clé privée générée pour vous connecter à Snowflake :

    $ snowsql -a <account_identifier> -u <user> --private-key-path <path>/rsa_key.p8
    
    Copy

    Si vous avez généré une clé privée cryptée, SnowSQL vous invite à saisir la phrase secrète que vous avez créée lors de la génération de la clé.

  3. Dans le code de votre application :

    1. Générez l’empreinte digitale (un hachage SHA-256) de la clé publique de l’utilisateur. Préfixez l’empreinte digitale avec SHA256:. Par exemple :

      SHA256:hash

      Vous pouvez également exécuter la commande SQL DESCRIBE USER pour obtenir la valeur de la propriété RSA_PUBLIC_KEY_FP.

    2. Générez un jeton Web JSON (JWT) avec les champs suivants dans la charge utile :

      Champ

      Description

      Exemple

      iss

      Émetteur du JWT. Réglez-le sur la valeur suivante :

      account_identifier.user.SHA256:public_key_fingerprint

      où :

      • account_identifier est votre identificateur de compte Snowflake.

        Si vous utilisez le localisateur de compte, excluez toute information sur la région du localisateur de compte.

      • user est votre nom d’utilisateur Snowflake.

      • SHA256:public_key_fingerprint est l’empreinte de la clé que vous avez générée à l’étape précédente.

      Note

      Les valeurs account_identifier et user doivent utiliser tous les caractères majuscules.

      MYORGANIZATION-MYACCOUNT.MYUSER.SHA256:public_key_fingerprint

      sub

      Objet pour le JWT. Réglez-le sur la valeur suivante :

      account_identifier.user

      MYORGANIZATION-MYACCOUNT.MYUSER

      iat

      Heure d’émission pour les JWT au format UTC. Définissez la valeur de l’heure actuelle en secondes ou en millisecondes.

      1615370644 (secondes) . 1615370644000 (millisecondes)

      exp

      Heure d’expiration pour les JWT au format UTC. Vous pouvez spécifier la valeur en secondes ou en millisecondes.

      Note

      Le JWT est valide au maximum une heure après l’émission du jeton, même si vous spécifiez un délai d’expiration plus long.

      1615374184 (secondes) . 1615374184000 (millisecondes)

    3. Dans chaque requête API que vous envoyez, définissez les en-têtes suivants :

      • Authorization: Bearer JWT

        JWT est le jeton que vous avez généré.

      • X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT

Exemple Python

Les sections suivantes décrivent comment générer un JWT et une empreinte à l’aide de Python.

Pour un exemple de génération d’un JWT en Python, voir sql-api-generate-jwt.py. L’exemple sql-api-generate-jwt.py utilise le module PyJWT, que vous pouvez installer en exécutant :

pip install pyjwt
Copy

Génération d’un jeton JWT en Python

Les sections de code suivantes démontrent comment générer un JWT. Pour un exemple complet, voir sql-api-generate-jwt.py.

Note

Cet exemple est destiné à servir de référence uniquement. N’utilisez pas ce code dans des applications ou des environnements de production.

from datetime import timedelta, timezone, datetime

# This example relies on the PyJWT module (https://pypi.org/project/PyJWT/).
import jwt

# Construct the fully qualified name of the user in uppercase.
# - Replace <account_identifier> with your account identifier.
#   (See https://docs.snowflake.com/en/user-guide/admin-account-identifier.html .)
# - Replace <user_name> with your Snowflake user name.
account = "<account_identifier>"

# Get the account identifier without the region, cloud provider, or subdomain.
if not '.global' in account:
    idx = account.find('.')
    if idx > 0:
        account = account[0:idx]
    else:
        # Handle the replication case.
        idx = account.find('-')
        if idx > 0:
            account = account[0:idx]

# Use uppercase for the account identifier and user name.
account = account.upper()
user = "<user_name>".upper()
qualified_username = account + "." + user

# Get the current time in order to specify the time when the JWT was issued and the expiration time of the JWT.
now = datetime.now(timezone.utc)

# Specify the length of time during which the JWT will be valid. You can specify at most 1 hour.
lifetime = timedelta(minutes=59)

# Create the payload for the token.
payload = {

    # Set the issuer to the fully qualified username concatenated with the public key fingerprint (calculated in the  previous step).
    "iss": qualified_username + '.' + public_key_fp,

    # Set the subject to the fully qualified username.
    "sub": qualified_username,

    # Set the issue time to now.
    "iat": now,

    # Set the expiration time, based on the lifetime specified for this object.
    "exp": now + lifetime
}

# Generate the JWT. private_key is the private key that you read from the private key file in the previous step when you generated the public key fingerprint.
encoding_algorithm="RS256"
token = jwt.encode(payload, key=private_key, algorithm=encoding_algorithm)

# If you are using a version of PyJWT prior to 2.0, jwt.encode returns a byte string, rather than a string.
# If the token is a byte string, convert it to a string.
if isinstance(token, bytes):
  token = token.decode('utf-8')
decoded_token = jwt.decode(token, key=private_key.public_key(), algorithms=[encoding_algorithm])
print("Generated a JWT with the following payload:\n{}".format(decoded_token))
Copy

Génération d’une empreinte en Python

Les sections de code suivantes montrent comment générer l’empreinte digitale. Pour un exemple complet, voir sql-api-generate-jwt.py.

from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives.serialization import Encoding
from cryptography.hazmat.primitives.serialization import PublicFormat
from cryptography.hazmat.backends import default_backend
..
import base64
from getpass import getpass
import hashlib
..
# If you generated an encrypted private key, implement this method to return
# the passphrase for decrypting your private key. As an example, this function
# prompts the user for the passphrase.
def get_private_key_passphrase():
    return getpass('Passphrase for private key: ')

# Private key that you will load from the private key file.
private_key = None

# Open the private key file.
# Replace <private_key_file_path> with the path to your private key file (e.g. /x/y/z/rsa_key.p8).
with open('<private_key_file_path>', 'rb') as pem_in:
    pemlines = pem_in.read()
    try:
        # Try to access the private key without a passphrase.
        private_key = load_pem_private_key(pemlines, None, default_backend())
    except TypeError:
        # If that fails, provide the passphrase returned from get_private_key_passphrase().
        private_key = load_pem_private_key(pemlines, get_private_key_passphrase().encode(), default_backend())

# Get the raw bytes of the public key.
public_key_raw = private_key.public_key().public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)

# Get the sha256 hash of the raw bytes.
sha256hash = hashlib.sha256()
sha256hash.update(public_key_raw)

# Base64-encode the value and prepend the prefix 'SHA256:'.
public_key_fp = 'SHA256:' + base64.b64encode(sha256hash.digest()).decode('utf-8')
Copy

Exemple Java

Pour un exemple de génération d’un jeton JWT en Java, voir SimpleStatementsApi.java.

Note

Cet exemple est destiné à servir de référence uniquement. N’utilisez pas ce code dans des applications ou des environnements de production.

Cet exemple utilise les bibliothèques tierces suivantes :

  • Swagger Codegen : une bibliothèque open source utile pour le développement d’APIs REST et d’applications.

  • Auth0 : fournit des APIs Java pour l’authentification et la génération de jetons JWT.

Exemple Node.js

Pour un exemple de génération d’un JWT en Node.js, voir sql-api-generate-jwt.js.

Note

Cet exemple est destiné à servir de référence uniquement. N’utilisez pas ce code dans des applications ou des environnements de production.