Gyosun
Snowflake Korea
Published in
11 min readJun 27, 2022

--

스노우플레이크(Snowflake)와 Keycloak 연계를 통한 클라이언트 인증 - OAuth

Snowflake는 데이터레이크, 데이터웨어하우스, 데이터 공유 등 다양한 워크로드를 처리할 수 있는 SaaS 기반의 데이터 클라우드 플랫폼 입니다.

Snowflake에 접속할 수 있는 클라이언트의 종류는 SNOWFLAKE UI를 통한 사용자 이외에도 BI 툴 및 Python, Go, Scala, Java와 같은 다양한 클라이언트들이 될 수 있는데, 일반적으로 Snowflake가 관리하는 사용자명과 패스워드를 사용할 수 있으며, 이외에도 클라이언트를 인증 및 역할 관리를 외부 툴과의 연계를 통해서 수행할 수 있습니다.

Oauth 기반의 클라이언트 인증

Snowflake는 OAuth 기반으로 외부 인증 툴을 통한 클라이언트 인증을 수행할 수 있으며, 이 때는 사용자명/패스워드가 아닌 외부 인증 툴이 발급한 토큰(Token)을 기반으로 인증을 수행합니다.

External Oauth Overview(https://docs.snowflake.com/en/user-guide/oauth-ext-overview.html#general-workflow)

위의 전체적인 Flow에서 Customer OAuth Authorization Server는 Keycloak을 의미하며, Client Application은 Python, Java와 같이 Snowflake에 접속을 수행하는 클라이언트 프로그램을 의미 합니다.

전체적인 Flow에 대해서 간단하게 설명하면,

  1. 클라이언트 프로그램은 먼저 Keycloak 에게 Token(Json Web Token)을 요청합니다. (2–3단계)

2. 응답 받은 Token을 기반으로 Snowflake에 접속하여 인증을 수행하며, 내부적인 절차에 의해 클라이언트와 Snowflake간의 인증이 완료 됩니다.(4–7번)

3. 4–7번 단계에서 Snowflake 는 클라이언트가 전달한 Token(Json Web Token)의 값을 바탕으로 정상적인 클라이언트인지 아닌지를 판단하게 되는데, 이를 위한 기본적인 정보(RSA Key, Audience 등)를 Snowflake에 등록하는 작업이 선행되어야 하며, 이는 1번 단계에서 1회만 수행되면 됩니다.

본 블로그 문서는 외부 인증 툴인 Keycloak(https://www.keycloak.org) 와 Snowflake와의 연동을 통한 Python 프로그램의 Snowflake 접속 인증을 Keycloak이 발급한 토큰을 통해서 수행하는 절차를 설명합니다.

보다 자세한 내용은 Snowflake 공식 문서의 내용을 참조하시면 됩니다.

Keycloak 설정

테스트를 위하여 Keycloak 서버를 Docker(16.1.1) 기반으로 설치 하였으며, 기본적인 Keycloak 설정은 본 문서에서는 생략 합니다.

Keycloak 은 Realm 은 객체 하위에 사용자 및 클라이언트에 대한 정보를 등록하고 관리를 수행하며, Snowflake 인증을 담당하는 Realm 을 생성 후 해당 Realm 하위에 클라이언트 및 사용자에 대한 정보를 관리하도록 구성합니다.

https://www.keycloak.org/docs/latest/server_admin/
<Snowflake Realm 생성 및 Client 리스트 화면>

Keycloak과 인증을 수행할 Client 등록 후, 해당 Client의 인증 방식, Token Expiration Time 등 기본적인 정보등을 입력합니다.

<클라이언트 상세 설정 정보>

Client Protocol, Access Type(Keycloak과 클라이언트 프로그램 간의 인증 방식)등을 정의합니다.

또한 Keycloak 에서 관리하는 사용자 추가 및 해당 사용자에 대한 패스워드 등을 설정 합니다.

Keycloak과 클라이언트 프로그램 테스트

Realm 등록, 클라이언트 등록, 사용자 등록이 완료되면, Keycloak 과 클라이언트 간에 Token(JWT)이 정상적으로 발급 되는지 테스트를 수행합니다.

테스트는 간단하게 curl 을 통하여 수행할 수 있습니다.

<Token 획득을 위한 curl Script 내용>

위의 여러 파라미터 내용 중 client_secret 내용은 아래와 같이 Keycloak UI 에서 확인이 가능합니다.

<Client Secret 확인>

위의 여러 설정들이 정상적으로 완료할 경우, 아래와 같이 access_token을 획득할 수 있습니다.

Keycloak 응답 메시지

클라이언트 프로그램에서 Snowflake 로 접속을 할 때는, 위의 Json 응답 메시지 중 access_token의 값을 인자로 사용해야 합니다. 그렇기 때문에 Snowflake의 설정과 access_token의 내용이 일치해야만 하며, 이를 위해 설정 초기에는 디버깅 목적으로 access_token의 내용을 직접 확인해야 하는 일들이 발생합니다.

access_token의 내용을 확인하기 위해서 아래의 jwt.io 사이트를 방문하여 access_token의 내용을 복사 후 디코딩을 수행하면, 실제 access_token의 내용이 어떤 식으로 구성되어 있는지 쉽게 확인이 가능합니다.

jwt.io 테스트 결과 화면

Snowflake 설정

클라이언트 프로그램은 Keycloak과 통신을 수행하여, Token 값을 획득한 후 해당 Token 값을 Snowflake에 전달하여 인증을 수행하게 됩니다.

위의 디코딩 된 Token(JWT)의 내용을 보면 Json 형태로 다양한 Key 값들을 가지고 있는 것을 확인할 수 있으며, 결국 Snowflake에서 인증을 수행하기 위해서는 미리 사전에 정의되어 있는 Key 값들이 Token 내에 존재해야 합니다.

Snowflake 인증 단계에서 필요로 하는 Token 내의 값은 아래의 링크에서 확인이 가능합니다.

Token 내에 반드시 포함되어야 하는 정보

일반적으로 Token 내에 위의 Json 필드들이 없을 경우, Keycloak 내에서 설정을 통해 추가를 할 수 있으며, 유사한 필드의 값이 있으나, 필드의 Key 이름이 다를 경우는 Snowflake 의 Mapping 기능을 통하여 필요로 하는 Key 값의 이름을 일부 변경할 수 있습니다.

Token이 정상적으로 발급되고, 해당 Token 내에 필요로 하는 모든 값들이 있을 경우, Snowflake 내에서 해당 값들을 디코딩 할 수 있는 기본적인 정보들을 설정하여야 합니다.

Snowflake는 이를 위하여 security integration 이라는 객체를 제공하며, 해당 객체를 통해서 Token 인증을 위한 여러가지 맵핑 정보를 설정합니다.

Snowflake Security Integration

위의 파라미터의 내용 중 RSA_PUBLIC_KEY의 값은 Keycloak의 Realm Settings -> Keys -> RS256의 값을 복사 후 사용하며, Public Key 방식의 인증이 아닌 경우(JWS_KEYS_URL) Keycloak의 jwks_uri 정보를 이용합니다.

jwks_uri 에 대한 정보는 Realm -> General -> Endpoints 중 OpenID Endpoint Configuration을 클릭 시 관련 정보들을 확인할 수 있습니다. 또한 issuer 에 대한 정보도 확인 가능합니다.

Endpoints 선택 시 관련 정보 확인 가능

위에 언급된 Snowflake Security Integration 객체를 생성하며, issuer, rsa_public_key, user_mapping, audience_list 등을 각 환경에 맞게 등록 후, 해당 설정이 정확한지 테스트를 수행합니다.

테스트는 Snowflake 가 제공하는 함수를 통해서 가능하며, 아래와 같은 SQL을 통해서 Token에 대한 Validation 이 가능합니다.

Token validation

클라이언트 접속 방법 설정

일반적으로 클라이언트 프로그램이 Snowflake 에 접속 시, Snowflake 내에서 관리하는 유저명과 패스워드로 접속을 수행합니다. 위와 같이 Keycloak 연계 및 OAuth 기반으로 사용자 인증을 수행할 경우는 아래와 같은 형태로 접속 방식의 변경이 필요합니다.

Snowflake Python Connector Example

Snowflake 에 접속 시, 사용자명 / 패스워드가 아닌 Keycloak 으로 부터 전달받은 Token을 전달 받아서 접속을 수행합니다. 위 예제는 Keycloak 으로 부터 Token을 전달 받는 부분이 빠져있습니다만, curl 테스트와 마찬가지로 REST API 방식을 통해서 Keycloak을 호출 후 응답 받은 데이터의 access_token 부분만 추출하여 전달하면 되기 때문에 매우 간단하게 코딩 추가가 가능합니다.

SNOWFLAKE 역할(ROLE)에 대한 맵핑

OAuth 기반으로 Snowflake 에 접속을 수행할 때, 해당 클라이언트가 사용할 수 있는 역할에 대한 정의를 수행할 수 있습니다.

이는 Token 내에 정의되어 있는 값 중 scope 영역을 활용하여 Keycloak 에서 제어가 가능합니다. 상세한 내용은 아래의 링크를 통해서 확인이 가능하며, scope 의 값을 session:role-any 일 경우는 클라이언트에서 정의하는 역할에 대해서 특별한 제약 없이 사용이 가능합니다.

상세한 역할에 대한 제어를 위한 scope 값 설정은 아래의 링크에서 확인이 가능합니다.

이상 Snowflake와 Keycloak(Custom) 연계를 통한 OAuth 기반의 클라이언트 인증 방식에 대해서 알아 보았습니다.

--

--