本文へスキップ

CKA 概念ノート: RBAC、ユーザー証明書、kubeconfig

  • kubernetes
  • cka
  • rbac
  • csr
  • kubeconfig

基準: kubeadm クラスタ v1.35.9 (libvirt VM 3 台) でコマンドを確認

Role、RoleBinding、ServiceAccount、kubectl auth can-i の基本は CKAD 概念ノート: ServiceAccount、アクセス制御、SecurityContext にまとめたので、ここでは管理者側でさらに見るものだけを扱う。

目次

ユーザーはどこにいるのか

Kubernetes には User オブジェクトがない。apiserver はリクエストに付いた認証情報から username と group を取り出して使うだけ。

認証方法usernamegroup
X.509 クライアント証明書CNO (複数可)
ServiceAccount tokensystem:serviceaccount:<ns>:<name>system:serviceaccounts、system:serviceaccounts:<ns>
OIDC など設定した claim設定した claim

だから「ユーザー jane を作る」というのは、CN=jane の証明書をクラスタ CA に署名してもらうこと。RBAC binding の subject kind: User、name: jane はこの文字列と照合されるだけ。

CSR でユーザー証明書を発行

1. 鍵と CSR を作る

openssl genrsa -out jane.key 2048
openssl req -new -key jane.key -out jane.csr -subj "/CN=jane/O=dev-team"

2. CertificateSigningRequest オブジェクト

apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: jane
spec:
  request: <base64 < jane.csr | tr -d "\n" の結果>
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400
  usages:
    - client auth
フィールド値
requestPEM の CSR ファイルを base64 で 1 行に
signerNameユーザーのクライアント証明書は kubernetes.io/kube-apiserver-client
usagesclient auth
expirationSeconds任意。上の例は 24 時間

3. 承認と証明書の取り出し

kubectl get csr jane
# NAME   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
# jane   kubernetes.io/kube-apiserver-client   kubernetes-admin   24h                 Pending

kubectl certificate approve jane
kubectl get csr jane            # CONDITION: Approved,Issued

kubectl get csr jane -o jsonpath='{.status.certificate}' | base64 -d > jane.crt
openssl x509 -in jane.crt -noout -subject -issuer
# subject=O = dev-team, CN = jane
# issuer=CN = kubernetes
  • 拒否は kubectl certificate deny jane
  • Approved だけで Issued が付かないなら signer が署名していない。kubeadm クラスタでは controller-manager が署名する

kubeconfig

kubeconfig は 3 つの部分: clusters (どこへ)、users (誰として)、contexts (2 つの組み合わせ + デフォルト namespace)。

kubectl config set-credentials jane \
  --client-key=jane.key --client-certificate=jane.crt --embed-certs=true
kubectl config set-context jane --cluster=kubernetes --user=jane --namespace=dev
kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
          jane                          kubernetes   jane               dev
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin
  • --embed-certs=true: ファイルパスの代わりに中身を kubeconfig に入れる。付けないとパスだけ保存される
  • 別の kubeconfig ファイルを作るなら --kubeconfig=jane.kubeconfig を付け、set-cluster で server のアドレスと CA も入れる必要がある
  • kubectl config use-context jane で切り替え、1 回だけなら kubectl --context jane ...
$ kubectl --context jane auth whoami
Username   jane
Groups     [dev-team system:authenticated]

権限を与える前は、認証は通るが認可で止められる。

$ kubectl --context jane get pods
Error from server (Forbidden): pods is forbidden: User "jane" cannot list resource "pods" in API group "" in the namespace "dev"

Forbidden (403) なら認証は通っている。Unauthorized (401) なら証明書や token から問題。

Role と ClusterRole の組み合わせ

kubectl create role pod-reader -n dev --verb=get,list,watch --resource=pods
kubectl create rolebinding jane-pod-reader -n dev --role=pod-reader --user=jane
Role の種類Binding の種類効果
RoleRoleBindingその namespace の中だけ
ClusterRoleRoleBindingClusterRole のルールを RoleBinding がある namespace の中だけで
ClusterRoleClusterRoleBindingすべての namespace + クラスタスコープのリソース
RoleClusterRoleBinding不可

ClusterRole + RoleBinding ではクラスタスコープのリソース (nodes、PV、namespace など) を与えられない。実際に試した。

kubectl create clusterrole node-reader --verb=get,list --resource=nodes
kubectl create rolebinding jane-nodes -n dev --clusterrole=node-reader --user=jane
kubectl --context jane get nodes
# Error from server (Forbidden): nodes is forbidden: User "jane" cannot list resource "nodes" in API group "" at the cluster scope

kubectl create clusterrolebinding jane-nodes --clusterrole=node-reader --user=jane
kubectl --context jane get nodes     # 成功

subject の種類:

kubectl create rolebinding ... --user=jane
kubectl create rolebinding ... --group=dev-team                  # 証明書の O フィールド
kubectl create rolebinding ... --serviceaccount=dev:ci           # <namespace>:<name>

