審計 GCP IAM 權限 是做什麼的?
使用時機
- 執行 GCP 組織或專案 IAM 組態安全評估時
- 識別具有過多權限或未使用存取權的服務帳戶時
- 合規要求需要審查存取控制與角色指派時
- 調查因 IAM 組態錯誤可能導致的橫向移動時
- 縮小受損憑證的爆炸半徑,透過限制權限範圍時
請勿使用 於 VPC 防火牆規則審計(請使用網路安全工具)、GKE RBAC 審計(請使用 Kubernetes 專用 RBAC 工具),或 IAM 動作的即時威脅偵測(請使用 SCC 事件威脅偵測)。
先決條件
- GCP 組織或專案,需具備
roles/iam.securityReviewer與roles/cloudAsset.viewer角色 - 已驗證的 gcloud CLI,且具備適當權限
- 已啟用 Cloud Asset API(
gcloud services enable cloudasset.googleapis.com) - 已啟用 IAM Recommender API(
gcloud services enable recommender.googleapis.com) - 已啟用 Policy Analyzer API(
gcloud services enable policyanalyzer.googleapis.com)
工作流程
步驟 1:列舉整個組織的 IAM 綁定
列出組織、資料夾與專案層級的所有 IAM 綁定,以了解完整的存取範圍。
# 組織層級 IAM 綁定
gcloud organizations get-iam-policy ORG_ID \
--format=json > org-iam-policy.json
# 搜尋整個組織中的所有 IAM 政策
gcloud asset search-all-iam-policies \
--scope=organizations/ORG_ID \
--format="table(resource, policy.bindings.role, policy.bindings.members)" \
--limit=500
# 找出所有擁有 Owner 角色的使用者與服務帳戶
gcloud asset search-all-iam-policies \
--scope=organizations/ORG_ID \
--query="policy:roles/owner" \
--format="table(resource, policy.bindings.members)"
# 找出所有使用原始角色 (Owner, Editor, Viewer) 的綁定
gcloud asset search-all-iam-policies \
--scope=organizations/ORG_ID \
--query="policy:roles/owner OR policy:roles/editor" \
--format=json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for result in data:
resource = result.get('resource', '')
for binding in result.get('policy', {}).get('bindings', []):
role = binding.get('role', '')
if role in ['roles/owner', 'roles/editor']:
for member in binding.get('members', []):
print(f'{resource} | {role} | {member}')
"
步驟 2:稽核服務帳戶及其金鑰
識別具有過多權限、使用者管理金鑰及未使用帳戶的服務帳戶。
# 列出專案中的所有服務帳戶
gcloud iam service-accounts list \
--project=PROJECT_ID \
--format="table(email, displayName, disabled)"
# 檢查使用者管理的金鑰(應盡量減少)
for sa in $(gcloud iam service-accounts list --project=PROJECT_ID --format="value(email)"); do
keys=$(gcloud iam service-accounts keys list \
--iam-account="$sa" \
--managed-by=user \
--format="table(name.basename(),validAfterTime,validBeforeTime)")
if [ -n "$keys" ]; then
echo "=== $sa ==="
echo "$keys"
fi
done
# 找出所有專案中具有管理員角色的服務帳戶
gcloud asset search-all-iam-policies \
--scope=organizations/ORG_ID \
--query="policy.bindings.members:serviceAccount AND (policy:roles/owner OR policy:roles/editor OR policy:admin)" \
--format="table(resource, policy.bindings.role, policy.bindings.members)"
# 檢查服務帳戶的 IAM 政策(誰可以假冒)
for sa in $(gcloud iam service-accounts list --project=PROJECT_ID --format="value(email)"); do
echo "=== $sa ==="
gcloud iam service-accounts get-iam-policy "$sa" --format=json 2>/dev/null
done
步驟 3:使用 IAM Recommender 識別過多權限
利用 GCP 的 IAM Recommender 找出授予比實際使用更多存取權限的角色。
# 列出專案的 IAM 角色建議
gcloud recommender recommendations list \
--project=PROJECT_ID \
--recommender=google.iam.policy.Recommender \
--location=global \
--format="table(name, description, priority, stateInfo.state)"
# 取得詳細建議
gcloud recommender recommendations describe RECOMMENDATION_ID \
--project=PROJECT_ID \
--recommender=google.iam.policy.Recommender \
--location=global \
--format=json
# 列出 IAM 使用洞察
gcloud recommender insights list \
--project=PROJECT_ID \
--insight-type=google.iam.policy.Insight \
--location=global \
--format="table(name, description, severity, category)"
# 套用建議(審查後)
gcloud recommender recommendations mark-claimed RECOMMENDATION_ID \
--project=PROJECT_ID \
--recommender=google.iam.policy.Recommender \
--location=global \
--etag=ETAG
步驟 4:使用 Policy Analyzer 分析有效權限
使用 Policy Analyzer 判斷特定主體或資源的有效存取權限。
# 檢查誰可以存取特定資源
gcloud asset analyze-iam-policy \
--organization=ORG_ID \
--full-resource-name="//storage.googleapis.com/projects/_/buckets/sensitive-data-bucket" \
--format="table(identityList.identities, accessControlLists.accesses.role)"
# 檢查特定使用者可以存取哪些資源
gcloud asset analyze-iam-policy \
--organization=ORG_ID \
--identity="user:[email protected]" \
--format="table(accessControlLists.resources.fullResourceName, accessControlLists.accesses.role)"
# 檢查誰可以執行特定動作
gcloud asset analyze-iam-policy \
--organization=ORG_ID \
--full-resource-name="//cloudresourcemanager.googleapis.com/projects/PROJECT_ID" \
--permissions="iam.serviceAccounts.actAs,iam.serviceAccountKeys.create" \
--format="table(identityList.identities, accessControlLists.accesses.permission)"
# 找出所有具有 allUsers 或 allAuthenticatedUsers 存取權的主體
gcloud asset search-all-iam-policies \
--scope=organizations/ORG_ID \
--query="policy:allUsers OR policy:allAuthenticatedUsers" \
--format="table(resource, policy.bindings.role, policy.bindings.members)"
步驟 5:檢查網域委派與假冒風險
識別具有網域委派與假冒能力的服務帳戶。
# 檢查具有網域委派的服務帳戶
# (需要 Admin SDK 存取權以列出委派帳戶)
gcloud iam service-accounts list --project=PROJECT_ID --format=json | python3 -c "
import json, sys
accounts = json.load(sys.stdin)
for sa in accounts:
email = sa.get('email', '')
# 檢查服務帳戶是否啟用了網域委派
# 這需要 Admin SDK API 存取權
print(f'SA: {email} - Check admin.google.com for delegation status')
"
# 找出其他身分可以假冒的服務帳戶
for sa in $(gcloud iam service-accounts list --project=PROJECT_ID --format="value(email)"); do
policy=$(gcloud iam service-accounts get-iam-policy "$sa" --format=json 2>/dev/null)
if echo "$policy" | python3 -c "
import json, sys
p = json.load(sys.stdin)
for b in p.get('bindings', []):
if b['role'] in ['roles/iam.serviceAccountTokenCreator', 'roles/iam.serviceAccountUser']:
print(f' {b[\"role\"]}: {b[\"members\"]}')
" 2>/dev/null; then
echo "=== 假冒風險:$sa ==="
fi
done
步驟 6:產生稽核報告並套用補救措施
彙整發現結果並實施建議的權限縮減。
# 移除原始角色並取代為預先定義角色
gcloud projects remove-iam-policy-binding PROJECT_ID \
--member="user:[email protected]" \
--role="roles/editor"
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="user:[email protected]" \
--role="roles/compute.viewer"
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="user:[email protected]" \
--role="roles/storage.objectViewer"
# 刪除未使用的服務帳戶金鑰
gcloud iam service-accounts keys delete KEY_ID \
--iam-account=SA_EMAIL
# 停用未使用的服務帳戶
gcloud iam service-accounts disable SA_EMAIL --project=PROJECT_ID
主要概念
| 術語 | 定義 |
|---|---|
| 原始角色 | 傳統 GCP 角色 (Owner, Editor, Viewer),授予跨所有服務的廣泛權限,不建議用於生產環境 |
| 預先定義角色 | GCP 管理的角色,限定於特定服務與動作,提供比原始角色更精細的存取控制 |
| IAM Recommender | GCP 基於機器學習的服務,分析實際權限使用情況,並建議角色縮減以達成最小權限 |
| Policy Analyzer | 用於分析整個組織層級中有效 IAM 存取的工具,可回答誰可以存取什麼的問題 |
| 服務帳戶金鑰 | 服務帳戶驗證的使用者管理憑證,屬於安全風險,因為金鑰可被匯出且不會自動過期 |
| 網域委派 | 授予服務帳戶假冒 Google Workspace 網域中任何使用者的能力,是重大的權限提升風險 |
工具與系統
- gcloud CLI:查詢與管理 GCP IAM 政策、服務帳戶與角色綁定的主要工具
- IAM Recommender:基於機器學習的建議引擎,根據實際使用情來減少過多權限
- Policy Analyzer:組織層級的有效存取分析工具,用於了解誰可以存取什麼
- Cloud Asset Inventory:跨專案搜尋 IAM 政策與資源中繼資料的工具
- ScoutSuite:多雲端稽核工具,具備 GCP IAM 專用檢查功能,可審查角色指派與服務帳戶
常見情境
情境:減少 GCP 組織中原始角色的使用
背景:稽核發現組織中 60% 的 IAM 綁定使用了原始角色 (Owner/Editor)。安全團隊需要遷移到預先定義角色,同時不中斷開發人員的工作流程。
方法:
- 執行
gcloud asset search-all-iam-policies盤點所有原始角色綁定 - 使用 IAM Recommender 取得基於機器學習的替代預先定義角色建議
- 針對每個綁定,使用 Policy Analyzer 了解主體實際存取的資源
- 建立對應文件:原始角色 -> 所需的特定預先定義角色
- 在測試期間,同時套用預先定義角色與原始角色
- 使用 Cloud Audit Logs 監控存取遭拒錯誤
- 在確認兩週內無存取問題後,移除原始角色
陷阱:原始角色包含所有 GCP 服務的權限,因此取代它們需要多個預先定義角色。如果觀察期間未涵蓋所有使用案例,Recommender 可能建議過於嚴格的角色。當沒有預先定義角色符合所需確切權限集時,自訂角色可以填補缺口。
輸出格式
GCP IAM 權限稽核報告
===================================
組織:acme-org (ORG_ID: 123456789)
已稽核專案:25
稽核日期:2026-02-23
IAM 綁定摘要:
綁定總數: 342
使用原始角色: 205 (60%)
使用預先定義角色: 112 (33%)
使用自訂角色: 25 (7%)
重大發現:
[IAM-001] 具有 Owner 角色的服務帳戶
SA: [email protected]
角色:roles/owner (角色於專案 prod-project)
使用者管理金鑰:3 (最舊:14 個月)
補救措施:以特定預先定義角色取代,刪除舊金鑰
[IAM-002] allAuthenticatedUsers 綁定
資源:gs://public-data-bucket
角色:roles/storage.objectViewer
風險:任何 Google 帳戶持有者均可讀取儲存桶內容
補救措施:限制為特定使用者群組或服務帳戶
服務帳戶健康狀態:
服務帳戶總數: 67
有使用者管理金鑰: 23
金鑰超過 90 天: 18
未使用帳戶 (90+ 天): 12
具有網域委派: 2
Recommender 建議:
建議總數: 45
優先級高: 12
預計減少的權限數量: 2,847 個個別權限