カスタムクライアント用のSnowflake OAuth の構成¶
このトピックでは、カスタムクライアントの OAuth サポートを構成する方法について説明します。
このトピックの内容:
ワークフロー¶
カスタムクライアントの OAuth を構成するには、次の高レベルの手順が必要です。
クライアントをSnowflakeに登録します。クライアントを登録するには、統合を作成します。統合は、Snowflakeと OAuth をサポートするクライアントなどのサードパーティサービスの間のインターフェイスを提供するSnowflakeオブジェクトです。
登録プロセスは、クライアント ID とクライアントシークレットを定義します。
Snowflake OAuth エンドポイントへの呼び出しを構成して、Snowflake認証サーバーから認証コードをリクエストし、アクセストークンをリクエストおよび更新します。
初期認証リクエストのオプションの「範囲」パラメーターは、アクセストークンによって許可されるロールを制限し、さらに更新トークンの動作を構成するために使用できます。
注釈
セカンダリロールへのセッション中のロール切り替えは、Snowflake OAuth ではサポートされていません。
OAuth ワークフローでこの動作が必要な場合は、代わりに外部 OAuth を使用してください。
詳細については、 外部 OAuth でのセカンダリロールの使用 をご参照ください。
Snowflake OAuth 統合を作成する¶
CREATE SECURITY INTEGRATION コマンドを使用して、Snowflake OAuth 統合を作成します。統合を作成するときは、必ず OAUTH_CLIENT = CUSTOM
を指定してください。
注釈
この SQL コマンドを実行できるのは、アカウント管理者(ACCOUNTADMIN ロールを持つユーザー)または CREATE INTEGRATION グローバル権限を持つロールのみです。
統合の使用から特定のロールをブロックする¶
オプションの BLOCKED_ROLES_LIST パラメーターを使用すると、統合での使用をユーザーが明示的に同意 できない Snowflakeロールをリストできます。
デフォルトでは、 ACCOUNTADMIN、 SECURITYADMIN、 ORGADMIN のロールはこのリストに含まれており、削除できません。ユーザーがこれらのロールでSnowflake OAuth を使用できるようにするビジネス上のニーズがあり、セキュリティチームがそれを許可している場合は、 Snowflakeサポート に連絡し、アカウントに対してこれらのロールを許可するようにリクエストしてください。
Snowflake OAuth カスタムクライアントでのクライアントリダイレクトの使用¶
Snowflakeは、Snowflake OAuth カスタムクライアントでのクライアントリダイレクトの使用をサポートします。これには、サポートされているSnowflakeクライアントでのクライアントリダイレクトおよび OAuth の使用が含まれます。
詳細については、 クライアント接続のリダイレクト をご参照ください。
ネットワークポリシーの管理¶
Snowflakeは OAuthのネットワークポリシーをサポートしています。詳細については、 ネットワークポリシー をご参照ください。
統合の例¶
次の例では、キーペア認証を使用する OAuth 統合を作成します。統合では、1日(86400秒)後に期限切れになる更新トークンが許可されます。統合により、ユーザーは SYSADMIN をアクティブロールとしてセッションを開始できなくなります。
CREATE SECURITY INTEGRATION oauth_kp_int
TYPE = OAUTH
ENABLED = TRUE
OAUTH_CLIENT = CUSTOM
OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'
OAUTH_REDIRECT_URI = 'https://localhost.com'
OAUTH_ISSUE_REFRESH_TOKENS = TRUE
OAUTH_REFRESH_TOKEN_VALIDITY = 86400
BLOCKED_ROLES_LIST = ('SYSADMIN')
OAUTH_CLIENT_RSA_PUBLIC_KEY ='
MIIBI
...
';
OAuth エンドポイントを呼び出す¶
OAuth エンドポイントは、クライアントが認証コードをリクエストし、アクセストークンをリクエストおよび更新するために呼び出す URLs です。これらのエンドポイントは、エンドポイントが呼び出されたときに実行される特定の OAuth 2.0ポリシーを参照します。
Snowflakeは、次の OAuth エンドポイントを提供します。
- 認証:
<SnowflakeアカウントURL>/oauth/authorize
- トークンリクエスト:
<SnowflakeアカウントURL>/oauth/token-request
<snowflake_account_url>
が有効なSnowflakeアカウントである場合 URL。たとえば、エンドポイント https://myorg-account_xyz.snowflakecomputing.com/oauth/authorize
と https://myorg-account_xyz.snowflakecomputing.com/oauth/token-request
を使用できます。Snowflakeアカウント URL でサポートされている形式のリストについては、 URL での接続 を参照してください。
セキュリティ統合の有効な OAuth エンドポイントのリストを確認するには、 DESCRIBE INTEGRATION を実行してから、 OAUTH_ALLOWED_AUTHORIZATION_ENDPOINTS
および OAUTH_ALLOWED_TOKEN_ENDPOINTS
プロパティの値を表示します。
トークンエンドポイント¶
このエンドポイントは、リクエストパラメーターに応じてアクセストークンまたはリフレッシュトークンを返します。トークンエンドポイントは次のとおりです。
<snowflake_account_url>/oauth/token-request
条件:
snowflake_account_url
有効な Snowflakeアカウント URL を指定します。たとえば、
https://myorg-account_xyz.snowflakecomputing.com/oauth/token-request
です。
HTTP メソッド¶
POST
POST リクエストのコンテンツ型のヘッダーが次のように設定されていることを確認します。
Content-type: application/x-www-form-urlencoded
リクエストヘッダー¶
クライアント ID とクライアントシークレットを認証ヘッダーに含める必要があります。現在、Snowflakeは 基本認証スキーム のみをサポートしています。つまり、期待される値は次の形式です。
Basic Base64(client_id:client_secret)
条件:
ヘッダー値 |
データ型 |
必須 |
説明 |
---|---|---|---|
|
文字列 |
はい |
統合のクライアント ID 。 |
|
文字列 |
はい |
統合のクライアントシークレット。 |
クライアント ID とクライアントシークレットの両方は、 SYSTEM$SHOW_OAUTH_CLIENT_SECRETS 関数を使用して取得できます。
client_id
と client_secret
の間の :
文字に注意してください。
リクエスト本文¶
パラメーター |
データ型 |
必須 |
説明 |
---|---|---|---|
|
文字列 |
はい |
要求された付与のタイプ: . |
|
文字列 |
はい |
トークンエンドポイントから返された認証コード。 |
|
文字列 |
はい |
認証コードを引き換えるときに、以前のリクエストからトークンエンドポイントに返された更新トークン。 |
|
文字列 |
はい |
認証コードをリクエストするときに認証 URL で使用されるリダイレクト URI。 |
|
文字列 |
いいえ |
認証リクエストが |
応答¶
次のフィールドを持つ JSON オブジェクトが返されます。
フィールド |
データ型 |
説明 |
---|---|---|
|
文字列 |
Snowflakeセッションの確立に使用されるアクセストークン |
|
文字列 |
更新トークン。クライアントが更新トークンをパブリッシュしないように構成されている場合、またはユーザーが |
|
整数 |
トークンの有効期限が切れるまでの残りの秒数 |
|
文字列 |
アクセストークンタイプ。現在、常に |
|
文字列 |
アクセストークンが属するユーザー名。現在、アクセストークンの認証コードを交換する場合にのみ返されます。 |
成功した応答の例¶
次の例は、アクセストークンと更新トークンの認証コードを交換するときの正常な応答を示しています。
{
"access_token": "ACCESS_TOKEN",
"expires_in": 600,
"refresh_token": "REFRESH_TOKEN",
"token_type": "Bearer",
"username": "user1",
}
失敗した応答の例¶
次の例は、失敗した応答を示しています。
{
"data" : null,
"message" : "This is an invalid client.",
"code" : null,
"success" : false,
"error" : "invalid_client"
}
message
文字列値はエラーの説明であり、 error
はエラータイプです。返されるエラーの種類の詳細については、 OAuth エラー コード をご参照ください。
コード交換の証明キー¶
Snowflakeは、 RFC 7636 で説明されているように、 authorization_code
付与タイプを使用してアクセストークンを取得するためのコード交換用の証明キー(PKCE)をサポートしています。PKCE は、認証コード傍受による攻撃の可能性を減らすために使用でき、クライアントシークレットを十分安全に保持できない可能性があるクライアントに適しています。
デフォルトでは、 PKCE はオプションであり、 code_challenge
および code_challenge_method
パラメーターが両方とも認証エンドポイント URLに含まれている場合にのみ強制されます。ただし、Snowflakeは、 OAuth フローをより安全にするために、クライアントに対してすべての認証に PKCE を要求することを 強く お勧めします。
以下は、Snowflakeの PKCE の仕組みを説明しています。
クライアントは コード確認 と呼ばれるシークレットを作成し、それを変換して コードチャレンジ を生成します。クライアントはシークレットを保持します。
重要
セクション4.1 RFC 7636 に従って、許可された ASCII 文字から コード識別子 を生成します。
ユーザーを認証 URL に誘導するクライアントは、次の2つのクエリパラメーターを追加します。
code_challenge
ステップ1で生成されたコードチャレンジを指定します。
code_challenge_method
コードチャレンジを生成するために、ステップ1のコード確認で使用される変換を指定します。現在、Snowflakeは SHA256 のみをサポートしているため、この値は
S256
に設定する必要があります。SHA256 の変換アルゴリズムはBASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
です。
ユーザーがリクエストされた範囲に同意するか、Snowflakeがそのユーザーに同意があると判断した後、認証コードがパブリッシュされます。
クライアントは、Snowflake認証サーバーから認証コードを受け取り、トークンエンドポイントへのリクエストの
code_verifier
とともに送信します。Snowflakeは
code_verifier
値を変換し、変換された値が認証の生成時に使用されるcode_challenge
値と一致することを確認します。これらの値が一致する場合、許可サーバーはアクセストークンと更新トークンをパブリッシュします。
キーペア認証の使用¶
Snowflakeは、 OAuth トークンエンドポイントの呼び出しに、一般的なユーザー名/パスワード認証ではなく、キーペア認証の使用をサポートしています。この認証方法には、2048ビット(最小)の RSA キーペアが必要です。OpenSSL を使用して PEM (Privacy Enhanced Mail)公開/秘密キーペアを生成します。公開キーは、Snowflakeクライアントを使用するSnowflakeユーザーに割り当てられます。
公開/秘密キーペアを構成するには、
ターミナルウィンドウのコマンドラインから、暗号化された秘密キーを生成します。
$ openssl genrsa 2048 | openssl pkcs8 -topk8 -v2 des3 -inform PEM -out rsa_key.p8
OpenSSL は、秘密キーファイルの暗号化に使用されるパスフレーズの入力を求めます。Snowflakeは、強力なパスフレーズを使用して秘密キーを保護することをお勧めします。このパスフレーズを記録します。Snowflakeに接続するときにこれを入力します。パスフレーズは秘密キーの保護にのみ使用され、Snowflakeに送信されることは決してありません。
サンプル PEM 秘密キー
-----BEGIN ENCRYPTED PRIVATE KEY----- MIIE6TAbBgkqhkiG9w0BBQMwDgQILYPyCppzOwECAggABIIEyLiGSpeeGSe3xHP1 wHLjfCYycUPennlX2bd8yX8xOxGSGfvB+99+PmSlex0FmY9ov1J8H1H9Y3lMWXbL ... -----END ENCRYPTED PRIVATE KEY-----
コマンドラインから、秘密キーを参照して公開キーを生成します。
$ openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
サンプル PEM 公開キー
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy+Fw2qv4Roud3l6tjPH4 zxybHjmZ5rhtCz9jppCV8UTWvEXxa88IGRIHbJ/PwKW/mR8LXdfI7l/9vCMXX4mk ... -----END PUBLIC KEY-----
公開キーファイルと秘密キーファイルを保存用のローカルディレクトリにコピーします。ファイルへのパスを記録します。
秘密キーは PKCS#8(公開キー暗号化標準)形式を使用して格納され、前の手順で指定したパスフレーズを使用して暗号化されることに注意してください。ただし、オペレーティングシステムが提供するファイル許可メカニズムを使用して、ファイルを不正アクセスから保護する必要があります。ファイルが使用されていない場合、ファイルを保護するのはユーザーの責任です。
ALTER SECURITY INTEGRATION を使用して、公開キーを統合オブジェクトに割り当てます。例:
ALTER SECURITY INTEGRATION myint SET OAUTH_CLIENT_RSA_PUBLIC_KEY='MIIBIjANBgkqh...';
注釈
アカウント管理者のみが ALTER SECURITY INTEGRATION コマンドを実行できます。
コマンド内で公開キーのヘッダーとフッターを除外します。
DESCRIBE INTEGRATION を使用して、公開キーのフィンガープリントを確認します。
DESC SECURITY INTEGRATION myint; +----------------------------------+---------------+----------------------------------------------------------------------+------------------+ | property | property_type | property_value | property_default | |----------------------------------+---------------+----------------------------------------------------------------------+------------------| ... | OAUTH_CLIENT_RSA_PUBLIC_KEY_FP | String | SHA256:MRItnbO/123abc/abcdefghijklmn12345678901234= | | | OAUTH_CLIENT_RSA_PUBLIC_KEY_2_FP | String | | | ... +----------------------------------+---------------+----------------------------------------------------------------------+------------------+
注釈
OAUTH_CLIENT_RSA_PUBLIC_KEY_2_FP
プロパティについては、このトピックの キーローテーション で説明しています。以下のサンプルコードを変更して実行します。このコードは、秘密キーを使用して JWT をエンコードし、そのトークンをSnowflake認証サーバーに渡します。
セキュリティパラメーターを更新します。
<秘密キー>
: テキストエディターでrsa_key.p8
ファイルを開き、BEGIN
ヘッダーとEND
フッターの間の行をコピーします。
セッションパラメーターを更新します。
<account_identifier>
:アカウントのフルネームを指定します(Snowflakeが提供)。
JSON ウェブトークン(JWT)フィールドを更新します。
- post body
次の標準フィールド(「クレーム」)を持つ JSON オブジェクト:
属性
データ型
必須
説明
iss
文字列
はい
client_id.public_key_fp
の形式で JWT をパブリッシュしたプリンシパルを指定します。client_id
は OAuth クライアント統合のクライアント ID で、public_key_fp
は確認中に使用される公開キーのフィンガープリントです。sub
文字列
はい
account_identifier.client_id
の形式の JWT のサブジェクト。account_identifier
はSnowflakeアカウントの完全な名前で、client_id
は OAuth クライアント統合のクライアント ID です。アカウントがホストされているクラウドプラットフォーム(AWS またはAzure)と地域によっては、完全なアカウント名 に 追加 セグメントが必要な場合があります。詳細については、 トークンエンドポイント のaccount
変数の説明をご参照ください。iat
タイムスタンプ
いいえ
トークンがパブリッシュされた時刻。
exp
タイムスタンプ
はい
トークンの有効期限。この期間は比較的短くする必要があります(例:数分)。
サンプルコード
private_key
値には、-----BEGIN
ヘッダーと-----END
フッターが含まれていることに注意してください。import datetime import json import urllib import jwt import requests private_key = """ <private_key> """ public_key_fp = "SHA256:MR..." def _make_request(payload, encoded_jwt_token): token_url = "https://<account_identifier>.snowflakecomputing.com/oauth/token-request" headers = { u'Authorization': "Bearer %s" % (encoded_jwt_token), u'content-type': u'application/x-www-form-urlencoded' } r = requests.post( token_url, headers=headers, data=urllib.urlencode(payload)) return r.json() def make_request_for_access_token(oauth_az_code, encoded_jwt_token): """ Given an Authorization Code, make a request for an Access Token and a Refresh Token.""" payload = { 'grant_type': 'authorization_code', 'code': oauth_az_code } return _make_request(payload, encoded_jwt_token) def make_request_for_refresh_token(refresh_token, encoded_jwt_token): """ Given a Refresh Token, make a request for another Access Token.""" payload = { 'grant_type': 'refresh_token', 'refresh_token': refresh_token } return _make_request(payload, encoded_jwt_token) def main(): account_identifier = "<account_identifier>" client_id = "1234" # found by running DESC SECURITY INTEGRATION issuer = "{}.{}".format(client_id, public_key_fp) subject = "{}.{}".format(account_identifier, client_id) payload = { 'iss': issuer, 'sub': subject, 'iat': datetime.datetime.utcnow(), 'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=30) } encoded_jwt_token = jwt.encode( payload, private_key, algorithm='RS256') data = make_request_for_access_token(oauth_az_code, encoded_jwt_token) refresh_token = data['refresh_token'] data = make_request_for_refresh_token(refresh_token, encoded_jwt_token) access_token = data['access_token'] if __name__ == '__main__': main()
トークンが作成されたら、トークンエンドポイントにリクエストで送信します。リクエストでは、次のように、通常クライアント ID およびクライアントシークレットに使用される基本認証形式の代わりに、認証ヘッダーとしてベアラー認証形式が必要です。
"Authorization: Bearer JWT_TOKEN"
キーローテーション¶
Snowflakeは、複数のアクティブキーをサポートして、連続したローテーションを可能にします。内部的に従う有効期限のスケジュールに基づいて、公開キーと秘密キーをローテーションして交換します。
現在、 ALTER SECURITY INTEGRATION の OAUTH_CLIENT_RSA_PUBLIC_KEY
および OAUTH_CLIENT_RSA_PUBLIC_KEY_2
パラメーターを使用して、最大2個の公開キーを1人のユーザーに関連付けることができます。
キーをローテーションするには:
キーペア認証の使用 の次の手順を完了します(このトピック内)。
新しい秘密キーと公開キーのセットを生成します。
統合に公開キーを割り当てます。公開キーの値を
OAUTH_CLIENT_RSA_PUBLIC_KEY
またはOAUTH_CLIENT_RSA_PUBLIC_KEY_2
(現在使用されていないキーの値)に設定します。例:alter integration myint set oauth_client_rsa_public_key_2='JERUEHtcve...';
Snowflakeに接続するようにコードを更新します。新しい秘密キーを指定します。
Snowflakeは、送信された秘密キーに基づいて、認証のための正しいアクティブな公開キーを確認します。
統合から古い公開キーを削除します。例:
alter integration myint unset oauth_client_rsa_public_key;
エラーコード¶
OAuth に関連付けられたエラーコードのリスト、および認証フロー、トークンのリクエストまたは交換中、または OAuth フロー完了後のSnowflakeセッション作成時に JSON BLOBで返されるエラーについては、 エラーコード をご参照ください。