在雲端原生應用的時代,敏感資料的安全管理是確保系統安全性的核心挑戰。Kubernetes 作為容器編排的事實標準,其 Secrets 管理機制承載著保護密碼、API 金鑰、憑證等關鍵資訊的重責大任。隨著 Kubernetes 生態系統的持續演進,Secrets 管理從最初的簡單 Base64 編碼,發展至今日的多層次加密、動態金鑰輪替與外部整合等企業級功能。
本文將深入探討 Kubernetes Secrets 管理的完整實踐,從原生 KMS (Key Management Service) 加密機制的技術演進與配置細節,到 CSI (Container Storage Interface) Secrets Store 的整合應用與最佳實踐,再到 HashiCorp Vault 等外部解決方案的深度整合策略。我們將涵蓋金鑰管理的核心概念、加密提供者的選擇與配置、動態 Secrets 的實現方式,以及如何建構完整的安全管理流程。此外,文章也將探討威脅建模、事件回應、自動化安全檢測等進階主題,並展望 Kubernetes Secrets 管理的未來發展趨勢,包括原生加密的簡化、動態 Secrets 的標準化,以及與外部 Vault 服務的深度整合等方向。
Kubernetes 原生 Secrets 加密機制
Kubernetes 原生提供了多種機制來保護 Secrets 的安全,其中 KMS 加密是最重要的安全功能之一。透過 KMS,我們能夠確保儲存在 etcd 中的 Secrets 資料在靜態時也能獲得強大的加密保護。
KMS 加密架構演進
Kubernetes 的 KMS 加密機制經歷了從 KMSv1 到 KMSv2 的重要演進,這個演進不僅提升了安全性,也改善了效能與可靠性。
# KMSv2 EncryptionConfiguration 完整配置範例
# 展示 KMS 加密提供者的進階配置與最佳實踐
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
# 配置需要加密的資源類型
# Secrets 是最常見的加密目標
- resources:
- secrets
providers:
# KMSv2 加密提供者配置
# 使用外部 KMS 進行金鑰管理
- kms:
# KMS 提供者名稱,用於識別與管理
name: aws-kms-provider
# KMS 外掛端點
# 使用 Unix socket 進行安全通訊
endpoint: unix:///var/run/kmsplugin/socket.sock
# 快取大小設定
# 快取加密金鑰以提升效能
cachesize: 1000
# API 版本,使用 v2 獲得最新功能
apiVersion: v2
# 超時設定
# 設定與 KMS 提供者通訊的超時時間
timeout: 3s
# 備援加密提供者
# 使用本地 AES-GCM 作為備援
- aesgcm:
# 金鑰配置
# 使用 Kubernetes Secret 儲存金鑰
keys:
- name: key1
# Base64 編碼的 32 位元組金鑰
secret: c2VjcmV0IGlzIHNlY3VyZQ==
# Identity 提供者
# 用於未加密的資料讀取
# 主要用於遷移場景
- identity: {}
# 配置其他需要加密的資源
- resources:
- configmaps
providers:
- kms:
name: aws-kms-provider
endpoint: unix:///var/run/kmsplugin/socket.sock
cachesize: 500
apiVersion: v2
- identity: {}
---
# KMSv1 配置範例 (已棄用,僅供參考)
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
# KMSv1 配置
# 注意: KMSv1 將在 Kubernetes 1.29 中移除
- kms:
name: legacy-kms-provider
endpoint: unix:///var/run/kmsplugin/socket.sock
cachesize: 100
# KMSv1 不支援 timeout 設定
KMSv2 相較於 KMSv1 的主要改進包括:每次加密操作都會產生新的資料加密金鑰 (DEK),提供更強的安全保證;支援金鑰輪替操作,無需重啟 API Server;改善的錯誤處理與可觀測性;以及更好的效能表現。
KMS 加密提供者實作
實作 KMS 加密需要配置外部金鑰管理服務。以下是使用 AWS KMS 的完整實作範例。
# AWS KMS Provider 完整部署配置
# 1. KMS Plugin DaemonSet 部署
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: aws-kms-plugin
namespace: kube-system
labels:
app: aws-kms-plugin
spec:
selector:
matchLabels:
app: aws-kms-plugin
template:
metadata:
labels:
app: aws-kms-plugin
spec:
# 使用主機網路以存取 Unix socket
hostNetwork: true
# 容忍主節點污點
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
# 優先排程至控制平面節點
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: Exists
containers:
- name: kms-plugin
# 使用官方 AWS KMS 外掛映像
image: public.ecr.aws/aws-kms/aws-encryption-provider:v1.0.0
imagePullPolicy: IfNotPresent
# 配置命令列參數
command:
- /aws-encryption-provider
args:
# 指定 AWS KMS 金鑰 ARN
- --key=arn:aws:kms:us-east-1:111122223333:key/12345678-1234-1234-1234-123456789012
# 指定 AWS 區域
- --region=us-east-1
# 監聽位址
- --listen=/var/run/kmsplugin/socket.sock
# 日誌等級
- --loglevel=4
# 環境變數配置
env:
# AWS 認證配置
# 使用 IAM Role for Service Accounts (IRSA)
- name: AWS_ROLE_ARN
value: arn:aws:iam::111122223333:role/kms-plugin-role
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
# 掛載 Unix socket 目錄
volumeMounts:
- name: socket-dir
mountPath: /var/run/kmsplugin
- name: token
mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
readOnly: true
# 資源限制
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
# 健康檢查
livenessProbe:
exec:
command:
- /bin/sh
- -c
- test -S /var/run/kmsplugin/socket.sock
initialDelaySeconds: 10
periodSeconds: 10
# 掛載主機目錄供 API Server 存取
volumes:
- name: socket-dir
hostPath:
path: /var/run/kmsplugin
type: DirectoryOrCreate
- name: token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 86400
audience: sts.amazonaws.com
# 服務帳號配置
serviceAccountName: aws-kms-plugin
---
# ServiceAccount 與 RBAC 配置
apiVersion: v1
kind: ServiceAccount
metadata:
name: aws-kms-plugin
namespace: kube-system
annotations:
# 綁定 IAM Role
eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/kms-plugin-role
---
# 監控 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: kms-plugin-monitoring
namespace: kube-system
data:
# Prometheus 監控指標
metrics.yaml: |
- job_name: 'kms-plugin'
static_configs:
- targets: ['localhost:8080']
這個完整的 KMS Plugin 部署展示了如何在 Kubernetes 叢集中實作 AWS KMS 整合,包括外掛部署、認證配置與監控設定。
加密資料遷移策略
當啟用新的加密配置或更改加密提供者時,需要執行資料遷移以確保所有現有 Secrets 都使用新的加密方式。
#!/bin/bash
#############################################
# Kubernetes Secrets 加密遷移工具
# 版本:1.0.0
# 作者:玄貓(BlackCat)
# 功能:自動化遷移 Secrets 至新加密配置
#############################################
set -euo pipefail
# 全域配置
readonly LOG_FILE="/var/log/k8s-secrets-migration.log"
readonly BACKUP_DIR="/backup/secrets-migration-$(date +%Y%m%d_%H%M%S)"
readonly API_SERVER="https://kubernetes.default.svc"
# 日誌函式
log() {
local level=$1
shift
local message="$*"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] [${level}] ${message}" | tee -a "${LOG_FILE}"
}
# 檢查前置條件
check_prerequisites() {
log "INFO" "檢查前置條件..."
# 檢查 kubectl
if ! command -v kubectl &> /dev/null; then
log "ERROR" "kubectl 未安裝"
exit 1
fi
# 檢查叢集連線
if ! kubectl cluster-info &> /dev/null; then
log "ERROR" "無法連線至 Kubernetes 叢集"
exit 1
fi
# 檢查權限
if ! kubectl auth can-i get secrets --all-namespaces &> /dev/null; then
log "ERROR" "權限不足,無法讀取 Secrets"
exit 1
fi
log "INFO" "前置條件檢查通過"
}
# 備份現有 Secrets
backup_secrets() {
log "INFO" "開始備份 Secrets..."
# 建立備份目錄
mkdir -p "${BACKUP_DIR}"
# 取得所有命名空間
local namespaces=$(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}')
# 逐一備份各命名空間的 Secrets
for ns in ${namespaces}; do
log "INFO" "備份命名空間: ${ns}"
# 匯出 Secrets
kubectl get secrets -n "${ns}" -o yaml > "${BACKUP_DIR}/${ns}-secrets.yaml"
# 計算校驗和
sha256sum "${BACKUP_DIR}/${ns}-secrets.yaml" > "${BACKUP_DIR}/${ns}-secrets.yaml.sha256"
done
log "INFO" "Secrets 備份完成: ${BACKUP_DIR}"
}
# 驗證加密配置
verify_encryption_config() {
log "INFO" "驗證加密配置..."
# 檢查 EncryptionConfiguration
local config_file="/etc/kubernetes/encryption-config.yaml"
if [[ ! -f "${config_file}" ]]; then
log "ERROR" "找不到加密配置檔案: ${config_file}"
exit 1
fi
# 驗證 YAML 語法
if ! kubectl create --dry-run=client -f "${config_file}" &> /dev/null; then
log "ERROR" "加密配置檔案語法錯誤"
exit 1
fi
log "INFO" "加密配置驗證通過"
}
# 執行 Secrets 重新加密
reencrypt_secrets() {
log "INFO" "開始重新加密 Secrets..."
# 取得所有命名空間
local namespaces=$(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}')
local total_secrets=0
local processed_secrets=0
# 計算總數
for ns in ${namespaces}; do
local count=$(kubectl get secrets -n "${ns}" --no-headers 2>/dev/null | wc -l)
total_secrets=$((total_secrets + count))
done
log "INFO" "總計 ${total_secrets} 個 Secrets 需要處理"
# 逐一處理
for ns in ${namespaces}; do
log "INFO" "處理命名空間: ${ns}"
# 取得所有 Secrets
local secrets=$(kubectl get secrets -n "${ns}" -o jsonpath='{.items[*].metadata.name}')
for secret in ${secrets}; do
# 更新 Secret 以觸發重新加密
# 使用 annotate 避免實際修改 Secret 內容
if kubectl annotate secret "${secret}" -n "${ns}" \
encryption-migration="$(date +%s)" --overwrite &> /dev/null; then
((processed_secrets++))
# 每 10 個 Secret 顯示進度
if (( processed_secrets % 10 == 0 )); then
local progress=$((processed_secrets * 100 / total_secrets))
log "INFO" "進度: ${processed_secrets}/${total_secrets} (${progress}%)"
fi
else
log "WARNING" "無法處理 Secret: ${ns}/${secret}"
fi
done
done
log "INFO" "Secrets 重新加密完成"
log "INFO" "總計處理: ${processed_secrets}/${total_secrets}"
}
# 驗證加密狀態
verify_encryption() {
log "INFO" "驗證加密狀態..."
# 使用 etcdctl 直接查詢 etcd
# 確認資料已正確加密
local etcd_pod=$(kubectl get pods -n kube-system -l component=etcd -o jsonpath='{.items[0].metadata.name}')
if [[ -z "${etcd_pod}" ]]; then
log "WARNING" "找不到 etcd pod,跳過直接驗證"
return 0
fi
# 隨機選擇一個 Secret 進行驗證
local test_secret=$(kubectl get secrets --all-namespaces -o jsonpath='{.items[0].metadata.name}')
local test_ns=$(kubectl get secrets --all-namespaces -o jsonpath='{.items[0].metadata.namespace}')
log "INFO" "測試 Secret: ${test_ns}/${test_secret}"
# 查詢 etcd 中的原始資料
local etcd_key="/registry/secrets/${test_ns}/${test_secret}"
if kubectl exec -n kube-system "${etcd_pod}" -- \
etcdctl get "${etcd_key}" --print-value-only | grep -q "k8s:enc:kms"; then
log "INFO" "驗證成功: Secret 已使用 KMS 加密"
else
log "WARNING" "驗證失敗: Secret 可能未正確加密"
fi
}
# 清理舊備份
cleanup_old_backups() {
log "INFO" "清理舊備份..."
# 保留最近 7 天的備份
find /backup -name "secrets-migration-*" -type d -mtime +7 -exec rm -rf {} \; 2>/dev/null || true
log "INFO" "舊備份清理完成"
}
# 主要執行流程
main() {
log "INFO" "========================================="
log "INFO" "Kubernetes Secrets 加密遷移工具"
log "INFO" "========================================="
# 檢查權限
if [[ $EUID -ne 0 ]]; then
log "WARNING" "建議以 root 權限執行此工具"
fi
# 執行各項檢查
check_prerequisites
verify_encryption_config
# 詢問確認
echo ""
read -p "是否要繼續執行 Secrets 遷移? (yes/no): " -r
if [[ ! $REPLY =~ ^yes$ ]]; then
log "INFO" "使用者取消操作"
exit 0
fi
# 執行遷移
backup_secrets
reencrypt_secrets
verify_encryption
cleanup_old_backups
log "INFO" "========================================="
log "INFO" "遷移作業完成"
log "INFO" "備份位置: ${BACKUP_DIR}"
log "INFO" "========================================="
}
main "$@"
這個遷移工具提供了完整的 Secrets 加密遷移流程,包括備份、重新加密、驗證與清理等功能。
@startuml
!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
title Kubernetes Secrets 加密流程
participant "應用程式" as App
participant "Kubernetes API Server" as API
participant "KMS 外掛" as Plugin
participant "外部 KMS" as KMS
participant "etcd" as ETCD
App -> API: 建立/更新 Secret
activate API
API -> Plugin: 請求加密 DEK
activate Plugin
Plugin -> KMS: 請求產生/加密 DEK
activate KMS
KMS --> Plugin: 返回加密後的 DEK
deactivate KMS
Plugin --> API: 返回加密後的 DEK
deactivate Plugin
API -> API: 使用 DEK 加密 Secret 資料
API -> ETCD: 儲存加密後的 Secret
activate ETCD
ETCD --> API: 確認儲存成功
deactivate ETCD
API --> App: 返回建立成功
deactivate API
... 稍後讀取 Secret ...
App -> API: 讀取 Secret
activate API
API -> ETCD: 取得加密的 Secret
activate ETCD
ETCD --> API: 返回加密資料
deactivate ETCD
API -> Plugin: 請求解密 DEK
activate Plugin
Plugin -> KMS: 請求解密 DEK
activate KMS
KMS --> Plugin: 返回解密後的 DEK
deactivate KMS
Plugin --> API: 返回解密後的 DEK
deactivate Plugin
API -> API: 使用 DEK 解密 Secret 資料
API --> App: 返回解密後的 Secret
deactivate API
@enduml這個流程圖清楚展示了 Kubernetes Secrets 使用 KMS 進行加密與解密的完整流程。
CSI Secrets Store 整合實踐
CSI Secrets Store 提供了一種優雅的方式來整合外部 Secrets 管理系統,讓應用程式能夠透過標準的 Kubernetes Volume 機制存取外部 Vault 中的 Secrets。
CSI Driver 部署與配置
部署 CSI Secrets Store Driver 是整合外部 Secrets 的第一步。
# CSI Secrets Store Driver 完整部署配置
# 1. Helm Values 配置
# values.yaml
linux:
enabled: true
# 啟用同步至 Kubernetes Secrets
enableSecretRotation: true
rotationPollInterval: "2m"
# 資源配置
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 50m
memory: 100Mi
# 啟用 Secrets 同步功能
syncSecret:
enabled: true
# 啟用指標收集
metrics:
enabled: true
port: 8080
# RBAC 配置
rbac:
install: true
pspEnabled: false
---
# 2. AWS Secrets Manager Provider 配置
apiVersion: v1
kind: ServiceAccount
metadata:
name: aws-provider-installer
namespace: kube-system
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/secrets-store-role
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: csi-secrets-store-provider-aws
namespace: kube-system
labels:
app: csi-secrets-store-provider-aws
spec:
selector:
matchLabels:
app: csi-secrets-store-provider-aws
template:
metadata:
labels:
app: csi-secrets-store-provider-aws
spec:
serviceAccountName: aws-provider-installer
hostNetwork: true
containers:
- name: provider
image: public.ecr.aws/aws-secrets-manager/secrets-store-csi-driver-provider-aws:1.0.r2
imagePullPolicy: Always
args:
- --provider-volume=/etc/kubernetes/secrets-store-csi-providers
resources:
requests:
cpu: 50m
memory: 100Mi
limits:
cpu: 200m
memory: 200Mi
volumeMounts:
- name: provider-vol
mountPath: /etc/kubernetes/secrets-store-csi-providers
volumes:
- name: provider-vol
hostPath:
path: /etc/kubernetes/secrets-store-csi-providers
type: DirectoryOrCreate
---
# 3. SecretProviderClass 配置範例
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets
namespace: default
spec:
# 指定提供者
provider: aws
# 配置參數
parameters:
# AWS Secrets Manager 區域
region: us-east-1
# 要掛載的 Secrets
objects: |
- objectName: "app/database/password"
objectType: "secretsmanager"
objectAlias: "db-password"
- objectName: "app/api/key"
objectType: "secretsmanager"
objectAlias: "api-key"
- objectName: "app/tls/cert"
objectType: "secretsmanager"
objectAlias: "tls-cert"
# 同步至 Kubernetes Secret
secretObjects:
- secretName: app-database-credentials
type: Opaque
data:
- objectName: "db-password"
key: password
- secretName: app-api-credentials
type: Opaque
data:
- objectName: "api-key"
key: api-key
- secretName: app-tls-certificate
type: kubernetes.io/tls
data:
- objectName: "tls-cert"
key: tls.crt
---
# 4. Pod 使用範例
apiVersion: v1
kind: Pod
metadata:
name: app-with-secrets
namespace: default
spec:
serviceAccountName: app-sa
containers:
- name: app
image: myapp:latest
volumeMounts:
# 掛載 Secrets 作為檔案
- name: secrets-store
mountPath: "/mnt/secrets"
readOnly: true
env:
# 從同步的 Secret 讀取環境變數
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-database-credentials
key: password
- name: API_KEY
valueFrom:
secretKeyRef:
name: app-api-credentials
key: api-key
volumes:
- name: secrets-store
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "app-secrets"
這個完整的 CSI Secrets Store 配置展示了從 Driver 部署、Provider 配置到應用程式整合的完整流程。
HashiCorp Vault 整合
HashiCorp Vault 是業界領先的 Secrets 管理解決方案,提供了豐富的功能與強大的安全保證。
# HashiCorp Vault 與 Kubernetes 整合配置
# 1. Vault Helm Values
# values.yaml
server:
# 啟用 HA 模式
ha:
enabled: true
replicas: 3
raft:
enabled: true
setNodeId: true
config: |
ui = true
listener "tcp" {
tls_disable = 0
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_cert_file = "/vault/userconfig/vault-tls/tls.crt"
tls_key_file = "/vault/userconfig/vault-tls/tls.key"
}
storage "raft" {
path = "/vault/data"
retry_join {
leader_api_addr = "https://vault-0.vault-internal:8200"
leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
}
retry_join {
leader_api_addr = "https://vault-1.vault-internal:8200"
leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
}
retry_join {
leader_api_addr = "https://vault-2.vault-internal:8200"
leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
}
}
# 資源配置
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 512Mi
cpu: 500m
# 啟用 Vault Injector
injector:
enabled: true
replicas: 2
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 512Mi
cpu: 500m
---
# 2. Kubernetes Auth 配置
# vault-k8s-auth.sh
#!/bin/bash
# Vault 位址
export VAULT_ADDR="https://vault.example.com:8200"
# 啟用 Kubernetes Auth
vault auth enable kubernetes
# 配置 Kubernetes Auth
vault write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token
# 建立策略
vault policy write app-policy - <<EOF
path "secret/data/app/*" {
capabilities = ["read", "list"]
}
path "database/creds/app-role" {
capabilities = ["read"]
}
EOF
# 建立角色
vault write auth/kubernetes/role/app \
bound_service_account_names=app-sa \
bound_service_account_namespaces=default \
policies=app-policy \
ttl=24h
---
# 3. 動態資料庫憑證配置
# 啟用資料庫引擎
vault secrets enable database
# 配置 PostgreSQL 連線
vault write database/config/postgres \
plugin_name=postgresql-database-plugin \
allowed_roles="app-role" \
connection_url="postgresql://{{username}}:{{password}}@postgres:5432/appdb?sslmode=require" \
username="vault" \
password="vault-password"
# 配置角色
vault write database/roles/app-role \
db_name=postgres \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
---
# 4. Pod 注入範例
apiVersion: v1
kind: Pod
metadata:
name: app-with-vault
namespace: default
annotations:
# 啟用 Vault 注入
vault.hashicorp.com/agent-inject: "true"
# Vault 角色
vault.hashicorp.com/role: "app"
# 注入 Secret
vault.hashicorp.com/agent-inject-secret-database: "database/creds/app-role"
vault.hashicorp.com/agent-inject-secret-api-key: "secret/data/app/api-key"
# 注入範本
vault.hashicorp.com/agent-inject-template-database: |
{{- with secret "database/creds/app-role" -}}
postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/appdb
{{- end -}}
spec:
serviceAccountName: app-sa
containers:
- name: app
image: myapp:latest
env:
- name: DATABASE_URL
value: file:///vault/secrets/database
- name: API_KEY_FILE
value: /vault/secrets/api-key
這個 Vault 整合配置展示了從 Vault 部署、Kubernetes 認證配置到動態憑證產生的完整流程。
DevSecOps 安全實踐
建立完善的 DevSecOps 文化與實踐是確保 Kubernetes Secrets 安全的關鍵。
自動化安全掃描
自動化掃描能夠及早發現 Secrets 洩露與安全漏洞。
# GitLab CI/CD Secrets 掃描 Pipeline
stages:
- scan
- audit
- remediate
# Secrets 洩露掃描
secrets_scan:
stage: scan
image: trufflesecurity/trufflehog:latest
script:
# 掃描 Git 歷史記錄
- trufflehog git file://. --json --no-update > secrets-scan.json
# 掃描檔案系統
- trufflehog filesystem . --json --no-update >> secrets-scan.json
artifacts:
reports:
secret_detection: secrets-scan.json
paths:
- secrets-scan.json
expire_in: 30 days
# Kubernetes Secrets 稽核
k8s_secrets_audit:
stage: audit
image: aquasec/kubectl:latest
script:
# 檢查未加密的 Secrets
- kubectl get secrets --all-namespaces -o json | jq '.items[] | select(.type=="Opaque")' > unencrypted-secrets.json
# 檢查過期的 Secrets
- kubectl get secrets --all-namespaces -o json | jq '.items[] | select(.metadata.creationTimestamp < "2023-01-01")' > old-secrets.json
artifacts:
paths:
- unencrypted-secrets.json
- old-secrets.json
威脅建模與事件回應
建立系統化的威脅建模流程能夠提早識別潛在風險。
# Kubernetes Secrets 威脅建模範例
## 資產識別
- etcd 資料庫
- KMS 加密金鑰
- ServiceAccount Tokens
- 應用程式 Secrets
## 威脅分析
1. **未授權存取**
- 風險: 攻擊者透過受損 Pod 存取 Secrets
- 緩解: 實施 RBAC、Network Policies
2. **資料外洩**
- 風險: Secrets 被記錄至日誌或監控系統
- 緩解: 配置日誌過濾、審查監控配置
3. **金鑰洩露**
- 風險: KMS 金鑰被盜用
- 緩解: 定期輪替、實施最小權限原則
## 事件回應計畫
1. 檢測階段: 監控異常存取模式
2. 隔離階段: 撤銷受損憑證
3. 根除階段: 輪替所有 Secrets
4. 恢復階段: 驗證系統安全性
5. 事後檢討: 更新安全策略
結語
Kubernetes Secrets 管理是容器化應用安全的基石,從原生 KMS 加密到外部 Vault 整合,每個層面都需要精心設計與實作。本文深入探討了 KMS 加密機制的演進、CSI Secrets Store 的整合實踐、HashiCorp Vault 的深度應用,以及 DevSecOps 安全文化的建立。
隨著雲端原生技術的持續演進,Secrets 管理將朝向更自動化、更安全、更易用的方向發展。動態 Secrets、自動金鑰輪替、零信任架構等新興實踐將逐漸成為標準。組織需要持續學習、積極實踐,建立完善的安全管理流程,才能在這個快速變化的領域中保持競爭力。