OpenID Connect란?
- 우선 OAuth 2.0을 알아야 하는데,
- 간단히 말하면 Open Authorization이라고 하여, 권한 허가를 위한 프로토콜이며,
- 이기능을 IdP에 구현이 되어 있다.
- 그럼 IdP는 무엇인가?
- 간단히 말하면 실제 사용자 정보를 제공해주는 사용자 정보 제공자로,
- 페이스북, 구글같은 곳에서 사용자 정보을 가지고 있고,
- 이곳에서 OAuth2.0기능도 가지고 있어서, 사용자 인증과 권한을 제공해 줄수 있다.
- 그럼 OpenID Connect는 뭐하는 녀석이지?
- OpenID Connect는 인증 표준 규격을 정의하는 프로토콜에 가깝고 모든 구현은 IdP쪽의 OAuth에 들어 있다고 생각하면된다.
- OpenID Connect가 하고 싶은것은 사용자 인증과 사용자 신원 정보 제공인데,
- 그렇다면 OpenID Connect로 OAuth에있는 사용자 신원 정보를 제공해 달라고 권한을 요청하는것이고,
- IdP는 OAuth 기능과 사용자 정보도 가지고 있으니, OpenID Connect프로토콜을 이용하여, IdP에 요청하여 사용자 인증과 신원 정보를 받으면 되겠네?
OAuth 2.0
- Google, Facebook, Twitter 등에서 자신의 서비스를 외부 시스템에서 사용할 수 있게 제공해주기 위해서 생겨난 기술이고,
- OAuth 인증을 받으면, 다른 애플리케이션에서 Google의 본인 계정의 profile정보 등을 Request해서 가져올수 있다.
- OAuth는 사용자 인증 보다는 제한된 사람에게 (혹은 시스템) 제한된 권한을 어떻게 잘 부여할 것인가에 대해서 중점적으로 다룬다.
- 이에 반해 OpenID는 인증 시스템으로써 사용자 정보를 관리하고 인증하는 것에 초점이 맞춰져 있다.
- 참고로, OAuth 1.0과 2.0이 있는데... 아래는 2.0d에 대해서만 말한다.
- OpenID Connect: 사용자 인증 및 사용자 정보 제공(id token)
- OAuth: 권한 부여(access token) 페이스북 posting권한, profile 검색등..
Identity Provider (OpenID Provider)
- IdP는 실제 사용자 정보를 제공해주는 사용자 정보 제공자이다.
- 살제 OpenID Connect는 인증표준 규격을 정의하는 프로토콜에 가깝고, 실제 인증 및 사용자 정보제공은 IdP를 통해서 수행하는것이다.
- 여기서 IdP에서 발급되는 id Token과 Access Token의 역할이 다르다는것이 중요하다.
- 실제 Flow는 아래와 가깝다.
-
사용자 정보 제공자IdP(Google)
-
사용자 접속 서버(eBay)
- 접속 서버는 IdP서버에 client-id를 발급 받은 서버로 IdP에 접근할때, 해당 client-id로 접근해야한다.
-
access token : 사용자 권한 정보
-
id token : 사용자 신원 정보가 담긴 토큰 (jwt)
-
그림에서 보듯이, 사용자는 실제 eBay에 접속하려고 하지만 실제 사용되는 인증은 Google을 통해 인증이 되는것으로
-
사전에 eBay는 Google에서 발급 받은 client_id를 가지고 있다.
-
eBay에 접속하면 Google 로그인 화면이 나오고
-
Google 로그인을 하면, id token과 access token이 발급된다.
-
이 token을 이용하여 허용된 범위에서 Google에 개인 정보를 가져올 수 있다.
OAuth2.0을 사용하기 위해서는 IdP의 OAuth공급자에서 client_id, client_secret과 같은 정보를 받아 등록을 해야한다.
- 이것은 OAuth2.0으로 인증 받으려고 하는 Application단에서 필요한것으로, 현재 Application이 OAuth2.0을 제공하는 IdP와의 연결 관계를 가질수 있다.
- 아래 실습 과정에서 Google OAuth 2.0 playgroud를 통해서 client_id, client_secret을 발급 받을수 있으며 이것으로 application을 등록해야한다.
kubernetes api-server사용시 OpenID Connect 사용하기
- 위에서 실제 사용된 Flow와는 조금 다르지만, 비슷한 절차를 가진다.
- 사용을 위한 전제 환경 구성이 필요하다.
- 위의 IdP에 접속(중개) 서버를 등록하는 과정으로 아래 실습 과정을 참고하면 될것같다.
- 사용자는 IdP(google, facebook...)에 가입한 사용자이며,
- IdP OAuth2.0에 접속할 Kubernetes api server에 대한 client_id를 발급받는다.
- 발급받은 client_id를 Kubernetes api server에 등록한다.
1. 사용자가 IdP(OAuth시스템)에 로그인한다.
2. 사용자 인증이되면, IdP는 사용자 신원 정보를 jwt형태로 id token을 전달한다.
3. 사용자는 전달 받은 토큰을 HTTP Authentication 헤더에 Bearer 토큰으로 쿠버네티스에 전송합니다.
4. 쿠버네티스 API서버는 전달 받은 JWT토큰이 자신이 생성한 OAuth Client ID인지, 변조되었는지 확인합니다.
5. 모든 절차가 정상적으로 끝나면 인증이완료 된것으로 본다.
실습 과정
1. 인증 중개 서버를 구성하기 위해서는 Test를 위한 Google OAuth 2.0 playgroud 사용 하거나, Google developer에서 OAuth Client ID를 생성하고 사용자 인증 중개 서버를 구축하는 방법이 있음
2. 중개서버와 IdP를 연결 해야하는데...
- 만약 Google OAuth 2.0 playgrout을 사용한다면
- https://developers.google.com/oauthplayground
- “Select & authorize APIs”
- Google OAuth2 API v2 선택
- openid 클릭
- Authorize APIs 클릭
- Google Login 화면에서 로그인
- "Exchange authorization code for tokens" 클릭
- “Configure request to API”에서 client_id, id_token을 확인 할수 있다.
- client_id : OAuth Client ID를 이용하여 토큰을 생성했는지 확인을 위한것으로, kubernetes api-server에 client id를 등록 해야한다.
- id_token : 사용자 신원정보가 있는 jwt 토큰으로 쿠버네티스에서 인증
-
쿠버네티스 API 서버 설정
- token에는
- api 서버로 명령 요청시 외부 인증 서버에 다시 확인 할 필요 없음
- --oidc-issuer-url: OAuth IdP로 구글 OAuth 사용을 나타냅니다.
- --oidc-client-id: Step3 “Configure request to API”에서 복사한 client_id
# API 서버 설정 파일
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
# -----[kube-apiserver.yaml]------
- kube-apiserver
- --allow-privileged=true
- --authorization-mode=Node,RBAC
# .....
- --oidc-issuer-url=https://accounts.google.com
- --oidc-client-id=$client_id
# --------------------------------
- 쿠버네티스 인증
- 먼저 default namespace에 pod를 리스팅할 권한을 줘야 함
kubectl create clusterrolebinding oidc-admin --clusterrole cluster-admin --user https://accounts.google.com#xxxx
# clusterrolebinding.rbac.authorization.k8s.io/oidc-admin created
# Step3 "Configure request to API"에서 복사한 id_token을 환경변수로 저장합니다.
export JWT_TOKEN=eyJhbGciOiJSUzI1NiIs.vb2dsZS5jb20iLCJxxxxx
kubectl get pod -n kube-system --token $JWT_TOKEN
# 내부적으로 api-server로 요청할때 header에 authorization을 붙힌다.
# 성공!
- 근데 아무리 생각해도...
- api-server에 IdP에 대한 주소와 client-id만 등록했는데, 어떻게 token을 사용하여 인증이되는건지 모르겠다.. ㅜㅜ
- api-server가 client-id로 IdP에 접근해서 token을 가지고 있던가, valid 체크하면될거 같긴한데... 그런내용이 없다.