審計 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 Releases 下載) - 可存取叢集的稽核日誌,以便將 RBAC 發現與實際 API 存取進行關聯
工作流程
步驟 1:列舉具有危險權限的 ClusterRoles 與 Roles
識別具有萬用字元權限、機密存取、Pod exec 或權限提升能力的角色。
# 列出所有具有萬用字元動詞的 ClusterRoles
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:審計 ClusterRoleBindings 與 RoleBindings
檢視綁定以識別哪些主體具有提升權限,並偵測過度廣泛的群組指派。
# 列出所有 ClusterRoleBindings 及其主體
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 進行全面分析
使用 rbac-tool 進行自動化 RBAC 分析,包括 who-can 查詢與策略生成。
# 誰可以跨所有命名空間取得機密
kubectl rbac-tool who-can get secrets
# 誰可以建立 Pod(可能導致容器逃逸)
kubectl rbac-tool who-can create pods
# 誰可以 exec 進入 Pod
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 # 列出危險 Roles
python3 -m kubiscan -rcr # 列出危險 ClusterRoles
python3 -m kubiscan -rrb # 列出危險 RoleBindings
python3 -m kubiscan -rcrb # 列出危險 ClusterRoleBindings
# 尋找危險的服務帳號
python3 -m kubiscan -rs # 危險的服務帳號
# 尋找使用危險服務帳號執行的 Pod
python3 -m kubiscan -rp # 危險的 Pod
# 檢查權限提升路徑
python3 -m kubiscan -pe # 權限提升向量
# 生成完整報告
python3 -m kubiscan -a # 所有檢查
步驟 5:審計服務帳號 Token 掛載與使用
檢查不必要的服務帳號 Token 掛載,這些掛載可能讓受損的 Pod 進行橫向移動。
# 尋找自動掛載服務帳號 Token 的 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)')
"
# 尋找具有非預設 Token 機密的服務帳號
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 與安全策略
執行 Kubeaudit 進行全面的安全檢查,包含 RBAC 相關發現。
# 執行所有 kubeaudit 檢查
kubeaudit all --kubeconfig ~/.kube/config
# 執行特定的 RBAC 相關檢查
kubeaudit privesc # 檢查 allowPrivilegeEscalation
kubeaudit rootfs # 檢查 readOnlyRootFilesystem
kubeaudit nonroot # 檢查 runAsNonRoot
kubeaudit capabilities # 檢查危險的能力
# 以 JSON 格式輸出以供處理
kubeaudit all --kubeconfig ~/.kube/config -f json > kubeaudit-results.json
關鍵概念
| 術語 | 定義 |
|---|---|
| RBAC | Kubernetes 中以角色為基礎的存取控制,根據使用者或服務帳號的角色來規範叢集資源的存取 |
| ClusterRole | 叢集層級的角色定義,指定跨所有命名空間適用的權限(資源上的動詞) |
| ClusterRoleBinding | 在叢集範圍內將 ClusterRole 與主體(使用者、群組、服務帳號)關聯 |
| Service Account | 與 Pod 關聯的身份,用於向 Kubernetes API 伺服器進行驗證,預設為自動掛載,除非停用 |
| automountServiceAccountToken | Pod 規格欄位,控制服務帳號 Token 是否自動掛載至 Pod 檔案系統 |
| Privilege Escalation | RBAC 動詞(bind、escalate、impersonate),允許使用者為自己或他人授予提升的權限 |
工具與系統
- kubectl:用於查詢 Kubernetes RBAC 資源(角色、綁定、服務帳號)的主要 CLI
- rbac-tool:kubectl 外掛,提供 RBAC 分析,包括 who-can 查詢、視覺化與策略生成
- KubiScan:Python 工具,用於掃描 Kubernetes RBAC 中的危險權限與權限提升路徑
- Kubeaudit:安全審計工具,檢查 Pod 與工作負載是否存在安全反模式,包括 RBAC 問題
- rakkess:kubectl 外掛,顯示目前使用者對所有資源類型的存取矩陣
常見場景
場景:審計由多個開發團隊共用的 EKS 叢集
背景:一個共用 EKS 叢集服務於四個開發團隊。RBAC 在初始設定時已配置,但已有 12 個月未審查。團隊回報能夠存取其他團隊的命名空間。
處理方式:
- 列出所有 ClusterRoleBindings,識別授予已驗證使用者廣泛存取的綁定
- 執行
kubectl rbac-tool who-can get secrets尋找可以跨命名空間讀取機密的主體 - 發現一個 ClusterRoleBinding 將
edit權限授予system:authenticated,使所有使用者擁有叢集層級的寫入存取 - 執行 KubiScan 識別具有危險權限的服務帳號,以及使用提升權限服務帳號執行的 Pod
- 將該 ClusterRoleBinding 替換為每個團隊的命名空間範圍 RoleBindings
- 對不需要 API 存取的工作負載停用 automountServiceAccountToken
- 建立 NetworkPolicy 以隔離團隊間的命名空間流量
陷阱:移除 ClusterRoleBindings 可能導致 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