【実務・中級編】 Kubernetes RBACにおける最小権限の原則とClusterRoleの過剰付与リスク – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

お疲れ様。最近、クラウドネイティブなインフラの設計レビューをしていて、一番頭が痛くなるのがKubernetesの権限周りのガバナンス不足なんだよね。

「とりあえず動くようにする」という魔力に負けて、ClusterRole に resources: ["*"] や verbs: ["*"] なんていうワイルドカードをぶち込んでいるYAMLを見ると、セキュリティチーフとしては血の気が引く。あれは、自宅の玄関の鍵を開け放して、リビングの真ん中に「どうぞご自由にお金を持っていってください」と札を立てているようなものだからね。

今回は、Kubernetes環境におけるRBAC(Role-Based Access Control)の罠、特に過剰な権限付与が招く地獄と、それを現場でどうねじ伏せるかについて、実戦の知見を交えて解説しよう。

—

1. 攻撃者はどう狙う?ワイルドカードと特権昇格の悪夢

Kubernetesの設計において、開発チームの利便性を優先するあまり、次のような ClusterRole を作成してしまうケースが後を絶たない。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: overly-permissive-developer
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]

この設定の何が危険か。もし、この強力な権限を持つサービスアカウントやユーザーのトークンが、万が一アプリケーションの脆弱性(例えば、不完全なSSRFやコンテナのRCE)を通じて外部に漏洩したとしよう。

攻撃者は、Kubernetes APIサーバーへ直接リクエストを飛ばし、集群全体のマスターノードを含むすべてのリソースを掌握する。さらに厄介なのが、Kubernetes特有の特権昇格(Privilege Escalation)を招く2つの動詞、escalate と bind だ。

escalate と bind という名のパンドラの箱

  • escalate 権限: ユーザーが、自分が持っている権限よりも強力な権限を持つ Role や ClusterRole を作成・変更できるようになる。つまり、実質的に「全権限への昇格チケット」を自分で発行できるようになる。
  • bind 権限: 既存の強力なロール(例えば cluster-admin)を、任意のサービスアカウントやユーザーに紐付ける(Bindingする)ことを許可する。

これらがワイルドカード(*)や不適切なスコープ設定によって付与されていると、攻撃者は瞬時にクラスタの管理者権限(cluster-admin)を手に入れ、すべてのシークレット(DBのパスワードや外部APIの認証情報)を抜き取り、マイニング用のコンテナをばら撒く。インシデントレスポンスの現場で、これをやられたら復旧には数日〜数週間、下手をすれば企業の社会的信用が吹き飛ぶ。

—

2. 最小権限の原則(PoLP)に基づく設計アプローチ

では、現場のエンジニアとしてどう防ぐべきか。答えはシンプルで、「必要最小限のNamespaceに、必要最小限のリソースと動詞だけを許可する」ことだ。

1. ClusterRoleの乱用をやめる: クラスタ全体に影響する操作が本当に必要なシステムコンポーネント以外は、原則として Role と RoleBinding を使い、Namespaceスコープに閉じ込める。
2. 動詞(Verbs)を厳選する: ["*"] は絶対に使わない。本当に get, list, watch だけ景観確認のために必要なのか、あるいは create, update が必要なのかを精査する。
3. escalate と bind を剥奪する: 通常の開発者や一般的なアプリケーション用サービスアカウントに、これらの権限を与える正当な理由は存在しない。

—

3. 【実践】セキュアなRBACマニフェスト実装例

それでは、具体的なコードで示そう。以下は、特定のNamespace(例: production-app)において、アプリケーションの監視やヘルスチェックを行うためのサービスアカウントに対し、必要最低限の権限(Podの参照および特定のConfigMapの更新のみ)を安全に付与するKubernetesマニフェストのサンプルだ。

このYAMLは、そのままコピーして検証環境に適用できる。

apiVersion: v1
kind: Namespace
metadata:
  name: production-app
---
# アプリケーション監視・運用のための専用サービスアカウント
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-operator-sa
  namespace: production-app
  labels:
    security.example.com/hardened: "true"
---
# Namespaceスコープに限定したRoleの定義
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-operator-role
  namespace: production-app
rules:
  # 1. Podの状態確認(get, list, watch)のみを許可。deleteやcreateは含まない。
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]

  # 2. ConfigMapは動的な設定変更のため update を許可するが、削除(delete)や作成(create)は禁止する。
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["app-runtime-config"] # 特定のConfigMapだけに操作を限定
    verbs: ["get", "list", "update"]

  # ※ 注意: apiGroupsに "*", resourcesに "*", verbsに "escalate" や "bind" は絶対に含まない。
---
# RoleとServiceAccountを紐付けるRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-operator-binding
  namespace: production-app
subjects:
- kind: ServiceAccount
  name: app-operator-sa
  namespace: production-app
roleRef:
  kind: Role
  name: app-operator-role
  apiGroup: rbac.authorization.k8s.io

この設定のポイントは、resourceNames を使って操作できるリソースの名称まで限定している点だ。これにより、万が一サービスアカウントの権限が悪用されても、影響範囲を特定の ConfigMap 1つにまで絞り込むことができる。

—

4. 現場のセキュリティチェックリスト

リリース前のCI/CDパイプラインや、K8sマニフェストのレビュー時には、必ず以下の項目をチェックしてほしい。

  • [ ] ClusterRole または Role の rules[*].verbs に * が含まれていないか?
  • [ ] apiGroups や resources に * を指定して、意図しないリソースへのアクセスを許していないか?
  • [ ] 開発者向け、あるいはアプリ用のロールに escalate や bind 権限が混入していないか?
  • [ ] クラスタ全体を見渡す権限が必要な場合を除き、すべて Role と RoleBinding(Namespaceスコープ)で設計されているか?
  • [ ] kube-bench などのツールや、OPA/Gatekeeper、Kyvernoなどのポリシーエンジンを使って、過剰な権限を持つマニフェストのデプロイを自動検知・ブロックする仕組みを入れているか?

セキュリティは「面倒くさい」と感じた瞬間からほころびが生じる。しかし、インフラの根幹であるKubernetesの権限管理を怠ると、一撃で会社が傾くレベルの踏み台事故につながる。

「動けばいいや」の精神を捨て、今日から君のプロジェクトのRBACを厳格に締め直してくれ。頼んだよ!

コメント

タイトルとURLをコピーしました