Skip to main content

신원확인, 통합인증관리 오픈소스 '키클락'을 알아보자

About 12 minKubernetesVMCNCFIAMKeyCloakArticle(s)blogyozm.wishket.comkubernetesvmcncfiamkeycloak

신원확인, 통합인증관리 오픈소스 '키클락'을 알아보자 관련

Kubernetes > Article(s)

Article(s)

신원확인, 통합인증관리 오픈소스 '키클락'을 알아보자 | 요즘IT
국내 IT 기업은 한국을 넘어 세계를 무대로 할 정도로 뛰어난 기술과 아이디어를 자랑합니다. 이들은 기업 블로그를 통해 이러한 정보를 공개하고 있습니다. 요즘IT는 각 기업의 특색 있고 유익한 콘텐츠를 소개하는 시리즈를 준비했습니다. 이들은 어떻게 사고하고, 어떤 방식으로 일하고 있을까요?

*KubeCon + Cloud Native North America 2023에서 발표한 <Beyond Passwords: Keycloak's Contributions to IAM(Identity and Access Management) + Security>open in new window를 정리한 글입니다. 발표 내용을 3회로 나누어 발행합니다. 이번 1부에서는 키클락open in new window의 기능과 이점에 대해 살펴봅니다. 2부에서는 키클락을 구성하기 위해 실행해야 할 사전 작업을 알아보고, 3부에서는 키클락을 사용하여 EKS, GKE와 같은 관리형 쿠버네티스 클러스터를 통합인증 하여 관리하는 방법에 대해 살펴봅니다. 발표 자료는 KubeCon NA 2023 홈페이지open in new window에서 다운받으실 수 있습니다.

이번 1부에서 살펴볼 내용은 다음과 같습니다.

  1. 키클락에 대한 간단한 소개
  2. IAM의 의미
  3. 인증과 인가의 차이점
  4. 키클락을 사용할 때 대표적인 이점
  5. 키클락에서 통합 인증을 위해서 사용하는 기법

키클락에 대한 간단한 소개

키클락은 신원(Identity)을 확인하고 통합 인증 관리(Access Management)를 해 줄 수 있는 오픈소스입니다. 키클락은 2023년 4월에 CNCF(Cloud Native Computing Foundation)에 인큐베이팅(incubating) 레벨로 합류하였습니다. 주요 관리 주체는 레드햇입니다.

Keycloack is an open-source identity and access management solution for modern applications and services, built on top of industry security standard protocols.

Keycloak was accepted to CNCF on April 10, 2023 at the incubating maturity level.

키클락이 쿠버네티스와 같은 컨테이너 오케스트레이션에서 차지하는 위상을 알고자 하신다면 다음의 링크를 통해서 왼쪽 상단에 있는 키클락을 확인해 보시는 것도 좋습니다.

2024 쿠버네티스 표준 아키텍처 (출처: 본인 깃허브, 키클락 부분 강조 필요)
2024 쿠버네티스 표준 아키텍처 (출처: 본인 깃허브, 키클락 부분 강조 필요)

키클락에서 언급하는 신원 확인 및 통합 인증 관리라는 의미로 쓰이는 IAM에 대해서 이미 클라우드 서비스를 사용하시는 분들이라면 한 번쯤은 들어보셨을 것입니다. 하지만 IAM은 클라우드 서비스에 국한 되어 사용되는 것은 아닙니다. IAM에 대해서 익숙하지 않은 분들을 위해서 이를 우선 설명하도록 하겠습니다.


IAM의 의미

IAM
IAM

IAM(Identity and Access Management)은 한마디로, 식별할 수 있는 '특정 대상'에게 리소스에 대해 적합한 접근 '권한'을 부여하는 관리 시스템입니다. 여기서 '특정 대상'은 Email 같은 사용자 계정이나, 특정 서버가 될 수 있고 '권한'은 CRUD(create, read, update, delete) 같은 권한(Permission)이나, 다수의 권한이 하나로 묶인 역할(Role)이 될 수 있습니다.

따라서 IAM은 특정 대상을 확인하는 인증(Authentication, Authn)과 인증 이후 리소스에 접근할 수 있는 권한을 부여하는 인가(Authorization, Authz)로 이루어져 있습니다. 그러므로 IAM을 이해하기 위해서는 인증과 인가를 이해할 필요가 있습니다. 다음 그림과 함께 인증과 인가에 대해서 정리해 보겠습니다.


인증과 인가의 차이점

인증(Authentication)

인증은 IT를 제외하고도 우리 일상에서 굉장히 많이 사용되는 개념입니다. 대표적인 예시로는 인터넷뱅킹을 사용하기 위해서 뱅킹 애플리케이션 상에서 우리가 공동인증서(공인인증서)를 통해서 송금자가 본인임을 확인하는 것도 인증으로 볼 수 있습니다.

여기서 또 다른 예시를 들자면, KubeCon과 같은 행사에서는 입장하는 사람들의 신원을 확인하기 위해서 신분증 및 여권과 KubeCon 행사 입장권을 구매 내역으로 본인임을 증빙하여 아래와 같은 KubeCon 입장을 위한 티켓을 받을 수 있습니다.

이 티켓에는 이름, 소속, 그리고 행사장에서의 역할이 쓰여있습니다. 그래서 KubeCon 행사장에서 이 티켓을 패용하고 있다면 행사장 입구를 지키는 사람이 티켓을 보고, 이 사람이 KubeCon 행사장에 입장이 가능한지 판별합니다. 이 절차를 인증이라고 합니다. (사실 QR을 찍어서 정확하게 확인합니다.)

인가(Authorization)

인가는 인증을 통해서 대상이 허용되는 사람이라는 것을 안 이후에 일어나게 됩니다. 예를 들면 IT 컨퍼런스라면 행사 참여자는 크게 발표자와 청중으로 나누어질 것입니다. 이때 모든 행사 참석자가 발표자로 인가되지 않기 때문에 발표자 단상에 올라서 발표할 수는 없을 것입니다. 하지만 발표자라고 인가가 된 사람이라면 아래의 그림과 같이 발표자로서 무대에 올라가서 발표를 할 수 있습니다! 이와 같은 것을 '특정 권한을 인가 받았다'고 말할 수 있습니다.


키클락을 사용할 때 대표적인 이점

그런데 인증/인가라는 개념이 키클락을 통해서만 이루어질까요?

우리가 이미 즐겨 사용하고 있는 아이디와 비밀번호에는 인증/인가가 이미 포함되어 있습니다. 하지만 아이디와 비밀번호에는 치명적인 단점이 존재하는데, 모두 다 기억하고 있어야 한다는 것입니다. 그리고 보안적인 관점에서 모든 아이디와 비밀번호를 쉽게 작성하는 것은 매우 안 좋습니다.

위의 그림은 웃자고 만든 것이기는 하지만, 실제로 근거가 있는 게, 비밀번호가 쉬워서 탈취되는 경우가 꽤 많이 있습니다. 아래 통계는 2023년 기준으로 가장 많이 사용된 비밀번호 입니다.

'Top 20 most common passwords of 2023'

RANKPASSWORDTIME TAKEN TO CRACKNUMBER OF TIMES USED
1123456< 1 Second4,524,867
2admin< 1 Second4,008,850
312345678< 1 Second1,371,152
4123456789< 1 Second1,213,047
51234< 1 Second969,811
612345< 1 Second728,414
7password< 1 Second710,321
8123< 1 Second528,086
9Aa123456< 1 Second319,725
101234567890< 1 Second302,709
[CNBC] Most common passwords: 70% can be cracked in less than a second

NordPass has revealed its study of the 200 most common passwords in 2023. Is yours on the list?

보안 안정성 측면에서 안전한 비밀번호를 만들기 위해서는 다음과 같은 방법을 권고하고 있습니다.

비밀번호 베스트 프랙티스 2023

  • 모든 계정에 강력하고 고유한 비밀번호가 설정되어 있는지 확인하세요.
  • 비밀번호는 대문자, 소문자, 숫자, 기호를 조합하여 사용하세요.
  • 비밀번호보다는 기억하기 쉬운 최소 14자 이상의 비밀번호 문구를 사용하세요.
  • 여러 계정에서 비밀번호를 재사용하지 마세요
  • 소셜 미디어 프로필(생년월일, 배우자 또는 애완동물 이름 등)에서 찾을 수 있거나 다른 사람에게 알려진 정보를 비밀번호에 사용하지 마세요.
  • 특히 민감한 데이터가 포함된 계정의 경우 2단계 인증이 설정되어 있는지 확인하세요.
  • 안전한 비밀번호 생성기를 사용하여 임의의 문자열을 생성하세요
  • 사전에 나오는 단어와 일반적으로 사용되는 비밀번호를 사용하지 마세요.
  • 강력한 비밀번호와 안전한 저장소를 생성하려면 비밀번호 관리자를 사용하고 비밀번호 저장소에 길고 복잡한 비밀번호 문구를 설정하세요.
