Service Foundry
Young Gyu Kim <credemol@gmail.com>

OAuth2 Proxy as a Standalone Reverse Proxy on Kubernetes

oauth2 proxy introduction

Introduction

This guide provides step-by-step instructions for installing OAuth2 Proxy as a standalone reverse proxy on Kubernetes. By following this guide, you will integrate OAuth2 authentication into the Jaeger UI using Keycloak as the Identity Provider (IdP).

What is OAuth2 Proxy?

OAuth2-Proxy is a flexible, open-source tool that can act as either a standalone reverse proxy or a middleware component integrated into existing reverse proxy or load balancer setups. It provides a simple and secure way to protect your web applications with OAuth2 / OIDC authentication.

— OAuth2 Proxy
https://github.com/oauth2-proxy/oauth2-proxy

OAuth2 Proxy Architecture

simplified architecture
Figure 1. OAuth2 Proxy Architecture

Reverse Proxy Mode

In reverse proxy mode, OAuth2 Proxy intercepts requests to your application and redirects users to an OAuth2 provider for authentication.

Middleware Mode

As middleware, OAuth2 Proxy can integrate into an existing infrastructure to handle authentication for multiple applications.

Key components of this Guide

  • Keycloak (Identity Provider) - Deployed in the keycloak namespace

  • Jaeger v2 with Memory Store - Deployed in the o11y namespace

  • OAuth2 Proxy - Deployed in the o11y namespace

Installing Dependencies

  • cert-manager

  • OpenTelemetry Collector Operator

$ ./install-dependencies.sh

Installing Keycloak

For detailed Keycloak installation instructions, refer to Keycloak and Spring Boot with OAuth 2.0 and OpenID Connect (OIDC)

To use a separate URL for Keycloak, I created the service with the type LoadBalancer.

custom-values.yaml - service
service:
  type: LoadBalancer
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip

To get the external IP address of the Keycloak service, run the command below:

$ kubectl -n keycloak get svc keycloak

Example output:

NAME       TYPE           CLUSTER-IP      EXTERNAL-IP                                                              PORT(S)        AGE
keycloak   LoadBalancer   10.100.62.187   a135bed50a0204aee8f53817ec45a913-434675855.ca-west-1.elb.amazonaws.com   80:32569/TCP   7h3m

In my case, the external IP address is a135bed50a0204aee8f53817ec45a913-434675855.ca-west-1.elb.amazonaws.com. You might have a different external IP address.

This value will be used when set oidc_issuer_url in the custom-values.yaml file.

Keycloak Configuratoin

  • Realm: nsa2-realm

  • Client ID: nsa2-o11y

  • Client Secret: get from the Keycloak console

  • User: devops

Installing Jaeger v2 with Memory Store

For installation details, refer to the link below:

To get the service name of the otel-collector service, run the command below:

$ kubectl -n o11y get service otel-collector
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                       AGE
otel-collector   ClusterIP   10.100.237.241   <none>        16686/TCP,4317/TCP,4318/TCP   36m

'http://otel-collector.o11y.svc.cluster.local:16686' will be used to set upstreams in the custom-values.yaml file. In case of oauth2-proxy installed in the same namespace, you can use 'http://otel-collector:16686'.

Installing OAuth2 Proxy

We are going to Install OAuth2 Proxy using the Helm chart.

For more information about the OAuth2 Proxy Helm chart, refer to the link below:

Add and Update the Helm Repository

$ helm repo add oauth2-proxy https://oauth2-proxy.github.io/manifests

$ helm repo update oauth2-proxy
#$ helm install my-release oauth2-proxy/oauth2-proxy

Pull the OAuth2 Proxy Helm Chart

Target the directory where you want to save the OAuth2 Proxy Helm chart.

$ mkdir -p $HOME/Dev/helm/charts/oauth2-proxy

$ helm pull oauth2-proxy/oauth2-proxy -d $HOME/Dev/helm/charts/oauth2-proxy

Verify the OAuth2 Proxy Helm chart in the directory $HOME/Dev/helm/charts/oauth2-proxy.

$ ls -l $HOME/Dev/helm/charts/oauth2-proxy

-rw-r--r--@ 1 young  staff  131387 Mar 19 10:49 oauth2-proxy-7.12.6.tgz

Get default values

To read the default values of the OAuth2 Proxy Helm chart, run the command below:

$ helm show values oauth2-proxy/oauth2-proxy > values.yaml

The values.yaml file contains the default values of the OAuth2 Proxy Helm chart.

oauth2-secret.yaml

