在容器化應用架構日益普及的今日,機敏資料的安全管理成為開發與維運團隊面臨的重大挑戰。傳統將密碼、API 金鑰、資料庫憑證等敏感資訊直接寫在設定檔或環境變數的做法,不僅增加資料外洩風險,也違反現代資安規範的基本要求。Kubernetes 雖然提供原生的 Secret 物件,但其資料僅以 Base64 編碼儲存在 etcd 中,缺乏完整的加密保護與存取控制機制。HashiCorp Vault 作為業界領先的機敏資料管理平台,提供集中化的機敏資料儲存、動態存取控制、完整的稽核追蹤,以及與 Kubernetes 的深度整合能力。本文將從實務角度出發,詳細說明如何在 Kubernetes 環境中部署與設定 Vault,並探討生產環境所需的高可用性架構設計。
HashiCorp Vault 在 Kubernetes 的部署與基礎操作
建立可靠的機敏資料管理系統,首要任務是正確部署 Vault 服務並掌握基本的操作流程。雖然 Vault 支援多種部署模式,但在 Kubernetes 環境中,透過 Helm Chart 進行部署是最常見且便捷的方式。這種部署方法不僅簡化設定過程,也能充分利用 Kubernetes 的資源管理與自動化能力。然而在實際操作前,理解 Vault 的核心概念與運作機制至關重要,這將有助於後續的設定調整與問題排查。
Vault 服務的啟動與網路連線建立
假設團隊已經透過 Helm 在 Kubernetes 叢集中成功部署 Vault,並且完成初始化與解封流程。解封是 Vault 的重要安全機制,確保系統重啟後需要經過授權才能存取加密的機敏資料。在開發或測試階段,為了方便本地操作與除錯,通常會使用埠轉發技術將叢集內的 Vault 服務映射到本地端點。
透過 kubectl port-forward 指令,可以在本地機器與 Kubernetes Pod 之間建立安全的網路通道。這個指令會將本地的 8200 埠對應到叢集中 vault-0 Pod 的 8200 埠,讓開發者能直接使用 Vault CLI 工具與服務互動,而不需要透過 Kubernetes Service 或 Ingress 進行存取。這種方法特別適合開發階段的快速迭代,但在生產環境中應該改用正式的服務端點與 TLS 加密連線。
kubectl port-forward vault-0 8200:8200
建立埠轉發後,需要設定 Vault CLI 的連線參數。透過環境變數 VAULT_ADDR 指定 Vault 服務的位址,這個變數會被 CLI 工具自動讀取並用於後續所有操作。在本地開發環境中,位址通常設定為 http://0.0.0.0:8200,代表透過本地迴路介面連線到轉發的埠。生產環境則應使用完整的 HTTPS 網址,並配合適當的 TLS 憑證驗證。
身份驗證與機敏資料引擎啟用
Vault 採用嚴格的身份驗證機制,所有操作都需要有效的身份憑證。在初始化階段,系統會產生根令牌,這是擁有最高權限的特殊憑證,能執行所有管理操作。根令牌通常儲存在初始化過程產生的金鑰檔案中,例如 cluster-keys.json,這個檔案包含解封金鑰與根令牌等關鍵資訊,必須妥善保管避免外洩。
實務上會使用 jq 工具從 JSON 檔案中提取根令牌。jq 是強大的命令列 JSON 處理器,能精確解析複雜的 JSON 結構。提取根令牌後,透過 vault login 指令進行身份驗證,成功後 CLI 會取得操作權限並將憑證快取在本地設定檔中,後續指令就不需要重複提供令牌。
export VAULT_ADDR=http://0.0.0.0:8200
VAULT_ROOT_TOKEN=$(jq -r ".root_token" cluster-keys.json)
vault login $VAULT_ROOT_TOKEN
完成身份驗證後,下一步是啟用機敏資料引擎。Vault 採用插件式架構,支援多種類型的機敏資料引擎,各自提供不同的功能特性。Key-Value 引擎是最基礎也最常用的類型,適合儲存靜態的機敏資料如密碼、API 金鑰等。KV 引擎有兩個版本,版本二提供完整的版本控制功能,是目前建議使用的版本。
啟用機敏資料引擎時需要指定掛載路徑,這個路徑決定後續存取機敏資料時的 URL 結構。慣例上會使用 secret 作為路徑名稱,但可以根據組織需求自訂。一個 Vault 實例可以同時啟用多個機敏資料引擎,分別掛載在不同路徑,提供靈活的資料組織方式。
vault secrets enable -path=secret kv-v2
機敏資料的儲存與讀取操作
啟用機敏資料引擎後,就可以開始儲存實際的機敏資料。KV 引擎採用階層式的路徑結構,類似檔案系統的目錄設計。每個機敏資料項目都儲存在特定路徑下,路徑可以包含多層目錄結構,方便依照應用程式或環境進行組織。
儲存機敏資料使用 vault kv put 指令,後面接著完整的路徑與鍵值對。路徑的設計應該具有語意性,讓團隊成員能直觀理解其用途。舉例來說,secret/webapp/config 清楚表示這是 webapp 應用的設定相關機敏資料。一個路徑可以儲存多組鍵值對,形成邏輯上的資料集合,方便批次讀取與管理。
vault kv put secret/webapp/config username="static-user" password="static-password"
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
start
:開發者執行 kubectl port-forward;
:建立本地與 Pod 的網路通道;
:設定 VAULT_ADDR 環境變數;
:從金鑰檔案提取根令牌;
:執行 vault login 驗證身份;
if (驗證成功?) then (是)
:快取憑證到本地設定;
:啟用 KV-v2 機敏資料引擎;
:指定掛載路徑為 secret;
:儲存機敏資料到指定路徑;
:記錄路徑與鍵值對資訊;
stop
else (否)
:顯示驗證失敗錯誤;
stop
endif
@enduml儲存機敏資料後,應該立即驗證讀取功能是否正常運作。在 Kubernetes 叢集環境中,Vault 通常以多節點模式部署,透過 Raft 共識協定同步資料。驗證讀取功能時,可以刻意連線到不同的 Vault Pod,確認資料已經正確複製到所有節點。這個測試步驟雖然簡單,卻能及早發現叢集同步問題或網路設定錯誤。
切換到不同節點的方式同樣是修改埠轉發的目標 Pod。將原本指向 vault-0 的轉發改為 vault-1,即可連線到叢集中的另一個節點。由於先前已經完成身份驗證且憑證快取在本地,不需要重新登入就能直接執行讀取操作。vault kv get 指令會從指定路徑讀取機敏資料,並以結構化的表格格式顯示所有鍵值對。
kubectl port-forward vault-1 8200:8200
vault kv get secret/webapp/config
成功讀取機敏資料時,CLI 會輸出類似下方的結果。輸出分為多個區塊,metadata 區塊包含版本號、建立時間等後設資料,data 區塊則顯示實際的鍵值對內容。這種分離設計讓使用者能同時取得資料內容與版本資訊,方便追蹤機敏資料的變更歷史。
====== Metadata ======
Key Value
--- -----
created_time 2025-11-17T02:30:45.123456Z
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password static-password
username static-user
開發模式與生產模式的架構差異
Vault 提供兩種截然不同的運作模式,分別針對開發測試與正式營運的需求設計。理解這兩種模式的差異至關重要,錯誤的模式選擇可能導致開發效率低落或是生產環境的安全風險。開發模式著重於快速啟動與操作便利性,犧牲部分安全特性換取開發體驗。生產模式則全面強化安全防護,透過嚴謹的初始化流程與加密機制,確保機敏資料在企業環境中的安全性。
開發模式的特性與限制
開發模式的設計理念是讓開發者能快速建立測試環境,專注於應用程式開發而不需要處理複雜的安全設定。這種模式下,Vault 啟動時會自動完成初始化與解封,無需手動輸入解封金鑰。所有資料都儲存在記憶體中,重啟後會完全清空,這種暫時性的特質非常適合測試場景,但絕對不能用於保存重要資料。
開發模式使用單一的解封金鑰,而非生產環境的多重金鑰機制。這簡化了啟動流程,但也意味著缺乏金鑰分散管理的安全保障。此外,開發模式不支援高可用性部署,Vault 以單一實例運行,沒有容錯能力。一旦服務中斷,所有資料都會遺失,且無法自動恢復服務。
這些特性決定開發模式只適用於本地開發環境或臨時測試場景。開發者可以快速啟動 Vault,進行功能驗證與整合測試,完成後直接關閉服務。由於資料不會持久化,也不需要擔心清理測試資料的問題。然而任何需要資料保存或是接近真實環境的測試,都應該改用生產模式進行。
生產模式的安全機制設計
生產模式從根本上重新設計所有的安全機制,確保符合企業級應用的嚴格要求。最顯著的差異在於初始化流程,生產模式需要管理者手動執行初始化指令,系統會產生多個解封金鑰與根令牌。這些金鑰採用 Shamir 秘密分享演算法進行分割,這是密碼學領域的經典演算法,能將一個秘密分割成多個部分,只有收集到足夠數量的部分才能重建原始秘密。
Shamir 演算法的核心概念是門檻方案,管理者可以指定總共產生幾個金鑰分片,以及需要多少分片才能完成解封。典型的設定是產生五個分片,需要其中三個才能解封,這種設計稱為 3-of-5 門檻方案。這種機制提供極高的安全性與可用性平衡,即使遺失兩個分片,系統仍然可以解封;同時單一分片外洩也不會造成安全威脅,因為攻擊者需要取得至少三個分片才能解封 Vault。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "Shamir 秘密分享機制" {
component "主加密金鑰" as master
component "金鑰分片 1" as shard1
component "金鑰分片 2" as shard2
component "金鑰分片 3" as shard3
component "金鑰分片 4" as shard4
component "金鑰分片 5" as shard5
master --> shard1 : 分割
master --> shard2 : 分割
master --> shard3 : 分割
master --> shard4 : 分割
master --> shard5 : 分割
}
component "解封過程" as unseal {
[收集分片]
[門檻驗證]
[重建金鑰]
}
shard1 --> [收集分片]
shard2 --> [收集分片]
shard3 --> [收集分片]
[收集分片] --> [門檻驗證] : 3-of-5
[門檻驗證] --> [重建金鑰] : 門檻達成
[重建金鑰] --> master : 恢復
@enduml金鑰分片的分配策略是生產部署的重要考量。建議將分片分配給不同的管理者,並儲存在不同的安全位置,如硬體安全模組、加密的金鑰管理系統,或是實體保險箱。這種分散管理確保沒有單一個人或系統能獨立解封 Vault,實現職責分離的安全原則。同時也提供災難恢復的保障,即使部分金鑰遺失,只要剩餘的分片數量仍達到門檻,系統就能持續運作。
生產模式的另一個重要特性是持久化儲存。不同於開發模式的記憶體儲存,生產環境會將資料寫入持久化的後端儲存系統。Vault 支援多種儲存後端,包含整合式的 Raft 儲存,以及外部系統如 Consul、etcd、PostgreSQL 等。選擇適當的儲存後端需要考慮效能、可靠性、備份策略等因素,這將在後續章節深入探討。
高可用性架構的設計與實作
企業級的機敏資料管理系統必須具備高可用性,確保服務能持續運作不受單點故障影響。Vault 的高可用性架構建立在叢集化部署與共識協定的基礎上,透過多個節點組成叢集,自動處理故障轉移與資料同步。這種架構不僅提升系統可靠性,也能分散負載提升整體效能。然而高可用性的實現需要仔細的規劃與設定,錯誤的架構選擇可能無法達到預期的可靠性目標。
Raft 共識協定的運作原理
Vault 採用 Raft 作為分散式共識協定,這是經過嚴格證明且廣泛應用的演算法,被許多知名系統如 etcd、Consul 採用。Raft 的設計目標是提供易於理解的共識機制,同時確保資料一致性與系統可用性。在 Raft 叢集中,節點分為 Leader 與 Follower 兩種角色,任何時刻只有一個 Leader 負責處理寫入請求,其他節點作為 Follower 接收並複製 Leader 的資料變更。
當客戶端發送寫入請求時,無論請求到達哪個節點,最終都會被轉發到 Leader 處理。Leader 將變更記錄寫入本地日誌後,會將這個變更複製到所有 Follower 節點。只有當大多數節點確認收到變更後,Leader 才會認為這筆寫入已經完成,並回應客戶端成功。這種多數確認機制確保即使部分節點故障,已確認的資料仍然安全保存在多數節點上。
讀取請求的處理較為靈活,Follower 節點也能直接回應讀取請求,不需要轉發給 Leader。這種設計能有效分散讀取負載,提升系統整體吞吐量。然而需要注意的是,Follower 的資料可能略微落後於 Leader,在極端情況下可能讀到稍舊的版本。對於需要強一致性的場景,可以設定所有讀取都經由 Leader 處理,確保永遠讀到最新的資料。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
actor "客戶端" as client
package "Vault 叢集" {
component "Leader 節點" as leader {
[處理寫入]
[日誌複製]
[狀態機更新]
}
component "Follower 節點 1" as follower1 {
[接收日誌]
[確認複製]
[處理讀取]
}
component "Follower 節點 2" as follower2 {
[接收日誌]
[確認複製]
[處理讀取]
}
}
database "持久化儲存" as storage
client --> leader : 寫入請求
client --> follower1 : 讀取請求
client --> follower2 : 讀取請求
leader --> follower1 : 複製日誌
leader --> follower2 : 複製日誌
follower1 --> leader : 確認收到
follower2 --> leader : 確認收到
leader --> storage : 持久化資料
follower1 --> storage : 持久化資料
follower2 --> storage : 持久化資料
@enduml故障偵測與自動恢復機制
高可用性架構的核心價值在於自動故障恢復,當 Leader 節點發生故障時,叢集必須能快速選出新的 Leader 恢復服務。Raft 透過心跳機制偵測節點健康狀態,Leader 會定期向所有 Follower 發送心跳訊息,表示自己仍在正常運作。如果 Follower 在指定時間內沒有收到心跳,就會認定 Leader 已經故障,啟動選舉程序。
選舉過程中,Follower 會將自己升級為候選人,向其他節點發送投票請求。候選人需要獲得大多數節點的投票才能成為新的 Leader,這確保同一時間只會產生一個 Leader,避免腦裂問題。一旦選舉完成,新的 Leader 會立即開始接收寫入請求並複製資料,整個恢復過程通常在幾秒內完成,對服務的影響降到最低。
建議在不同的實體機器或虛擬機上部署 Vault 節點,進一步提升容錯能力。如果所有節點都運行在同一台主機上,該主機故障會導致整個叢集癱瘓。理想的部署策略是將節點分散在不同的可用區域甚至不同的資料中心,這樣即使整個區域發生災難,叢集仍能在其他區域繼續運作。這種跨區域部署需要考慮網路延遲對共識效能的影響,通常建議叢集節點間的網路延遲不超過數十毫秒。
儲存後端的選擇策略
高可用性部署的另一個關鍵決策是儲存後端的選擇。Vault 的整合式 Raft 儲存提供最簡化的部署模式,不需要額外維護外部儲存系統。整合儲存與 Vault 程序運行在同一個容器中,資料直接寫入掛載的持久化磁碟區,減少網路往返延遲,提升讀寫效能。這種設計也簡化運維複雜度,團隊不需要具備額外儲存系統的專業知識。
外部儲存後端如 Consul 或 etcd 提供獨立的儲存層,能與 Vault 解耦部署。這種架構的優勢在於儲存層可以獨立擴展與維護,不受 Vault 服務影響。某些組織已經有成熟的 Consul 或 etcd 營運經驗,重用現有基礎設施能降低導入成本。然而外部儲存也增加架構複雜度,需要額外管理儲存叢集的健康狀態與資料備份。
對於大多數 Kubernetes 部署場景,建議優先考慮整合式 Raft 儲存。Kubernetes 提供完善的持久化磁碟區管理機制,能確保資料的持久性與可靠性。透過 StatefulSet 部署 Vault,每個 Pod 都會綁定專屬的 PersistentVolumeClaim,即使 Pod 重新排程到不同節點,資料仍然保留在原有的磁碟區中。這種設計充分利用 Kubernetes 的優勢,簡化整體架構。
Key-Value 機敏資料引擎的版本選擇
Vault 的 KV 引擎歷經兩個主要版本的演進,版本一提供基礎的鍵值儲存功能,版本二在此基礎上加入完整的版本控制機制。理解兩個版本的差異有助於選擇符合專案需求的引擎類型,避免功能不足或是資源浪費的問題。隨著機敏資料管理需求的複雜化,版本控制已經成為企業環境的標準要求,版本二因此成為目前的主流選擇。
KV 版本二的版本控制機制
KV 版本二為每個機敏資料路徑維護完整的歷史記錄,每次更新都會產生新的版本號並保存舊版本的內容。預設設定會保留最近十個版本,這個數字可以根據需求調整,在版本保存數量與儲存成本之間取得平衡。版本控制的價值在於提供時光機般的回溯能力,當發現機敏資料設定錯誤導致應用程式異常時,能快速回復到先前的正常版本。
版本化的機敏資料儲存也支援稽核需求,安全團隊能追蹤機敏資料的變更歷史,了解何時由誰進行哪些修改。這對於符合法規要求的組織特別重要,如金融或醫療產業通常要求完整的資料變更記錄。透過版本控制,能重建任意時間點的機敏資料狀態,滿足稽核人員的查核需求。
刪除操作在版本二引擎中採用軟刪除設計,執行刪除指令後,版本會被標記為已刪除但實際資料仍保留在儲存層。這種設計提供誤刪除的保護機制,管理者能取消刪除標記恢復資料。然而軟刪除也意味著儲存空間不會立即釋放,累積的已刪除版本可能佔用大量空間。若要真正清除資料釋放空間,需要使用 destroy 指令永久銷毀特定版本。
vault kv destroy -mount=secret -versions=5 secret/webapp/admin
上述指令會永久銷毀 secret/webapp/admin 路徑的第五個版本,這個操作無法復原,應該謹慎執行。通常只有在確認某個版本包含錯誤或洩露的資料,且已經過適當的事件回應程序後,才會執行 destroy 操作。建立明確的資料銷毀政策與權限控制,避免誤操作導致重要資料遺失。
KV 版本一的應用場景
KV 版本一採用簡單的鍵值儲存模型,不支援版本控制功能。每次更新會直接覆寫舊資料,無法回溯到先前的版本。這種設計的優勢在於儲存效率,由於不需要保存歷史版本,儲存空間需求顯著降低。對於儲存成本敏感或是機敏資料變更頻繁的場景,版本一可能是更經濟的選擇。
某些類型的機敏資料本質上不需要版本控制,例如臨時性的 API 金鑰或是測試環境的憑證。這些資料的歷史版本沒有保存價值,反而會佔用不必要的儲存空間。在這種情況下,使用版本一引擎更為適當,避免資源浪費。
然而需要注意的是,缺乏版本控制在某些情況下會造成困擾。如果誤操作覆寫重要的機敏資料,且沒有其他備份機制,資料將永久遺失無法恢復。因此除非有明確的理由,否則建議優先選用版本二引擎,版本控制提供的保護價值通常遠超過增加的儲存成本。
存取控制與政策管理機制
機敏資料管理的核心挑戰之一是確保只有授權的實體能存取特定的資料。Vault 提供完善的政策系統,能定義細粒度的存取權限規則,實現最小權限原則。政策定義哪些路徑允許哪些操作,並將政策綁定到身份實體上,如使用者帳號、服務帳號或是應用程式角色。透過適當的政策設計,能確保每個應用程式只能存取自己需要的機敏資料,降低橫向移動攻擊的風險。
政策的定義與套用
Vault 的政策使用 HCL 語言定義,這是 HashiCorp 開發的設定語言,兼具人類可讀性與機器解析能力。一個典型的政策會指定路徑模式,以及允許在該路徑上執行的操作,如讀取、寫入、刪除等。路徑可以使用萬用字元實現靈活的匹配規則,例如 secret/webapp/* 匹配所有以 secret/webapp/ 開頭的路徑。
以下範例展示一個簡單的政策定義,允許讀取 secret/devwebapp/config 路徑的機敏資料。這個政策採用最小權限設計,只授予讀取能力,不允許修改或刪除。在實務上,開發環境的應用程式通常只需要讀取權限,所有機敏資料的更新都應該透過 CI/CD 流程或是管理介面進行,避免應用程式意外修改設定。
path "secret/data/devwebapp/config" {
capabilities = ["read"]
}
政策定義完成後,需要建立並附加到身份實體。在 Kubernetes 整合場景中,通常會將政策附加到 Kubernetes 的 ServiceAccount。應用程式 Pod 使用特定的 ServiceAccount 執行,Vault 透過 Kubernetes 身份驗證機制驗證 ServiceAccount 的身份,然後根據附加的政策決定授予哪些權限。這種整合讓應用程式不需要管理額外的憑證,直接利用 Kubernetes 的身份系統。
動態憑證與臨時存取權
Vault 的進階功能之一是動態生成臨時憑證,這種設計能顯著提升安全性。傳統的靜態憑證一旦洩露,攻擊者能長期使用該憑證存取資源。動態憑證具有生命週期限制,在指定時間後自動失效,縮小攻擊窗口。即使憑證洩露,攻擊者能利用的時間也相當有限。
在 Kubernetes 整合中,Vault 能為每個 Pod 生成專屬的臨時令牌。Pod 啟動時透過 ServiceAccount 向 Vault 驗證身份,Vault 回應一個具有時效性的令牌,Pod 使用這個令牌存取機敏資料。令牌的有效期通常設定為數小時到數天,依照應用程式的重啟頻率調整。這種設計確保即使某個 Pod 被入侵,攻擊者取得的令牌也會在短時間內失效。
實作動態憑證需要在應用程式中加入令牌更新邏輯,定期向 Vault 請求延長令牌有效期或是取得新的令牌。許多 Vault 客戶端函式庫已經內建這個功能,能自動處理令牌續期,簡化應用程式開發。然而需要注意的是,令牌更新需要網路連線,應用程式應該妥善處理網路故障或 Vault 服務中斷的情況,避免令牌過期導致服務中斷。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
actor "應用程式 Pod" as app
participant "Kubernetes API" as k8s
participant "Vault 伺服器" as vault
database "機敏資料儲存" as secret
app -> k8s : 取得 ServiceAccount Token
k8s --> app : 回傳 SA Token
app -> vault : 使用 SA Token 驗證
vault -> k8s : 驗證 Token 有效性
k8s --> vault : 確認 Token 有效
vault -> vault : 檢查附加政策
vault --> app : 回傳臨時 Vault Token
app -> vault : 使用 Vault Token 讀取機敏資料
vault -> vault : 驗證權限
vault -> secret : 查詢資料
secret --> vault : 回傳加密資料
vault -> vault : 解密資料
vault --> app : 回傳機敏資料
@endumlCyberArk Conjur 機敏資料管理方案
除了 HashiCorp Vault,市場上還有其他成熟的機敏資料管理解決方案。CyberArk Conjur 是其中的重要選項,提供企業級的機敏資料保護功能。Conjur 結合開源社群版本與商業版本,前者提供核心功能供開發測試使用,後者加入進階的企業特性如技術支援與額外的整合選項。理解 Conjur 的架構與特性,能幫助團隊在選擇機敏資料管理方案時做出更全面的評估。
Conjur 的架構組成
Conjur 採用多層架構設計,透過不同元件的協作提供完整的機敏資料管理功能。最前端是反向代理層,通常使用 Nginx 擔任這個角色,負責處理 TLS 加密終止與負載平衡。所有外部請求都會先經過反向代理,代理驗證 TLS 憑證後將請求轉發到後端的 Conjur 應用層。這種設計將 TLS 處理與應用邏輯分離,簡化 Conjur 核心程式的複雜度。
Conjur 應用層是基於 Ruby 開發的服務,實作機敏資料的邏輯處理與存取控制。應用層負責身份驗證、權限檢查、資料加解密等核心功能,是整個系統的大腦。應用層採用無狀態設計,所有狀態資料都儲存在後端資料庫,這讓應用層能水平擴展,透過增加實例數量提升處理能力。
資料持久化層使用 PostgreSQL 關聯式資料庫,儲存機敏資料與系統設定。選擇 PostgreSQL 的原因在於其成熟穩定的特性,以及豐富的企業級功能如串流複製、時間點恢復等。機敏資料在寫入資料庫前會先加密,即使資料庫檔案被竊取,攻擊者也無法直接讀取內容。PostgreSQL 的列層級安全性與稽核功能,也為 Conjur 提供額外的安全保障。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "Conjur 機敏資料管理系統" {
component "反向代理層" as proxy {
[Nginx]
[TLS 終止]
[負載平衡]
}
component "應用服務層" as app {
[Conjur 主程式]
[身份驗證]
[權限控制]
[加解密引擎]
}
database "資料持久層" as db {
[PostgreSQL]
[加密資料]
[稽核日誌]
}
component "金鑰管理" as key {
[主加密金鑰]
[資料加密金鑰]
}
}
cloud "外部整合" as external {
[AWS KMS]
[硬體安全模組]
}
actor "客戶端應用" as client
client --> proxy : HTTPS 請求
proxy --> app : 轉發請求
app --> db : 讀寫資料
app --> key : 取得金鑰
key --> external : 金鑰保護
@enduml高可用性與容錯設計
Conjur 同樣採用 Raft 共識協定實現高可用性,這與 Vault 的設計理念一致。叢集中的節點分為主節點與跟隨節點,主節點處理所有寫入請求,跟隨節點複製主節點的資料變更。當主節點故障時,叢集會自動選舉新的主節點,恢復服務運作。這個過程對客戶端應用是透明的,大多數情況下能在秒級時間內完成故障轉移。
資料庫層的高可用性同樣重要。PostgreSQL 支援多種複製模式,包含同步複製與非同步複製。同步複製確保資料寫入主資料庫後,至少一個備用資料庫確認收到資料才回應成功,這提供最強的資料一致性保證。非同步複製則允許主資料庫立即回應成功,資料稍後才複製到備用資料庫,這種模式效能較好但可能在極端故障下遺失少量資料。
建議在不同的可用區域部署 Conjur 節點與資料庫實例,提升整體系統的容錯能力。使用 Kubernetes 部署時,可以利用 Pod 反親和性規則,確保節點分散在不同的實體主機上。搭配適當的資料備份策略,如定期的完整備份與連續的 WAL 歸檔,能確保即使發生嚴重災難,也能從備份恢復系統。
金鑰管理與加密架構
Conjur 的金鑰管理採用分層架構,使用主加密金鑰保護資料加密金鑰,資料加密金鑰再用於加密實際的機敏資料。這種設計稱為封裝金鑰管理,主加密金鑰通常數量少且很少變更,資料加密金鑰則可能有許多個並定期輪換。這種分層讓金鑰管理更靈活,輪換資料加密金鑰時不需要重新加密所有資料。
主加密金鑰的保護至關重要,Conjur 支援多種保護選項。最簡單的方式是將主金鑰加密後儲存在檔案系統,但這仍有洩露風險。更安全的做法是整合外部金鑰管理服務,如 AWS KMS 或硬體安全模組。這些服務提供專業的金鑰保護能力,主金鑰永不離開安全邊界,Conjur 需要使用金鑰時透過 API 請求加解密操作。
資料庫中的機敏資料以加密形式儲存,即使資料庫管理員也無法直接讀取內容。查詢資料庫會看到類似下方的加密值,這些數值對於沒有解密金鑰的人來說毫無意義。這種設計提供深度防禦,即使攻擊者取得資料庫存取權限,仍然無法獲取實際的機敏資料。
SELECT resource_id, version, value
FROM secrets
WHERE resource_id = 'account:variable:test';
查詢結果顯示加密後的資料,value 欄位是十六進位編碼的加密內容,需要透過 Conjur 的解密機制才能還原原始數值。
resource_id | version | value
-------------------------+---------+------------------
account:variable:test | 1 | \x4a7b3c2d...
政策語言與權限控制
Conjur 使用 YAML 格式定義政策,這種宣告式的語法讓政策定義更加直觀。政策文件描述身份實體、資源物件,以及它們之間的權限關係。下方範例展示一個基本的政策結構,定義一個名為 ExamplePolicy 的政策空間,其中包含一個主機身份 webApp 與一個變數資源 secretVar。
- !policy
id: ExamplePolicy
body:
- !host webApp
- !variable secretVar
- !permit
role: !host webApp
privileges: [read, execute]
resource: !variable secretVar
這個政策授予 webApp 主機讀取與執行 secretVar 變數的權限。主機是 Conjur 中的非人類身份,代表應用程式或服務。變數則是儲存機敏資料的容器,可以包含密碼、API 金鑰等敏感資訊。permit 指令明確宣告權限關係,實現最小權限原則。
Conjur 的政策系統支援繼承與群組概念,能建立複雜的權限結構。例如可以定義一個管理員群組,將多個使用者加入群組,然後授予群組特定權限,群組中的所有成員都會自動繼承這些權限。這種設計簡化大規模環境的權限管理,避免為每個使用者個別設定權限的繁瑣作業。
企業級機敏資料管理的關鍵要素
建立完善的機敏資料管理體系需要綜合考慮多個面向,單純選擇工具不足以解決所有問題。組織需要建立明確的政策與流程,培養團隊的安全意識,並持續監控與改進系統。以下探討企業級機敏資料管理必須具備的核心能力,這些能力構成評估任何機敏資料管理方案的基準。
資料加密的深度防禦
加密是機敏資料保護的基石,但加密本身有許多細節需要正確處理。資料應該在傳輸過程中加密,防止網路竊聽攻擊。所有與機敏資料儲存系統的通訊都應該使用 TLS 協定,並驗證伺服器憑證的有效性,避免中間人攻擊。應用程式不應該接受自簽憑證或是停用憑證驗證,這些做法會破壞 TLS 提供的安全保障。
資料在儲存層也必須加密,這稱為靜態加密。即使攻擊者取得儲存系統的實體存取權限,如竊取硬碟或備份媒體,也無法讀取加密的資料。加密金鑰的管理是靜態加密的關鍵,金鑰應該儲存在與資料分離的位置,並受到額外的存取控制保護。使用硬體安全模組或雲端金鑰管理服務能顯著提升金鑰的安全性。
金鑰輪換是加密管理的重要實務,定期更換加密金鑰能降低金鑰洩露的長期影響。然而金鑰輪換需要仔細規劃,確保舊金鑰在所有資料重新加密前仍然可用。使用封裝金鑰架構能簡化金鑰輪換,只需要輪換資料加密金鑰並用新的主金鑰重新封裝,不需要重新加密所有資料。
版本控制與稽核追蹤
機敏資料的版本控制提供時間維度的可追溯性,能回答何時發生哪些變更的問題。這對於事件調查特別重要,當發現安全事件時,版本歷史能幫助重建攻擊時間軸,了解攻擊者可能取得哪些資料。版本控制也支援合規性要求,許多產業規範要求保存完整的資料變更記錄。
稽核日誌記錄所有對機敏資料的存取與操作,包含讀取、寫入、刪除等動作。每條日誌應該包含足夠的上下文資訊,如操作時間、執行者身份、目標資源、操作結果等。這些資訊讓安全團隊能分析存取模式,偵測異常行為。例如某個應用程式突然大量讀取平常不會存取的機敏資料,可能表示帳號被入侵或是應用程式出現異常行為。
{
"timestamp": "2025-11-17T10:30:45.123Z",
"operation": "read",
"subject": "demo:host:webapp",
"resource": "demo:variable:database_password",
"result": "success",
"source_ip": "10.0.1.42",
"user_agent": "conjur-client/1.2.3"
}
稽核日誌應該儲存在獨立的安全系統中,避免攻擊者能修改或刪除日誌掩蓋攻擊痕跡。將日誌串流到 SIEM 系統或是雲端日誌服務,能提供額外的保護層級。定期審查稽核日誌,建立自動化的異常偵測規則,能及早發現潛在的安全威脅。
Kubernetes 整合的最佳實務
與 Kubernetes 的整合應該遵循原生的身份認證機制,利用 ServiceAccount 實現無憑證的身份驗證。這種方法避免在應用程式中硬編碼憑證或是透過環境變數傳遞敏感資訊。ServiceAccount 的 Token 由 Kubernetes 自動管理,具有生命週期限制,並且能與 Pod 的生命週期綁定。
機敏資料的注入方式有多種選擇,各有優缺點。最簡單的方式是透過 Init Container 在 Pod 啟動前取得機敏資料,寫入共享磁碟區供主容器使用。這種方法實作簡單,但機敏資料會以明文形式存在磁碟區中,存在一定風險。較安全的做法是使用 Sidecar 容器持續從機敏資料儲存系統取得資料,並透過本地 API 提供給主容器,機敏資料始終保持在記憶體中不落地。
某些機敏資料管理系統提供 Mutating Webhook 機制,能在 Pod 建立時自動注入機敏資料。這種方法對應用程式完全透明,不需要修改應用程式程式碼或 Deployment 設定。Webhook 會攔截 Pod 建立請求,根據 Pod 的標註或命名空間,自動加入 Sidecar 容器與必要的設定。這種自動化大幅簡化應用程式的機敏資料存取,但也增加系統複雜度,需要仔細測試確保不會影響正常的 Pod 部署。
災難恢復與業務持續性
即使有完善的高可用性設計,仍然需要規劃災難恢復策略,應對極端情況如整個資料中心失效。備份是災難恢復的基礎,應該定期執行完整備份並妥善保管。備份資料同樣需要加密保護,並儲存在與生產系統分離的位置,避免同一災難同時摧毀生產與備份。
測試備份恢復流程至關重要,許多組織擁有備份但從未實際測試恢復過程,災難發生時才發現備份無法使用。建議定期執行災難恢復演練,模擬系統完全失效的情境,驗證能否從備份成功恢復。演練過程中記錄恢復所需時間與遇到的問題,持續改進災難恢復計畫。
高可用性與災難恢復是互補而非替代的關係。高可用性處理常見的故障情境如單一節點失效,確保服務持續運作。災難恢復則應對罕見但嚴重的災難,如整個區域服務中斷。完整的業務持續性計畫應該同時包含這兩個面向,依照組織的恢復時間目標與恢復點目標,設計適當的架構與流程。
結語
機敏資料管理是現代雲原生應用架構的重要基礎,直接影響系統的安全性與可靠性。HashiCorp Vault 與 CyberArk Conjur 等成熟方案提供企業級的機敏資料保護能力,透過加密、存取控制、稽核追蹤等機制,確保敏感資訊的安全。然而工具只是解決方案的一部分,組織還需要建立完善的政策、流程與技術能力,才能真正實現安全的機敏資料管理。
在 Kubernetes 環境中實作機敏資料管理,需要深入理解容器化應用的特性與 Kubernetes 的安全模型。利用 ServiceAccount 進行身份驗證、透過政策實現最小權限、使用動態憑證降低洩露風險,這些實務能顯著提升整體安全水準。同時高可用性部署與災難恢復規劃確保服務的可靠性,讓機敏資料管理系統成為值得信賴的基礎設施。
隨著雲端技術的演進與安全威脅的變化,機敏資料管理的實務也在持續發展。新的加密演算法、更細緻的存取控制機制、更智慧的異常偵測方法不斷出現。團隊應該保持學習,關注產業趨勢與最佳實務的演變,持續改進機敏資料管理策略。透過技術、流程與人員能力的全面提升,建立真正安全可靠的機敏資料保護體系。