2025. 2. 25. 00:44ㆍDevops/Opensource
opensource를 이용하다보면 로그인 Page가 없는경우가 있다. 그런경우는 추가 개발을 해주던가 해야하는데 이런부분을 쉽게 리버스프록시를 사용하여 해 줄 수 있는 opensource가 있는데 그게 바로 oauth2-proxy이다 또한 keycloak을 연동하면 로그인페이지를 사용하여 페이지 이동전에 로그인을하여 이동할 수 있다. 물론.. 단점은 로그아웃이 없다는 점이다..(URL을 수동으로 넣으면 로그아웃은 가능!) 아키텍쳐는 이렇다.

우리는 이번에 인증 middleware로 사용하기 위해 ingress nginx을 사용하여 oauth-proxy와 keycloak 사용해보고자한다
그리고 keycloak은 20버전 위, oauth2-proxy는 7버전 위를 사용하는것을 추천한다.
- keycloak version : 23.0.6
- oauth2-proxy : 7.8.1
이 글은 Keycloak이 설치되어있음을 가정하에 진행합니다.. 그리고 oauth2-proxy는 helm chart로 설치하며, 순서는 keycloak에 client를 생성 후 oauth2-proxy를 설치 후 application ingress에 auth annotation 삽입과 노출 순서로 진행됩니다.
1. Keycloak 설정
먼저 keycloak에서는 client를 설정해줘야합니다. 저는 oauth2-proxy라는 이름의 client를 생성했습니다.


이후 사용하고자하는 URL주소의 callback주소를 입력해줘야합니다.
예를 들어 접속하고자하는 주소가 swlee.test.com 이라면 http://swlee.test.com/oauth2/callback 을 넣어줘야합니다.
그리고 추가도 가능합니다. 저는 아래와 로그인 페이지 없는 URL을 넣었습니다.

그리고 client를 위한 전용 audience mapper를 구성해줘야 합니다. 할당된 클라이언트 범위에 있는 'oauth2-proxy-dedicated'를 클릭하여 전용 Mapper창에 들어가서 추가를 해줍니다.
추가적으로 권한 관리를 위해 User Mapper나 Group Mapper를 추가해도 됩니다




