@int128

int128.hatenablog.com

KeycloakのOpenID ConnectでKubernetes Dashboardにアクセスする

TL;DR

  • Keycloakはオープンソースの統合ID管理ツールでOpenID ConnectやSAMLに対応している。
  • Kubernetes DashboardOpenID ConnectのIDトークンによる認証に対応している。
  • RBACを設定することで、ユーザやグループによるアクセス制御ができる。
  • 以下の設定が必要になる。
    • Keycloak(OpenID Connect IdP)
    • kube-apiserver(Kubernetes APIサーバ)
    • keycloak-proxy(OpenID Connectに対応したリバースプロキシ)
    • Kubernetes Dashboard

Getting Started

Keycloak

Keycloakは Helm chart からインストールできます。

OpenID Connectで認証できるようにKeycloakを設定します。ここではKeycloakに以下のレルムとユーザが存在しており、ユーザはグループに参加しているものとします。

  • レルム名: hello
  • ユーザ名: foo
  • グループ名: admin

まず、新しいクライアントを作成します。Settingsタブで下表の内容を設定します。

項目 設定値
Client ID kubernetes
Client Prorocol openid-connect
Access Type confidential
Valid Redirect URIs https://keycloak-dashboard.example.com/oauth/callback

Credentialsタブを開くとClient Secretが表示されるのでメモしておきます。後述するkeycloak-proxyの設定で必要になります。

Mappersタブで新しいマッパーを作成します。ここではグループによるアクセス制御を行いたいので groups クレームを返すように下表の内容を設定します。

項目 設定値
Name groups
Mapper Type Group Membership
Token Claim Name groups

kube-apiserver

kube-apiserverに下表の引数を渡すように設定します。

引数名 設定値
--oidc-issuer-url https://keycloak.example.com/auth/realms/hello
--oidc-client-id kubernetes
--oidc-groups-claim groups

kopsの場合は kops edit cluster で以下を設定します。設定したら kops update clusterkops rolling-update cluster でmastersを再作成しておきます。

spec:
  kubeAPIServer:
    oidcClientID: kubernetes
    oidcGroupsClaim: groups
    oidcIssuerURL: https://keycloak.example.com/auth/realms/hello

kube-awsの場合は cluster.yaml で以下を設定します。設定したら kube-aws update でスタックを更新します。

       oidc:
         enabled: true
         issuerUrl: https://keycloak.example.com/auth/realms/hello
         clientId: kubernetes
         groupsClaim: groups

keycloak-proxy

Kubernetes Dashboardは単体では認証の機能を持っていないため、OpenID Connectに対応したプロキシを利用します。OpenID Connectに対応したプロキシはいくつかありますが、ここでは keycloak-proxy を利用します。keycloak-proxyはGoで書かれた軽量なプロキシです*1

keycloak-proxyには下表の引数を渡します。

引数名 設定値
--listen 0.0.0.0:3000
--discovery-url https://keycloak.example.com/auth/realms/hello
--client-id kubernetes
--client-secret KeycloakのClient Secret
--redirection-url https://kubernetes-dashboard.example.com
--enable-refresh-tokens true
--encryption-key 32文字のランダム文字列
--upstream-url https://kubernetes-dashboard.kube-system.svc.cluster.local
--resources=uri /*

下記の内容でDeployment, Service, Ingressを作成します。

kubectl apply -f kubernetes-dashboard-proxy.yaml

(3/15追記)ここでは自分でManifest YAMLを書きましたが、Helm Chartからインストールすることも可能です。

なお、nginx-ingress を利用している場合は proxy_buffer_size を大きめに設定してください。nginx-ingress Helm chart の場合はconfig YAMLで下記を設定します。

controller:
  config:
    proxy-buffer-size: "64k"

Kubernetes Dashboard

Kubernetes DashboardHelm chart からインストールできます。

helm install stable/kubernetes-dashboard --namespace kube-system --name kubernetes-dashboard

ブラウザで https://kubernetes-dashboard.example.com を開くとダッシュボードが表示されます。現時点ではユーザやグループに何も権限を付与していないので Unauthorized という警告が出るはずです。

現在のグループに cluster-admin ロールを付与してみましょう。これでダッシュボードが正しく表示されるはずです。

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

グループごとに適切なロールを設定することで、一般グループは参照のみ、管理者グループは更新可能といったアクセス制御を実現できます。

解説

本稿で紹介した構成を図にすると下図のようになります。

Webブラウザ
↓
keycloak-proxy → Keycloak
↓
Kubernetes Dashboard
↓
kube-apiserver

まず、WebブラウザでKubernetes DashboardのURLにアクセスすると、keycloak-proxyはKeycloakにリダイレクトします。Keycloakで認証が成功するとIDトークンが発行されます。keycloak-proxyはデフォルトではIDトークンをCookieに格納します。

再びWebブラウザでKubernetes DashboardのURLにアクセスすると、keycloak-proxyはIDトークンを Authorization ヘッダにセットしてリクエストをKubernetes Dashboardに転送します。Kubernetes DashboardAuthorization ヘッダのIDトークンを使ってkube-apiserverにアクセスします。

すなわち、Kubernetes Dashboardはkube-apiserverにIDトークンを転送するだけで、IDトークンによる認証やアクセス制御はkube-apiserverに委譲する設計となっています。わざわざkube-apiserverの引数を設定する必要があるのはこのような理由です。

まとめ

OpenID Connectに対応したリバースプロキシを用いてKubernetes Dashboardを外部に公開する方法を説明しました。

参考:


入門 Kubernetes

入門 Kubernetes

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

*1:他に evry/docker-oidc-proxy も利用できるが、トークンのリフレッシュに対応していない。