사용자 지정 클라이언트용 Snowflake OAuth 구성하기¶
이 항목에서는 사용자 지정 클라이언트를 위한 OAuth 지원을 구성하는 방법을 설명합니다.
이 항목의 내용:
워크플로¶
사용자 지정 클라이언트를 위해 OAuth를 구성하려면 다음 개요 수준 단계가 필요합니다.
Snowflake에 클라이언트를 등록합니다. 클라이언트를 등록하려면 통합을 생성합니다. 통합은 OAuth를 지원하는 클라이언트와 같이 Snowflake와 서드 파티 서비스 간의 인터페이스를 제공하는 Snowflake 오브젝트입니다.
등록 프로세스는 클라이언트 ID 및 클라이언트 시크릿을 정의합니다.
Snowflake OAuth 엔드포인트에 대한 호출을 구성하여 Snowflake 인증 서버에서 인증 코드를 요청하고 액세스 토큰을 요청 및 새로 고칩니다.
초기 인증 요청의 선택적 “범위” 매개 변수는 액세스 토큰에서 허용되는 역할을 제한하고 새로 고침 토큰의 동작을 구성하기 위한 용도로 추가로 사용할 수 있습니다.
참고
Snowflake OAuth에서는 세션 내 역할을 보조 역할로 전환하는 기능이 지원되지 않습니다.
이 동작이 OAuth 워크플로에 필요한 경우 외부 OAuth를 대신 사용하십시오.
자세한 내용은 External OAuth가 포함된 보조 역할 사용하기 섹션을 참조하십시오.
Snowflake OAuth 통합 만들기¶
CREATE SECURITY INTEGRATION 명령을 사용하여 Snowflake OAuth 통합을 생성합니다. 통합을 생성할 때 OAUTH_CLIENT = CUSTOM
을 지정해야 합니다.
참고
계정 관리자(ACCOUNTADMIN 역할의 사용자) 또는 전역 CREATE INTEGRATION 권한이 있는 역할만 이 SQL 명령을 실행할 수 있습니다.
통합 사용에서 특정 역할 차단하기¶
선택적 BLOCKED_ROLES_LIST 매개 변수를 사용하면 통합과 함께 사용하여 사용자가 명시적으로 동의할 수 없는 Snowflake 역할을 나열할 수 있습니다.
기본적으로 ACCOUNTADMIN, SECURITYADMIN 및 ORGADMIN 역할은 이 목록에 포함되며 제거할 수 없습니다. 사용자에게 이러한 역할로 Snowflake OAuth를 사용해야 하는 작업이 있고 보안 팀이 이를 허용하는 경우, Snowflake 지원 에 문의하여 계정에서 이러한 역할을 허용하도록 요청하십시오.
Snowflake OAuth 사용자 지정 클라이언트에서 클라이언트 리디렉션 사용하기¶
Snowflake는 지원되는 Snowflake 클라이언트에서 클라이언트 리디렉션과 OAuth 사용을 포함하여, Snowflake OAuth 사용자 지정 클라이언트에서의 클라이언트 리디렉션 사용을 지원합니다.
자세한 내용은 클라이언트 연결 리디렉션하기 섹션을 참조하십시오.
네트워크 정책 관리하기¶
Snowflake는 OAuth를 위한 네트워크 정책을 지원합니다. 자세한 내용은 네트워크 정책 섹션을 참조하십시오.
통합 예¶
다음은 키 페어 인증을 사용하는 OAuth 통합을 만드는 예입니다. 통합에서는 1일(86,400초) 후에 만료되는 새로 고침 토큰을 허용합니다. 통합은 사용자가 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 오류 코드 를 참조하십시오.
PKCE(Proof Key for Code Exchange)¶
Snowflake는 RFC 7636 의 설명과 같이 authorization_code
권한 타입을 사용하여 액세스 토큰을 획득하기 위한 PKCE(Proof Key for Code Exchange)를 지원합니다. PKCE를 사용하면 인증 코드 가로채기 공격의 가능성을 줄일 수 있으며, 클라이언트 시크릿의 보안을 완벽하게 보호할 수 없는 클라이언트에 적합합니다.
기본적으로, PKCE는 선택 사항이며 code_challenge
및 code_challenge_method
매개 변수가 둘 다 인증 엔드포인트 URL에 포함된 경우에만 적용됩니다. 하지만 Snowflake는 클라이언트의 모든 인증에서 PKCE를 요청하여 OAuth 흐름의 보안을 강화하는 것을 강력히 권장합니다.
다음을 Snowflake용 PKCE의 작동 방법을 설명합니다.
클라이언트가 코드 검증 도구 라는 시크릿을 생성하고 변환을 수행하여 코드 챌린지 를 생성합니다. 클라이언트는 해당 시크릿을 유지합니다.
중요
RFC 7636의 섹션 4.1 에 따라 허용되는 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개의 공개 키를 단일 사용자와 연결할 수 있습니다.
키를 순환하려면:
이 항목에서 키 페어 인증 사용하기 의 단계를 완료합니다.
새 개인 및 공개 키 세트를 생성합니다.
공개 키를 통합에 할당합니다. 공개 키 값을
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 흐름 완료 후 Snowflake 세션 생성 시 OAuth와 관련된 오류 코드 목록 및 JSON blob에 반환된 오류에 대해서는 오류 코드 를 참조하십시오.