본문 바로가기
클라우드/Kubernetes

Grafana OAuth 방식으로 Keycloak Login 연동하기 #JWT 토큰 발행

by 정권이 내 2022. 5. 18.

Grafana OAuth 방식으로 Keycloak 연동하기 (JWT 토큰)

 

Grafana에서는 로그인할때 OAuth 방식을 사용할수있도록 기능을 제공하고 있습니다. OAuth에 대한 자세한 내용은 아래 링크를 참고하면 됩니다.

 

OAuth - 위키백과, 우리 모두의 백과사전

OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근

ko.wikipedia.org

 

Keycloak은 인증, 권한에 대한 서비스와 SSO기능을 제공하는 오픈소스 입니다. Grafana의 로그인방식은 자체적으로 제공하는 계정 로그인 방식이 기본이지만 외부 인증툴을 사용하는 방법도 있습니다. 이 포스팅에서는 Grafana, Keycloak을 연동하여 Grafana 로그인시 Keycloak 인증을 거치도록 하는 방법을 설명해보겠습니다.

쿠버네티스 환경을 기반으로한 설명입니다.

 

Grafana 설치 (Prometheus Stack)

Grafana 설치는 아래에 나와있는 글을 참고하면 됩니다.

 

[Kubernetes] PLG(Prometheus, Loki, Grafana) Stack 설치, 운영하기

쿠버네티스에 PLG 스택 운영하기 쿠버네티스상에 PLG 스택을 호환성있게 운영하기위해서 처음에는 Promethes, Loki, Grafana를 모두 각각 Deployment 를 만들어서 설정을 맞춰 보았는데 생각만큼 잘 맞물려

ksr930.tistory.com

 

Keycloak 설치및 실행

QuickStart 방식으로 Keycloak 공식 사이트에서 제공하는 설치방법을 설명드리겠습니다.

 

keycloak yaml 다운로드

공식 사이트에서 제공하는 yaml를 바로 사용해도 되지만 쿠버네티스 환경에서 실행할경우 테스트를 위해 NodePort로 설정하는것이 편리하기 때문에 먼저 다운로드받고 내용을 수정해서 실행합니다.

wget https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/latest/kubernetes-examples/keycloak.yaml

 

내용 수정

spec:
ports:
- name: http
port: 8080
targetPort: 8080

위 부분을 아래와 같이 수정합니다.

 

spec:
ports:
- name: service
nodePort: 31985 # 임의의 중복되지않는 포트로 설정
port: 8080
protocol: TCP
targetPort: 8080

 

Keycloak 실행

kubectl create -f keycloak.yaml -n keycloak

 

Keycloak 실행 확인

아래와 같이 pod, service가 정상적인 실행이 확인됬으면 브라우저에서 UI에 접속해보겠습니다.

kubectl get all -n keycloak
NAME                            READY   STATUS    RESTARTS   AGE
pod/keycloak-5667b84f54-2d2xh   1/1     Running   0          22h

NAME               TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/keycloak   NodePort   10.43.252.212   <none>        8080:31985/TCP   22h

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/keycloak   1/1     1            1           22h

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/keycloak-5667b84f54   1         1         1       22h

 

Keycloak UI 접속

img

 

UI 화면의 왼쪽 Administration Console로 이동하여 로그인을 합니다. 로그인 정보는 keycloak.yaml 에 admin/admin이 기본값으로 설정되있습니다.

 

realm, client 생성

1. realm 생성

realm 이란 Keycloak에서 인증, 권한의 부여가 적용되는 범위를 나타내는 단위입니다. realm에서 여러개의 client를 설정할수 있고 realm 내부에 설정된 client들은 SSO를 사용할수 있게 됩니다.

 

  • Master realm : Keycloak 설치시 생성되는 관리자용 realm입니다. Master realm에는 client를 설정하지 않고 하위에 realm들을 생성하고 관리하는 용도로 사용합니다.
  • Other realm : Master realm에서 생성한 realm입니다. 각 realm에는 client를 설정할수 있는데 SSO를 사용할 애플리케이션이라고 볼수 있습니다.

Realms and applications

 

화면왼쪽탭 Master realm에 커서를 위치하면 Add realm이 보이는데 클릭해서 Grafana라는 이름으로 realm을 생성합니다.

img

 

img

 

2. Client 생성

왼쪽탭 Client에서 Create 버튼을 눌러 새로운 client를 생성합니다. 이 client는 Grafana에서 인증하기 위한 용도입니다.

  • Client ID : grafana.com
  • Client Protocol : openid-connect
  • Root URL : Grafana UI의 주소

img

 

img

 

Client 설정

1. Setting

Client를 생성하면 바로 설정화면으로 넘어가는데 Setting 탭의 옵션을 다음과 같이 수정하고 저장합니다.

  • Access Type : confidentials
  • Root URL : ${authBaseUrl}
  • Valid Redirect URIs : <Grafana URL>/login/generic_oauth
  • Base URL : /login/generic_oauth
  • Admin URL, Web Origins 삭제