World Password Day 2023 – Password Tips and Best Practices

Thursday, May 4, 2023, is World Password Day. Established in 2013, the event is observed on the first Thursday of May with the goal of improving awareness of the importance of creating complex and unique passwords and adopting password best practices to keep sensitive information private and confide

위 권고대로 비밀번호를 생성할 때 '계정마다 고유한 비밀번호를 만들기'는 어려울 뿐만 아니라 관리하기도 어렵습니다. 이런 문제가 개인으로서는 각자의 방법으로 진행하면 되지만, 조직에서는 정책적으로 시스템적으로 해결해야 합니다.

이런 경우에 보통 일반적인 기업에서는 중앙 집중 시스템에서 계정을 인증하고 각 서비스에 인증된 사용자임을 알려주는 방법을 사용하고 있습니다. 이러한 기능을 구현하는 대표적인 서비스가 윈도의 AD(Active Directory)를 이용한 LDAP 인증입니다. 그리고 이와 같은 형태를 바로 SSO(Single-Sign On)라고 부릅니다.

SSO는 사용자가 한 가지 로그인 정보로 여러 애플리케이션과 서비스에 대해 동시에 인증을 받는 방법입니다. 위에서 예시로 설명한 회사 내부의 AD를 이용한 통합 인증 외에도 각 서비스에서 소셜 로그인을 통해서 로그인을 진행하는 것도 SSO를 통한 기능입니다.

<FontIcon icon="fas fa-globe"/>요즘IT의 로그인 화면에도 포함되어 있는 소셜 SSO 기능
요즘IT의 로그인 화면open in new window에도 포함되어 있는 소셜 SSO 기능

사실 SSO 기능은 Oktaopen in new windowOneLoginopen in new window 처럼 유명한 Identity 관리 솔루션이 유료로 제공하는 기능이지만 키클락은 오픈소스이기에 우리는 이 기능을 무료로 구현할 수 있습니다.


키클락에서 통합 인증을 위해서 사용하는 기법

키클락은 위와 같은 통합 인증을 위해서 인증 표준인 'OIDC(OpenId Connect / OAuth 2.0(Open Authorization 2.0open in new window)'를 사용할 수 있습니다. 물론 OIDC 외에도 'SAML 2.0(Security Assertion Markup Language)'open in new window을 사용할 수 있습니다.

