前言
你可能已經聽過很多遍這個不算秘密的秘密了--Kubernetes Secrets 不是加密的!Secret 的值是儲存在 etcd 中的 base64 encoded(編碼) 字串。這意味著,任何可以訪問你的叢集的人,都可以輕鬆解碼你的敏感資料。任何人?是的,幾乎任何人都可以,尤其是在叢集的 RBAC 設定不正確的情況下。任何人都可以訪問 API 或訪問 etcd。也可能是任何被授權在 Namespace 中建立 pod 或 Deploy,然後使用該許可權檢索該 Namespace 中所有 Secrets 的人。 如何確保叢集上的 Secrets 和其他敏感資訊(如 token)不被洩露?在本篇博文中,我們將討論在 K8s 上構建、部署和執行應用程式時加密應用程式 Secrets 的幾種方法。
K8s 的 Secrets
在 Kubernetes 叢集上執行的應用程式可以使用 Kubernetes Secrets,這樣就無需在應用程式程式碼中儲存 token 或密碼等敏感資料。
當前預設 Kubernetes 叢集內 Secrets 的典型工作流程如下:
-
Dev 階段:使用 CICD 的應用程式開發人員將 git 作為管理部署到叢集的配置的真實來源。訪問控制有助於確保對該資源庫的訪問安全,但這本身並不總能確保應用程式的敏感資訊不被洩露。
-
Ops 階段:API 伺服器會在叢集上建立 Kubernetes Secrets 資源,你可以在這裡 這裡 閱讀有關 Secrets 生命週期的更多資訊。 儲存在 etcd 中的 Secrets 可由應用程式 pod 以三種方式之一使用:
- 作為一個或多個容器的 卷掛載 中的檔案。
- 作為容器 環境變數。
- 由 Pod 的 kubelet 在拉取映象時使用。
在這三種情況下,密文中的值在使用前都會被解碼 (decode)。
那麼,既然我們知道了它的工作原理,為什麼只對密文進行 base64 編碼還不夠呢?
Base64 編碼為什麼不算密文?
Base64 編碼是一種二進位制到文字的編碼方案,它將 24 位二進位制資料表示為 6 位 base64 數字。它用於在網路上傳輸大量資料,尤其是影像檔案等大型檔案。它的主要功能是在資料透過網路傳輸時提供資料的完整性。要明確,編碼 (encode) 並不是加密 (encrypt)。
在任何 Linux 終端上試試這個。
$ echo -n 'not encrypted' | base64
bm90IGVuY3J5cHRlZA==
$ echo -n 'bm90IGVuY3J5cHRlZA==' | base64 --decode
not encrypted
如上,無論是在將 Secrets 傳輸到群集時,還是在群集上使用時,任何可以訪問你係統的人都可以輕鬆解碼你的 Secrets。
問題來了
作為 DevSecOps 管理員,您顯然面臨著兩個挑戰:
- 如何加密和管理叢集外的敏感資料,即在構建和部署階段進入叢集之前?
- 如何在叢集內執行應用程式時保護敏感資料的安全?
以下是加密 K8s Secrets 的幾種方案。
在部署到群集之前對機密進行加密
作為將程式碼推送到 git 倉庫(又稱應用程式的 "真相源")的開發人員,您可以在將程式碼推送到 git 倉庫之前對應用程式使用的敏感資訊進行加密。下面將介紹兩種常見的方法,用於在機密提交到 git 倉庫並部署到 OpenShift 叢集之前對其進行加密:
使用 Bitnami Sealed Secrets
Bitnami Sealed Secrets 簡介
Bitnami Sealed Secrets: Kubernetes 的“加密的 Secrets”.
典型使用場景:
遇到的問題:“我可以在 git 中管理我所有的 K8s 配置,除了 Secrets。”
解決方案:將您的 Secret 加密到 SealedSecret 中,即使在公共儲存庫中也可以安全儲存。SealedSecret 只能由目標叢集中執行的控制器解密,其他人(甚至原始作者)無法從 SealedSecret 中獲得原始 Secret。
Bitnami Sealed Secrets 使用流程
使用 Bitnami Sealed Secrets 的工作流程示例如下:
- 叢集管理員在 K8s 叢集上部署 Sealed secrets 控制器
- 開發者需要在本地計算機上安裝
kubeseal
CLI。 - 開發者建立一個 Secret 資源,然後由
kubeseal
CLI 在執行時從控制器中獲取金鑰,對該資源進行加密或密封。對於網路受限的環境,公鑰也可以儲存在本地並由 kubeseal 使用。 Kubeseal 將建立一個SealedSecret
自定義資源。 - 開發者將此 CR 推送到自己的 git 倉庫中
- 可使用 ArgoCD 等 CD 工具在叢集上部署 CR。
- 控制器將檢測到 SealedSecret 資源,並使用叢集上的私鑰對其進行解密。
使用 KSOPS/Mozilla SOPS
KSOPS/Mozilla SOPS 簡介
- Mozilla SOPS - sops 是加密檔案的編輯器,支援 YAML,JSON,ENV,INI 和 BINARY 格式,並使用 AWS KMS,GCP KMS,Azure Key Vault,age 和 PGP 進行加密。
- KSOPS - 一個靈活的 SOPS 加密資源的 Kustomize 外掛
KSOPS/Mozilla SOPS 使用流程
如果使用 Argo CD 在 Kubernetes 中部署應用程式,則可以使用 Kustomize SOPS 外掛,該外掛用於解密使用 SOPS 加密的資源。
在叢集上,管理員將:
- 部署 ArgoCD
- 使用 age 生成金鑰
- 在 特定(如
GitOps
) Namespace 中建立儲存公鑰和私鑰的金鑰 - 定製 Argo CD 以使用 Kustomize SOPS 外掛
- 將公鑰推送到 Git 倉庫
開發人員將:
- 在本地控制檯建立 Secret
- 使用 SOPS CLI 下載公鑰並加密密文
- 用加密後的 Secrets 生成 KSOPS yaml 並推送到 Git 倉庫
ArgoCD 在叢集上部署 Secrets 之前,會使用 KSOPS 對機密檔案進行解密。
小結
上面這兩種方法都適用於使用非對稱加密技術對機密檔案進行加密。兩者都提供了在敏感資料作為 Secrets 部署到叢集之前對其進行解密的方法。Sealed secrets 與 Kubernetes 原生整合。SOPS / KSOPS 可以獨立工作,不需要叢集上的控制器。另外,Sealed secrets 使用 AES-256-GCM 等強 crypto,而 SOPS 使用 gpg 和 age。SOPS 提供與雲提供商 KMS 的整合,而 SealedSecrets 目前還沒有,但計劃在未來實現整合(參見 這裡)。 SOPS 不只可以對 Secrets 的值加密,還支援 yaml、json、env var 和二進位制值加密,因此也可用於加密 helm chart。
不過,正如你所看到的,加密的資料一旦進入叢集,就會在使用前被解密。因此,這基本上只解決了部分問題。接下來,我們需要看看如何在群集中保護這些資料的安全。讓我們看看在叢集上加密資料的不同選項。
加密 K8s 群集上的 Secrets
K8s 的 etcd 加密選項
預設情況下,K8s 容器平臺不對 etcd 資料進行加密。但是原生 K8s, 以及一些 K8s 發行版,提供了啟用基於 etcd 的加密選項。
以下是相關的一些參考文件:
- 原生 K8s: 靜態加密機密資料 | Kubernetes
- OpenShift: Encrypting etcd data | Security and compliance | OpenShift Container Platform 4.13
- K3s: Secret 加密 | K3s
讀者可以進一步閱讀以瞭解詳情。
使用 KMS 驅動進行資料加密
除了上面 etcd 的(靜態)加密方案之外,原生 K8s 和一些 K8s 發行版也提供了基於 KMS 驅動進行(動態)資料加密的方案。
以下是相關的一些參考文件:
- 原生 K8s: 使用 KMS 驅動進行資料加密 | Kubernetes
- GKE: 在應用層對 Secret 加密 | Google Kubernetes Engine (GKE) | Google Cloud
- Amazon EKS: Enabling secret encryption on an existing cluster - Amazon EKS
- 使用阿里雲 KMS 進行 Secret 的落盤加密 (alibabacloud.com)
公有云/私有云/資料中心磁碟加密選項
在 K8s 中使用 EBS 的公有云/私有云/資料中心節點級加密可以提供額外的加密層。這裡以公有云為例說明:
-
AWS: 在 AWS 上託管 K8s 群集時,可以啟用 Amazon EBS 加密,為 EC2 例項提供加密。Amazon EBS 加密在建立加密卷和快照時使用 AWS KMS 金鑰。它使用 AES-256-XTS 進行塊密碼加密。 建立加密 EBS 卷並將其附加到支援的例項型別時,以下型別的資料將被加密:
- 加密卷內的靜態資料
- 卷和例項之間移動的所有資料
- 從加密卷建立的所有快照
- 從這些快照建立的所有卷
-
Azure: 為連線到 Azure Key Vault 的 Azure Managed Disks 提供加密選項
-
Google 為 Google Cloud Storage 提供加密選項。兩者預設都使用 AES 256 金鑰,但也可以使用客戶管理和提供的金鑰,並與 KMS 整合。
使用第三方 Secrets 儲存整合的 Secrets
選擇第三方 Secrets 儲存的一個重要原因是,透過集中式 Secrets 儲存解決方案,確保在叢集之外管理 Secrets 的生命週期。這些 Secrets 儲存提供的身份驗證和授權策略及程式與群集上的不同,也許更適合控制應用程式資料訪問。這些解決方案大多還提供監管機構要求的信封加密和 HSM 支援。流行的解決方案包括 HashiCorp Vault、CyberArk Conjur、AWS Secret Store、Azure Key Vault、Google Secret Manager、1Password 等。
Sidecar 解決方案
Vault 等解決方案可用於注入應用程式 pod 的特定 Secrets。在這種情況下,sidecar/init 容器都負責對 Secret Provider 進行身份驗證,然後應用程式可以在必要時使用返回的 Secrets。與 Provider 的連線是透過 TLS 進行的,以確保 Secrets 檢索的安全性。Vault 透過使用 響應封裝 提供額外的安全性,這使您可以在中間人無法看到憑證的情況下傳遞憑證。選擇這些解決方案的客戶可以決定將機密儲存在叢集上或叢集外。通常情況下,如果客戶一直使用 Vault 來滿足其基礎架構和其他應用需求,他們會傾向於與這些解決方案整合,以便在 K8s 上獲得無縫的機密管理體驗。
Secrets 儲存 CSI(SSCSI)驅動程式和提供商解決方案
Secrets Store CSI 驅動程式允許將 Secrets 和其他敏感資訊作為卷掛載到應用程式 pod 中。Secrets Store CSI 驅動程式使用 gRPC 與提供程式通訊,以便從 SecretProviderClass 自定義資源中指定的外部 Secrets Store 中檢索 Secrets 內容。一旦連線了卷,其中的資料就會載入到容器的檔案系統中。與上述從特定提供商引入 Secrets 內容的 sidecar 解決方案不同,SSCSI 驅動程式可以配置為從多個不同的 Secret Provider 檢索 Secrets 內容。有關驅動程式和提供商如何工作的更多資訊,請參閱 此處。
不希望將秘密儲存在 etcd 中作為 Kubernetes 秘密的客戶主要會選擇 SSCSI,原因如下
- 他們可能有嚴格的合規性要求,因此有必要僅在中央儲存區而非叢集中儲存和管理機密。
- 他們可能會在控制平面不由他們管理的環境中引入工作負載,因此他們希望完全控制工作負載的機密,而不相信平臺管理員能做到這一點。例如,客戶將工作負載引入托管服務提供商叢集的租戶中,或者將工作負載引入控制平面不由其管理的雲平臺中。
SSCSI 驅動程式並不直接提供保護非卷標掛載機密的方法,例如那些需要作為環境變數或映象拉取機密的 Secrets,或者那些你可能直接在群集上建立用於管理 Ingress 證書的 Secrets。不過,你可以使用 sync secrets 功能,它可以建立 Kubernetes Secrets,然後為作為 Env 變數的 Secret 提供支援。
External Secrets Operator (ESO)
External Secrets Operator (ESO)是一種使用者友好型解決方案,用於將外部秘密管理解決方案中的秘密同步到 Kubernetes Secrets 中。 ESO 作為部署資源執行在 Kubernetes 叢集中,利用自定義資源定義(CustomResourceDefinitions,CRD)透過 SecretStore 資源配置對 Secret Provider 的訪問,並利用 ExternalSecret 資源管理 Kubernetes 秘密資源。
客戶在以下情況下會選擇 ESO:
- 他們需要與平臺輕鬆整合,並便於開發人員使用
- 他們對叢集的控制平面高度信任--尤其是在如何對 etcd 進行加密配置或如何在叢集上管理 RBAC 方面
- 他們在機密管理方面有多叢集用例,需要跨叢集機密整合
- 他們需要為非應用程式使用管理平臺 Secrets,例如用於 Ingress、自動化、影像拉取的機密
- 需要在叢集上修改 Secrets,併為特定應用提供模板
- 最後,也是最重要的一點是,他們的用例需要叢集上的 Secrets
將應用程式與 HSM (硬體安全模組) 整合
最高階別安全,將應用程式或 K8s 與 HSM (硬體安全模組) 整合。細節略。
總結
今天,我們瞭解 K8s 提供的各種加密選項,以及每種選項如何保護敏感資料,可以根據您的使用案例和實際情況做出明智的選擇。
以下是筆者的一些個人建議, 僅供參考:
- 主要使用 AWS 的,可以根據安全級別選擇:EBS 加密或 KMS 加密
- 在資料中心使用 K8s, 且有 K8s 叢集外的 Secrets 需要管理的,推薦使用 Hashicorp Vault
- 在資料中心使用 K8s, 且只有 K8s Secrets 加密需求,那麼 etcd 靜態加密、ESO 都是可以考慮的選項
三人行, 必有我師; 知識共享, 天下為公. 本文由東風微鳴技術部落格 EWhisper.cn 編寫.