img

 

2. Credentials

저장하고 나면 상단에 Credentials 탭이 새로 생깁니다. 해당 탭에서 Secret이 생성되는데 나중에 Grafana 설정에서 사용해야 하는 값이므로 따로 복사를 해놓습니다.

img

 

3. Roles

Roles 탭에서 Add Role을 클릭하여 다음과 같이 생성합니다. 여기서 Role Name은 Grafana에서 사용할 권한 레벨 입니다. Grafana에는 admin, editor, viewer 레벨이 있는데 admin 으로 생성합니다.

img

 

admin role을 생성후 role에대한 설정을 할수있는데 Composite Roles 옵션을 ON 으로 설정하고 아래와 같이 설정합니다.

Client Roles에 Client ID 를 선택후 Available Roles에 있는 admin을 Associated Roles에 할당합니다.

img

 

4. Scope

Scope 탭의 Full Scope Allowed 옵션을 OFF로 설정합니다.

img

 

5. Mapper

Mapper 탭에서 Create로 새 mapper를 생성후 아래와 같이 설정후 저장합니다.

  • Name: Roles
  • Mapper Type: User Client Role
  • Client ID: grafana.com
  • Token Claim Name: roles
  • Claim JSON type: string

img

 

User 생성

이제 grafana.com 클라이언트를 사용할 user를 만들어보겠습니다. Keycloak UI 왼쪽탭의 Users에서 새 user를 생성합니다.

img

 

1. Credentials

생성후 Credentials 탭에서 패스워드를 설정하는데 Temporary 옵션은 OFF로 설정후 저장합니다.

img

 

2. Role Mappings

Client에서 Role 설정했던 방법과 같이 Role 설정을 해야합니다.

img

 

 

JWT 토큰발행 테스트

터미널에서 아래의 명령어로 토큰을 발행해볼수 있습니다. client-secret에는 client 설정의 Credentials 탭에서 확인할수 있습니다.

curl -s \
-d "client_id=grafana.com" \
-d "client_secret=<client-secret>" \
-d "username=user" \
-d "password=1234" \
-d "grant_type=password" \
"<Keycloak URL>/realms/Grafana/protocol/openid-connect/token"

 

토큰이 정상적으로 발행됬다면 json 형식의 문자열이 반환되는데 https://jwt.io/#debugger-io 사이트에서 access-token 내용을 복사하여 디코딩 해볼수있습니다. 디코딩된 데이터의 PAYLOAD 부분에서 아래 내용이 나오는것이 확인된다면 정상적으로 토큰이 발행된것입니다.

"resource_access": {
"grafana.com": {
"roles": [
"admin"
]
}
}

 

Grafana 설정

Grafana helm 파일에서 아래와 같은 옵션을 env 항목에 추가후 업데이트 합니다.

env:
GF_SERVER_DOMAIN: "<grafana Domain>"
GF_SERVER_ROOT_URL: "<grafana URL>"
GF_AUTH_GENERIC_OAUTH_ENABLED: "true"
GF_AUTH_GENERIC_OAUTH_NAME: "Login Keycloak"
GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP: "true"
GF_AUTH_GENERIC_OAUTH_CLIENT_ID: "grafana.com"
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: "<client-secret>"
GF_AUTH_GENERIC_OAUTH_SCOPES: profile
GF_AUTH_GENERIC_OAUTH_AUTH_URL: "<keycloak URL>/realms/Grafana/protocol/openid-connect/auth"
GF_AUTH_GENERIC_OAUTH_TOKEN_URL: "<keycloak URL>/realms/Grafana/protocol/openid-connect/token"
GF_AUTH_GENERIC_OAUTH_API_URL: "<keycloak URL>/realms/Grafana/protocol/openid-connect/userinfo"
GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH: "contains(roles[*], 'admin') && 'Admin' || contains(roles[*], 'editor') && 'Editor' || 'Viewer'"
helm upgrade kube-prometheus-stack . -n monitoring

 

업데이트후에 Grafana UI 접속을 하면 기존 로그인 버튼 밑에 Sing in with Login Keycloak 버튼이 새로 생성됩니다. 이 버튼을 클릭하여 keycloak에서 생성한 user 정보로 로그인을 합니다.

img

 

img

 

Grafana UI에 로그인이 됬다면 왼쪽 하단의 사용자 정보를 눌러서 keycloak에서 생성한 user 정보와 일치하는지 확인합니다.

keycloak의 user에서 설정한 role 정보대로 admin 권한으로 설정된것을 확인할수 있습니다.

img

img

 

 

참조

https://janikvonrotz.ch/2020/08/27/grafana-oauth-with-keycloak-and-how-to-validate-a-jwt-token/

https://nyeongnyeong.tistory.com/261

 

반응형

댓글