kubernetes RBAC認証をやってみる
概要
ロールベースのアクセス制御 (RBAC:Role-based access controlの) は、組織内の個々のユーザーの役割に基づいて、
システムへのアクセス権限を管理する仕組みたいですね。
RBACの仕組みを考える上で、必要な知識をざっくり理解してから設定を試してみたいと思います。
環境
- minikube version: v1.32.0
- Kubernetes v1.28.3
- Ubuntu 22.04.4 LTS(WSL)
RBACの前提知識
RBACには、ユーザに必要なKubernetes操作(API)権限を付与するものです。
なので、ユーザとKubernetes操作(API)がどんなものが理解しないと
どんな権限(Role)を設定していいかわからないと思います。
まず、「Kubernetesのユーザ」「KubernetesのAPI」をざっくり理解しましょう。
Kubernetesのユーザとは
Kubernetesクラスターには、ユーザーが「サービスアカウント」と「通常のユーザー」の2種類あります。
サービスアカウントはシステム間のやり取り用(CDCIツールとかはこれ)、
通常のユーザーは人間用(kubectlコマンドの操作はこれ)ですね。
詳しくは公式ドキュメントを参照してください。
KubernetesのAPIとは
概要
Kubernetesは、すべての操作とコンポーネント間の通信、および外部ユーザーのコマンドは、
REST API にて操作を行っています。
詳しくは以下ドキュメントを参照してください。
RBACでルールを設定するには、このAPIの仕様をある程度理解した方がいいので、
もう少しだけKubernetes API の理解を深めていきましょう。
Kubernetesの API形式は?
REST API呼び出しなので、全てのリソースはURL形式でアクセスできるパスがあります。
すべてのリソース タイプは、クラスター ( /apis/GROUP/VERSION/*
) または、
名前空間 ( /apis/GROUP/VERSION/namespaces/NAMESPACE/*
) の形式のようです。
詳しくは以下ドキュメントを参照してください。
リソース タイプのざっくりとした一覧はここが参考になります。
また、リソースは全てAPIグループ配下にあります。主なグループは以下になります。
- core(legacyとも呼ばれる)グループは、RESTパス
/api/v1
にある - 名前付きのグループは、RESTパス
/apis/$GROUP_NAME/$VERSION
にある
詳細はここで確認ください。
リソース(Pod)がどのグループを使っているのかは”kubectl api-resources ”コマンドで確認することができます。
詳細は過去に書いたこの記事を参照してください。
https://0222-nnn.com/kubernetes-kubectl-api-resources-コマンドでapi-リソースを調べてみる/#st-toc-h-11
リソースの詳細なURL(API)はここで確認できます。
KubernetesのAPIリソースに対する操作は?
Kubernetes API は、HTTP 経由で提供されるリソースベース (RESTful) のプログラム インターフェースなので
標準の HTTP メソッドのPOST、PUT、PATCH、DELETE、GET にてリソースの取得、作成、更新、削除による操作を行います。
詳細はここで確認ください。
KubernetesのRBACとは?
KubernetesのRBACを設定するには、「認可」「オブジェクト」「権限」の知識が必要になります。
この点をざっくり理解していきましょう。
Kubernetesの認可とは?
Kubernetes APIへのアクセスコントロールは、ユーザ認証(Authentication)を確認後、
リクエストのリソースに対して認可(Authorization)されているか確認します。
Kubernetes API サーバーでは、認可(Authorization)がいくつか存在しており、
RBACとは、Kubernetes API サーバーのいくつかある認可モードのうちの1つです。
詳細はここで確認ください。
KubernetesのRBACのオブジェクとは?
RBACでは、「Role」「ClusterRole」「RoleBinding」「ClusterRoleBinding」の
4種類のオブジェクトがあります。
Role、ClusterRole には、権限のセットを表すルールが含まれています。
権限はホワイトリスト(許可)方式でブラックリスト(拒否)方式はありません。
RoleBinding、ClusterRoleBindingは、ロール(Role、ClusterRole )で定義された権限を
ユーザー又はサービスアカウントに紐づけ保持します。
4種類(Role、ClusterRole、 RoleBinding、ClusterRoleBinding)の主な違いは以下です。
オブジェクト | 説明 |
---|---|
ClusterRole | 任意の Namespace またはクラスタ全体に適用できる一連の権限。 |
Role | 1 つの Namespace に制限されている一連の権限。 |
RoleBinding | Roleまたは ClusterRoleを特定の Namespace 内のユーザーやサービスアカウントにバインドします。 |
ClusterRoleBinding | クラスタ内のすべての Namespace のユーザーやサービスアカウントにClusterRoleをバインドします。 |
主な用途としては、Namespace 内でロールを定義する場合は Role を使用し、
クラスター全体でロールを定義する場合は ClusterRole を使用します。
ちなみに、Role と ClusterRole は似ていますが、Kubernetes のオブジェクトは Namespace に属するか、属さないかのいずれかであるため、両者は別々に定義されています。
詳細はここで確認ください。
RoleとClusterRoleの操作権限について
Kubernetesでは、APIリソースに対する操作は、HTTP メソッド(POST、PUT、PATCH、DELETE、GET )にて実行しますが、これをAPI verbsと呼ぶようです。
Kubernetes API の get, create, update, patch, delete, proxy は、それぞれ特定の1つのリソースに対して操作を行います。
一方、list は複数のリソースの一覧を取得し、watch はリソースの状態の変化をリアルタイムで監視します。deletecollection は、特定の条件に合致する複数のリソースを一括で削除する操作です。
HTTPメソッドとAPI verbs を一覧にすると以下のようになります。
HTTP メソッド | request verb | kubectl 例 |
---|---|---|
POST | create | kubectl create XX |
GET, HEAD | get (個別リソース) | kubectl get po XX |
list (リソースの一覧) | kubectl get po | |
watch (リソースの変更監視) | kubectl get po XX --watch | |
PUT | update | kubectl replace XX |
PATCH | patch | kubectl patch XX |
DELETE | delete (個別リソース) | kubectl delete XX |
deletecollection (リソースの一括削除) | kubectl delete XX |
詳細はここで確認ください。
Kubernetesの操作権限は、このapiGroups、resources、verbsを組み合わせたルールをRole又はClusterRoleで設定します。
ルール設定に必要なapiGroups、resources、verbsは"kubectl api-resources”コマンドを使えば、簡単に確認できます。
- コマンド例
kubectl api-resources --namespaced=true # 名前空間付きのすべてのリソースを表示します
kubectl api-resources --namespaced=false # 名前空間のないすべてのリソースを表示します
kubectl api-resources -o wide # すべてのリソースを拡張された形(別名 "wide")で表示します
kubectl api-resources --api-group=apps # "apps" APIグループのすべてのリソースを表示します
- 実行例
tech-0222@MSI:~$ kubectl api-resources --namespaced=true
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
tech-0222@MSI:~$ kubectl api-resources --namespaced=false
NAME SHORTNAMES APIVERSION NAMESPACED KIND
componentstatuses cs v1 false ComponentStatus
namespaces ns v1 false Namespace
nodes no v1 false Node
persistentvolumes pv v1 false PersistentVolume
tech-0222@MSI:~$ kubectl api-resources -o wide
NAME SHORTNAMES APIVERSION NAMESPACED KIND VERBS
CATEGORIES
bindings v1 true Binding create
componentstatuses cs v1 false ComponentStatus get,list
configmaps cm v1 true ConfigMap create,delete,deletecollection,get,list,patch,update,watch
endpoints ep v1 true Endpoints create,delete,deletecollection,get,list,patch,update,watch
events ev v1 true Event create,delete,deletecollection,get,list,patch,update,watch
limitranges limits v1 true LimitRange create,delete,deletecollection,get,list,patch,update,watch
namespaces ns v1 false Namespace create,delete,get,list,patch,update,watch
tech-0222@MSI:~$ kubectl api-resources --api-group=apps
NAME SHORTNAMES APIVERSION NAMESPACED KIND
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
tech-0222@MSI:~$
詳しくは、以下を確認してください。
RBACをやってみる
事前準備
Role作成し設定するにはユーザが必要になりますので、試験用にサービスアカウントと
RoleとClusterRoleの違いを確認するためテスト用のnamespacesも用意します。
また、権限を確認する為にテスト用のPodを起動します。
※crulによるAPIの操作を試したい場合は、Podを作成してください。
- namespace
tech-0222@MSI:~$ kubectl create ns test-ns
namespace/test-ns created
# 確認
tech-0222@MSI:~$ kubectl get ns test-ns
NAME STATUS AGE
test-ns Active 7s
tech-0222@MSI:~$
- service account
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl create sa test-sa-role -n test-ns
serviceaccount/test-sa-role created
tech-0222@MSI:~$ kubectl create sa test-sa-cluster-role
serviceaccount/test-sa-cluster-role created
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl create sa test-sa-cluster-role-mics
serviceaccount/test-sa-cluster-role-mics created
tech-0222@MSI:~$
#確認
tech-0222@MSI:~$ kubectl get sa
NAME SECRETS AGE
default 0 11d
test-sa-cluster-role 0 4d17h
test-sa-cluster-role-mics 0 1s
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl get sa -n test-ns test-sa-role
NAME SECRETS AGE
test-sa-role 0 60s
tech-0222@MSI:~$
- pod
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl run test-pod-role --image=nginx -n test-ns
pod/test-pod-role created
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl run test-pod-cluster-role --image=nginx
pod/test-pod-cluster-role created
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl get po -n test-ns
NAME READY STATUS RESTARTS AGE
test-pod-role 1/1 Running 0 29s
tech-0222@MSI:~$ kubectl get po
NAME READY STATUS RESTARTS AGE
test-pod-cluster-role 1/1 Running 0 13s
tech-0222@MSI:~$
Kubernetesの RBACでRoleを作成してみる
テスト用で作成したリソースを使ってnamespace:test-nsのPodに対してGet、listだけを実行できるルールを作成してみます。
例
- コマンド
#作成
tech-0222@MSI:~$ kubectl create role test-role --resource=pods --verb=get,list -n test-ns
role.rbac.authorization.k8s.io/test-role created
tech-0222@MSI:~$
#確認
tech-0222@MSI:~$ kubectl get role -n test-ns test-role -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role
namespace: test-ns
resourceVersion: "314694"
uid: 5e7ce931-4780-4d8f-b2f1-384b43200d85
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
tech-0222@MSI:~$
- yaml 形式で作成したい際には、以下結果をファイルに書き出してから作成しましょう
tech-0222@MSI:~$ kubectl create role test-role --resource=pods --verb=get,list -n test-ns --dry-run=client -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: test-role
namespace: test-ns
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
tech-0222@MSI:~$
Roleの設定は以下と「kubectl create role --help」コマンドが参考になります。
Kubernetesの RBACでClusterRoleを作成してみる
Cluster全体でPODに対してだけ全ての権限があるルールを作成してみます。
例
- コマンド
tech-0222@MSI:~$ kubectl create clusterrole test-cluster-role --resource=pods --verb=*
clusterrole.rbac.authorization.k8s.io/test-cluster-role created
tech-0222@MSI:~$
#あとでテストするようで同じルールで名前が違うClusterRoleを作成します
tech-0222@MSI:~$ kubectl create clusterrole test-cluster-role-mics --resource=pods --verb=*
clusterrole.rbac.authorization.k8s.io/test-cluster-role-mics created
tech-0222@MSI:~$
#確認
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl get clusterrole test-cluster-role -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-cluster-role
resourceVersion: "315265"
uid: 29677ae2-4183-47aa-9cc8-e60077728ec8
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- '*'
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl get clusterrole test-cluster-role-mics -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-cluster-role-mics
resourceVersion: "315505"
uid: 4ee69c3a-fdae-4f7b-8c70-e286c3df4b63
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- '*'
tech-0222@MSI:~$
ClusterRoleを設定する際には、以下と「kubectl create clusterrole --help」コマンドが参考になります。
Kubernetesの RBACでRoleBinding と ClusterRoleBindingを作成してみる
作成したRole とClusterRole を service account にセット(Binding)してみましょう。
- コマンド(Role+RoleBindingの組み合わせ)
tech-0222@MSI:~$ kubectl create rolebinding test-role-binding --role=test-role --serviceaccount=test-ns:test-sa-role -n test-ns
rolebinding.rbac.authorization.k8s.io/test-role-binding created
#確認
tech-0222@MSI:~$ kubectl get rolebindings.rbac.authorization.k8s.io -n test-ns test-role-binding -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-role-binding
namespace: test-ns
resourceVersion: "331922"
uid: 5a5b074a-62a7-4473-b54a-bdc7d8fcdc2e
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: test-role
subjects:
- kind: ServiceAccount
name: test-sa-role
namespace: test-ns
tech-0222@MSI:~$
- コマンド(ClusterRole+ClusterRoleBindingの組み合わせ)
tech-0222@MSI:~$ kubectl create clusterrolebinding test-cluster-role-binding --clusterrole=test-cluster-role --serviceaccount=default:test-sa-cluster-role
clusterrolebinding.rbac.authorization.k8s.io/test-cluster-role-binding created
tech-0222@MSI:~$
#確認
tech-0222@MSI:~$ kubectl get clusterrolebindings.rbac.authorization.k8s.io test-cluster-role-binding -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-cluster-role-binding
resourceVersion: "332209"
uid: d9762ca6-57ea-4a7b-af86-079d6cf8098a
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: test-cluster-role
subjects:
- kind: ServiceAccount
name: test-sa-cluster-role
namespace: default
tech-0222@MSI:~$
- コマンド(ClusterRole+RoleBindingの組み合わせ)
tech-0222@MSI:~$ kubectl create rolebinding test-cluster-role-mics-role-binding --clusterrole=test-cluster-role-mics --serviceaccount=default:test-sa-cluster-role-mics
rolebinding.rbac.authorization.k8s.io/test-cluster-role-mics-role-binding created
tech-0222@MSI:~$
#確認
tech-0222@MSI:~$ kubectl get rolebindings.rbac.authorization.k8s.io test-cluster-role-mics-role-binding -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-cluster-role-mics-role-binding
namespace: default
resourceVersion: "332384"
uid: 05c97a32-a754-4341-90b6-02a5e26a4857
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: test-cluster-role-mics
subjects:
- kind: ServiceAccount
name: test-sa-cluster-role-mics
namespace: default
tech-0222@MSI:~$
RoleBinding と ClusterRoleBindingを設定する際には、以下と「kubectl create rolebinding --help」「 kubectl create clusterrolebinding --help」コマンドが参考になります。
KubernetesのRole とClusterRole 設定を確認してみる
作成したRole設定の操作権限は、kubectl auth can-i コマンドで確認できます。
ただし、このコマンドはデフォルトでkubectlを実行中するユーザーの権限しか確認できません。
--as-uid オプションを使えば、別ユーザー(例えば、作成したサービスアカウント)の
権限で確認することができますので、今回はこれを使ってみます。
今回ロールを設定したユーザは、サービスアカウントなので形式は「system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)」で指定します。
- コマンド(Role+RoleBindingの組み合わせ)
- 想定
- namespace:test-nsのPodに対してGet、listが実行できる
- 想定
#Roleで許可したものだけ結果がYESになっているので成功!
tech-0222@MSI:~$ kubectl auth can-i list pods --as=system:serviceaccount:test-ns:test-sa-role -n test-ns
yes
tech-0222@MSI:~$ kubectl auth can-i get pods --as=system:serviceaccount:test-ns:test-sa-role -n test-ns
yes
#Roleで許可していない結果はがNOになっている
tech-0222@MSI:~$ kubectl auth can-i create pods --as=system:serviceaccount:test-ns:test-sa-role -n test-ns
no
tech-0222@MSI:~$ kubectl auth can-i patch pods --as=system:serviceaccount:test-ns:test-sa-role -n test-ns
no
tech-0222@MSI:~$ kubectl auth can-i delete pods --as=system:serviceaccount:test-ns:test-sa-role -n test-ns
no
tech-0222@MSI:~$
#NamespaceがないとPodでもエラーとなっているので想定通り
tech-0222@MSI:~$ kubectl auth can-i get pods --as=system:serviceaccount:test-ns:test-sa-role
no
tech-0222@MSI:~$
- コマンド(ClusterRole+ClusterRoleBindingの組み合わせ)
- 想定
- PODにだけ全ての権限を実行できる
- 想定
#ClusterRole で許可した通りPodに対して権限がOK+ネームスペースの指定なくても問題なし
tech-0222@MSI:~$ kubectl auth can-i list pods --as=system:serviceaccount:default:test-sa-cluster-role
yes
tech-0222@MSI:~$ kubectl auth can-i get pods --as=system:serviceaccount:default:test-sa-cluster-role
yes
tech-0222@MSI:~$ kubectl auth can-i create pods --as=system:serviceaccount:default:test-sa-cluster-role
yes
tech-0222@MSI:~$ kubectl auth can-i patch pods --as=system:serviceaccount:default:test-sa-cluster-role
yes
tech-0222@MSI:~$
#許可していないリソースだとNGになる
tech-0222@MSI:~$ kubectl auth can-i patch deploy --as=system:serviceaccount:default:test-sa-cluster-role
no
tech-0222@MSI:~$ kubectl auth can-i patch configmaps --as=system:serviceaccount:default:test-sa-cluster-role
no
tech-0222@MSI:~$
- コマンド(ClusterRole+RoleBindingの組み合わせ)
- 想定
- PODに対してだけ全ての権限を実行できるが、対象はnamespace:defaultだけ
- 想定
#許可しているリソース+指定ネームスペースだと正常
tech-0222@MSI:~$ kubectl auth can-i create pods --as=system:serviceaccount:default:test-sa-cluster-role-mics -n default
yes
tech-0222@MSI:~$ kubectl auth can-i get pods --as=system:serviceaccount:default:test-sa-cluster-role-mics -n default
yes
tech-0222@MSI:~$ kubectl auth can-i list pods --as=system:serviceaccount:default:test-sa-cluster-role-mics -n default
yes
tech-0222@MSI:~$
#許可していないリソースやネームスペースだとNGの結果
tech-0222@MSI:~$ kubectl auth can-i list pods --as=system:serviceaccount:default:test-sa-cluster-role-mics -n test-ns
no
tech-0222@MSI:~$ kubectl auth can-i list deploy --as=system:serviceaccount:default:test-sa-cluster-role-mics -n default
no
tech-0222@MSI:~$
詳細は以下ドキュメントや「kubectl auth can-i —help」コマンドが参考になります。
また、サービスアカウントのフォーマットはここが参考になります。
ちなみに、ServiceAccountはTokenを発行してcurlでAPIを呼び出すこともでき、
この方法を使えば、実際にリソースの作成や確認をAPIで行えます。
curlでAPIを呼び出して操作する詳細は過去の記事のここを参考にしてください。
今回は考えなかったRBAC のベスト プラクティスについて
今回の記事では触れませんでしたが、権限設計はセキュリティに直結するため、ベストプラクティスを参考にしっかり設計を検討した方がいいですね。