ポン酢ブログ(β)

The harder you work, the luckier you get. - Gary Player

おうち Kubernetes のための Auth0 コトハジメ

おうち Kubernetes をはじめて一週間が経ちましたが、やはり手元に3ノードある Kubernetes は便利ですね。早くマスターの HA 構成もしたいところです。

今回は、そんなおうち Kubernetes の認証を OpenID Connect で行うコトハジメをしてみたいと思います。

kubelogin を使ったログイン

kubectl を使ったクラスタへのログインに kubelogin というプラグインを導入します。

これは OpenID Connect プロバイダから認証のリクエストを送り、プロバイダからもらった結果をプラグインに戻したのち、トークンを元に kube-apiserver へのリクエストを行います。その結果元に、クラスタの操作を行います。(そのためには権限を付与する必要がありますが)

いわゆる GKE などでいう gcloud 認証情報ヘルパーのようなモノです。kube-apiserver 自体は OpenID Connect に対応しているものの、 Authorization Code Flow を実現するためには kubelogin のようなプラグインが必要です。さまざまな方が自作されていて、 k8s-oidc-helper というものもあるのでそちらでも良いと思います。

Auth0 を IdP とした設定手順

Google Workspace も持っているのですが、グループやロールを柔軟に設定したいと思ったので Auth0 を使用することにしました。

Auth0 でテナントを作成したら、ダッシュボードから API を選択して API を作成します。 Enable RBAC と Add Permissions in the Access Token を有効にします。 offline_access を要求する場合はAllow Offline Access も入れておくと良いでしょう。(これは自分で必要なら、入れてください)

f:id:atpons:20201122104648p:plain

f:id:atpons:20201122105253p:plain

f:id:atpons:20201122105612p:plain

User と Role を適当に作成します。今回は Role に admin というものを追加しました。

f:id:atpons:20201122104901p:plain

Auth0 の認証プロセスをカスタマイズできる Rules 機能を使って、ロールをカスタムクレームとして含ませます。Rules を以下のように作成します。

function (user, context, callback) {
  const namespace = '<custom_claim_prefix>';
  const assignedRoles = (context.authorization || {}).roles;

  let idTokenClaims = context.idToken || {};
  let accessTokenClaims = context.accessToken || {};

  idTokenClaims[`${namespace}/roles`] = assignedRoles;
  accessTokenClaims[`${namespace}/roles`] = assignedRoles;

  context.idToken = idTokenClaims;
  context.accessToken = accessTokenClaims;

  callback(null, user, context);
}

あとは kubelogin をします。

kubectl oidc-login setup --oidc-issuer-url=https://<tenant>.us.auth0.com/  --oidc-client-id=<api_client_id> --oidc-client-secret=<api_client_secret>- --oidc-extra-scope=offline_access
{
  "<custom_claim_prefix>/roles": [
    "admin"
  ],
  "iss": ...
}

表示に従って、 kubectl config set-credentialsを行います。

その後、API Serverへの設定を行います。Set up the Kubernetes API serverの表示される通りに設定すると、Userをバインドする形になります。今回はグループでバインドしたいので、手動で設定します。まず kube-apiserver の引数に以下を足します。 kubeadm で構築した場合は sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml 等で開いて、以下を足します。

    - --oidc-issuer-url=https://<tenant>.us.auth0.com/
    - --oidc-client-id=<client_id>
    - --oidc-groups-claim=<custom_claim_prefix>/roles
    - '--oidc-groups-prefix=auth0:'

oidc-groups-claim と oidc-groups-prefix を使うことで、独自のグループクレームを使うことができます。

作成した admin ロールを cluster-admin にバインドする ClusterRoleBinding の例は以下の通りです。

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

これを既存の cluster-admin で適用した後、kubectl oidc-login setupを行ったクライアントでkubectl --user=oidc cluster-infoなどを行って動作確認してください。

終わりに

これで Kubernetes クラスタOpenID Connect による IdP との連携が可能になりました。また、グループによる権限制御もできるようになり便利になりました。この内容自体は他の IdP でも利用できるので、ぜひ試してみてください。

参考