- Name은 aud라고 명시했습니다.
- Included Client Audience는 oauth2-proxy를 선택해줍니다
- Included Custom Audience는 입력을 해도되고 안해도되지만 aud로 추가줍니다.
- Add to ID Token, Add to access Token, Add to instrospection은 로그인 후 어플리케이션에도 JWT 토큰을 upstream 해야하기에 On으로 해줍니다.
설정이 완료되면 이후에는 oauth2-proxy에 해당 client와 clientSecret을 사용하여 oauth2-proxy를 구성합니다.
2. Oauth2-proxy 설치
설치는 helm chart로 설치하며 value.yaml은 custom으로 구성해서 설치합니다. 저는 prometheus 대시보드를 인증후 들어가도록 하기위해 promeheus와 연동하여 진행했습니다.
- helm add repository & update
먼저 helm repo를 등록해주고 update를 진행합니다.
$ helm repo add oauth2-proxy https://oauth2-proxy.github.io/manifests
$ helm repo update
- Create Namespace
$ k create ns oauth2-proxy
namespace/oauth2-proxy created
- oauth2-proxy의 value.yaml 다운로드
$ wget https://raw.githubusercontent.com/oauth2-proxy/manifests/refs/heads/main/helm/oauth2-proxy/values.yaml
$ ls
value.yaml
- value.yaml 수정
수정은 config와 ingress 쪽만 수정해줍니다.
ingress의 주소는 내가 로그인 페이지를 띄울 주소를 넣어줘야합니다.
config:
# Add config annotations
annotations: {}
# OAuth client ID
# Follow instructions to configure Keycloak client
# https://oauth2-proxy.github.io/oauth2-proxy/configuration/providers/keycloak_oidc
# Oauth2 client configuration. From Keycloak configuration
clientID: "oauth2-proxy"
clientSecret: "keycloak에서 만든 clientSecret을 입력해주세요"
# Cookie secret
# Create a new secret with the following command
# openssl rand -base64 32 | head -c 32 | base64
cookieSecret: "bG5pRDBvL0VaWis3dksrZ05vYnJLclRFb2VNcVZJYkg="
# The name of the cookie that oauth2-proxy will create
# If left empty, it will default to the release name
cookieName: "oauth2-proxy"
# Config file
configFile: |-
# Provider config
provider="keycloak-oidc"
provider_display_name="Keycloak"
redirect_url="http://prometheus.test.com/oauth2/callback"
oidc_issuer_url="http://keycloak.test.com/realms/master"
code_challenge_method="S256"
ssl_insecure_skip_verify=true
# Upstream config
http_address="0.0.0.0:4180"
upstreams="file:///dev/null"
email_domains=["*"]
cookie_domains=["test.com"]
cookie_secure=false
scope="openid"
whitelist_domains=[".test.com"]
insecure_oidc_allow_unverified_email="true"
ingress:
enabled: true
className: "nginx"
pathType: Prefix
path: /oauth2
annotations:
# Enable cert-manager to create automatically the SSL certificate and store in Secret
# Possible Cluster-Issuer values:
# * 'letsencrypt-issuer' (valid TLS certificate using IONOS API)
# * 'ca-issuer' (CA-signed certificate, not valid)
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
hosts:
- prometheus.test.com
여기서 email_domains=["*] 이부분과 insecure_oidc_allow_unverified_email="true" 은 꼭 넣어주셔야합니다...( 안넣으면 Email 확인 해달라는 에러가 나옴 해당부분은 아래에 에러 부분에 나옵니다...)
- Install helm chart
설정이 완료되었다면 oauth2-proxy를 설치해줍니다. 내가 노출하고자하는 application과 같은 namespace에 배포를 해주는게 좋습니다.. svc를 공유하기때문에 만약에 같은 namespace가아니라면 해당 oauth2-proxy service를 externalName으로 지정해야 공유가 됩니다.
$ helm install oauth2-proxy oauth2-proxy/oauth2-proxy -f values.yaml --namespace oauth2-proxy
- application을 노출하기
프로메테우스를 노출시키려고 했었기에.. kube-prometheus을 설치하고 dashboard를 노출시킬려면 ingress를 수정해야한다. 수정시 annotation에만 해당 내용만 넣어주면 된다.
아래의 3가지를 넣어주고 저장하면 된다.
nginx.ingress.kubernetes.io/auth-response-headers: Authorization
nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri
nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
완성된 yaml은 아래와 같다..
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-response-headers: Authorization
nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri
nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
creationTimestamp: "2024-12-27T00:12:19Z"
generation: 4
labels:
app: kube-prometheus-stack-prometheus
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/part-of: kube-prometheus-stack
app.kubernetes.io/version: 59.0.0
chart: kube-prometheus-stack-59.0.0
heritage: Helm
name: kube-prometheus-stack-prometheus
namespace: oauth2-proxy
spec:
ingressClassName: nginx
rules:
- host: prometheus.test.com
http:
paths:
- backend:
service:
name: kube-prometheus-stack-prometheus
port:
number: 9090
path: /
pathType: ImplementationSpecific
2-1. oauth2-proxy 구성중 에러 해결
- Error redeeming code during OAuth2 callback: email in id_token (admin@admin.com) isn't verified

접속시 500 Error를 내뱉는경우가 있다.. 해당부분이 무슨에러인지 해서 oauth2-proxy 로그를 보니
Error redeeming code during OAuth2 callback: email in id_token (admin@admin.com) isn't verified 이러한 에러다 한마디로 email 인증이 안되어서 생긴문제라는 것이다...

이부분은 email_domains=["*] 이부분과 insecure_oidc_allow_unverified_email="true" 을 안넣어서 생긴문제이기에 꼭 넣고 다시 배포해줍니다.
- 무한 Redirect ,504 Gateway, 403 Forbided 등등...
처음에는 application 에 /oauth2인증에 대한 부분을 같이 넣어서 진행했다. 근데 문제가 계속 해결이 안되었다 ㅠㅠ..그리고 엄청찾아봤다.oauth2-proxy redirect , oauth2-proxy 403 forbid 등등 검색해서.. 찾아봐도 결과는 잘나오지 않았다. 그리고 chatgpt도 잘 알려주지 않았다..
그러다보니 여러가지를 해결해보고자 ingress를 고치고 수정하고 하다보니 504도나오고 무한 리다이렉트도 나오고 403도 나오고 정말 힘들었음.. 근데 그 이유는 아래의 yaml에 있었다. (결국 내잘못..)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-response-headers: Authorization
nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri
nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
creationTimestamp: "2024-12-27T00:12:19Z"
generation: 4
labels:
app: kube-prometheus-stack-prometheus
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/part-of: kube-prometheus-stack
app.kubernetes.io/version: 59.0.0
chart: kube-prometheus-stack-59.0.0
heritage: Helm
name: kube-prometheus-stack-prometheus
namespace: oauth2-proxy
spec:
ingressClassName: nginx
rules:
- host: prometheus.test.com
http:
paths:
- backend:
service:
name: oauth2-proxy
port:
number: 80
path: /oauth2
pathType: Prefix
- backend:
service:
name: kube-prometheus-stack-prometheus
port:
number: 9090
path: /
pathType: ImplementationSpecific
ingress 호스트 prometheus.test.com 안에 nginx auth에대한 annotaion을 사용한다면 prometheus.test.com 에 대한 ingress를 하나 더 만들어줘야한다.. 그래서 oauth2-proxy 를 배포하기 위해 설정한 ingress을 꼭 만들어야 한다는것이다..
만들게되면 prometheus.test.com 의 배포된 ingress는 꼭 2개가 되어야한다는 점이다.. (1개는 auth인증을 위한 app yaml 1개는 oauth2-proxy )이다. 그래서분기가 되면 아래와 같이 나오는 것이다.
- prometheus-ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-response-headers: Authorization
nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri
nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
creationTimestamp: "2024-12-27T00:12:19Z"
generation: 4
labels:
app: kube-prometheus-stack-prometheus
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/part-of: kube-prometheus-stack
app.kubernetes.io/version: 59.0.0
chart: kube-prometheus-stack-59.0.0
heritage: Helm
name: kube-prometheus-stack-prometheus
namespace: oauth2-proxy
spec:
ingressClassName: nginx
rules:
- host: prometheus.test.com
http:
paths:
- backend:
service:
name: kube-prometheus-stack-prometheus
port:
number: 9090
path: /
pathType: ImplementationSpecific
- oauth2-proxy ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
meta.helm.sh/release-name: oauth2-proxy
meta.helm.sh/release-namespace:oauth2-proxy
nginx.ingress.kubernetes.io/proxy-buffer-size: 16k
creationTimestamp: "2025-02-25T06:10:02Z"
generation: 1
labels:
app: oauth2-proxy
app.kubernetes.io/component: authentication-proxy
app.kubernetes.io/instance: oauth2-proxy
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: oauth2-proxy
app.kubernetes.io/part-of: oauth2-proxy
app.kubernetes.io/version: 7.8.1
helm.sh/chart: oauth2-proxy-7.11.1
name: oauth2-proxy
namespace: oauth2-proxy
resourceVersion: "634840087"
uid: f2343b5a-7512-49c2-a454-80b130e31169
spec:
ingressClassName: nginx
rules:
- host: prometheus.test.com
http:
paths:
- backend:
service:
name: oauth2-proxy
port:
number: 80
path: /oauth2
pathType: Prefix
3. 결과
prometheus.test.com을 접속하게되면 아래와 같은 redirect 즉 keycloak 로그인 페이지가 뜹니다. 로그인하게되면...


로그인하게 되면 한번 개발자 도구를 봐보자..


Cookie에 oauth2-proxy가 들어간것을 알수있다...
4. 정리
원래는 istio를 통해 oauth2-proxy를 연동했었었다. 그때는 쉽게 쉽게 했는데 nginx는 생각보다 연동이 잘안되어서 애를 좀 먹었다. 이유는 뭐.. 흐름을 이해 못해서였을지도 모르지만.. 결론은 잘되서 기분좋았다
아직 문제를 다 해결한건 아니지만 (로그아웃도 문제고 cookie에 대한부분) 추후에 시간이 있다면 관련글을 또 올려야겠습니다. 그리고 session도 redis에 넣어서 관리가 가능하던데.. 근데 keycloak을 사용하면 infinitspan 으로 session을 관리하기에 안해도 되지않을까한다..
현재 istio도 글을 올리고있으니 다음은 istio와 연동하는 방법이나 올려야겠다..