名前は同じなのに権限が違う
目標
サービスアカウントreader1つにRole・RoleBinding・ClusterRole・ClusterRoleBindingを順番に付けながら、権限がどこまで(ネームスペース/クラスター)、そして何まで(動詞・リソース)及ぶのかを、kubectl auth can-i --asで直接確認します。トークンの自動マウントを無効にする方法もあわせて見ます。
なぜ重要なのか
KubernetesのAPIサーバーに入ってくるすべてのリクエストは、「誰が(主体)何を(動詞)どこに(リソース・ネームスペース)」で判定されます。RBACには許可リストしかなく、拒否ルールがないため、権限はバインディングが増えるほど和集合としてしか大きくなりません。同じ名前のreaderでも、どのバインディングがどの範囲に付いているかによって、できることがまったく変わります。
Roleは1つのネームスペース内でのみ有効で、ノードのようにネームスペースのないリソースは、ClusterRoleとClusterRoleBindingでしか権限を与えられません。また、Podはデフォルトでサービスアカウントのトークンを受け取るため、APIを使わないPodでこれを無効にするのが、最小権限の第一歩です。
ステップ
- ネームスペース
kcna-rbacとサービスアカウントreaderを作成してください。 - Role
pod-viewer(podsのget/list/watch)とRoleBindingreader-podsを作成してください。 - 同じ権限が
defaultネームスペースでは通用しないことを確認し、scope.txtに書いてください。 - 別のRole
cm-viewer(configmapsのget/list)とRoleBindingreader-cmsを作成してください。 - ClusterRole
node-viewerとClusterRoleBindingreader-nodesで、ノードの参照を許可してください。 - Pod
appをreaderで動かしますが、トークンの自動マウントは無効にしてください。 - readerがPodを作成したり、ワイルドカード権限を使ったりできないことを確認し、
write-check.txtに書いてください。 - 4つのcan-iの結果を
/root/kcna-rbac/report.txtに帳簿として残してください。
参考
- サービスアカウントになりすますとき、主体名は
system:serviceaccount:<네임스페이스>:<이름>の形式です(プレースホルダーはネームスペースと名前です)。 kubectl auth can-i --list -n kcna-rbac --as=...で、その主体が持つ権限の全体を見られます。- 公式ドキュメント: RBAC認可の使用・RBACのベストプラクティス
権限のない新入社員のアカウントが到着する
ネームスペースkcna-rbacを作成し、その中にサービスアカウントreaderを作成してください。
サービスアカウントは、人ではないワークロードがAPIサーバーに自分を名乗るための身元です。ネームスペースに属するオブジェクトなので、先にネームスペースを作成する必要があります。createを--dry-run=client -o yamlで出力してapplyすれば、何度実行しても安全です。作成直後のreaderには、権限がまったくありません。
Podを見せるだけで、削除はさせない
ネームスペースkcna-rbacにRolepod-viewerを作成してください。ルールは、コアグループ("")のpodsに対するget・list・watch、ただそれだけでなければなりません。そしてRoleBindingreader-podsで、このRoleをサービスアカウントkcna-rbac:readerに結び付けてください。
RBACには許可しかなく、拒否はありません。Roleは「何ができるか」のリストで、RoleBindingは、そのリストを「誰に」与えるかを決めます。PodはコアAPIグループなので、apiGroupsは空文字列です。kubectl create roleの--verb/--resource、kubectl create rolebindingの--role/--serviceaccount(形式はネームスペース:名前)オプションを調べてみてください。確認はkubectl auth can-i <동사> pods --as=system:serviceaccount:<ns>:<이름>で行います(プレースホルダーは動詞とサービスアカウント名です)。
隣のネームスペースでは何も見えない
新しいオブジェクトは作成しません。readerがdefaultネームスペースでPodをlistできるかをkubectl auth can-iで確認し、その結果を/root/kcna-rbac/scope.txtにlist-pods-default=<yes|no>の1行で書いてください。
RoleとRoleBindingはネームスペースに属します。そのため、その権限はバインディングのあるネームスペース内でのみ有効です。-nの値だけを変えて、同じ質問を2回投げてみてください。推測で書かず、can-iが返した値をそのまま写してください。
権限は付け足すのではなく、別に結び付ける
既存のpod-viewerには手を触れず、ネームスペースkcna-rbacに別のRolecm-viewerを作成してください。ルールは、コアグループのconfigmapsに対するget・listです。RoleBindingreader-cmsでreaderに結び付けてください。readerはConfigMapをlistできますが、deleteはできない状態でなければなりません。
1つの主体に複数のバインディングが付くと、権限は和集合になります。そのため、役割を用途別に細かく分けておくと、あとで1つだけ外しやすくなります。pod-viewerにconfigmapsを紛れ込ませると、採点ツールに検出されます。ステップ2と同じ方法で、役割とバインディングを1つずつ作ればよいです。
ノードはネームスペースの外にある
ClusterRolenode-viewer(コアグループのnodesに対するget・list)を作成し、ClusterRoleBindingreader-nodesでサービスアカウントkcna-rbac:readerに結び付けてください。readerがノードをlistできる状態にしてください。
ノード・PV・StorageClassのようなクラスタースコープのリソースはネームスペースがないため、Roleでは権限を与えられません。ClusterRoleをRoleBindingで結び付けても、範囲は1つのネームスペース内に絞られるだけなので、ノードを見るにはClusterRoleBindingが必要です。kubectl create clusterrolebindingの--clusterroleオプションを見てください。ノードに対するcan-iには-nを付けません。
APIを使わないPodに鍵を持たせない
ネームスペースkcna-rbacにPodapp(イメージnginx:1.27-alpine)を作成してください。このPodはサービスアカウントreaderで動かしますが、サービスアカウントのトークンが自動でマウントされないよう、automountServiceAccountTokenをfalseにしてください。
Podはデフォルトで、自分のサービスアカウントのトークンをkube-api-access-*ボリュームとして受け取ります。コンテナが突破されると、そのトークンでAPIを呼び出せてしまうので、APIを使わないPodはトークンを受け取らないほうが望ましいです。Podのspecに、serviceAccountNameとautomountServiceAccountTokenの2つのフィールドを一緒に書いてください。kubectl get pod app -o yamlで、volumesにkube-api-accessがないかも確認してみてください。
読み取り専用のアカウントがPodを作成しようとしたら
readerがネームスペースkcna-rbacでPodをcreateできるか、そしてすべてのリソースにすべての動詞(ワイルドカード)を使えるかを、kubectl auth can-iで確認してください。どちらもnoでなければなりません。Podのcreateの結果を、/root/kcna-rbac/write-check.txtにcreate-pods=<yes|no>の1行で書いてください。
ここまでに与えた動詞は、get・list・watchだけです。createは、別に許可しない限り拒否されます。ワイルドカードの質問は、リソースと動詞の位置に、引用符で囲んだアスタリスクを入れて投げられます。ここでyesが返るなら、前のステップで権限を広く与えすぎているので、Roleのルールを見直してください。
readerの権限マップを帳簿に残す
readerの権限を/root/kcna-rbac/report.txtに、ちょうど4行で書いてください。list-pods-in-ns=yes、list-pods-in-default=no、list-nodes=yes、create-pods=noです。値は、実際のkubectl auth can-iの結果と一致している必要があります。
採点ツールは、各行を、サービスアカウントreaderになりすました実際のcan-iの結果と照合します。4つの質問は、それぞれkcna-rbacのpodsのlist、defaultのpodsのlist、クラスタースコープのnodesのlist、kcna-rbacのpodsのcreateです。自分で尋ねた答えを写してください。