デフォルトの ClusterRole

ClusterRole用途備考
cluster-adminすべてClusterRoleBinding ならクラスタ全体、RoleBinding ならその namespace 全体
adminnamespace 管理者Role/RoleBinding を作成可能。ResourceQuota と namespace 自体は変更不可
editほとんどの読み書きRole、RoleBinding は変更不可
view読み取りSecret を除く

dev-team group に view を ClusterRoleBinding で与えてみた:

リクエスト結果
get deploy -n kube-system許可
get secrets -n kube-systemForbidden (view は Secret を除く)
get nodesForbidden (view は namespace のリソースだけ)
kubectl create sa ci -n dev
kubectl create rolebinding ci-edit -n dev --clusterrole=edit --serviceaccount=dev:ci
kubectl auth can-i create deploy -n dev --as=system:serviceaccount:dev:ci        # yes
kubectl auth can-i create rolebinding -n dev --as=system:serviceaccount:dev:ci   # no

aggregated ClusterRole

aggregationRule がある ClusterRole には、label selector に合う他の ClusterRole の rules を controller が自動でまとめて入れる。自分で書いた rules は上書きされる。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
    - matchLabels:
        rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # controller が埋める
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-endpoints
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
rules:
  - apiGroups: [""]
    resources: ["services", "endpoints", "pods"]
    verbs: ["get", "list", "watch"]
$ kubectl get clusterrole monitoring -o jsonpath='{.rules}'
[{"apiGroups":[""],"resources":["services","endpoints","pods"],"verbs":["get","list","watch"]}]

デフォルトの admin、edit、view もこの方式。CRD の権限をデフォルトの role に差し込むときに使う label:

$ kubectl get clusterrole admin -o jsonpath='{.aggregationRule}'
{"clusterRoleSelectors":[{"matchLabels":{"rbac.authorization.k8s.io/aggregate-to-admin":"true"}}]}

rbac.authorization.k8s.io/aggregate-to-view: "true"、aggregate-to-edit、aggregate-to-admin。

権限の確認

kubectl auth can-i list pods -n dev --as jane                     # yes
kubectl auth can-i create pods -n dev --as jane                   # no
kubectl auth can-i list pods -n dev --as bob --as-group dev-team  # group の権限だけ確認
kubectl auth can-i --list -n dev --as jane
pods    []   []   [get list watch]
nodes   []   []   [get list]

--list の結果には、デフォルトの binding ですべての認証済みユーザーが受け取る権限 (selfsubjectaccessreviews など) や CNI が追加した権限も混ざって出る。

binding の変更

RoleBinding の roleRef は変更できない。

$ kubectl patch rolebinding jane-pod-reader -n dev --type=merge \
    -p '{"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"view"}}'
The RoleBinding "jane-pod-reader" is invalid: roleRef: Invalid value: ...: cannot change roleRef

role を変えるには binding を消して作り直す。subjects は変更できる。

紛らわしいものの比較

比較AB
証明書の CN vs Ousernamegroup
kube-apiserver-client signer vs kubelet-serving などユーザー/クライアント証明書。手動で承認kubelet 用。kubelet がリクエストする
CSR の Approved vs Issued人が承認signer が署名して status.certificate に入れる
set-credentials vs set-contextuser の項目 (鍵、証明書)cluster + user + namespace の組み合わせ
ClusterRole + RoleBinding vs + ClusterRoleBindingその namespace の中。クラスタのリソースは不可全体 + クラスタのリソース
edit vs adminRBAC オブジェクトは変更不可namespace 内の Role/RoleBinding を変更可能
401 vs 403認証失敗認証成功、権限なし

試験のポイント

速く解くコマンド

openssl genrsa -out u.key 2048
openssl req -new -key u.key -out u.csr -subj "/CN=u/O=g"
cat u.csr | base64 | tr -d "\n"
kubectl certificate approve u
kubectl get csr u -o jsonpath='{.status.certificate}' | base64 -d > u.crt
kubectl config set-credentials u --client-key=u.key --client-certificate=u.crt --embed-certs=true
kubectl config set-context u --cluster=kubernetes --user=u

kubectl create role|clusterrole <name> --verb=... --resource=...
kubectl create rolebinding|clusterrolebinding <name> --role|--clusterrole=... --user|--group|--serviceaccount=...
kubectl auth can-i <verb> <resource> [-n ns] --as <user> [--as-group <group>]
  • CSR の YAML は公式ドキュメント「Certificate Signing Requests」の normal user の例をコピーして request だけ変えると速い
  • --resource の subresource は pods/log のように書く

kubectl explain

kubectl explain csr.spec            # request, signerName, usages, expirationSeconds
kubectl explain clusterrole.aggregationRule
kubectl explain rolebinding.subjects

参考ドキュメント