Kubernetes クラスタで X509 クライアント証明書を使用してユーザを作成する

はじめに

Kubernetes のユーザという概念には Service Account と通常のユーザ 2 種類がある。前者の Service Account が Kubernetes クラスタ内で管理されるオブジェクトである一方、後者の通常のユーザを管理する仕組みは Kubernetes にはなく、あくまでクラスタ内の認証局(CA)に署名された証明書を用いることで認証済みかどうかを判別する仕組みになっている。そこからさらに RBAC という仕組みでどういうリソースにどういう操作ができるかと詳細な制限をかけることができる。

今回はタイトルにある通り、2 種類のユーザのうち Service Account ではなく通常のユーザの作成方法についてまとめてみる。

今回利用する環境

  • OS
    • macOS Monterey 12.4
  • Kubernetes クラスタ
    • Docker Desktop for Mac
    • v1.24.0
alias k=kubectl

クライアント証明書の作成

今回は、X509 クライアント証明書での認証を使用する。

秘密鍵の作成

まずは、PKI 秘密鍵とそれを元に証明書署名要求(CSR)を作成する。ここではユーザ名(CN)を test と指定している。

openssl genrsa -out test.key 2048

openssl req -new -key test.key -out test.csr -subj "/CN=test"

CertificateSigningRequest の作成

kubectl を使って Kubernetes クラスタに CSR を作成する。作成する CSR オブジェクトの雛形は下記のようになっている。

csr.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: test
spec:
  request: # ここに CSR ファイルの内容を base64 エンコードした文字列をペーストする
  signerName: kubernetes.io/kube-apiserver-client
  usages:
    - client auth

普通に base64 した値をコピー & ペーストしてもいいが、yq コマンドを使用してワンライナーで csr.yaml を更新すると以下のようになる。

request="$(cat test.csr | base64 | tr -d "\n")" yq -i '.spec.request = strenv(request)' csr.yaml

CSR を作成してすぐに確認すると Pending になっていることが分かる。

k apply -f csr.yaml

k get csr
NAME   AGE   SIGNERNAME                            REQUESTOR            REQUESTEDDURATION   CONDITION
masa   4s    kubernetes.io/kube-apiserver-client   docker-for-desktop   <none>              Pending

作成した CSR を承認し、証明書を取得する。

k certificate approve test
certificatesigningrequest.certificates.k8s.io/test approved

k get csr
NAME   AGE   SIGNERNAME                            REQUESTOR            REQUESTEDDURATION   CONDITION
test   73s   kubernetes.io/kube-apiserver-client   docker-for-desktop   <none>              Approved,Issued

kubectl certificate approve を実行した後に再度確認すると Approved,Issued になったのが分かる。

RBAC の設定

作成したユーザが Kubernetes クラスタにアクセスするためのロールとロールバインディングを作成する。

# Role
k create role test-role --verb=get --verb=list --resource=pods
role.rbac.authorization.k8s.io/test-role created

# Rolebinding
k create rolebinding test-binding --role test-role --user test
rolebinding.rbac.authorization.k8s.io/test-binding created

ここでは、Pod の情報取得という限定した権限を与えておく。

kubeconfig に設定を追加

CSR から証明書を取得して、ユーザ情報として使用する。

k get csr test -o jsonpath='{ .status.certificate }' | base64 -d > test.crt

# User
k config set-credentials test --client-key=test.key --client-certificate=test.crt --embed-certs=true
User "test" set.

# Context
k config set-context test --cluster=docker-desktop --user=test
Context "test" created.

Docker Desktop の Kubernetes クラスタを使用している場合 ~/.kube/config に設定が追加される。

動作確認

事前に Pod を作成しておく。

k run nginx --image nginx

k get po
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          32m

kubectl auth can-i コマンド1を使って test ユーザに権限があるかを確認する。

もちろん kubectl config use-context で context を切り替えて動作確認しても良い。

# Pod の一覧を取得
k auth can-i list pod --as test
yes

# Pod の詳細を取得
k auth can-i get pod --as test
yes

# Pod の作成
k auth can-i create pod --as test
no

# Pod の削除
k auth can-i delete pod --as test
no

# Service の一覧を取得
k auth can-i list service --as test
no

# Deployment の一覧を取得
k auth can-i list deployment --as test
no

# kube-system namespace の Pod の一覧を取得
k auth can-i list pod -n kube-system --as test
no

Pod の一覧取得はできるが、その他のリソースの操作や Pod に対しての他の操作ができないことも確認できた!

まとめ

今回は、X509 クライアント証明書での認証を使用してユーザを作成する方法をまとめてみた。半年前くらい CKA の勉強でこの辺勉強したが忘れかけていたので復習がてらやってみた。 他にも OIDC トークンなどを使用した認証もできるので、他の認証方法についても調べてみたい。

参考

Certificates and Certificate Signing Requests
Kubernetes certificate and trust bundle APIs enable automation of X.509 credential provisioning by providing a programmatic interface for clients of the Kubernetes API to request and obtain X.509 certificates from a Certificate Authority (CA). There is also experimental (alpha) support for distributing trust bundles. Certificate signing requests FEATURE STATE: Kubernetes v1.19 [stable] A CertificateSigningRequest (CSR) resource is used to request that a certificate be signed by a denoted signer, after which the request may be approved or denied before finally being signed.
Certificates and Certificate Signing Requests favicon kubernetes.io
Certificates and Certificate Signing Requests
Using RBAC Authorization
Role-based access control (RBAC) is a method of regulating access to computer or network resources based on the roles of individual users within your organization. RBAC authorization uses the rbac.authorization.k8s.io API group to drive authorization decisions, allowing you to dynamically configure policies through the Kubernetes API. To enable RBAC, start the API server with the --authorization-config flag set to a file that includes the RBAC authorizer; for example: apiVersion: apiserver.
Using RBAC Authorization favicon kubernetes.io
Using RBAC Authorization

Footnotes

  1. kube-apiserver へリクエストをチェックし、ユーザがアクセスできるか認可をデバッグできる。Checking API Access | Kubernetes