티스토리 뷰

Security/System&Tools

Grafana login using Keycloak OAuth

jacobbaek Jacob_baek 2021. 6. 15. 21:28

Grafana Login 을 Keycloak OAuth 방식을 사용하여 처리하는 과정에 대하여 간단히 정리하고자 한다.

실제 원하는 동작 구성은 다음과 같다.

Prerequites

두개의 서버를 준비하여 docker로 각 서비스를 동작시킬 예정이다.
(여기서는 가상머신 두개를 통해 환경을 구성했다. 실환경이라면 좀더 보안적인 요소와 설정에 대한 고려가 필요하다.)

  • keycloak server (13.0.1)
  • grafana server (8.0.2)

keycloak 서비스 준비

Keycloak 서비스를 동작시키기 위해 아래와 같은 docker 명령을 실행하자.

[root@keycloak-server ~]# docker run -d -p 8080:8080 -e KEYCLOAK_USER=admin --name keycloak -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:13.0.1

위 링크를 참조하면 Keycloak의 기본 설정에 대한 설명이 나와있으니 참고하면 좋을듯하다.

Keycloak 서비스가 올라왔으니 이제 아래 redhat 문서를 참고하여 keycloak에서 jwt token 사용이 가능한 환경을 만들어보자. 실제 

간단하게 순서를 정리해보면

  1. 새로운 realm 생성
  2. 생성된 realm에 client 생성
  3. client에 설정 추가 #1
  4. client에 설정 추가 #2
  5. user를 추가하여 로그인 가능한 환경 구성

환경이 구성되면 cURL을 사용해 JWT token을 발행해보자.

[root@keycloak-server ~]# curl -L -X POST 'http://192.168.56.9:8080/auth/realms/jwtrealm/protocol/openid-connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=jwttoken' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_secret=b49a1ea9-2dca-4b1d-ace2-e8b844208720' \
--data-urlencode 'scope=openid' \
--data-urlencode 'username=testuser1' \
--data-urlencode 'password=testuser1'
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwMDBBaFlDRWhLRjhqZlhpMk5wbmNsVFItM0t5dDRGc2VSVXFxUUpfa0ZzIn0.eyJleHAiOjE2MjM3MjI2NjIsImlhdCI6MTYyMzcyMjA2MiwianRpIjoiMDY4NzlkYTAtMWExYS00YmNlLTg2YTQtNTk2NDdiMmU1Y2EwIiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguNTYuOTo4MDgwL2F1dGgvcmVhbG1zL2p3dHJlYWxtIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImQ0YjBkYTc2LTgyZmYtNDhlMi05Y2Y0LTM0MjE0YjI1NjI5NCIsInR5cCI6IkJlYXJlciIsImF6cCI6Imp3dHRva2VuIiwic2Vzc2lvbl9zdGF0ZSI6IjQ1MWY2NmY1LTMxNDEtNDBhMy1hMDVlLWNkOTlkNGIyNDNhMiIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovLzE5Mi4xNjguNTYuOTo4MDgwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsImRlZmF1bHQtcm9sZXMtand0cmVhbG0iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJ1c2VyMSB0ZXN0IiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdHVzZXIxIiwiZ2l2ZW5fbmFtZSI6InVzZXIxIiwiZmFtaWx5X25hbWUiOiJ0ZXN0IiwiZW1haWwiOiJ0ZXN0dXNlcjFAY2FmZTI0Y29ycC5jb20ifQ.k4W5sK5nXL2rr_GUccWjVkwWu1h-0p1lNpqvC0s8cmeltCgiD8MGVRkg0aoNAoFCsfPAAfqe8XrJkSf1yTtqgP3FPQEmBWuBuXTeGFDW9s9VAir1O9M2tmT4iaVxZtb-rnvVg1u0AxHOQrI-CpdaRk89PZhQwhF9Efzw2OoQxMkcumiOVGFzy7DXlc1iX89XqrF5uB3cDSdhc9G_d2hRAT38YfQe-jh_w5MO-GCONPyIKeP6RIBzQ2gGIp-bnYhheFmI-640H2R5SPmXxM9XE73WkEVpoyDsT2bGhDTds5m4km8bgXEjxOLBRpgFPdoD6V0vXRqRPulkEVGIo_1RDw",
  "expires_in": 600,
  "refresh_expires_in": 1800,
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5MGM1YjllZC01OTc3LTQ4ZTYtODg0ZS02OWMxZTA4OTFjZTUifQ.eyJleHAiOjE2MjM3MjM4NjIsImlhdCI6MTYyMzcyMjA2MiwianRpIjoiNDExMTBlNmQtMDc5YS00N2M3LWIwYWUtZjM4MzkzNmYzMjE4IiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguNTYuOTo4MDgwL2F1dGgvcmVhbG1zL2p3dHJlYWxtIiwiYXVkIjoiaHR0cDovLzE5Mi4xNjguNTYuOTo4MDgwL2F1dGgvcmVhbG1zL2p3dHJlYWxtIiwic3ViIjoiZDRiMGRhNzYtODJmZi00OGUyLTljZjQtMzQyMTRiMjU2Mjk0IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6Imp3dHRva2VuIiwic2Vzc2lvbl9zdGF0ZSI6IjQ1MWY2NmY1LTMxNDEtNDBhMy1hMDVlLWNkOTlkNGIyNDNhMiIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwifQ.HxKAxSacp1r1uo50viaH_KcT5FzAKZxCIN2d13D01fk",
  "token_type": "Bearer",
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwMDBBaFlDRWhLRjhqZlhpMk5wbmNsVFItM0t5dDRGc2VSVXFxUUpfa0ZzIn0.eyJleHAiOjE2MjM3MjI2NjIsImlhdCI6MTYyMzcyMjA2MiwiYXV0aF90aW1lIjowLCJqdGkiOiJhZGJjZjY3YS05OGJlLTRlOGQtYTZkMi04MTdkMDM5MjE0YTEiLCJpc3MiOiJodHRwOi8vMTkyLjE2OC41Ni45OjgwODAvYXV0aC9yZWFsbXMvand0cmVhbG0iLCJhdWQiOiJqd3R0b2tlbiIsInN1YiI6ImQ0YjBkYTc2LTgyZmYtNDhlMi05Y2Y0LTM0MjE0YjI1NjI5NCIsInR5cCI6IklEIiwiYXpwIjoiand0dG9rZW4iLCJzZXNzaW9uX3N0YXRlIjoiNDUxZjY2ZjUtMzE0MS00MGEzLWEwNWUtY2Q5OWQ0YjI0M2EyIiwiYXRfaGFzaCI6Ilk3eUEyVVdpV0VyMXBsRDIwQzBmRHciLCJhY3IiOiIxIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoidXNlcjEgdGVzdCIsInByZWZlcnJlZF91c2VybmFtZSI6InRlc3R1c2VyMSIsImdpdmVuX25hbWUiOiJ1c2VyMSIsImZhbWlseV9uYW1lIjoidGVzdCIsImVtYWlsIjoidGVzdHVzZXIxQGNhZmUyNGNvcnAuY29tIn0.K8cU07zoZHMYLyYh5BLWvOoF4JbvRnizBe850hGTjXNYl84223_aGSfGGY-Gj-xpUXxuGbDrp8AC7v6q56rrspjo0CUpVEljYIBe5P5n3317A30XdFCxfjrI71IcjNHbHeLTMvjF6bao0HKQFxNRbLUFQPooklkG3t9_Ls3D8CAnmhnm1o3hlJzHPZpd9ASjzbBLzIAU51-l_LU-sncFMbPIky3Px2WRejZTOXJU8cJnsdJTnkT7IYMVMtJEwPp4O3byzEZVO0xDUOOvsHDwZbzF30RlIwR0xWyiEBMpYCqZjgA2RirSflW-slJEO6nZAtgJdUUorNwygLb8RcE-4w",
  "not-before-policy": 0,
  "session_state": "451f66f5-3141-40a3-a05e-cd99d4b243a2",
  "scope": "openid profile email"
}

