티스토리 뷰
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 사용이 가능한 환경을 만들어보자. 실제
간단하게 순서를 정리해보면
- 새로운 realm 생성
- 생성된 realm에 client 생성
- client에 설정 추가 #1
- client에 설정 추가 #2
- 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' 카테고리의 다른 글
how to check certificate with openssl (0) | 2023.11.29 |
---|---|
Teleport (0) | 2021.08.10 |
Wireguard (0) | 2020.07.02 |
metasploit (0) | 2013.06.10 |
- Total
- Today
- Yesterday
- Jenkinsfile
- openstack backup
- open policy agent
- openstacksdk
- crashloopbackoff
- Terraform
- Helm Chart
- metallb
- minio
- jenkins
- nginx-ingress
- K3S
- boundary ssh
- aquasecurity
- vmware openstack
- minikube
- ceph
- azure policy
- kata container
- socket
- GateKeeper
- kubernetes install
- wsl2
- ansible
- macvlan
- kubernetes
- DevSecOps
- hashicorp boundary
- mattermost
- OpenStack
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |