KeycloakのOpenID ConnectでKubernetes Dashboardにアクセスする
TL;DR
- Keycloakはオープンソースの統合ID管理ツールでOpenID ConnectやSAMLに対応している。
- Kubernetes DashboardはOpenID ConnectのIDトークンによる認証に対応している。
- RBACを設定することで、ユーザやグループによるアクセス制御ができる。
- 以下の設定が必要になる。
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 cluster
と kops 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 Dashboardは Helm 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 Dashboardは Authorization
ヘッダのIDトークンを使ってkube-apiserverにアクセスします。
すなわち、Kubernetes Dashboardはkube-apiserverにIDトークンを転送するだけで、IDトークンによる認証やアクセス制御はkube-apiserverに委譲する設計となっています。わざわざkube-apiserverの引数を設定する必要があるのはこのような理由です。
まとめ
OpenID Connectに対応したリバースプロキシを用いてKubernetes Dashboardを外部に公開する方法を説明しました。
参考:
- Kubernetes の認証と dex - Qiita
- Access control · kubernetes/dashboard Wiki · GitHub
- GitHub - gambol99/keycloak-proxy: A OpenID / Keycloak Proxy service
- 作者: Kelsey Hightower,Brendan Burns,Joe Beda,松浦隼人
- 出版社/メーカー: オライリージャパン
- 発売日: 2018/03/22
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
*1:他に evry/docker-oidc-proxy も利用できるが、トークンのリフレッシュに対応していない。