이와 같은 표준 프로토콜은 다양한 인증 사업자(IDP, Identity Provider, 쉽게 말하면 구글 깃허브 카카오등 에서 서비스 형태로 제공합니다. 따라서 손쉽게 통합 인증을 구현할 수 있습니다.

위에서 키클락의 여러 기능들에 인증과 인가가 들어있다고 말씀드렸던 이유가 바로 여기 있습니다. 키클락이 준수하는 OIDC'와 SAML 2.0'가 바로 인증과 인가를 위한 표준 프로토콜이기 때문입니다.

키클락으로 인증을 대동단결
키클락으로 인증을 대동단결

여기까지 키클락의 개념, IAM, 인증/인가 그리고 키클락의 이점과 통합 인증을 위한 기법에 대해서 대해 알아보았습니다.

다음 2부에서 키클락으로 멀티 쿠버네티스를 통합 인증하는 방법에 대해 알아보겠습니다.

키클락으로 통해서 EKS와 GKE를 통합 인증 관리
키클락으로 통해서 EKS와 GKE를 통합 인증 관리

키클락 구성을 위한 기나긴 사전 작업 한번에 보기 | 요즘IT
KubeCon + Cloud Native North America 2023에서 발표한 <Beyond Passwords: Keycloak's Contributions to IAM(Identity and Access Management) + Security>를 정리한 글입니다. 발표 내용을 3회로 나누어 발행합니다. 1부에서는 키클락에 대한 기능 소개와 이점에 대해 살펴보았습니다. 이번 2부에서는 키클락을 구성하기 위해 실행해야 할 사전 작업을 알아보고, 3부에서는 키클락을 사용하여 EKS, GKE와 같은 관리형 쿠버네티스 클러스터를 통합인증 하여 관리하는 방법에 대해 살펴봅니다.

모두가 이러한 실습 환경을 꾸미고 테스트할 수 없다는 것을 알고 있기 때문에 가능한 자세하게 실습하는 느낌으로 설명하였습니다. 이를 통해서 내용을 개괄적으로 이해할 수 있으면 좋겠습니다.

EKS와 GKE에 통합 인증 다이어그램 (차이점이 있답니다!!!)
EKS와 GKE에 통합 인증 다이어그램 (차이점이 있답니다!!!)

테스트를 위한 사전 준비 작업

지난 번 게시글을 통해서 키클락에 대해 어느정도 이해하셨을 것으로 생각합니다.

이제 실제로 멀티 쿠버네티스 환경에 있는 인증들을 키클락을 통해서 통합 관리하는 방법에 대해서, 실습을 통해 배워보도록 하겠습니다. 통합 인증을 구성하기 위해서 앞서 보여드렸던 [그림 1] 다이어그램과 같은 쿠버네티스 클러스터를 배포하고, 키클락을 구성하기 위해서 긴 사전 작업이 필요합니다.

1. 코드 및 사전 필요 구성 확인

실습을 진행하기 위해서 사용하는 스크립트 파일을 git clone을 통해서 내려받습니다.

git clone https://github.com/sysnet4admin/IaC.git
#
# Cloning into 'IaC'...
# remote: Enumerating objects: 2440, done.
# remote: Counting objects: 100% (688/688), done.
# remote: Compressing objects: 100% (282/282), done.
# remote: Total 2440 (delta 394), reused 673 (delta 379), pack-reused 1752
# Receiving objects: 100% (2440/2440), 17.93 MiB | 6.57 MiB/s, done.
# Resolving deltas: 100% (1337/1337), done.

Keycloak으로 이동한 후에 디렉터리 구조를 살펴봅니다.

cd IaC/Keycloak/
tree
#.
# ├── oncloud-1.site
# │   ├── Deploy-infra
# │   │   ├── 1-1.deploy-gke-env-w-keycloak.sh
# │   │   ├── 1-2.deploy-gke-ingress-4-https-keycloak.yaml
# │   │   ├── 1-3.clientconfig-gke-keycloak-w-oidc.yaml
# │   │   ├── 2-1.deploy-eks-env-only.sh
# │   │   ├── eksctl-config
# │   │   │   └── keycloak-w-oidc.yaml
# │   │   └── planB-keycloak-by-helm.yaml
# │   ├── EKS
# │   │   ├── 1.clusterrolebinding-4-devops-group-as-admin.yaml
# │   │   ├── 2-oncloud-1.swtich-ctx-hoon-to-soojin.sh
# │   │   └── 3.set-cred-4-oidc-user.sh
# │   ├── GKE
# │   │   ├── 1.clusterrolebinding-4-devops-group-as-admin-NOTWORK.yaml
# │   │   ├── 2-hoon.clusterrolebinding-4-devops-user-as-admin.yaml
# │   │   └── 2-soojin.clusterrolebinding-4-devops-user-as-admin.yaml
# │   └── kubelogin-installer.sh
# ├── oncloud-2.site
# │   ├── Deploy-infra
# │   │   ├── 1-1.deploy-gke-env-w-keycloak.sh
# │   │   ├── 1-2.deploy-gke-ingress-4-https-keycloak.yaml
# │   │   ├── 1-3.clientconfig-gke-keycloak-w-oidc.yaml
# │   │   ├── 2-1.deploy-eks-env-only.sh
# │   │   ├── eksctl-config
# │   │   │   └── keycloak-w-oidc.yaml
# │   │   └── planB-keycloak-by-helm.yaml
# │   ├── EKS
# │   │   ├── 1.clusterrolebinding-4-devops-group-as-admin.yaml
# │   │   ├── 2-oncloud-2.swtich-ctx-hoon-to-soojin.sh
# │   │   └── 3.set-cred-4-oidc-user.sh
# │   ├── GKE
# │   │   ├── 1.clusterrolebinding-4-devops-group-as-admin-NOTWORK.yaml
# │   │   ├── 2-hoon.clusterrolebinding-4-devops-user-as-admin.yaml
# │   │   └── 2-soojin.clusterrolebinding-4-devops-user-as-admin.yaml
# │   └── kubelogin-installer.sh
# ├── prerequisite-install-tools.sh
# └── README.md
# 
# 10 directories, 28 files
# root@k8s:~/IaC/Keycloak

Keycloak 디렉터리에 있는 prerequisite-install-tools.sh 셸 스크립트를 실행합니다

참고

이 부분을 실행한다고 해서 모든 필요 구성이 완료되지 않습니다. 환경에 따라 더 필요한 내용이 있을 수 있습니다.

prerequisite-install-tools.sh
#!/usr/bin/env bash

# krew
(
 set -x; cd "$(mktemp -d)" &&
 OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
 ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
 KREW="krew-${OS}_${ARCH}" &&
 curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" &&
 tar zxvf "${KREW}.tar.gz" &&
 ./"${KREW}" install krew
)

export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

# eskctl
brew install eksctl

# kubelogin for GCP
gcloud components install kubectl-oidc

# kubelogin for AWS
kubectl krew install oidc-login

해당 스크립트는 실습에 필요한 gcloud, eksctl, krew를 설치 또는 내려받습니다. 물론 이것 이외에도 환경에 따라 더 많은 사전 준비 작업이 필요할 수 있습니다. 사전에 필요한 내용들이 있다는 것을 명시적으로 알리기 위해서 작성된 스크립트라고 보면 됩니다

2. Keycloak의 접근을 위한 HTTPS 인증서와 퍼블릭 환경에서 사용할 수 있는 도메인을 구성

이 실습에서 키클락 통합 인증에 필요 충족 조건인 HTTPS 프토토콜로 키클락으로 접속할 수 있게 조치하기 위해서, 구글 클라우드에서 관리하는 관리형 인증서(MANAGE CERTIFICATE)를 통해 인증서를 사용하도록 처리할 것입니다.

구글에서 관리하는 관리형 인증서를 사용하기 위해 필요한 것이 퍼블릭 환경에서 사용할 수 있는 도메인입니다이와 같이 퍼블릭 클라우드 서비스를 이용하여 도메인을 통한 HTTPS 인증서 발급이 가능합니다. 이렇게 인증서를 발급하는 방식을 DNS Authorization이라고 합니다. AWS 이용시에는 Route53을 이용하면 됩니다.

도메인은 호스팅케이알, 가비아, goDaddy 와 같은 도메인 이름 등록기관 업체 홈페이지에서 일정 기간 동안 '임대(lease)'할 수 있습니다. 2편에서는 oncloud-1.site 라는 도메인을 사용해서 진행하도록 하겠습니다.

도메인을 구매하였다면 구글 클라우드에 Cloud DNS 서비스에 아래와 같이 현재 도메인을 연결해주도록 하겠습니다.

<FontIcon icon="fas fa-globe"/>구글 클라우드의 Cloud DNS 도메인 등록 그리고 가비아 화면의 도메인 네임 서버
구글 클라우드의 Cloud DNS 도메인 등록 그리고 가비아 화면의 도메인 네임 서버

3. 키클락이 배포될 GKE 클러스터 생성을 진행하고 이후에 키클락을 생성된 GKE에 배

위 단계를 전부 진행했다면 이제 키클락을 배포할 GKE 클러스터 배포를 위해서 1번 단계에서 내려받은 디렉터리에서 ./oncloud-1.site/Deploy-infra 디렉터리로 이동합니다. 나타난 디렉터리에서 1-1.deploy-gke-env-w-keycloak.sh 셸 스크립트를 실행하도록 하겠습니다. 이 셸 스크립트는 셸 환경 변수로 구글 클라우드 프로젝트, GKE가 배포되는 지역(Zone), GKE의 클러스터 이름과 클러스터 버전을 입력받아서 구글 클라우드로 공인 IP를 생성하고, GKE 클러스터를 입력 값에 맞게 설정한 다음 helm을 통하여 키클락을 배포하도록 설정하고 있습니다코드 내용 중 일부를 확인해보면서 GKE 클러스터 생성부터 키클락이 배포되는지 정리해보겠습니다.

Note

여기서부터 설명되는 코드는 일부만 발췌해서 설명하는 방식으로 진행되기 때문에 앞 뒤의 코드는 생략되어 있는 경우가 많습니다. 따라서 전체 코드를 살펴보자고 한다면, 해당 파일을 직접 열어서 보시는 것을 권장드립니다.

# static ingress IP. It will attach to Domain
gcloud compute addresses create hj-keycloak-oncloud-1-static-ip \
  --global \
  --ip-version IPV4<

키클락이 사용할 공인 IP를 미리 예약하는 것입니다. 이렇게 예약된 공인 IP는 추후 키클락이 배포가 완료된 다음에 GKE에 내장 인그레스 컨트롤러를 통해서 HTTPS 접속이 가능한 도메인과 IP 주소 매핑이 진행됩니다.

# Deploy GKE cluster for keycloak
gcloud container clusters create $KUBE_CLUSTER \
--num-nodes=3 \
--zone=${GCP_ZONE} \
--no-enable-autorepair \
--no-enable-autoupgrade \
--location-policy=BALANCED \
--enable-identity-service \
--cluster-version="${CLUSTER_VERSION}" \
--release-channel=None \
--labels=keycloak=oncloud-1<

GKE 클러스터를 생성하는 명령입니다. 이때 GKE에서 키클락 통합 인증을 구성하기 위해 --enable-identity-service 옵션을 사용해서 외부 OIDC를 통한 쿠버네티스 클러스터 인증이 가능하도록 설정합니다. 또한 GKE 클러스터의 경우 자동으로 쿠버네티스 버전이 업그레이드되는 기능이 존재합니다. 이는 실습을 구성했을 때 버전에 따른 사이드 이펙트가 발생할 가능성이 있기 때문에 버전 자동 업그레이드가 진행되지 않도록 --no-enable-autorepair, --no-enable-autoupgrade 옵션을 같이 사용합니다.

# Deploy keycloak
helm install keycloak oci://registry-1.docker.io/bitnamicharts/keycloak \
--set auth.adminUser=admin \
--set auth.adminPassword=admin \
--set production=true \
--set proxy=edge \
--version 17.1.1<

GKE 클러스터가 생성된 다음 kubeconfig를 gcloud 명령으로 가져오게 됩니다. 그다음 OCI 차트 저장소로부터 키클락을 설치합니다. 이렇게 키클락을 설치하게 되면 키클락이 동작하는 데 필요한 포스트그레스큐엘 데이터베이스와 키클락이 배포가 됩니다. 이렇게 배포된 키클락의 초기 ID와 패스워드는 admin 입니다.

4. HTTPS 인증서를 GKE 인그레스 컨트롤러에서 사용할 수 있도록 연결 작업을 진행

현재 디렉터리의 1-2.deploy-gke-ingress-4-https-keycloak.yamlkubectl create 을 통해 쿠버네티스 오브젝트를 배포합니다 이 때 Ingress와 함께 ManagedCertificate, FrontendConfig 와 같은 구글 클라우드의 커스텀 오브젝트가 같이 배포됩니다.

먼저 ManagedCertificate의 내용을 살펴보겠습니다.

apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: keycloak-managed-cert
spec:
  domains:
    - "oncloud-1.site"<

oncloud-1.site 도메인에 구글이 관리하는 인증서를 만들라는 내용을 담고 있습니다. 이때 spec.domains 아래로 적용이 되어야 하는 도메인을 입력해야 합니다. 여기서는 oncloud-1.site를 사용하도록 하겠습니다. 이렇게 구성하게 되면 외부에서 키클락 접속 시 oncloud-1.site 라는 도메인으로 접근이 가능합니다.

다음으로 FrontendConfig의 내용을 확인하겠습니다.

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: keycloak-config
spec:
  redirectToHttps:
    enabled: true<

키클락에 첫 화면(프론트엔드)에 접속 시 사용할 네트워크 설정을 입력하는 오브젝트입니다. 여기서는 HTTP 프로토콜로 접속 시 자동으로 HTTPS로 리다이렉트를 처리하라는 내용에 설정이 되어 있습니다.

실제 인그레스(Ingress)가 생성되는 부분입니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: keycloak-ingress
  annotations:
    spec.ingressClassName: "gce"
    kubernetes.io/ingress.global-static-ip-name: "hj-keycloak-oncloud-1-static-ip"
    networking.gke.io/managed-certificates: "keycloak-managed-cert"
    networking.gke.io/v1beta1.FrontendConfig: "keycloak-config"
spec:
  defaultBackend:
    service:
      name: keycloak
      port:
        number: 80<

이와 같은 설정을 ingress 오브젝트에서 애너테이션으로 참조해, GKE 내부 인그레스 컨트롤러를 통해 키클락을 외부에서 HTTPS 접속할 수 있도록 하는 것입니다. 위 과정을 통해서 키클락을 구성하는 경우 구글이 HTTPS 인증서를 발급하는 데 30분에서 2시간 정도가 소요됩니다.

5. 키클락에 접근해서 구글 OIDC에 접근해서 인증을 처리할 수 있는 설정을 진행

먼저 GKE에 배포가 완료된 키클락의 주소인 https://oncloud-1.siteopen in new window 로 접속해보겠습니다.

접속하면 다음과 같은 화면이 나타납니다. 나타난 화면에서 아이디는 , 비밀번호는 을 입력하면 배포된 키클락에 접속할 수 있습니다.
접속하면 다음과 같은 화면이 나타납니다. 나타난 화면에서 아이디는 admin, 비밀번호는 admin을 입력하면 배포된 키클락에 접속할 수 있습니다.

접속이 되었다면 좌측 메뉴Realm이라고 하는 단위를 설정하는 드롭다운 UI가 있습니다. 현재는 master 값으로 지정이 되어있습니다. 이 Realm은 쿠버네티스의 네임스페이스처럼 키클락 사용자, 인증 대상 애플리케이션 그리고 역할과 같은 것들을 관리하는 공간이라고 이해하시면 됩니다.

이 화면에서 쿠버네티스 통합 인증을 위한 목적으로 사용할 다른 Realm를 생성하기 위해서 <FontIcon icon="iconfont icon-select"/>을 누릅니다.
이 화면에서 쿠버네티스 통합 인증을 위한 목적으로 사용할 다른 Realm를 생성하기 위해서 [Create Realm]을 누릅니다.
Create realm 화면에서 쿠버네티스 클러스터 통합 인증을 위해서 Realm name에 를 입력하고 <FontIcon icon="iconfont icon-select"/> 버튼을 눌러  라는 realm을 생성하도록 하겠습니다.
Create realm 화면에서 쿠버네티스 클러스터 통합 인증을 위해서 Realm name에 kubernetes를 입력하고 [Create] 버튼을 눌러 kubernetes 라는 realm을 생성하도록 하겠습니다.

다음으로 키클락에서 인증에 대상이 되는 단위를 지정하는 Client를 설정하도록 하겠습니다.

이를 위해 키클락 화면 좌측에 위치한 <FontIcon icon="iconfont icon-select "/> 메뉴로 이동하겠습니다. 나타나는 화면에서 <FontIcon icon="iconfont icon-select"/> 메뉴를 눌러서 새로운 Client를 생성하도록 하겠습니다.
이를 위해 키클락 화면 좌측에 위치한 [Clients] 메뉴로 이동하겠습니다. 나타나는 화면에서 [Create client] 메뉴를 눌러서 새로운 Client를 생성하도록 하겠습니다.

Client를 생성하면 다음과 같은 화면이 나타납니다.

클라이언트는 쿠버네티스 클러스터 인증에 사용될 것이기 때문에 구분을 위해서 클라이언트 ID와 이름을 모 로 설정합니다. 다음으로, 인증 시 사용할 클라이언트 타입을 <FontIcon icon="iconfont icon-select"/>로 설정하도록 하겠습니다. 여기서 사용하는 OpenID Connect는 JWT(Json Web Token)을 이용하여 사용자 정보를 받아서 사용자의 신원을 확인하는 인증 프로토콜입니다. 마지막으로  값을 On으로 설정한 다음 <FontIcon icon="iconfont icon-select"/>를 눌러 다음으로 이동하겠습니다.
클라이언트는 쿠버네티스 클러스터 인증에 사용될 것이기 때문에 구분을 위해서 클라이언트 ID와 이름을 모 k8s-auth로 설정합니다. 다음으로, 인증 시 사용할 클라이언트 타입을 [OpenID Connect]로 설정하도록 하겠습니다. 여기서 사용하는 OpenID Connect는 JWT(Json Web Token)을 이용하여 사용자 정보를 받아서 사용자의 신원을 확인하는 인증 프로토콜입니다. 마지막으로 Always display in UI 값을 On으로 설정한 다음 [Next]를 눌러 다음으로 이동하겠습니다.
Client에 대해서 인증과 인가 설정을 모두 활성화하여야 통합 인증이 가능하므로, Client Authentication 및 Client Authorization 모두 <FontIcon icon="iconfont icon-select"/>으로 선택한 다음 <FontIcon icon="iconfont icon-select"/>를 눌러서 다음으로 이동하겠습니다.
Client에 대해서 인증과 인가 설정을 모두 활성화하여야 통합 인증이 가능하므로, Client Authentication 및 Client Authorization 모두 [On]으로 선택한 다음 [Next]를 눌러서 다음으로 이동하겠습니다.

클라이언트가 인증 사업자(IdP, Identity provider)를 통하여 인증이 완료된 다음에, id 정보를 전달할 곳을 설정하기 위한 화면입니다.

여기서 Valid redirect URIs를 <FontIcon icon="fas fa-globe"/> 그리고 <FontIcon icon="fas fa-globe"/>로 설정한 다음 <FontIcon icon="iconfont icon-select"/>를 눌러서 Client 생성을 완료합니다.
여기서 Valid redirect URIs를 http://localhost:8000open in new window 그리고 http://localhost:18000open in new window로 설정한 다음 [Save]를 눌러서 Client 생성을 완료합니다.

이번 실습에서는 사용자 정보에 기본 그룹 정보를 함께 포함시켜서 쿠버네티스 인증을 처리하고자 합니다. 이렇게 하는 이유는 쿠버네티스에서 직접 RBAC을 통해서 인가를 하기 위해서이며, RBAC을 기본 그룹 단위로 하는 이유는 특별한 설정을 하지 않아도 기본 적용되어 사용이 편리하기 때문입니다위의 내용을 처리하기 위해서 [Client scopes] 탭 메뉴로로 이동합니다.

먼저 Assigned client scope 목록에서 <FontIcon icon="iconfont icon-select"/>를 클릭합니다.
먼저 Assigned client scope 목록에서 [k8s-auth-dedicated]를 클릭합니다.
group 필드를 JWT에 추가하기 위해서 <FontIcon icon="iconfont icon-select"/> 드롭다운 버튼의 <FontIcon icon="iconfont icon-select"/>를 클릭합니다.
group 필드를 JWT에 추가하기 위해서 [Add mapper] 드롭다운 버튼의 [From predefined mappers]를 클릭합니다.
Add predefined mappers 팝업(또는 모달)이 열립니다. 이 중 <FontIcon icon="iconfont icon-select"/> 를 선택하고 <FontIcon icon="iconfont icon-select"/> 버튼을 클릭합니다.
Add predefined mappers 팝업(또는 모달)이 열립니다. 이 중 groups 를 선택하고 [Add] 버튼을 클릭합니다.

이 'groups' mapper는 JWT groups 키에 사용자의 Realm Role을 매핑하는 역할을 합니다. 이를 통해서 사용자의 Realm role이 JWT에 groups 정보로 추가가 됩니다.

다음으로 사용자에게 적용할 Realm Role을 만들기 위해서 키클락 좌측 메뉴에 위치한 Realm roles 메뉴로 이동 후 <FontIcon icon="iconfont icon-select"/>버튼을 클릭합니다.
다음으로 사용자에게 적용할 Realm Role을 만들기 위해서 키클락 좌측 메뉴에 위치한 Realm roles 메뉴로 이동 후 [Create roles]버튼을 클릭합니다.
JWT에 group 필드로 설정하는 값을 devops로 지정하기 위해서 Realm role의 이름을  로 설정하고 <FontIcon icon="iconfont icon-select"/>를 누릅니다.
JWT에 group 필드로 설정하는 값을 devops로 지정하기 위해서 Realm role의 이름을 devops 로 설정하고 [Save]를 누릅니다.

키클락에서 사용자를 추가하였을 때 사용자 관리를 위한 그룹이 필요합니다.

좌측에  메뉴로 이동해서 devops 그룹을 만들도록 하겠습니다.
좌측에 Groups 메뉴로 이동해서 devops 그룹을 만들도록 하겠습니다.
Realm Role과 혼선이 생기지 않도록 그룹의 이름을 으로 설정하고 <FontIcon icon="iconfont icon-select"/>를 누릅니다.
Realm Role과 혼선이 생기지 않도록 그룹의 이름을 devops-group으로 설정하고 [Create]를 누릅니다.
 그룹이 생성되었다면, 그룹 단위로 역할을 부여해 에 있는 사람들은 devops 역할을 가질 수 있도록 'Role mapping' 탭으로 이동한 후, <FontIcon icon="iconfont icon-select"/>를 누릅니다.
devops-group 그룹이 생성되었다면, 그룹 단위로 역할을 부여해 devops-group에 있는 사람들은 devops 역할을 가질 수 있도록 'Role mapping' 탭으로 이동한 후, [Assign role]를 누릅니다.
앞서 생성한 devops 역할을  그룹에 설정하기 위해서 devops 체크박스를 선택한 다음에 <FontIcon icon="iconfont icon-select"/>을 누릅니다.
앞서 생성한 devops 역할을 devops-group 그룹에 설정하기 위해서 devops 체크박스를 선택한 다음에 [Assign]을 누릅니다.

이 과정을 통해서 우리는 통합 인증에 필요한 인증 설정을 완료하였습니다. 다음으로는 실습 편의를 위하여 키클락 외부로부터 사용자가 키클락에 등록이 될 때 기본적으로 devops-group에 추가되도록 설정하도록 하겠습니다.

좌측 하단에 [Realm settings] 메뉴 아래 User registration 탭으로 이동합니다.

나타난 화면에서 <FontIcon icon="iconfont icon-select"/>탭을 선택 하고 <FontIcon icon="iconfont icon-select"/>버튼을 클릭합니다.
나타난 화면에서 [Default groups]탭을 선택 하고 [Add groups]버튼을 클릭합니다.
최초 사용자가  그룹에 들어갈 수 있도록 을 선택 후 <FontIcon icon="iconfont icon-select"/>를 클릭합니다.
최초 사용자가 devops-group 그룹에 들어갈 수 있도록 devops-group을 선택 후 [Add]를 클릭합니다.
<FontIcon icon="iconfont icon-select"/> 버튼을 누른 후 아래와 같이 Realm에 새롭게 추가되는 사용자에 대해서 에 추가되도록 설정한 것을 확인할 수 있습니다.
[Add] 버튼을 누른 후 아래와 같이 Realm에 새롭게 추가되는 사용자에 대해서 devops-group에 추가되도록 설정한 것을 확인할 수 있습니다.

6. 구글 클라우드에서 키클락의 외부 사용자 정보를 가져오도록 구성 추

앞서 [그림 1] 다이어그램에서 구글 API를 통해서 사용자를 가져오는 것을 확인할 수 있습니다. 이는 구글 API를 통해 구글 사용자 정보를 키클락에 저장시키는 기능인 Identity providers를 사용해서 연동을 진행합니다. 이 연동을 구성하기 위해서 먼저 구글 API에 접근할 수 있는 권한을 설정해야 합니다. 따라구글 클라우드 콘솔에서 Google API & Services > Credentials 메뉴open in new window로 이동하여서 연동 정보를 받은 후 키클락에서 구글 로그인을 통한 사용자 정보를 받을 수 있도록 처리하겠습니다.

구글 클라우드 콘솔 이동하였을 때 상단의 <FontIcon icon="iconfont icon-select"/>를 클릭하고 <FontIcon icon="iconfont icon-select"/>를 선택합니다.
구글 클라우드 콘솔 이동하였을 때 상단의 [+ CREATE CREDENTIALS]를 클릭하고 [OAuth client ID]를 선택합니다.
Application type은 현재 키클락이 웹으로 배포되어있으니 <FontIcon icon="iconfont icon-select"/>으로 설정하고, 이름은 로 설정하고 <FontIcon icon="iconfont icon-select"/>를 누릅니다.
Application type은 현재 키클락이 웹으로 배포되어있으니 [Web application]으로 설정하고, 이름은 hj-keycloak-oncloud-1-cred로 설정하고 [Create]를 누릅니다.

생성을 완료하면 keycloak Client의 Client ID와 Client Secret이 출력된 팝업으로 나타납니다.

Client ID와 Client Secret은 키클락과 구글 사용자 인증정보를 연결해주는 역할을 합니다.

정보를 확인하였다면 다시 키클락에서 Identity providers 메뉴로 이동한 후, 구글을 선택해서 구글 사용자가 키클락에 등록될 수 있도록 합니다.
정보를 확인하였다면 다시 키클락에서 Identity providers 메뉴로 이동한 후, 구글을 선택해서 구글 사용자가 키클락에 등록될 수 있도록 합니다.

구글 클라우드의 Google API & Services > Credentials 메뉴open in new window에서 생성한 Client ID(hj-keycloak-oncloud-1-cred)의 Client IDClient secret 값을 Google API & Services의 keycloak Client에서 명시된 Client ID와 Client secret 값으로 입력합니다.

  • 키클락 > Identity providers 메뉴 > Google
    • General settings
      • Client ID: 구글 클라우드 콘솔 > Google API & Services > Credentials > hj-keycloak-oncloud-1-cred Client ID
      • Client Secret: 구글 클라우드 콘솔 > Google API & Services > Credentials > hj-keycloak-oncloud-1-cred Client secret

여기서 Client ID와 Client Secret은 공개키와 개인키 역할을 합니다. Client ID는 공개되어 있지만, Client ID를 통해 받은 JWT를 복호화 하는 역할은 Client Secret이 수행합니다. 그렇기 때문에 Client Secret은 공개되면 안 되는 중요한 정보입니다.

구글 클라우드의 Google API & Services > Credentials 메뉴open in new window에서 생성한 Client ID(hj-keycloak-oncloud-1-cred)의 Authorized redirect URIs 주소를 Keycloak의 Redirect URI주소로 입력합니다.

  • 구글 클라우드 콘솔 > Google API & Services > Credentials 메뉴 > hj-keycloak-oncloud-1-cred
    • Authorized redirect URIs
      • URIs: 키클락 > Identity providers > Google > General settings의 'Redirected URI'
이를 그림으로 표현하면 다음과 같습니다.
이를 그림으로 표현하면 다음과 같습니다.

키클락과 구글 클라우드 콘솔에 대해서 값을 위와 같이 같이 설정한 후, 키클락의 설정을 적용하기 위해 [Save]를 클릭합니다.

7. 이메일 2차 인증 구성

.EKSopen in new window 등 관리형 쿠버네티스 서비스들은 OIDCopen in new window 방식의 인증을 구성할 때, 사용자 인증하는 방식으로 이메일 인증을 요구합니다. 이런 보안 요구사항을 만족하기 위해서 이메일 인증 옵션을 켠 후, 구글 SMTP 서버를 사용해서 이메일을 보낼 수 있는 설정을 진행하도록 하겠습니다.

키클락에서 이메일 인증 기능을 통해 이메일 발송을 설정하기 위해서, 키클락 관리자에 정보를 채워야합니다. 따라서 우측 상단  드롭다운을 클릭한 다음에 <FontIcon icon="iconfont icon-select"/>를 누릅니다.
키클락에서 이메일 인증 기능을 통해 이메일 발송을 설정하기 위해서, 키클락 관리자에 정보를 채워야합니다. 따라서 우측 상단 admin 드롭다운을 클릭한 다음에 [Manage account]를 누릅니다.
눌러서 나타난 화면에서 관리자 정보를 변경하기 위해서 <FontIcon icon="iconfont icon-select"/> 를 클릭합니다.
눌러서 나타난 화면에서 관리자 정보를 변경하기 위해서 [Personal info] 를 클릭합니다.
  • Email: 사용 가능한 Email (예: Gmail, Naver 등)
  • First name: 이름
  • Last name: 성
관리자의 이메일과 이름을 입력 후 <FontIcon icon="iconfont icon-select"/>를 클릭합니다.
관리자의 이메일과 이름을 입력 후 [Save]를 클릭합니다.
다시 진행하던 이메일 발송 설정을 하기 위해 상단의 <FontIcon icon="iconfont icon-select"/>을 클릭합니다.
다시 진행하던 이메일 발송 설정을 하기 위해 상단의 [Back to security admin console]을 클릭합니다.
오른쪽 상단에 의 이름이 변경된 것을 확인합니다.
오른쪽 상단에 admin의 이름이 변경된 것을 확인합니다.
사용자의 이메일 인증을 사용하기 위해서 Realm settings 메뉴의 로그인 탭에서 스크롤을 내려 <FontIcon icon="iconfont icon-select"/> 옵션을 으로 설정합니다.
사용자의 이메일 인증을 사용하기 위해서 Realm settings 메뉴의 로그인 탭에서 스크롤을 내려 [Verify email] 옵션을 On으로 설정합니다.

이메일 인증에 대한 옵션이 켜졌다면, 이메일을 보내기 위한 설정을 진행하기 위해서 Realm Settings에 Email 탭으로 이동합니다.

Email 탭의 Template 설정을 아래와 같이 구성합니다.
Email 탭의 Template 설정을 아래와 같이 구성합니다.
  • 키클락 > Realm settings 메뉴 > Email 탭
    • Template
      • From *: 이메일 계정
      • From display name: Keycloak Admin
      • Reply to: 이메일 계정
      • Reply to display name: Keycloak Admin
      • Envelope from: Keycloak Admin
Email 탭 아래 Connection & Authentication 설정을 아래와 같이 구성합니다.
Email 탭 아래 Connection & Authentication 설정을 아래와 같이 구성합니다.
  • 키클락 > Realm settings > Email
    • Connection & Authentication
      • Host: smtp.gmail.com (발송하는 smtp에 따라 설정은 다름)
      • Port: 465
    • Encryption
      • Enable SSL: On
      • Enable StartTLS: On
    • Username: Gmail 계정 (발송하는 smtp에 따라 다름)
    • Password: 계정 비밀번호

입력 후, [Save]를 눌러서 저장합니다.

길고 험난한 사전 작업을 완료했습니다. 앞으로는 키클락의 Client를 활용해 여러 쿠버네티스 클러스터의 인증을 OIDC를 통해서 처리하는 실습을 진행하도록 하겠습니다.


키클락을 활용한 통합 인증 실습하기 | 요즘IT
KubeCon + Cloud Native North America 2023에서 발표한 <Beyond Passwords: Keycloak's Contributions to IAM(Identity and Access Management) + Security>를 정리한 글입니다. 발표 내용을 3회로 나누어 발행합니다. 1부에서는 키클락에 대한 기능 소개와 이점에 대해 살펴보았습니다. 이번 2부에서는 키클락을 구성하기 위해 실행해야 할 사전 작업을 알아보고, 3부에서는 키클락을 사용하여 EKS, GKE와 같은 관리형 쿠버네티스 클러스터를 통합인증 하여 관리하는 방법에 대해 살펴봅니다.

8. GKE에 OIDC 기능 구성하기

먼저 현재 디렉터리에 위치한 1-3.clientconfig-gke-keycloak-w-oidc.yaml에 대해 알아보겠습니다.

.1-3.clientconfig-gke-keycloak-w-oidc.yaml은 사전 준비 작업에서 GKE 클러스터를 생성할 때 추가로 입력한 --enable-identity-service으로 만들어진 구글 클라우드에 커스텀 오브젝트입니다. 이 파일 내부에는 OIDC 인증을 위한 파라미터를 설정할 수 있습니다.

oidc:
  clientSecret: ...
  clientID: k8s-auth
  cloudConsoleRedirectURI: https://console.cloud.google.com/kubernetes/oidc
  extraParams: resource=token-groups-claim
  groupPrefix: '-'
  groupsClaim: groups
  issuerURI: https://oncloud-1.site/realms/kubernetes
  kubectlRedirectURI: http://localhost:8000
  scopes: openid
  userClaim: preferred_username
  userPrefix: '-'
internalServer: ""
name: hj-keycloak-oncloud-1-gke

이와 같은 파라미터에 대한 설명은 다음과 같이 정리할 수 있습니다.

  • clientSecret: [시크릿]
    • OIDC 공급업체가 OIDC 클라이언트 애플리케이션이 공유하는 ClientSecret입니다.
    • Google이 'k8s-auth'클라이언트를 식별할 수 있도록 'k8s-auth'클라이언트의 Client Secret을 입력합니다.
  • clientID: k8s-auth
    • OIDC 공급업체에게 인증을 요청하는 클라이언트 애플리케이션의 ID입니다.
    • 'k8s-auth'클라이언트의 Client ID를 입력합니다.
  • cloudConsoleRedirectURI: https://console.cloud.google.com/kubernetes/oidcopen in new window
  • extraParams: resource=token-groups-claim
    • OIDC 공급업체에 전송할 추가적인 키-값 매개변수입니다.
    • Google에게 그룹 클레임을 하기 위해 'resource=token-groups-claim'를 입력합니다.
  • groupPrefix: '-''
    • 기존 이름과 충돌을 방지하기 위해 추가하는 그룹 클레임에 추가되는 프리픽스입니다.
  • groupsClaim: groups
    • JWT 필드에서 사용자의 이름으로 사용할 필드를 입력합니다. 이 실습에서는 키클락에서 추가로 설정한 groups를 사용하기 위해서 groups로 설정합니다.
    • 키클락의 Realm Roles에 해당합니다.
  • issuerURI: https://oncloud-1.site/realms/kubernetesopen in new window
    • OIDC 승인을 요청하는 URL입니다. URI는 HTTPS를 사용해야 하며, 'https://example.com/adfs'과 같은 형식을 가졌습니다.
    • 'k8s-auth'클라이언트가 속한 'kubernetes' Realm 주소를 입력합니다.
  • kubectlRedirectURI: http://localhost:8000open in new window
    • 인가를 위해 kubectl oidc login에 사용되는 리디렉션 URL입니다.
    • 'k8s-auth'클라이언트의 'Valid redirect URIs'를 입력합니다.
  • scopes
    • OIDC 제공업체에 전송할 추가적인 범위입니다
    • Google에게 사용자 정보를 받아오기 위해 openid를 입력합니다.
  • userClaim: preferred_username
    • JWT 필드에서 사용자의 이름으로 사용할 필드를 입력합니다. 이 실습에서는 이메일을 바로 사용자 이름으로 사용하기 위해서 preferred_username을 사용합니다.
  • userPrefix: '-'
    • 기존 이름과 충돌을 방지하기 위해 유저 클레임에 추가된 프리픽스입니다. 유저 클레임이 email이 아닌 경우, 기본적으로 발급자 프리픽스가 Kubernetes API server에 제공된 userID 앞에 붙습니다. 그 결과 사용자 식별자는 'ISSUER_URI#USER'가 됩니다.
    • 본 실습에서는 유저 클레임을 email로 진행하므로 프리픽스를 '-'로 설정하여 프리픽스를 사용 중지합니다.
위에 설정에 필요한 은 kubernetes Realm - Client - k8s-auth - credentials 탭에 있는 Client secret을 복사하면 됩니다.
위에 설정에 필요한 client secret은 kubernetes Realm - Client - k8s-auth - credentials 탭에 있는 Client secret을 복사하면 됩니다.

값을 올바르게 채워넣었다면 kubectl replace -f 1-3.clientconfig-gke-keycloak-w-oidc.yaml로 변경합니다.

kubectl replace -f 1-3.clientconfig-gke-keycloak-w-oidc.yaml
#
# clientconfig.authentication.gke.io/default replaced

9. EKS를 OIDC 기능이 추가된 형태로 배포하기

GKE 이외의 AWS, Azure, Alibaba 등 다양한 클라우드 공급자들이 제공하는 관리형 쿠버네티스가 있지만, 국내에서 가장 많이 사용되는 AWS의 EKS 클러스터를 추가 배포하고 통합 인증을 구성하겠습니다.

OIDC 기능이 추가된 EKS를 배포하기 위해서는 2-1.deploy-eks-env-only.sh 스크립트를 실행하면 됩니다. 이 스크립트는 EKS를 관리하는 eksctl로 EKS 클러스터를 생성합니다. 이때 필요한 EKS 클러스터의 설정은 같은 위치에 있는 eksctl-config 디렉터리 아래의 keycloak-w-oidc.yaml에 정의되어 있습니다. EKS 클러스터에 적용될 키클락 통합 인증 부분은 다음과 같습니다.

identityProviders:
  - name: keycloak
    type: oidc
    issuerUrl: https://oncloud-1.site/realms/kubernetes
    clientId: k8s-auth
    usernameClaim: preferred_username
    usernamePrefix:
    groupsClaim: groups

코드를 보았을 때 usernameClaim으로 사용자 이름을 식별하고 groupsClaim을 통해서 group 정보를 식별하는 것을 확인할 수 있습니다. 또 키클락에 대한 인증 타입은 oidc이며 issuerUrl에는 GKE 구성과 동일하게 키클락에 접속 URL을 기입하고 있습니다.

다음으로는 OIDC 통합 인증을 수행할 때 마주할 수 있는 불편함을 해결하기 위해서 새로운 명령어인 kubelogin을 만들게 된 이야기를 하도록 하겠습니다.


kubelogin이 가지는 의미와 구조 설명

테스트를 위한 사전 준비 작업과 OIDC 기능을 포함하는 EKS와 GKE를 구성하였습니다. 이제 남은 것은 '통합 인증을 통해서 로그인을 진행하면되나?' 라는 생각이 드실 수 있겠지만, 아직은 통합 인증을 수행할 수 없습니다.

그 이유는 EKS와 GKE의 쿠버네티스 인증 방식은 OIDC를 이용하는 것은 같지만, 이때 사용되는 명령어와 명령어 구조가 다르기 때문입니다.

EKS는 kubectl과 같은 명령이 실행될 때 kubectl oidc-login get-token 명령어로 JWT를 키클락으로부터 전달받아서 인증하는 방식이고, GKE는 kubectl oidc login 명령으로 인증이 된 별도의 컨텍스트(context)를 생성해서 쿠버네티스 통합 인증을 진행하는 방식입니다. 클러스터 인증 명령어가 다르기 때문에 명령어를 두 개 써야 하는 문제가 발생하였습니다. 이를 효과적으로 해결하기 위해서 현재 설정 값에 따라 다르게 동작하는 새로운 명령어를 만들게 되었습니다. 이 명령어가 kubelogin 입니다.

아이디어는 이렇습니다. 현재 컨텍스트 이름 안에 gke라는 값이 있다면 해당 클러스터를 gke로 판별하여서 컨텍스트를 생성하도록 조치하고, 그 이외에는 kubectl oidc-login get-token 명령을 통해 JWT를 발급받아서 인증을 처리하게 하는 방식입니다. 그렇게 작성된 코드는 다음과 같습니다.

#!/usr/bin/env bash

function kubelogin() {
local vendor="$(cat ~/.kube/config | grep current-context | cut -d ':' -f2 | grep gke)"

if [ "$vendor" != "" ]; then
    kubectl oidc login --cluster="hj-keycloak-oncloud-1-gke" --login-config="/Users/mz01-hj/.keycloak/config"
else
    kubectl oidc-login get-token \
      --oidc-issuer-url=https://oncloud-1.site/realms/kubernetes \
      --oidc-client-id=k8s-auth \
      --oidc-client-secret=6qfWVLJ91PrGABqqXD613ScVk6j2Qw1d
fi
}

kubelogin

셸 스크립트를 통해서 간략하게 작성하다 보니 하드코딩되어 있는 부분이 많습니다. 따라서 구글 클라우드에서 다른 GKE 클러스터를 사용하게 되었을 때 발생하는 예외 상황에는 대응이 안 되어 있습니다. 그리고 키클락 클라이언트 시크릿이 변경될 때마다 값을 매번 업데이트 해야하는 불편함이 있습니다.

매번 업데이트해야 하는 불편함을 해결하기 위해서 kubelogin을 생성하는 kubelogin-installer.sh스크립트를 만들었습니다.

# declare variable.
DOMAIN_NAME=oncloud-1
CLIENT_SECRET=6qfWVLJ91PrGABqqXD613ScVk6j2Qw1d

#  keycloak-login-config
rm -rf ~/.keycloak ; mkdir ~/.keycloak
kubectl get clientconfig --context=hj-keycloak-${DOMAIN_NAME}-gke -n kube-public default -o yaml > ~/.keycloak/config

rm -rf /usr/local/bin/kubelogin
cat > "/usr/local/bin/kubelogin.tmp" <'EOF'
#!/usr/bin/env bash

function kubelogin() {
local vendor="$(cat ~/.kube/config | grep current-context | cut -d ':' -f2 | grep gke)"

if [ "$vendor" != "" ]; then
    kubectl oidc login --cluster="hj-keycloak-${DOMAIN_NAME}-gke" --login-config="/Users/mz01-hj/.keycloak/config"
else
    kubectl oidc-login get-token \
      --oidc-issuer-url=https://${DOMAIN_NAME}.site/realms/kubernetes \
      --oidc-client-id=k8s-auth \
      --oidc-client-secret=${CLIENT_SECRET}
fi
}

kubelogin
EOF

vendor='$vendor' DOMAIN_NAME=$DOMAIN_NAME CLIENT_SECRET=$CLIENT_SECRET envsubst < /usr/local/bin/kubelogin.tmp >> /usr/local/bin/kubelogin
rm /usr/local/bin/kubelogin.tmp
sudo chmod 755 "/usr/local/bin/kubelogin"
echo "kubelogin installed successfully"

.kubelogin-installer.shDOMAIN_NAME 이나 CLIENT_SECRET과 같은 값을 환경변수로 load 시켜서 kubelogin 셸 스크립트를 실행이 가능한 경로에 작성하는 방식입니다.

이제 테스트를 위한 모든 설정을 마쳤으니 EKS와 GKE에 대해서 인증/인가 실습을 진행하도록 하겠습니다.


EKS와 GKE에 대한 인증/인가 실습

어느 것을 먼저 해도 상관은 없지만, GKE는 새로 컨텍스트를 만들기 때문에 EKS를 먼저 하는 것이 좀 더 무난하게 실습할 수 있습니다. 따라서 EKS에 대한 인증/인가를 우선 실습하도록 하겠습니다.

1. EKS에 대한 인증/인가 실습

EKS 클러스터에 인증/인가 실습을 위해서 EKS 디렉터리로 이동하도록 하겠습니다.

tree EKS
# 
# EKS
# ├── 1.clusterrolebinding-4-devops-group-as-admin.yaml
# ├── 2-oncloud-1.swtich-ctx-hoon-to-soojin.sh
# └── 3.set-cred-4-oidc-user.sh
# 
# 0 directories, 3 files

첫 번째로 먼저 kubectl get pods 로 쿠버네티스 파드가 조회되는지 확인합니다.

eksctl로 EKS를 생성한 경우 최초에는 관리자 권한이 담긴 사용자이기 때문에 조회가 가능합니다. EKS 통합 인증의 경우 현재 상태에서 인가는 키클락을 통해서 진행되고 그다음 사용자로부터 쿠버네티스에 대한 인가는 RBAC을 통해서 이뤄집니다. 따라서 현재 디렉터리에 있는 1.clusterrolebinding-4-devops-group-as-admin.yaml을 적용해서 키클락 통합 인증을 통해 접속한 사용자들이 kubectl을 사용할 수 있도록 하겠습니다. 1.clusterrolebinding-4-devops-group-as-admin.yaml 은 쿠버네티스 클러스터 관리자 권한을 group이 devops 인 사람에게 부여하겠다는 내용을 담고 있습니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: oidc-group-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: devops

이렇게 클러스터롤바인딩으로 인가에 대한 부분을 설정하였습니다.

두 번째로 새로운 사용자로 EKS에 kubectl 사용이 가능한지 확인하기 위해서 새로운 사용자로 전환해야합니다. 현재 디렉터리에 위치한 2-oncloud-1.swtich-ctx-hoon-to-soojin.sh 으로 새로운 컨텍스트를 만들고 사용자를 변경하겠습니다.

이 셸 스크립트는 aws 명령을 통해서 EKS에 새로운 사용자로 접속할 수 있는 컨텍스트를 생성하는 명령입니다. 컨텍스트가 생성되고 새로운 컨텍스트로 변경된 후에 다시 kubectl get pods 명령을 입력한다면, 다음과 같이 새로운 컨텍스트에 대해서 인증하지 않아 에러가 발생합니다.

kubectl get pod
#
# error: You must be logged in to the server (Unauthorized)

세 번째로, 키클락을 이용한 통합인증 진행을 위해서 3.set-cred-4-oidc-user.sh셸 스크립트를 실행합니다. 3.set-cred-4-oidc-user.sh는 oidc-user라는 새로운 kubectl의 사용자를 만들고 kubeloginkubectl을 사용할 때마다 호출하도록 설정하는 내용의 스크립트입니다. 이를 통해서 키클락을 통한 JWT를 명령 실행 마다 받을 수 있고 인증이 가능하게 처리됩니다.

#!/usr/bin/env bash

kubectl config set-credentials oidc-user \
--exec-api-version=client.authentication.k8s.io/v1beta1 \
--exec-command=kubelogin

위 내용이 실제로는 아래와 같이 처리됩니다. 아래와 같은 현재 EKS를 포함한 온프레미스에 위치한 대부분의 쿠버네티스에 적용할 수 있는 통합 인증 설정입니다.

kubectl oidc-login get-token \
--oidc-issuer-url=https://oncloud-1.site/realms/kubernetes \
--oidc-client-id=k8s-auth \
--oidc-client-secret=[시크릿]

셸 스크립트를 실행하여 oidc-user라는 사용자를 만들었다면, kubectl get pods -A --user=oidc-user 명령을 통해서 다시 쿠버네티스 파드를 조회해보겠습니다. 해당 명령어를 입력하였을 때 터미널에 결과가 나타나지 않고 다음과 같은 웹 브라우저가 나타납니다.

이때 키클락에 대한 로그인 화면이 나타나는데, 여기서 우리는 <FontIcon icon="iconfont icon-select"/>을 눌러서 구글 로그인으로 인증을 진행해 보겠습니다.
이때 키클락에 대한 로그인 화면이 나타나는데, 여기서 우리는 [Google 버튼]을 눌러서 구글 로그인으로 인증을 진행해 보겠습니다.
<FontIcon icon="iconfont icon-select"/>을 선택했을 때 이미 브라우저 상에 연결된 이메일 계정이 있다면, 해당 이메일로 인증 메일이 발송되었으니 이메일을 확인해달라는 안내 문구가 나타납니다. (만약 없다면 이메일을 선택하는 메시지가 나옵니다.)
[Google 버튼]을 선택했을 때 이미 브라우저 상에 연결된 이메일 계정이 있다면, 해당 이메일로 인증 메일이 발송되었으니 이메일을 확인해달라는 안내 문구가 나타납니다. (만약 없다면 이메일을 선택하는 메시지가 나옵니다.)

실제로 사용하는 메일 서비스에 메일함을 확인하였을 때 아래와 같은 인증 메일이 온 것을 확인할 수 있습니다. 여기서[Link to e-mail address verification]을 누르면 터미널에서 실행했던 명령 결과가 나타납니다.

즉 이 과정을 통해서 EKS에서의 키클락 인증이 완료되고, 인증 완료된 그룹 devops의 권한으로 파드 조회 결과를 확인할 수 있게 된 것입니다.
즉 이 과정을 통해서 EKS에서의 키클락 인증이 완료되고, 인증 완료된 그룹 devops의 권한으로 파드 조회 결과를 확인할 수 있게 된 것입니다.
위와 같은 흐름을 생동감 있게 표현하면 다음과 같이 처리가 되는 것입니다.
위와 같은 흐름을 생동감 있게 표현하면 다음과 같이 처리가 되는 것입니다.

2. GKE에 대한 인증/인가

GKE 환경에서의 인증/인가를 테스트하기 위해서 상위 디렉터리에 위치한 GKE 디렉터리로 이동합니다.

tree GKE
#
# GKE
# ├── 1.clusterrolebinding-4-devops-group-as-admin-NOTWORK.yaml
# ├── 2-hoon.clusterrolebinding-4-devops-user-as-admin.yaml
# └── 2-soojin.clusterrolebinding-4-devops-user-as-admin.yaml

앞에서 말씀드린 것처럼 GKE의 경우 EKS와 다른 쿠버네티스 클러스터와 다르게 통합 인증을 위한 컨텍스트를 생성해야 합니다. 그래서 컨텍스트를 생성하기 위해 먼저 지금의 EKS 컨텍스트에서 GKE 컨텍스트로 이동이 필요합니다. 이는 kubectx 명령 또는 kubectl config use-context를 사용하면 바로 전환이 가능합니다.

지금 컨텍스트가 GKE로 변경되었다면, 여기서  명령어를 입력하도록 하겠습니다. 입력하게 되면 다음 브라우저 화면이 나타나면서 인증되었다고 나타납니다.
지금 컨텍스트가 GKE로 변경되었다면, 여기서 kubelogin 명령어를 입력하도록 하겠습니다. 입력하게 되면 다음 브라우저 화면이 나타나면서 인증되었다고 나타납니다.

터미널에는 다음과 같은 메시지가 출력됩니다.

#
# 2023/10/30 19:11:46 Started webserver on localhost: 8000.
# 2023/10/30 19:11:46 Attempting to open http://127.0.0.1:8000/login in default browser.
# 2023/10/30 19:11:47 OIDC Authentication successful.
#

인증이 완료되었다고 나타남과 동시에 새로운 컨텍스트가 생성되고, 지금 컨텍스트가 변경된 것을 확인할 수 있습니다.

위 과정을 생동감 있게 표현하면 다음과 같습니다.
위 과정을 생동감 있게 표현하면 다음과 같습니다.

현재 상태에서 GKE 클러스터에 kubectl get pods 를 입력한다면, 다음과 같은 에러가 나타납니다.

kubectl get pods
#
# Error from server (Forbidden): pods is forbidden: User "hj@mz.co.kr" cannot list resource "pods" in API group in the namespace "default"

이는 키클락을 통해서 인증은 완료되었지만 쿠버네티스 RBAC을 통해서는 인가가 되지 않아서 발생하는 에러입니다. 이 문제는 GKE 클러스터에 어드민 컨텍스트로 다시 돌아가 클러스터롤바인딩을 적용해주면 해결 됩니다. 적용할 클러스터롤바인딩은 2-hoon.clusterrolebinding-4-devops-user-as-admin.yaml 입니다.

kubectl apply -f
#
# 2-hoon.clusterrolebinding-4-devops-user-as-admin.yaml

Note

EKS와 동일하게 그룹을 사용하지 않는 이유는 이 글을 작성하는 시점에서 구글 GKE에서 JWT로부터 그룹에 대한 필드를 가져오는 기능이 정상동작하지 않고 있기 때문에 실습에서는 부득이하게 개인에 RBAC 인가 처리를 진행하고 있습니다. 따라서 이 부분은 향후 바꿀 수 있습니다.

다음으로 kubectx<클러스터이름>-<클러스터이름-anthos-default-user>와 같은 이름 형식을 사용하는 GKE 컨텍스트로 이동합니다. 이동하였다면 다시 kubectl get pods 를 입력해보겠습니다.

kubectl get pods
#
# NAME                    READY     STATUS     RESTARTS   AGE
# keycloak-0              1/1       Running    0          85m
# keycloak-postgresql-0   1/1       Running    0          85m

키클락을 통한 인증이 완료된 사용자가 이제는 kubectl get pods를 통해서 파드를 확인할 수 있는 것을 알아봤습니다.


키클락을 이용한 통합 인증으로 얻을 수 있는 이점들 정리

지금까지의 실습을 통해서 키클락을 이용한 쿠버네티스 통합 인증을 구성하고 서로 다른 클라우드에 배포된 쿠버네티스 클러스터에 인증/인가를 진행 했습니다. 정리를 위해서 키클락 통합 인증으로 얻을 수 있는 이점을 요약하도록 하겠습니다.

첫 번째는 단순하게 EKS, GKE 뿐만 아니라 온프레미스 쿠버네티스 클러스터를 비롯해 SAML과 OIDC를 지원하는 다른 오픈소스 앱들에서도 통합 인증을 구성할 수 있다는 장점이 있습니다.

두 번째로는 대부분 Okta와 Onelogin과 같은 솔루션을 사용하실 수 있지만 법령 상의 규제로 SaaS를 사용할 수 없는 금융권 및 공공기관에서 오픈소스를 활용해 내부 조직에 인증 사업자(IdP)를 구성하실 수 있습니다.

세 번째로는 인증과 인가에 대한 설정을 중앙에서 관리할 수 있다는 점입니다. 조직이 커지면 커질수록 사용자를 관리하고 권한을 부여하는 일들이 굉장히 힘든 일이 될 수 있는데, 키클락을 Realm과 Role로 사용자들에 대한 관리를 효율적으로 할 수 있다는 점입니다.

키클락을 사용하면서 얻을 수 있는 이점들
키클락을 사용하면서 얻을 수 있는 이점들

긴 글을 읽어주셔서 감사합니다.


관련 레퍼런스 사이트

sysnet4admin/IaC > Keycloak

Demo Source Code
int128/kubelogin

kubelogin Binary
외부 ID 공급업체를 사용하여 GKE 인증

이 페이지에서는 Google Kubernetes Engine(GKE) 클러스터에 인증을 수행하도록 외부 ID 공급업체를 구성하는 방법을 설명합니다.
Config File Schema - eksctl

AWS eksctl Configuration Guide (w/ OIDC Configuration)

이찬희 (MarkiiimarK)
Never Stop Learning.