Unyablog.

のにれんのブログ

dex と oauth2-proxy と ingress-nginx で OIDC ID token を取得して kubernetes-dashboad にログインする

Kubernetes では kubernetes-dashboard という各種リソースを見るためのダッシュボードが提供されている。

ブラウザ上で色々確認できるので便利なのだが、ログイン時は下のように自身の token か kubeconfig ファイルをアップロードする必要がある。

Kubernetes へのログインで Certificate や Token を使っている場合はそのままアップロードすればいいものの、 OIDC を設定したクラスタで OIDC 経由でログインしている場合は ID token を取得する必要があり、めんどくさい。

そこで、

  • oauth2-proxy で kubernetes 向けの OIDC ID token を dex から取得
  • ingress-nginx で ID token を Authorization header に Bearer token として付与し、 kubernetes-dashboard に送信

することでシームレスに見れるようにする。

dex

kubernetes が使っている client と同じ client id を使うので dex で新しく client を発行する必要はないが、 Callback URL を新たに登録する必要がある。

staticClients:
- id: kubernetes-client
  redirectURIs:
  - ...
  - 'https://{k8s dashboard domain}/oauth2/callback'
  ...

oauth2-proxy

oauth2-proxy は dex から id token を取得し、 ingress-nginx に Authorization Header として渡す役割を果たす。以下のような環境変数を設定すると良い。

      - name: OAUTH2_PROXY_PROVIDER
        value: oidc
      - name: OAUTH2_PROXY_OIDC_ISSUER_URL
        value: {OIDC issuer url}
      - name: OAUTH2_PROXY_COOKIE_DOMAINS
        value: {k8s dashboard domain}
      - name: OAUTH2_PROXY_WHITELIST_DOMAINS
        value:  {k8s dashboard domain}
      # Re-validate OAuth token per 1 hour
      - name: OAUTH2_PROXY_COOKIE_REFRESH
        value: 9m # id token の期限より短くする
      - name: OAUTH2_PROXY_SCOPE
        value: "openid profile groups offline_access email" # offline_access は refresh token の取得に使う。 email は oauth2-proxy の動作に必須
      - name: OAUTH2_PROXY_SET_AUTHORIZATION_HEADER
        value: "true"

ポイントは OAUTH2_PROXY_SET_AUTHORIZATION_HEADER で、これを true にすることで id token を Authorization Header として ingress-nginx に渡すことができる。

ingress-nginx

ingress-nginx は oauth2-proxy にリダイレクト(& reverse proxy)して Authorization Header を取得し、それを付けた上で kubernetes-dashboard に reverse proxy する。

構成としては、oauth2-proxy に reverse proxy するための認証がない Ingress と、kubernetes-dashboard に reverse proxy するための auth_request 付き Ingress を用意することになる。

oauth2-proxy 用 Ingress

oauth2-proxy の認証まわりの endpoint である /oauth2 配下を oauth2-proxy の service にわたす。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  rules:
  - host: {k8s dashboard host}
    http:
      paths:
      - path: /oauth2/
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard-oauth2-proxy
            port:
              number: 80

kubernetes-dashboardIngress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/auth-response-headers: "Authorization"
    nginx.ingress.kubernetes.io/auth-url: "https://{k8s dashboard host}/oauth2/auth"
    nginx.ingress.kubernetes.io/auth-signin: "https://{k8s dashboard host}/oauth2/start?rd=$scheme://$host$escaped_request_uri"
spec:
  rules:
  - host: kubernetes-dashboard.kmc.gr.jp
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard
            port:
              number: 443

ポイントは nginx.ingress.kubernetes.io/auth-response-headers: "Authorization" を設定することで、これで oauth2-proxy から来た Authorization Header を Request Header に設定して kubernetes-dashboard にリクエストを送ってくれる。

これで、 kuberentes-dashboard へのリクエストに OIDC で認証された kubernetes において valid な Authorization Header が乗るようになり、ユーザーの権限で Kubenetes dashboard が閲覧・編集できるようになった*1

*1:最初の Token を求める画面は出なくなる