-
Keycloak을 이용한 K8S 사용자 분리K8S 2022. 9. 4. 03:02
틀린 내용이 있을 수도 있습니다!
틀린 내용이 있다면 댓글로 달아주시면 감사하겠습니다!
이번 포스팅은 kubernetes korea group에서 진행한
[keycloak을 이용한 kubernetes 사용자 분리 방법]의 내용을 바탕으로 정리했다.
우선 keycloak이란 IAM 오픈소스로 다음과 같은 기능들을 제공한다.
- SSO
- OpenID, OAuth 2.0, SAML 2.0
- LDAP, AD
keycloak을 이용해서 사용자를 분리하는 방법
KeyCloak을 이용한 OIDC Flow
K8S에서 keycloak을 Identity Provider로 사용함으로써 OpenID connect를 사용할 수 있다.
1. 유저는 keycloak에게 요청을 보내 keycloak이 발급한 token을 받아온다.
2. 유저는 k8s 리소스를 사용하기 위해 발급받은 토큰을 kube-apiserver로 보낸다.
3. kube-apiserver는 받은 토큰이 유효한지 검증하기 위해 keycloak에게 확인을 한다.
4. 토큰이 유효하지 않다면 인증이 되지 않을 것이고, 유효하다면 해당 사용자는 k8s 사용자로 인증이 된다.
KeyCloak과 K8S 연동
1. keycloak 생성 및 https 적용하기
k8s에서 연동할 인증 서비스는 필수적으로 https를 사용해야 한다.
그래서 keycloak에 https를 적용해야 한다(정확히는 ingress를 통해서 https를 적용한다).
영상에서는 openssl을 이용해서 self-signed 인증서를 만든 후,
이를 secret으로 만들어 helm chart의 value 값에 해당 secret을 명시하여 keycloak을 생성하는데
이 과정은 그냥 넘어가겠다.
2. keycloak 세팅하기
1) realm을 생성한다.
realm은 개발자가 object를 관리할 때 사용하는 공간으로, k8s에서 namespace와 유사한 개념이다.
realm 내부에서는 관리자가 user, group, client 등을 만들 수 있다.
현 예제에서는 myrealm이라는 realm을 만든다.
2) myrealm에서 client 생성하기
client는 keycloak 인증을 사용할 application을 의미한다.
즉 리소스 서버가 된다.
우리는 k8s 리소스를 사용해야 하므로 kube-apiserver를 클라이언트로 등록한다.
Client ID는 kubernetes-client라고 하자.
참고로 client protocol은 openid-connect를 사용한다.
3) token에 group이라는 claim 추가하기
미리 말하면, k8s 사용자에게 rolebinding을 통해 권한을 줄 때 group 단위로 권한을 줄 것이다.
그래서 keycloak이 발급할 토큰에 groups라는 claim을 추가해야 한다.
새로운 claim을 추가하기 위해서는 protocol mapper를 사용한다.
kubernets-client라는 client에서 Mappers 탭으로 들어가면 protocol mapper를 생성할 수 있다.
groups이라는 protocol mapper를 생성한다.
이후 다음과 같은 정보를 추가한다.
- Mapper Type: User Client Role
- Client ID: kubernetes-client
- Token Claim Name: groups
4) Client의 Role 생성하기
group이나 user에게 추가하기 위한 role을 생성한다.
kubernetes-client의 Roles 탭에서 Role Name이 dev인 role을 만들자.
해당 role은 이름만 있으며, role의 구체적인 권한은 K8S RBAC을 통해서 정해줄 것이다.
5) Group 생성하기
group을 통해서 특정 그룹에 속한 사용자의 권한을 조정할 수 있다.
dev라는 group을 생성한 후, 해당 group에 kubernetes-client의 dev role을 추가한다.
6) User 생성하기
Username이 sjoh인 사용자를 생성한다.
참고로 credential 탭으로 들어가면 비밀번호를 설정할 수 있다.
User를 생성한 후, User의 Groups 탭에서 사용자 sjoh를 dev라는 group에 추가한다.
3. keycloak token 요청하기
이제 keycloak으로 요청을 보내서 Token을 얻어온다.
curl -k -X POST https://keycloak-url/auth/realms/myrealm/protocol/openid-connect/token \ -d grant_type=password \ # password 타입 사용 -d client_id=kubernetes-client \ # 생성한 client ID를 사용 -d username=sjoh \ # 생성한 User 사용 -d password=password \ # sjoh의 비밀번호 -d scope=openid
토큰을 받으면 토큰에는 다음과 같은 정보들이 들어가 있다.
1) access_token
2) expires_in
3) refresh_token
4) token_type
5) id_token
6) scope
...
여기서 id_token은 jwt token으로 이를 디코딩해보면, groups라는 claim이 추가되어 있는 것을 알 수 있다.
{ ... "groups": [ "dev" ], "preferred_username": "sjoh" }
또한 groups라는 claim에서 dev를 확인할 수 있고, preferred_username에 sjoh 값이 들어가 있는 것을 확인할 수 있다.
sjoh라는 유저는 dev라는 그룹에 속해 있는 것을 알 수 있는 것이다. (아마도?)
4. kube-apiserver 세팅
이제 해당 토큰을 kube-apiserver에게 보내 인증 요청을 할 수 있다.
하지만 토큰을 보내기에 앞서 kube-apiserver가 받은 토큰이 유효한지 확인하려면
kube-apiserver manifest에 oidc 정보를 추가해 주어야 한다.
필요한 내용은 다음과 같다.
- --oidc-issuer-url=https://keycloak-url/auth/realms/myrealm # keycloak url - --oidc-client-id=kubernetes-client # kube-apiserver가 사용할 client ID - --oidc-username-claim=preferred_username # username을 인식하기 위함 - --oidc-username-prefix=- - --oidc-groups-claim=groups # groups라는 claim을 인식하기 위함
5. kube-config세팅
sjoh라는 User로 kubectl을 사용하기 위한 설정이다.
keycloak에서 만든 User 정보를 나의 kubeconfig에 추가해야 한다.
해당 커맨드를 실행시키면, sjoh라는 k8s 유저가 생성된다.
kubectl config set-credentials "sjoh" \ --auth-provider=oidc \ --auth-provider-arg=idp-issuer-url="https://keycloak-url/auth/realms/myrealm" \ --auth-provider-arg="kubernetes-client" \ --auth-provider-arg=id-token="$id_token" \ --auth-provider-arg=refresh-token="$refresh_token" \
(id_token과 refresh token은 처음에 keycloak으로부터 받아온 토큰 내부에 있는 값이다)
이제 context를 생성한다.
sjoh라는 유저에 cluster를 매핑하여 cluster.local-sjoh라는 context를 생성한다.
kubectl config set-context cluster.local-sjoh --user=sjoh --cluster=cluster.local
생성된 context를 확인한다.
kubectl config get-contexts
생성한 context를 사용한다.
kubectl config use-context cluster.local-sjoh
이제부터 kubectl 커맨드를 사용했을 때, sjoh 라는 User로서 kubectl을 사용할 수 있게 된다.
하지만 현재는 아무 권한이 없기 때문에 모든 커맨드가 거부 된다.
role, rolebinding을 통해서 해당 유저에게 권한을 부여해야 한다.
rolebinding을 할 때는 생성한 dev group으로 role binding을 하자.
rolebinding과 role이 올바르게 적용되었다면, sjoh라는 User로 role에 지정된 리소스 권한을 사용할 수 있게 된다.
6. Tip
keycloak으로부터 받아온 토큰은 일정시간이 지나면 만료된다.
위에서 curl을 통해 토큰을 가져온 후, kubeconfig에 세팅하여 사용했는데
이러한 작업은 반복되면 굉장히 귀찮고 소모적이다.
따라서 토큰을 발급하고 세팅하는 스크립트를 따로 만들어서 사용하자.
https://www.youtube.com/watch?v=owaK-V2MAjU
반응형'K8S' 카테고리의 다른 글
Cert-manager와 Traefik IngressRoute을 이용한 nginx https 배포 (0) 2022.10.25 Ingress traefik을 이용한 nginx http 배포 (0) 2022.10.25 local 볼륨 동적 프로비저닝을 위한 PV, PVC 예제 (0) 2022.08.26 PV, PVC, SC 사용시 Tip! (0) 2022.08.17 Pod Status에 Error log만 찍기 (0) 2022.08.08