カスタムクライアント用の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ロールをリストできます。
By default, the ACCOUNTADMIN, SECURITYADMIN, GLOBALORGADMIN, and ORGADMIN roles are included in this list and cannot be removed. If you have a business need to allow users to use Snowflake OAuth with these roles, and your security team allows it, please contact Snowflake Support to request that these roles be allowed for your account.
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 エラー コード をご参照ください。
トークン交換¶
このエンドポイントは、 JSON Webトークン(JWT)と引き換えに、 OAuth アクセストークンを返します。例については、 チュートリアル1(ステップ5) をご覧ください。チュートリアルでは、このエンドポイントにリクエストを送信して JWT トークンと OAuth トークンを交換し、 OAuth トークンを使用してSnowpark Container Servicesサービスが公開するパブリックエンドポイントにアクセスします。
トークンエンドポイントは次のとおりです。
<snowflake_account_url>/oauth/token
条件:
snowflake_account_url有効な Snowflakeアカウント URL を指定します。例:
https://myorg-account_xyz.snowflakecomputing.com/oauth/token。
HTTP メソッド¶
POST
POST リクエストのコンテンツ型のヘッダーが次のように設定されていることを確認します。
Content-type: application/x-www-form-urlencoded
リクエスト本文¶
パラメーター |
データ型 |
必須 |
説明 |
|---|---|---|---|
|
文字列 |
有り |
これを |
|
文字列 |
有り |
これを |
|
文字列 |
有り |
JWT トークンを渡します。 |
例:
{
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'scope': 'session:role:TEST_ROLE ab12-orgname-acctname.snowflakecomputing.app',
'assertion': '<token>'
}
scope を指定する場合、 session:role:role_name はオプションです。指定されない場合、ユーザのデフォルトのロールが使用されます。
{
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'scope': 'ab12-orgname-acctname.snowflakecomputing.app',
'assertion': '<token>'
}
応答¶
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認証サーバーに渡します。
セキュリティパラメーターを更新します。
<private_key>: 復号化されたrsa_key.p8の内容( BEGIN と ENDを含む)。openssl rsa -in rsa_key.p8 -textを実行すると取得できます。
セッションパラメーターを更新します。
<account_locator>: アカウントロケータコード、例えばCIB07125。アカウント名は使用できません(例:myorg-account_xyz)。
次のトークンリクエストエンドポイントを更新します
_make_request()関数:<account_name>: これはアカウント識別子のアカウント名の形式です(例えばmyorg-account_xyz)。
公開キーのフィンガープリントを更新します:
<public_key_fp>: DESC SECURITY INTEGRATION コマンドを実行して取得。公開キーは2つあるので、正しいキーを参照していることを確認してください。
リダイレクト URIを更新します:
<redirect_uri>: 統合を構成しているリダイレクト URI。DESC SECURITY INTEGRATION コマンドを実行すると取得できます。
OAuth 認証コードを取得します:
<oauth_az_code>:/authorizeエンドポイントで認証した後に取得。注意:このコードは定期的に更新する必要があります。
JSON ウェブトークン(JWT)フィールドを更新します。
- post body
次の標準フィールド(「クレーム」)を持つ JSON オブジェクト:
属性
データ型
必須
説明
iss文字列
有り
client_id.public_key_fpの形式で JWT をパブリッシュしたプリンシパルを指定します。client_idは OAuth クライアント統合のクライアント ID で、public_key_fpは確認中に使用される公開キーのフィンガープリントです。sub文字列
有り
account_locator.client_id形式の JWT のサブジェクトaccount_locatorは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 = "<public_key_fp>" # SHA256:MR... def _make_request(payload, encoded_jwt_token): token_url = "https://<account_name>.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, 'redirect_uri': <redirect_uri> } 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_locator = "<account_locator>" client_id = "1234" # found by running DESC SECURITY INTEGRATION issuer = "{}.{}".format(client_id, public_key_fp) subject = "{}.{}".format(account_locator, 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で返されるエラーについては、 エラーコード をご参照ください。