KubernetesクラスタRBAC監査 は何をしますか?
使用するタイミング
- Kubernetesクラスタ(EKS、GKE、AKS、またはセルフマネージド)のセキュリティ評価を実施するとき
- RBACポリシーがユーザーやサービスアカウントに対して最小権限を適用しているかを検証するとき
- Kubernetesクラスタ内での潜在的ラテラルムーブメントや特権昇格を調査するとき
- コンプライアンス監査でアクセス制御と権限の文書化が必要なとき
- 新しいチームを共有クラスタにオンボーディングし、適切なRBACポリシーを定義するとき
使用しないでください: ネットワークポリシーの監査(CiliumやCalicoのネットワークポリシーツールを使用)、コンテナイメージスキャン(TrivyやGrypeを使用)、ランタイムセキュリティ監視(FalcoやSysdig Secureを使用)には使用しないでください。
前提条件
- kubectlがターゲットクラスタに対してクラスタ管理者または同等の読み取り権限で設定されていること
- rbac-toolがインストールされていること(
kubectl krew install rbac-toolまたはGitHubからバイナリをダウンロード) - KubiScanがインストールされていること(
pip install kubiscan) - Kubeauditがインストールされていること(
brew install kubeauditまたはGitHubリリースからダウンロード) - RBACの調査結果と実際のAPIアクセスを関連付けるために、クラスタの監査ログへアクセスできること
ワークフロー
ステップ1: 危険な権限を持つClusterRoleとRoleを列挙する
ワイルドカード権限、シークレットアクセス、Pod exec、昇格機能を持つロールを特定します。
# ワイルドカード動詞アクセスを持つすべてのClusterRoleを一覧表示
kubectl get clusterroles -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for role in data['items']:
name = role['metadata']['name']
for rule in role.get('rules', []):
verbs = rule.get('verbs', [])
resources = rule.get('resources', [])
if '*' in verbs or '*' in resources:
print(f'ClusterRole: {name}')
print(f' Verbs: {verbs}')
print(f' Resources: {resources}')
print(f' API Groups: {rule.get(\"apiGroups\", [])}')
print()
"
# シークレットを読み取れるロールを検索
kubectl get clusterroles -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for role in data['items']:
name = role['metadata']['name']
for rule in role.get('rules', []):
resources = rule.get('resources', [])
verbs = rule.get('verbs', [])
if ('secrets' in resources or '*' in resources) and ('get' in verbs or 'list' in verbs or '*' in verbs):
if not name.startswith('system:'):
print(f'ClusterRole: {name} -> can access secrets (verbs: {verbs})')
"
# Pod exec権限を持つロールを検索(コンテナエスケープリスク)
kubectl get clusterroles -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for role in data['items']:
name = role['metadata']['name']
for rule in role.get('rules', []):
resources = rule.get('resources', [])
if 'pods/exec' in resources or 'pods/*' in resources:
print(f'ClusterRole: {name} -> has pods/exec access')
"
ステップ2: ClusterRoleBindingとRoleBindingを監査する
誰が昇格されたアクセス権を持っているかを特定し、過度に広範なグループ割り当てを検出するためにバインディングを確認します。
# すべてのClusterRoleBindingとそのサブジェクトを一覧表示
kubectl get clusterrolebindings -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for binding in data['items']:
name = binding['metadata']['name']
role = binding['roleRef']['name']
subjects = binding.get('subjects', [])
for subject in subjects:
kind = subject.get('kind', '')
subj_name = subject.get('name', '')
ns = subject.get('namespace', 'cluster-wide')
print(f'{name} -> Role: {role} | {kind}: {subj_name} ({ns})')
" | sort
# cluster-adminへのバインディングを検索
kubectl get clusterrolebindings -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for binding in data['items']:
if binding['roleRef']['name'] == 'cluster-admin':
print(f\"Binding: {binding['metadata']['name']}\")
for subject in binding.get('subjects', []):
print(f\" {subject.get('kind')}: {subject.get('name')} (ns: {subject.get('namespace', 'N/A')})\")
"
# 認証済み全ユーザーにアクセス権を付与するバインディングを検索
kubectl get clusterrolebindings -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for binding in data['items']:
for subject in binding.get('subjects', []):
if subject.get('name') in ['system:authenticated', 'system:unauthenticated']:
print(f\"WARNING: {binding['metadata']['name']} grants {binding['roleRef']['name']} to {subject['name']}\")
"
ステップ3: rbac-toolで包括的な分析を実行する
who-canクエリやポリシー生成を含む、自動化されたRBAC分析にrbac-toolを使用します。
# すべての名前空間でシークレットを取得できるユーザー
kubectl rbac-tool who-can get secrets
# Podを作成できるユーザー(コンテナエスケープの可能性)
kubectl rbac-tool who-can create pods
# Podにexecできるユーザー
kubectl rbac-tool who-can create pods/exec
# 特権を昇格できるユーザー(bind/escalate動詞)
kubectl rbac-tool who-can bind clusterroles
kubectl rbac-tool who-can escalate clusterroles
# RBACポリシーレポートを生成
kubectl rbac-tool analysis
# RBAC関係を可視化
kubectl rbac-tool viz --outformat dot > rbac-graph.dot
dot -Tpng rbac-graph.dot -o rbac-graph.png
ステップ4: KubiScanでリスクのある権限を検出する
KubiScanを使用して、リスクのあるサービスアカウント、Pod、RBAC設定を自動的に特定します。
# KubiScanを実行してリスクのあるロールを検出
python3 -m kubiscan -rroles # リスクのあるRoleを一覧表示
python3 -m kubiscan -rcr # リスクのあるClusterRoleを一覧表示
python3 -m kubiscan -rrb # リスクのあるRoleBindingを一覧表示
python3 -m kubiscan -rcrb # リスクのあるClusterRoleBindingを一覧表示
# リスクのあるサービスアカウントを検出
python3 -m kubiscan -rs # リスクのあるサービスアカウント
# リスクのあるサービスアカウントで実行中のPodを検出
python3 -m kubiscan -rp # リスクのあるPod
# 特権昇格パスを確認
python3 -m kubiscan -pe # 特権昇格ベクター
# 完全なレポートを生成
python3 -m kubiscan -a # すべてのチェック
ステップ5: サービスアカウントトークンのマウントと使用状況を監査する
侵害されたPodからのラテラルムーブメントを可能にする可能性のある、不要なサービスアカウントトークンマウントを確認します。
# 自動マウントされたサービスアカウントトークンを持つPodを検索
kubectl get pods --all-namespaces -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for pod in data['items']:
name = pod['metadata']['name']
ns = pod['metadata']['namespace']
sa = pod['spec'].get('serviceAccountName', 'default')
automount = pod['spec'].get('automountServiceAccountToken', True)
if automount and sa != 'default':
print(f'{ns}/{name} -> SA: {sa} (token auto-mounted)')
"
# デフォルト以外のトークンシークレットを持つサービスアカウントを検索
kubectl get serviceaccounts --all-namespaces -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for sa in data['items']:
name = sa['metadata']['name']
ns = sa['metadata']['namespace']
secrets = sa.get('secrets', [])
if name != 'default' and len(secrets) > 0:
print(f'{ns}/{name}: {len(secrets)} secret(s) bound')
"
# 特権モードまたはホストアクセスで実行されているPodを確認
kubectl get pods --all-namespaces -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for pod in data['items']:
name = pod['metadata']['name']
ns = pod['metadata']['namespace']
for container in pod['spec'].get('containers', []):
sc = container.get('securityContext', {})
if sc.get('privileged', False) or sc.get('runAsUser', 1) == 0:
print(f'RISK: {ns}/{name}/{container[\"name\"]} - privileged={sc.get(\"privileged\",False)} runAsRoot={sc.get(\"runAsUser\",\"not set\")==0}')
"
ステップ6: KubeauditでRBACとセキュリティポリシーを検証する
RBAC関連の調査結果を含む包括的なセキュリティチェックのためにKubeauditを実行します。
# すべてのkubeauditチェックを実行
kubeaudit all --kubeconfig ~/.kube/config
# 特定のRBAC関連チェックを実行
kubeaudit privesc # allowPrivilegeEscalationを確認
kubeaudit rootfs # readOnlyRootFilesystemを確認
kubeaudit nonroot # runAsNonRootを確認
kubeaudit capabilities # 危険なcapabilitiesを確認
# 処理のためにJSONとして出力
kubeaudit all --kubeconfig ~/.kube/config -f json > kubeaudit-results.json
主要な概念
| 用語 | 定義 |
|---|---|
| RBAC | Kubernetesにおけるロールベースアクセス制御。個々のユーザーやサービスアカウントのロールに基づいてクラスタリソースへのアクセスを制御する方法 |
| ClusterRole | クラスタ全体のロール定義。すべての名前空間に適用されるリソースに対する権限(動詞)を指定する |
| ClusterRoleBinding | ClusterRoleをクラスタスコープでサブジェクト(ユーザー、グループ、サービスアカウント)に関連付ける |
| Service Account | Kubernetes APIサーバーへの認証のためにPodに関連付けられるID。無効にしない限り自動的にマウントされる |
| automountServiceAccountToken | サービスアカウントトークンをPodファイルシステムに自動マウントするかどうかを制御するPodスペックフィールド |
| Privilege Escalation | ユーザーが自分自身や他者に昇格された権限を付与できるようにするRBAC動詞(bind、escalate、impersonate) |
ツールとシステム
- kubectl: Kubernetes RBACリソース(ロール、バインディング、サービスアカウント)をクエリするための主要なCLI
- rbac-tool: who-canクエリ、可視化、ポリシー生成を含むRBAC分析用のkubectlプラグイン
- KubiScan: Kubernetes RBACでリスクのある権限や特権昇格パスをスキャンするPythonツール
- Kubeaudit: PodとワークロードをRBAC問題を含むセキュリティアンチパターンについてチェックするセキュリティ監査ツール
- rakkess: 現在のユーザーのすべてのリソースタイプに対するアクセスマトリックスを表示するkubectlプラグイン
一般的なシナリオ
シナリオ: 複数の開発チームが共有するEKSクラスタの監査
コンテキスト: 共有EKSクラスタが4つの開発チームにサービスを提供しています。RBACは初期設定時に構成されましたが、12か月間レビューされていません。チームは他のチームの名前空間にアクセスできると報告しています。
アプローチ:
- すべてのClusterRoleBindingを一覧表示し、認証済みユーザーに広範なアクセス権を付与するバインディングを特定する
kubectl rbac-tool who-can get secretsを実行し、名前空間をまたいでシークレットを読み取れるサブジェクトを検索する- ClusterRoleBindingが
editをsystem:authenticatedに付与しており、すべてのユーザーにクラスタ全体の書き込みアクセス権があることを発見する - KubiScanを実行し、リスクのある権限を持つサービスアカウントと、昇格されたサービスアカウントで実行されているPodを特定する
- ClusterRoleBindingを各チームの名前空間スコープのRoleBindingに置き換える
- APIアクセスを必要としないワークロードに対してautomountServiceAccountTokenを無効にする
- チーム間の名前空間トラフィックを分離するためのNetworkPolicyを作成する
落とし穴: ClusterRoleBindingを削除すると、クラスタ全体のアクセスに依存するCI/CDパイプラインやオペレーターが壊れる可能性があります。バインディングを削除する前に、どのワークロードがそのバインディングを使用しているかを常に監査してください。EKSはaws-auth ConfigMapを介してIAMロールをKubernetesグループにマッピングするため、RBACの変更はIAMロールのマッピングと調整する必要があります。
出力形式
Kubernetes RBAC Audit Report
===============================
Cluster: production-eks (EKS 1.28)
Audit Date: 2026-02-23
Namespaces: 12
RBAC INVENTORY:
ClusterRoles: 48 (18 custom, 30 system)
ClusterRoleBindings: 32 (12 custom, 20 system)
Roles (namespaced): 24
RoleBindings (namespaced): 36
Service Accounts: 67
CRITICAL FINDINGS:
[RBAC-001] ClusterRoleBinding Grants edit to system:authenticated
Binding: authenticated-edit
Effect: ALL authenticated users have edit access across ALL namespaces
Risk: Any user can modify resources in any namespace
Remediation: Replace with namespace-scoped RoleBindings per team
[RBAC-002] Custom ClusterRole with Wildcard Permissions
ClusterRole: developer-admin
Rules: verbs=["*"], resources=["*"], apiGroups=["*"]
Bindings: 4 users via developer-admin-binding
Risk: Equivalent to cluster-admin without the name
Remediation: Scope to specific resources and verbs needed
SUMMARY:
Principals with cluster-admin: 6 (recommended: <= 3)
Roles with wildcard permissions: 4
Service accounts with secret access: 12
Pods with auto-mounted tokens: 45 / 67
Privileged containers: 8