開發堅固的 Grafana 安全防護網:GCP IAP 與 Gateway API 整合實戰
在管理現代雲端基礎設施時,監控工具的安全性與可靠性至關重要。Grafana 作為熱門的監控視覺化平台,時常成為企業關鍵基礎設施的一部分。然而,近年來 Grafana 相關的 CVE 漏洞頻繁出現,讓安全團隊不得不尋找更強大的保護方案。
玄貓在多家企業的雲端安全架構設計過程中發現,結合 Google Cloud Identity-Aware Proxy (IAP) 與 Gateway API 的方案能提供優異的防護效果。今天就來分享如何透過 Terraform 自動化這套安全架構的建置流程。
安全架構的優勢與挑戰
在深入技術細節前,讓我們先了解這套架構的價值與可能遇到的挑戰。
架構優勢
- 流量安全閘道:所有進入 Grafana 的流量都會經過 GCP IAP 審查與過濾,大幅降低 Grafana CVE 漏洞被利用的風險
- 情境感知存取控制:可根據裝置信任狀態、網路位置、使用者群組等條件實施精細的存取策略
- DDoS 攻擊防護:受益於 Google 雲端的防護機制,有效抵禦分散式阻斷服務攻擊
- 完整稽核日誌:所有存取行為都會記錄詳細日誌,便於安全分析與合規要求
- 零信任架構整合:與現代零信任安全模型完美契合,實作身分驗證與授權的分離
潛在挑戰
- API 使用複雜化:透過程式化方式存取 Grafana API 變得較為複雜,因為請求必須透過 IAP 層
- 工具相容性:某些原生工具(如 Grafana Terraform Provider)可能無法直接使用,需要採取替代方案:
- 從內部網路連線到 Grafana 內部端點
- 使用臨時的 Kubernetes port-forward 將工具連線到本地主機(雖然需要額外步驟,但設定只需幾秒鐘)
前置需求
在開始整合前,請確保您已具備:
- 運作中的 Kubernetes 叢集
- 已設定好的 Ingress 或 Gateway 控制器
- 安裝並設定好的 Terraform 與 gcloud CLI 工具
原始碼參考
所有實作的完整原始碼可於 [此 GitHub 儲存函式庫https://github.com/vidbregar/grafana-gcp-iap) 取得,建議在執行下列步驟時參考。
設定 OAuth 授權畫面
這個步驟必須在 GCP 控制檯手動完成,但每個 GCP 專案只需執行一次:
- 開啟 Identity-Aware Proxy 頁面
- 點選「CONFIGURE CONSENT SCREEN」(設定同意畫面)
- 選擇「Internal」(內部)使用者類別
- 填寫必要欄位,並新增授權網域(例如,若 Grafana 網址為
grafana.example.com
,則新增example.com
)
在實務應用中,玄貓發現這個步驟經常被忽略,導致後續整合遇到困難。請務必確認 OAuth 設定完成並符合組織政策。
Grafana 設定調整
為了讓 Grafana 能與 GCP IAP 正確整合,需要調整其設定檔。以下是關鍵的 grafana.ini
設定:
grafana.ini:
...
database:
type: postgres
host: "<資料函式庫>:5432"
name: grafana
user: grafana
# password: "" # 從 GF_DATABASE_PASSWORD 環境變數取得
users:
allow_sign_up: false
allow_org_create: true
auto_assign_org: true
auto_assign_org_id: 1
auto_assign_org_role: Viewer
verify_email_enabled: false
default_theme: dark
viewers_can_edit: false
editors_can_admin: false
auth:
disable_login_form: true
# GCP IAP 設定
auth.jwt:
enabled: true
auto_sign_up: true
header_name: "X-Goog-Iap-Jwt-Assertion"
username_claim: "email"
email_claim: "email"
jwk_set_url: "https://www.gstatic.com/iap/verify/public_key-jwk"
expect_claims: '{"iss": "https://cloud.google.com/iap"}'
skip_org_role_sync: true
auth.google:
enabled: false
...
這裡最關鍵的是 auth.jwt
部分,它讓 Grafana 能夠識別並信任來自 GCP IAP 的 JWT 令牌,從而實作無縫的身分驗證。玄貓在實際佈署時發現,若未正確設定 expect_claims
,可能導致身分驗證失敗,因此特別留意這個引數。
使用 Helm 佈署 Grafana
接下來,使用 Terraform 的 Helm Provider 來佈署 Grafana:
resource "helm_release" "grafana" {
name = "grafana"
repository = "https://grafana.github.io/helm-charts"
chart = "grafana"
version = "8.8.1" # 對應 Grafana 版本 11.4.0
wait = false
atomic = true
force_update = false
namespace = "monitoring"
create_namespace = true
values = [file("${path.module}/file/values.yaml")]
# 其他設定...
}
在 values.yaml
中,可以進一步自訂 Grafana 的設定,例如資源限制、持久化儲存、服務帳號等。玄貓建議在生產環境中至少設定適當的資源請求與限制,以確保 Grafana 的穩定執行。
透過 Gateway 暴露服務
目前 Grafana Helm 圖表 對 Gateway 路由的支援較為有限。為了實作更靈活的設定,我們佈署額外的 Gateway Helm
resource "helm_release" "gateway" {
name = "grafana-gateway"
namespace = "monitoring"
chart = "${path.module}/grafana-gateway"
wait = false
force_update = false
atomic = true
# 其他設定...
}
關鍵在於 GCPBackendPolicy,它為 Gateway 新增 GCP IAP 支援:
spec:
default:
iap:
enabled: true
oauth2ClientSecret:
name: "grafana-oauth-secret"
OAuth 客戶端則透過 Terraform 建立,並傳遞給 Gateway Helm
resource "google_iap_client" "grafana" {
display_name = "Grafana"
brand = "projects/XXXXXXXXXXXX/brands/XXXXXXXXXXXX"
}
在實際佈署中,玄貓發現 brand ID 是最容易出錯的部分。確保使用正確的 GCP 專案 ID 和品牌 ID,可以透過 gcloud CLI 查詢:
gcloud iap oauth-brands list --project=YOUR_PROJECT_ID
授權存取設定
當 Kubernetes 資源應用後,GCP 會在背景自動建立一個 Backend Service。要授權存取,需要將適當的主體(使用者或群組)附加到這個 Backend Service。
目前,由於 Backend Service 的名稱是動態生成的,沒有直接的 Terraform 資源可以優雅地處理這個問題。不過,我們可以使用以下變通方法:
resource "google_iap_web_backend_service_iam_member" "member" {
project = var.project
web_backend_service = (
reverse(
split("/",
[for x in split(", ",
data.kubernetes_resource.gateway.object.metadata.annotations["networking.gke.io/backend-services"],
) : x if strcontains(x, "monitoring-grafana-80")][0]
)
)[0]
)
role = "roles/iap.httpsResourceAccessor"
member = "group:grafana-accessors@example.com"
}
這段程式碼從 Gateway 資源的註解中提取 Backend Service 的名稱,並為指定的群組授予存取許可權。這是一個技巧性的解決方案,但在 Terraform 中能有效運作。
實際應用情境與最佳實踐
在協助多家企業實施此架構後,玄貓總結了一些實用的最佳實踐:
1. 分層授權策略
使用 IAP 的優勢在於可以實施精細的授權策略。建議將使用者分為不同層級:
- 管理員:完整的 Grafana 管理許可權,限制特定信任裝置存取
- 開發團隊:編輯許可權,可以建立和修改儀錶板,但無法變更系統設定
- 營運團隊:檢視許可權,僅能檢視儀錶板
2. 備用存取機制
即使 IAP 極為可靠,仍建議設定緊急存取機制:
resource "kubernetes_service" "grafana_internal" {
metadata {
name = "grafana-internal"
namespace = "monitoring"
annotations = {
"cloud.google.com/neg" = "{\"ingress\": false}"
}
}
spec {
selector = {
"app.kubernetes.io/name" = "grafana"
}
port {
port = 3000
target_port = 3000
}
type = "ClusterIP"
}
}
這個內部服務允許在極端情況下,透過 kubectl port-forward 直接存取 Grafana。
3. 監控 IAP 本身
確保 IAP 運作正常同樣重要。建立專門的監控儀錶板追蹤:
- IAP 授權拒絕率
- 身分驗證延遲時間
- 可疑存取模式
常見問題排解
在實施過程中,玄貓經常遇到以下問題:
1. JWT 驗證失敗
症狀:使用者能透過 IAP,但無法登入 Grafana
解決方案:確認 Grafana 的 auth.jwt
設定正確,特別是 expect_claims
欄位
2. Backend Service 未正確建立
症狀:Gateway 佈署成功,但無法透過 IAP 存取 解決方案:檢查 GKE Gateway Controller 日誌,確保 GCP 服務帳號有足夠許可權
3. OAuth 客戶端重定向 URI 錯誤
症狀:身分驗證迴圈或 “redirect_uri_mismatch” 錯誤 解決方案:確保 OAuth 客戶端設定的重定向 URI 與 Gateway 主機名稱比對
隨著 Kubernetes Gateway API 的不斷發展,玄貓預見未來整合會變得更加簡便。特別是以下幾個方向值得關注:
- 多叢集 Gateway 支援:跨多個 GKE 叢集統一管理 Grafana 存取
- Policy Controller 整合:使用 GKE Policy Controller 自動強制執行 IAP 設定
- Workload Identity Federation:進一步增強與 Grafana 之間的身分整合
透過 GCP IAP、Gateway API 和 Terraform 的組合,我們不僅解決了當前的安全需求,也為未來的擴充套件奠定了堅實基礎。這種方法不僅適用於 Grafana,還可以擴充套件到其他需要安全存取的 Kubernetes 服務。
在數位轉型的時代,安全不再是事後考量,而是架構設計的核心要素。希望這篇能幫助您在保障安全的同時,充分發揮 Grafana 的強大監控能力。