Kubernetes 密碼管理是確保雲端原生應用程式安全的重要環節。GKE 與 KMS 的整合提供了一個強大的解決方案,可以有效保護敏感資訊。透過建立專屬的 KMS 鍵環和加密鍵,我們可以精細地控制加密流程,並確保只有授權的服務帳戶才能存取密碼。除了 GKE 和 KMS 的整合,文章也探討了其他外部密碼儲存方案,例如 HashiCorp Vault、CyberArk Conjur 等,以及 Secrets Store CSI Driver 的應用,讓讀者能更全面地瞭解 Kubernetes 密碼管理的各種選項。透過整合監控和日誌服務,我們可以即時監控密碼操作,並在發生異常時及時回應,進一步提升安全性。文章也提到了 HashiCorp Vault 的兩種版本,並說明瞭如何在開發環境中執行 Vault,以及如何將其整合到 Kubernetes 環境中,包含 Vault Agent Injector 的工作原理和 Kubernetes 認證的組態。這些步驟能協助開發者在 Kubernetes 環境中安全地管理敏感資訊,並確保應用程式的安全性。
使用 GKE 與 KMS 加強 Kubernetes 密碼管理
在現代雲端環境中,保護敏感資訊是至關重要的。GKE(Google Kubernetes Engine)與 KMS(Key Management Service)的整合,可以為 Kubernetes 叢集提供強大的密碼管理功能。這篇文章將探討如何利用 GKE 與 KMS 加密 Kubernetes 密碼,並整合其他雲端元件以增強安全性。
整合 GKE 與 KMS
GKE 預設會對靜態資料進行加密,並由 GCP 管理。然而,如果我們希望對加密過程有更多控制,可以使用自行管理的 KMS 鍵來加密 Kubernetes 中的資料。以下是具體步驟:
1. 設定 KMS 鍵環
首先,我們需要在 GCP 專案中建立一個 KMS 鍵環:
resource "google_kms_key_ring" "ksm_key_ring" {
name = "ksm-key-ring"
location = var.region
}
2. 建立加密鍵
接著,在該鍵環中建立一個加密鍵:
resource "google_kms_crypto_key" "ksm_secret_key" {
name = "ksm-secret-encryption"
key_ring = google_kms_key_ring.ksm_key_ring.id
lifecycle {
prevent_destroy = false
}
}
3. 授予 Kubernetes 服務帳戶許可權
為了讓 Kubernetes 叢集能夠使用這個鍵進行加解密操作,我們需要授予適當的許可權:
data "google_project" "project" {}
resource "google_kms_crypto_key_iam_binding" "ksm_secret_key_encdec" {
crypto_key_id = google_kms_crypto_key.ksm_secret_key.id
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
members = [
"serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com"
]
}
說明:
這段程式碼首先建立了一個 KMS 鍵環,然後在該鍵環中建立了一個加密鍵。接著,我們授予了 Kubernetes 叢集所需的許可權,使其能夠使用這個鍵進行加解密操作。
在 Kubernetes 叢集中啟用資料函式庫加密選項
在叢集組態中啟用資料函式庫加密選項,使其使用自行管理的客戶鍵(CMK):
resource "google_container_cluster" "gke_cluster" {
name = "secrets-cluster"
location = var.region
...
database_encryption {
key_name = google_kms_crypto_key.ksm_secret_key.id
state = "ENCRYPTED"
}
}
說明:
這段程式碼在 Kubernetes 叢集組態中啟用了資料函式庫加密選項,並使用我們提供的 KMS 鍵來加密 Secrets。這樣,我們就可以更靈活地管理和控制資料的加密過程。
整合監控與日誌
完善的安全策略不僅僅是加密,還包括監控和日誌記錄。透過整合 Google Cloud 的監控和日誌服務,我們可以實時監控密碼操作,並在發生異常時及時回應。
探討外部密碼儲存
除了雲端提供者自身的密碼管理工具外,還有許多外部的密碼儲存解決方案可以選擇。以下是一些常見的外部密碼儲存提供者:
- HashiCorp Vault
- CyberArk Conjur
- AWS Secrets Manager
- Azure Key Vault
Secrets Store CSI Driver
Secrets Store CSI Driver 是一種透過容器儲存介面(CSI)卷來整合外部密碼儲存提供者的方法。這種方法不需要修改 Kubernetes 的核心程式碼,就可以擴充套件叢集的儲存能力。
常見的 CSI 提供者外掛:
- AWS 提供者
- Azure 提供者
- GCP 提供者
- Vault 提供者
說明:
這些外掛允許我們將外部密碼儲存提供者整合到 Kubernetes 中,從而提高安全性和靈活性。
透過 HashiCorp Vault 進行 Kubernetes 密碼管理
在前幾章中,我們聚焦於與雲端服務提供商搭配的 CSI Secrets Store CSI 驅動程式。這裡介紹了一個新的提供者:Vault 提供者,它是由 HashiCorp 提供的密碼儲存解決方案。列表上的所有密碼提供者都支援高用性,並提供稽核和記錄功能。這些元素確保了資料治理和安全性。除了 CSI 驅動程式解決方案外,還有其他方法可以整合密碼管理。其中一種是 Secrets Injector 元件,我們將在接下來探討。
Secrets Injector
Secrets Injector 元件提供另一種方式來將密碼注入應用程式和外部密碼儲存提供者所託管的密碼。像 HashiCorp Vault 和 CyberArk Conjur 這樣的密碼管理器支援透過 Sidecar Injector 使用密碼儲存。這些 Sidecar Injector 主要關注授權和驗證方面,當從密碼儲存接收密碼時,並處理與 Kubernetes 工作負載的整合。
然而,需要注意的是,注入密碼並不總是需要一個複雜的二進位制檔案與 Kubernetes 互動。例如,考慮 GCP Secret Manager。目前還沒有一個官方的二進位制檔案可以從 Secret Manager 接收密碼,然後將其附加到 Pod。這並不妨礙我們實施一個安全的解決方案來達成相同的結果。我們可以使用 Workload Identity,如第 10 章「探索 GCP 上的雲端密碼儲存」中所述。透過 Workload Identity,我們的 Kubernetes 工作負載可以與 Secret Manager 互動。接著,我們可以使用 GCP Secret Manager 的客戶端函式庫,透過初始化容器將密碼本地掛載到 Pod。
此配方可以應用於其他形式的儲存。重點是使用 Workload Identity;安全性透過其保持完好無損。我們不必在 etcd 中儲存任何密碼,以便與 Secret Manager 互動。相反,Kubernetes 工作負載將被分配某些許可權以便與 Secret Manager 互動。
在其他形式的密碼管理中,例如 HashiCorp Vault,驗證和與密碼儲存的互動方式與我們之前看到的有所不同,但安全性品質保持不變。存取密碼以安全且授權的方式進行,遵循最小許可權原則。我們將在下一章中探討這一點。
總結來說,我們概述了可以使用的一些外部密碼提供者來將我們的密碼注入 Kubernetes。接下來,我們將重點放在 HashiCorp Vault 及其功能上。
HashiCorp Vault
在快速演變的分散式計算領域中,保護敏感資訊至關重要。作為容器協調領域的長官者,Kubernetes 需要強大的解決方案來管理密碼——應用程式正常組態和執行所必需的敏感資料。HashiCorp Vault 在解決這些挑戰方面脫穎而出,提供了一套全面的工具來進行 Kubernetes 叢集中的安全密碼管理。
HashiCorp Vault 提供一個集中的、加密的解決方案,確保密碼保持機密且永遠不會暴露在應用程式碼或組態檔案中。它與 Kubernetes 的整合不僅簡化了密碼管理,還加強了容器化應用程式的安全性,引入了動態秘密、安全秘密注入到 Pod 中以及專為 Kubernetes 的身份驗證方法等功能。這些功能促進了 HashiCorp Vault 和 Kubernetes 之間安全通訊和秘密檢索機制的靈活性、安全性和效率。
HashiCorp Vault 動態生成短期憑證以供需求使用的能力使其區別於本地 Kubernetes 機密。後者通常未加密地儲存在 etcd 中,隨著應用程式規模擴充套件而變得難以管理。HashiCorp Vault 的方法縮小了攻擊面積、增強了安全性並解決了潛在的秘密管理問題。
此外,HashiCorp Vault 的廣泛稽核日誌記錄確保了透明度和責任追蹤機制,有助於遵從規範並迅速回應安全事件。透過將 HashiCorp Vault 整合到 Kubernetes 離線佈署中,組織能夠實作強大且安全且符合規範的容器化應用環境。
HashiCorp Vault 的兩種版本
HashiCorp Vault 有開源版本和企業版本可供選擇;以下將重點介紹開源版本。
使用 HashiCorp Vault 作為秘密儲存
HashiCorp Vault 不僅可以作為秘密儲存來使用,還可以包含我們應用程式中的秘密資料。這使得將 Kubernetes 秘密資料託管到 Vault 中成為可能。這可以透過兩種方式實作:讓 Vault 在 Kubernetes 外部執行或讓它在 Kubernetes 中執行。
外部 HashiCorp Vault 儲存
首先看看如何將外部 HashiCorp Vault 與 Kubernetes 整合。對於我們的需求來說,可以使用 Minikube 安裝。
建立 Docker 滿足外部之需求
我們將建立一個 Docker 容器來執行 Vault 例項:
services:
vault_node_1:
image: vault:1.13.3
container_name: vault_node_1
ports:
- "8200:8200"
environment:
內容解析:
- services:定義 Docker Compose 中要執行的一組服務。
- vault_node_1:定義一個名為 vault_node_1 的服務。
- image:指定要使用的 Docker 映象版本為
vault:1.13.3。 - container_name:設定容器名稱為
vault_node_1。 - ports:對映主機上的 8200 號埠到容器內部的同一號埠。
- environment:設定環境變數(目前尚未填寫)。
這些設定完成後即可啟動 Docker Compose 架構並觀察如何整合 Hashicorp 與 Kubernetes 的運作流程。
下一步行動
接下來玄貓會探討更多詳細設定及相關技術原理等內容之說明
使用 HashiCorp Vault 與 Kubernetes 整合管理機密
在現代軟體開發中,機密管理是一個至關重要的議題。HashiCorp Vault 是一款流行的機密管理工具,能夠有效地保護敏感資訊。本篇文章將探討如何在開發環境中執行 Vault,並將其整合到 Kubernetes 環境中。
開發環境中的 Vault 設定
首先,我們來看看如何在開發環境中執行 Vault。以下是一些基本的設定:
VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
VAULT_DEV_ROOT_TOKEN_ID: mytoken
VAULT_LOG_LEVEL: debug
volumes:
- haproxy.cfg:/haproxy.cfg
我們可以使用 Docker Compose 或單獨的 Docker 指令來執行 Vault。以下是兩種方法的範例:
$ docker compose up
或者使用單獨的 Docker 指令:
$ docker run -p 8200:8200 --rm -v haproxy.cfg:/haproxy.cfg --name vault_node_1 -e VAULT_DEV_ROOT_TOKEN_ID=mytoken -e VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200 -e VAULT_LOG_LEVEL=debug vault:1.13.3
這兩種方法的結果是相同的。使用 Docker Compose 的好處是可以將所有設定集中在一個檔案中,但單獨的 Docker 指令也同樣有效。選擇哪種方法取決於個人的偏好。
需要注意的是,這裡我們執行的是開發模式的 Vault,這種模式不適合用於生產環境。開發模式主要用於除錯和簡化例子的使用。
內容解密:
- VAULT_DEV_LISTEN_ADDRESS:這個變數設定了 Vault 在開發模式下的監聽地址。
- VAULT_DEV_ROOT_TOKEN_ID:這個變數設定了 Vault 的根 token,擁有最高許可權。
- VAULT_LOG_LEVEL:這個變數設定了日誌級別為 debug,方便除錯。
- volumes:這個部分用來掛載組態檔案。
在 Kubernetes 中安裝 Vault
要將 Vault 整合到 Kubernetes 中,我們需要安裝 Vault 二進位制檔案。最簡單的方法是使用 Helm 圖表。
首先,取得我們的外部 Vault 地址:
$ EXTERNAL_VAULT_ADDR=$(minikube ssh "dig +short host.docker.internal" | tr -d '\r')
接著,安裝 Vault:
$ helm repo add hashicorp https://helm.releases.hashicorp.com
$ helm repo update
$ helm install vault hashicorp/vault --set "global.externalVaultAddr=http://$EXTERNAL_VAULT_ADDR:8200" --set="csi.enabled=true"
這些命令會安裝 Vault 套件並設定外部 Vault 地址,讓 Kubernetes 指向該地址。同時,我們啟用了 CSI(Container Storage Interface),以便在後續範例中展示 CSI 的功能。
檢查安裝成功
要確認我們的安裝成功,可以檢查 vault-agent-injector 的佈署狀態:
$ kubectl get deployment vault-agent-injector
如果看到 vault-agent-injector 的狀態為 1/1,表示安裝成功。
探討 Vault Agent Injector 的工作原理
Vault Agent Injector 是一個重要的元件,它負責修改 Pod 規格以包含 Vault Agent 容器。這些容器會從 Vault 中提取 Secrets 並將其附加到 Pod 中。
當一個 Pod 初始化時,會發生以下動作:
- Agent 會識別使用 Vault Secrets 的 Pod。
- Pod 規格會被修改以包含 Vault Agent 容器。
- Vault 初始化容器會提取 Secrets 並將其附加到 Pod 作為分享記憶體卷。
- 如果 Secrets 在 Vault 中變更,Vault Sidecar Injector 會更新 Secrets。
Vault Agent Injector Pod 被賦予 vault-agent-injector-clusterrole 許可權角色。
此圖示展示了 Pod 建立時的流程:
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title GKE 與 KMS 整合強化 Kubernetes 密碼管理
package "Kubernetes Cluster" {
package "Control Plane" {
component [API Server] as api
component [Controller Manager] as cm
component [Scheduler] as sched
database [etcd] as etcd
}
package "Worker Nodes" {
component [Kubelet] as kubelet
component [Kube-proxy] as proxy
package "Pods" {
component [Container 1] as c1
component [Container 2] as c2
}
}
}
api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2
note right of api
核心 API 入口
所有操作經由此處
end note
@enduml內容解密:
- Vault Agent Injector:這個元件會在 Pod 建立時攔截請求並修改 Pod 規格。
- Pod 規格修改:包含了將 Vault Agent 容器加入到 Pod 中的步驟。
- Secrets 提取:從 Vault 提取 Secrets 並注入到 Pod 中。
組態 Kubernetes 認證
為了讓 Vault 與 Kubernetes 與互動,我們需要組態 Kubernetes 認證。首先,建立一個名為 vault-sa-token 的 Secret:
apiVersion: v1
kind: Secret
metadata:
name: vault-sa-token
annotations:
kubernetes.io/service-account.name: vault
type: kubernetes.io/service-account-token
然後應用這個 YAML 檔案:
$ kubectl apply -f vault-secret.yaml
接著,組態 Kubernetes 認證:
# 取得 Kubernetes secret for the service account
$ VAULT_HELM_SECRET_NAME=$(kubectl get secrets --output=json | jq -r '.items[].metadata | select(.name|startswith("vault")).name')
# 取得 service account token
$ TOKEN_REVIEW_JWT=$(kubectl get secret $VAULT_HELM_SECRET_NAME --output='go-template={{ .data.token }}' | base64 --decode)
# 取得 Kubernetes certificate
$ KUBE_CA_CERT=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.certificate-authority-data}' | base64 --decode)
# 取得 Kubernetes host
$ KUBE_HOST=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.server}')
# 指向本地 vault 地址
$ export VAULT_ADDR=http://0.0.0.0:8200
# 使用 root token登入 vault
$ vault login mytoken
# 啟用 Kubernetes 認證方法
$ vault auth enable kubernetes
# 寫入 Kubernetes 認證組態 (假設你已經準備好相關組態資訊)
以上步驟完成後,Vault 和 Kubernetes 就可以透過服務帳戶令牌進行認證了。
內容解密:
- 建立 Secret:為服務帳戶建立 Secret。
- Kubernetes 認證:組態 Kubernetes 認證方法,使得 Vault 能夠透過服務帳戶令牌與 Kubernetes API 互動。