In oauth2-secret.yaml, we will create a secret named oauth2-secret that contains the followings:

  • client-id

  • client-secret

  • cookie-secret

$ set CLIENT_ID=YOUR_CLIENT_ID
$ set CLIENT_SECRET=YOUR_CLIENT_SECRET
$ set COOKIE_SECRET=YOUR_COOKIE_SECRET

$ CLIENT_ID=nsa2-o11y
$ CLIENT_SECRET=gZ343TCd0kBehqTOkGZFkbL4WvXoa3Ss
$ COOKIE_SECRET=$( openssl rand -base64 32 | head -c 32 | base64)
#$ COOKIE_SECRET=$(openssl rand -base64 32)
# OR
# $ COOKIE_SECRET=$(head -c 32 /dev/urandom | base64 )

$ kubectl -n o11y create secret generic oauth2-secret \
  --from-literal=client-id=$CLIENT_ID \
  --from-literal=client-secret=$CLIENT_SECRET \
  --from-literal=cookie-secret=$COOKIE_SECRET \
  --dry-run=client -o yaml | yq eval 'del(.metadata.creationTimestamp)' > oauth2-secret.yaml

For more information about data items in the secret, refer to the link below:

this secret is used in the custom-values.yaml file.

config:
  existingSecret: oauth2-secret

To apply the secret, run the command below:

$ kubectl apply -f oauth2-secret.yaml

custom-values.yaml

Here is the custom-values.yaml file that I used to install oauth2-proxy on Kubernetes

custom-values.yaml
# values.yaml - line 18
config:
  (1)
  existingSecret: oauth2-secret

  configFile: |
    (2)
    provider = "oidc"
    (3)
    oidc_issuer_url = "http://a135bed50a0204aee8f53817ec45a913-434675855.ca-west-1.elb.amazonaws.com/realms/nsa2-realm"
    email_domains = ["*"]
    cookie_secure = false
    (4)
    upstreams = ["http://otel-collector:16686"]
    #upstreams = ["http://otel-collector.o11y.svc.cluster.local:16686"]
    redirect_url = "http://oauth2-proxy.nsa2.com:4180/oauth2/callback"
    scope = "openid email profile"
    pass_access_token = true
    pass_authorization_header = true
    pass_user_headers = true
    set_authorization_header = true
    (5)
    cookie_domains = ".nsa2.com"
    cookie_name = "_oauth2_proxy"
    cookie_refresh = "2m"
    cookie_expire = "24h"

# values.yaml - line 94
extraArgs:
  - --cookie-secure=false
  - --skip-provider-button
  - --ssl-insecure-skip-verify
1 existingSecret: oauth2-secret contains the client-id, client-secret, and cookie-secret.
2 provider: "oidc"
3 oidc_issuer_url: nsa2-realm URL
4 upstreams: "http://otel-collector:16686" or "http://otel-collector.o11y.svc.cluster.local:16686"
5 cookie_domains: Cookie domain.

Install OAuth2 Proxy using Helm

To install OAuth2 Proxy, run the command below:

$ helm upgrade --install oauth2-proxy \
  $HOME/Dev/helm/charts/oauth2-proxy/oauth2-proxy-7.12.6.tgz \
  -f custom-values.yaml --namespace o11y --create-namespace

$ helm upgrade --install oauth2-proxy \
  oauth2-proxy/oauth2-proxy --version "7.12.6" \
  -f custom-values.yaml --namespace o11y --create-namespace

To access the OAuth2 Proxy, we can either use port-forward or create a Ingress. In this guide, we will use port-forward.

$ kubectl -n o11y port-forward svc/oauth2-proxy 4180:80

Add the following entry to the /etc/hosts file:

127.0.0.1	oauth2-proxy.nsa2.com

To access the OAuth2 Proxy, open a browser and navigate to http://oauth2-proxy.nsa2.com:4180. As upstreams is set to http://otel-collector:16686, you will be redirected to the Keycloak login page and then to the Jaeger UI.

kc devops login
Figure 2. Keycloak Login for OAuth2 Proxy

Use any user from the Keycloak realm to login.

oauth2 proxy jaeger
Figure 3. Jaeger UI

Make sure that the URL is the oauth2-proxy.nsa2.com:4180 that is not Jaeger UI.

Now we can use OIDC authentication to access the Jaeger UI.

Conclusion

In this guide, we successfully installed OAuth2 Proxy as a standalone reverse proxy on Kubernetes. We integrated OAuth2 authentication with the Jaeger UI using Keycloak as the Identity Provider (IdP). This setup enhances security by enabling OIDC-based authentication for accessing Jaeger.