サーバーへの認証

このトピックでは、Snowflake SQL API を使用するときにサーバーに対して認証する方法について説明します。

リクエストを送信する場合、リクエストには認証情報が含まれている必要があります。次のセクションでは、この情報をリクエストに追加する方法について説明します。

このトピックの内容:

OAuth の使用

OAuth を使用するには、次のステップに従います。

  1. 認証のために OAuth を設定します。

    OAuth を設定して OAuth トークンを取得する方法の詳細については、 OAuth の紹介 をご参照ください。

  2. 生成された OAuth トークンを使用してSnowflakeに接続できることを確認するために、 SnowSQL を使用します。

    • Linuxおよび MacOS システムの場合

    $ snowsql -a <account_identifier> -u <user> --authenticator=oauth --token=<oauth_token>
    
    Copy
    • Windowsシステムの場合

    $ snowsql -a <account_identifier> -u <user> --authenticator=oauth --token="<oauth_token>"
    
    Copy
  3. 送信する各 API リクエストで、次のヘッダーを設定します。

    • Authorization: Bearer oauth_token

      ここで、 oauth_token は生成された OAuth トークンです。

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

      X-Snowflake-Authorization-Token-Type ヘッダーを省略することもできます。このヘッダーが存在しない場合、Snowflake は Authorization ヘッダーのトークンが OAuth トークンであると想定します。

キーペア認証の使用

キーペア認証を使用するには、次のステップに従います。

  1. キーペア認証を設定します。

    このプロセスの一環として、次を実行する必要があります。

    1. 公開キーと秘密キーのペアを生成します。生成された秘密キーはファイル内にある必要があります(例: rsa_key.p8 という名前)。

    2. 公開キーをSnowflakeユーザーに割り当てます。ユーザーにキーを割り当てたら、 DESCRIBE USER コマンドを実行します。出力では、 RSA_PUBLIC_KEY_FP プロパティは、ユーザーに割り当てられた公開キーのフィンガープリントに設定する必要があります。

    キーペアを生成してユーザーにキーを割り当てる方法については、 キーペア認証とキーペアローテーション をご参照ください。フィンガープリントを作成して JWT トークンを生成する言語固有の例については、以下をご参照ください。

  2. 生成された秘密キーを使用して Snowflake に接続 できることを確認するために、 SnowSQL を使用します。

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

    暗号化された秘密キーを生成した場合、 SnowSQL は、キーの生成時に作成したパスフレーズの入力を求めます。

  3. アプリケーションコード内で、

    1. ユーザーの公開キーのフィンガープリント(SHA-256ハッシュ)を生成します。フィンガープリントの前に SHA256: を付けます。例:

      SHA256:hash

      SQL DESCRIBE USER コマンドを実行して、 RSA_PUBLIC_KEY_FP プロパティから値を取得することもできます。

    2. ペイロードに次のフィールドを含む JSON Webトークン(JWT) を生成します。

      フィールド

      説明

      iss

      JWT の発行者。次の値に設定します。

      account_identifier.user.SHA256:public_key_fingerprint

      条件:

      • account_identifier は、Snowflakeの使用する アカウント識別子 です。

        アカウントロケーター を使用している場合は、アカウントロケーターからリージョン情報を除外します。

      • user は、Snowflakeユーザー名です。

      • SHA256:public_key_fingerprint は、前のステップで生成したフィンガープリントです。

      注釈

      account_identifieruser の値は、すべて大文字を使用する必要があります。

      MYORGANIZATION-MYACCOUNT.MYUSER.SHA256:public_key_fingerprint

      sub

      JWT の件名。次の値に設定します。

      account_identifier.user

      MYORGANIZATION-MYACCOUNT.MYUSER

      iat

      JWT の発行時刻(UTC)。値を秒またはミリ秒の現在の時間値に設定します。

      1615370644 (秒) . 1615370644000 (ミリ秒)

      exp

      JWT の有効期限(UTC)。値は、秒またはミリ秒で指定できます。

      注釈

      JWT は、より長い有効期限を指定した場合でも、トークンが発行されてから最大1時間まで有効です。

      1615374184 (秒) . 1615374184000 (ミリ秒)

    3. 送信する各 API リクエストで、次のヘッダーを設定します。

      • Authorization: Bearer JWT

        JWT は、生成したトークンです。

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

Pythonの例

次のセクションでは、Pythonを使用して JWT とフィンガープリントを生成する方法について説明します。

Python で JWT を生成する例については、 sql-api-generate-jwt.py をご参照ください。 sql-api-generate-jwt.py の例では、次のコマンドを実行してインストールできる PyJWT モジュール を使用しています。

pip install pyjwt
Copy

Pythonでの JWT の生成

コードの次のセクションは、 JWT を生成する方法を示しています。完全な例については、 sql-api-generate-jwt.py をご参照ください。

注釈

この例は、参照としてのみ使用することを目的としています。このコードは、実稼働アプリケーションまたは環境では使用しないでください。

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

Pythonでのフィンガープリントの生成

コードの次のセクションでは、フィンガープリントを生成する方法を示します。完全な例については、 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

Javaの例

Javaで JWT を生成する例については、 SimpleStatementsApi.java をご参照ください。

注釈

この例は、参照としてのみ使用することを目的としています。このコードは、実稼働アプリケーションまたは環境では使用しないでください。

この例では、次のサードパーティライブラリを使用しています。

  • Swagger Codegen: REST APIsとアプリケーションの開発に役立つオープンソースライブラリ。

  • Auth0: 認証と JWT トークンの生成にJava APIs を提供。

Node.jsの例

Node.jsで JWT を生成する例については、 sql-api-generate-jwt.js をご参照ください。

注釈

この例は、参照としてのみ使用することを目的としています。このコードは、実稼働アプリケーションまたは環境では使用しないでください。