위와 같이 cURL로 발행된 token 정보가 출력되는것을 볼수 있고 이를 통해 JWT token 발행이 정상적으로 이루어짐을 확인할 수 있다.

Grafana 서비스 준비

이제 OAuth 방식으로 인증을 수행할 grafana를 동작시켜보자.
(아래와 같은 docker-compose.yml을 기반으로 동작될 예정이다.)

[root@grafana-server ~]# cat docker-compose.yml
version: "3"

services:
  grafana:
    image: grafana/grafana
    user: root
    restart: unless-stopped
    container_name: grafana
    ports:
      - 3000:3000
    volumes:
      - ./data:/var/lib/grafana
      - ./conf:/etc/grafana
      - ./logs:/var/log/grafana

아래 docker-compose up 명령을 통해 grafana를 실행하면

[root@grafana-server ~]# docker-compose up -d

docker-compose에 지정했던 volume들 기반으로 conf directory가 생성된다.
생성된 conf directory에서 grafana.ini를 다음과 같이 수정해보자.

...

[server]
domain = 192.168.56.10

...

[auth.generic_oauth]
enabled = true
name = keycloakOAuth
allow_sign_up = true
client_id = jwttoken
client_secret = b49a1ea9-2dca-4b1d-ace2-e8b844208720
;scopes = user:email,read:org
scopes = profile
;empty_scopes = false
;email_attribute_name = email:primary
;email_attribute_path =
;login_attribute_path =
;name_attribute_path =
;id_token_attribute_name =
auth_url = http://192.168.56.9:8080/auth/realms/jwtrealm/protocol/openid-connect/auth
token_url = http://192.168.56.9:8080/auth/realms/jwtrealm/protocol/openid-connect/token
api_url = http://192.168.56.9:8080/auth/realms/jwtrealm/protocol/openid-connect/userinfo

여기서 앞에 keycloak설정중 Valid Redirect URIs에 grafana URL을 추가해주자.

만약 grafana URL을 추가하지 않은 경우 invalid redirect_url 이라는 error 메세지를 만날수 있다.
하여 필히 grafana URL을 추가해주자.

 

로그인

이제 OAuth를 이용한 Grafana 로그인준비가 완료되었다.
실제 로그인을 수행해보자.

'Security > System&Tools' 카테고리의 다른 글

Teleport  (0) 2021.08.10
Grafana login using Keycloak OAuth  (0) 2021.06.15
Wireguard  (0) 2020.07.02
metasploit  (0) 2013.06.10
댓글
댓글쓰기 폼