如何使用 Mozilla SOPS 優(yōu)雅的管理你的 Kubernetes Secret
默認(rèn)情況下,Kubernetes Secret(機(jī)密信息)以 base64 編碼存儲(chǔ)在YAML文件中。因?yàn)樾畔⑷狈用芡ǔ?huì)導(dǎo)致如何安全地存儲(chǔ)秘密的問題。當(dāng)然您也不想將敏感的配置數(shù)據(jù)放入 git 存儲(chǔ)庫,因?yàn)樗皇墙?jīng)過base64編碼而已。
echo <base64_representation> | base64 -d.
一個(gè)典型的解決方案是使用Azure Key Vault或HashiCorp Vault 等服務(wù)來保留敏感數(shù)據(jù)??梢允褂肧ecrets Store CIS 驅(qū)動(dòng)程序?qū)⑦@些服務(wù)與 Kubernetes 集成。但是,依賴附加服務(wù)意味著除了 Kubernetes 之外,您還必須管理和維護(hù)該服務(wù)。此外,根據(jù)您用于存儲(chǔ)敏感數(shù)據(jù)的服務(wù),某些敏感配置必須存儲(chǔ)在某處以配置 CIS 驅(qū)動(dòng)程序。
作為替代方案,您可以使用Mozilla SOPS (SOPS)來加密和解密您的 Kubernetes 機(jī)密文件。通過 SOPS 加密的信息可以存儲(chǔ)在源代碼版本控制中。加密的信息將在部署到 Kubernetes 之前在本地解密。本文演示了如何將YAMLSOPS 與 Azure Key Vault 結(jié)合使用來加密和解密 Kubernetes 機(jī)密(文件),這允許您將信息與其他 Kubernetes 清單直接存儲(chǔ)在 git 中。
什么是 Mozilla SOPS
Mozilla的標(biāo)準(zhǔn)操作程序(加解密操作)是一個(gè)與平臺(tái)無關(guān)的CLI,用于不同格式的編輯加密的文件-包括yaml,json,ini,binary,和其它。SOPS 支持多個(gè)后端使用密鑰進(jìn)行加密和解密。以下是五個(gè)最受歡迎的支持場(chǎng)景:
- PGP
- Azure 密鑰保管庫
- 知識(shí)管理系統(tǒng)
- GCP知識(shí)管理系統(tǒng)
- HashiCorp 金庫
為了針對(duì) Azure Key Vault 進(jìn)行身份驗(yàn)證,SOPS 按以下順序嘗試多種身份驗(yàn)證模式:
- 客戶憑證
- 客戶證書
- 用戶名密碼
- 托管服務(wù)身份 (MSI)
- Azure CLI 身份驗(yàn)證
盡管 Azure CLI 身份驗(yàn)證無障礙,但我建議您在本地開發(fā)機(jī)器上使用 Azure 服務(wù)主體 (SP)。要在 Kubernetes 中使用 SOPS 解密機(jī)密(例如,如果您使用 GitOps 運(yùn)算符,例如 Flux),您應(yīng)該考慮使用托管服務(wù)標(biāo)識(shí) (MSI) 和 Azure AD Pod 標(biāo)識(shí)的組合。(有關(guān)詳細(xì)的演練,請(qǐng)考慮官方全量文檔https://www.thorsten-hans.com/encrypt-your-kubernetes-secrets-with-mozilla-sops/?utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-8D9JEMI3MsO2qdM0KGA0m3685hu1H0RBcgBj6rDozFznQ7_Ra-tmzdJYwuE7Hf2TfjXwqk#:~:text=flux%20documentation%20for%20a%20detailed%20walk-through)。
預(yù)配 Azure 服務(wù)主體 (SP)
若要?jiǎng)?chuàng)建新的 Azure SP,請(qǐng)使用以下命令:
# create a service principal
az ad sp create-for-rbac -n sp-sops-keyvault -o json
# {
# "appId": "00000000-0000-0000-000000000000",
# "displayName": "http://sp-sops-keyvault",
# "name": "http://sp-sops-keyvault",
# "password": "00000000-0000-0000-000000000000",
# "tenant": "<your_tenant_identifier>
# }
SOPS(以及一些即將推出的命令)需要存儲(chǔ)在環(huán)境變量中的進(jìn)行身份驗(yàn)證。也就是說,您可以使用以下命令快速將appId、tenant和存儲(chǔ)password在本地環(huán)境變量中export:
export AZURE_CLIENT_ID=<appId>
export AZURE_CLIENT_SECRET=<password>
export AZURE_TENANT_ID=<tenant>
如果您想將 SOPS 集成到您的 CI 管道中,請(qǐng)考慮使用存儲(chǔ)庫機(jī)密(這是在 GitHub 上下文中調(diào)用敏感配置數(shù)據(jù)的方式)或有競(jìng)爭(zhēng)力的解決方案來處理您的 CI 系統(tǒng)中的敏感數(shù)據(jù)。
預(yù)配 Azure Key Vault 實(shí)例
你需要一個(gè) Azure Key Vault 實(shí)例。使用 Azure CLI 預(yù)配新的 Azure Key Vault 非常簡(jiǎn)單,如以下代碼段所示:
# create a new Resource Group
az group create -n rg-sops-sample -l germanywestcentral
# create a Key Vault instance
az keyvault create -n kv-sops-sample \
-g rg-sops-sample \
-l germanywestcentral
# create an access policy for the SP
az keyvault set-policy -n kv-sops-sample \
-g rg-sops-sample \
--spn $AZURE_CLIENT_ID \
--key-permissions encrypt decrypt
在 Azure Key Vault 中創(chuàng)建用于加密和解密的密鑰
此時(shí),您必須在我們新創(chuàng)建的 Azure Key Vault 實(shí)例中創(chuàng)建用于加密和解密的實(shí)際密鑰:
# create an key for encryption / decryption
az keyvault key create -n sops-sample-key \
--vault-name kv-sops-sample \
--ops encrypt decrypt \
--protection software
除了身份驗(yàn)證信息,SOPS 還需要我們剛剛創(chuàng)建的密鑰的標(biāo)識(shí)符。同樣,使用 Azure CLI 并將標(biāo)識(shí)符存儲(chǔ)在環(huán)境變量中:
# read and store key identifier
export KEY_ID=$(az keyvault key show -n sops-sample-key \
--vault-name kv-sops-sample \
--query key.kid -o tsv)
安裝 Mozilla SOPS
如前所述,SOPS 是一個(gè)跨平臺(tái)的 CLI。您可以從 GitHub 下載 CLI,網(wǎng)址為https://github.com/mozilla/sops/releases。確??蓤?zhí)行文件作為PATH變量的一部分放在文件夾中。
# download sops cli for macOS
curl -O -L -C - https://github.com/mozilla/sops/releases/download/v3.7.1/sops-v3.7.1.darwin
# move and rename the cli to /usr/bin
sudo mv sops-v3.7.1.darwin /usr/bin/sops
# make it executable
sudo chmod +x /usr/bin/sops
# latest macOS may prevent you from using SOPS CLI
# use System Preferences > Security & Privacy to whitelist SOPS
加密 Kubernetes Secret
首先,使用kubectl以下命令創(chuàng)建一個(gè)常規(guī)的 Kubernetes 密鑰:
# create the Kubernetes secret
kubectl create secret generic demo \
--from-literal mysecret=secret_value \
-o yaml \
--dry-run=client > secret.encoded.yml
# print the contents of secret.encoded.yml
cat secret.encoded.yml
# apiVersion: v1
# data:
# mysecret: c2VjcmV0X3ZhbHVl
# kind: Secret
# metadata:
# creationTimestamp: null
# name: demo
如您所見,密鑰存儲(chǔ)在其base64表示中。現(xiàn)在,使用 SOPS CLI 創(chuàng)建密鑰的加密變體。特別是在考慮在 Flux 中解密機(jī)密時(shí),請(qǐng)確保您提供--encrypted-regex參數(shù)并將加密限制為僅存儲(chǔ)在data和 中的值stringData。
# encrypt secret.encoded.yml using SOPS
sops --encrypt --encrypted-regex '^(data|stringData)$' \
--azure-kv $KEY_ID secret.encoded.yml > secret.encrypted.yml
# print the contents of secret.encrypted.yml
cat secret.encrypted.yml
# apiVersion: v1
# data:
# mysecret: ENC[AES256_GCM,data:gz/WAjWte3bCnNm6e+G4ow==,iv:VB4pAv833tDdD4n76h4CqEZNpGdwA3V1QGWp7PK/Jfc=,tag:CcUy3rti4XcWArmHANVS8Q==,type:str]
# kind: Secret
# metadata:
# creationTimestamp: null
# name: demo
# sops:
# kms: []
# gcp_kms: []
# azure_kv:
# - vault_url: https://kv-sops-sample.vault.azure.net
# name: sops-sample-key
# version: ee44c0c0cc9e4620aa4f4c86c4942047
# created_at: "2021-08-02T20:55:40Z"
# enc: EjszDACgiDP8rW3wzs-7fAmFzlAhCq0-R9YlA9cuPcq78EXEeNTC8OnlSdXQAGdGrgE9oylu1HKZa4RB9GxzzVDav8uNVPp67NPmC4-teeA5iRE4jqlp1An6sG6CpkZGcAmKWpfj_DEWecqrNGWSLTA2hI_HKwG5xNkFh9Myik6732W-XL65IFqgepcFrNIzeHetznO0j1iISNXqMeJjeCnZ6Qq0jcXUMIfQnXjAllKfjSukiT3A3GlWxP0j50Z328t-JHi5RowYHT-hC8FDOdR_U95sqnFd27RgEXmbDIU6IGvP3vmCiZJz4YQCPXaGhySvFY6qCEoCbCSC4RaoWw
# hc_vault: []
# age: []
# lastmodified: "2021-08-02T20:55:41Z"
# mac: ENC[AES256_GCM,data:AmKRnzoImfIzPa3JBcuxUKRrse5uZwJGukpLj1wxed3R7lsUN+QAV1+WkfNyeMoW5C3ek7j20Xpbvzi+MgP8zcQOwWSwA79Svgz3hKMn9eTRTfgU+4jYezIIHCwkv61MTN8RGW5AhOInYP8oRPW3zKD+SbBO/Jeu7SC+/oVn07I=,iv:S4Th+0quL84lhJtA/lugEv+iLc+WhWEYPSlXGWKhd/M=,tag:CUGg8+UM7gNSzfjJx1Ua1w==,type:str]
# pgp: []
# encrypted_regex: ^(data|stringData)$
# version: 3.7.1
默認(rèn)情況下,信息的加密版本包含有關(guān) Azure Key Vault 以及用于加密和解密的密鑰的基本信息。此信息使解密變得容易,您將在幾分鐘后看到。但是,您也可以提供自定義.sops.yaml配置文件以從實(shí)際機(jī)密文件中刪除此元數(shù)據(jù)。此時(shí),您可以刪除密鑰的編碼版本,并使用以下命令將加密版本添加到 git:
# delete encoded version of the secret
rm secret.encoded.yml
# add encrypted secret to source control and commit it
git add secret.encrypted.yml
git commit -m 'chore: add encrypted secret'
解密 Kubernetes Secrets 以進(jìn)行部署
要將密鑰部署到 Kubernetes,您必須對(duì)其進(jìn)行解密。同樣,SOPS CLI 可以提供幫助。解密后的密鑰可以直接通過管道傳輸?shù)絢ubectl部署,如以下代碼段所示:
# decrypt and deploy the secret
sops --decrypt secret.encrypted.yml | kubectl apply -f -
將密碼回顯服務(wù)器部署到 Kubernetes
將機(jī)密信息存儲(chǔ)在 Kubernetes 中,您可以配置 echo 容器,它將通過HTTP. 注意envFrom清單的一部分。先前創(chuàng)建的機(jī)密信息填充到環(huán)境變量:
apiVersion: v1
kind: Pod
metadata:
name: echo
labels:
app: echo
spec:
containers:
- image: thorstenhans/env-via-http:0.0.1
name: main
ports:
- containerPort: 5000
protocol: TCP
envFrom:
- secretRef:
name: demo
optional: true
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
cpu: 100m
memory: 48Mi
部署后,使用簡(jiǎn)單的端口轉(zhuǎn)發(fā)并curl驗(yàn)證部署:
# deploy the sample pod
kubectl apply -f pod.yml
# verify pod is running
kubectl get po
#
# NAME READY STATUS RESTARTS AGE
# echo-74bc9c6d74-vh5lr 1/1 Running 0 4m38s
# activate port forwarding
kubectl port-forward echo-74bc9c6d74-vh5lr --port 8080:5000
#
# Forwarding from 127.0.0.1:8080 -> 5000
# Forwarding from [::1]:8080 -> 5000
# start a new terminal session
# issue an HTTP request to the echo pod with curl
curl http://localhost:8080 | jq
您應(yīng)該獲得一個(gè)JSON包含 Pod 內(nèi)所有可用環(huán)境變量的對(duì)象,包括mysecret解密值為的環(huán)境變量secret_value。
{
"hostName": "echo-74bc9c6d74-vh5lr",
"envVars": [
"KUBERNETES_SERVICE_PORT=443",
"KUBERNETES_PORT=tcp://10.0.0.1:443",
"HOSTNAME=echo-74bc9c6d74-vh5lr",
"SHLVL=1",
"PORT=5000",
"HOME=/root",
"mysecret=secret_value",
"KUBERNETES_PORT_443_TCP_ADDR=10.0.0.1",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"KUBERNETES_PORT_443_TCP_PORT=443",
"KUBERNETES_PORT_443_TCP_PROTO=tcp",
"KUBERNETES_SERVICE_PORT_HTTPS=443",
"KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443",
"KUBERNETES_SERVICE_HOST=10.0.0.1",
"PWD=/"
]
}
結(jié)論
能夠在源代碼控制中安全地存儲(chǔ)機(jī)密信息非常好。SOPS 使加密和解密秘密的過程變得輕松。與 Azure Key Vault 等服務(wù)的無縫集成非常棒。團(tuán)隊(duì)會(huì)發(fā)現(xiàn)這種方法非常有用,尤其是在從傳統(tǒng)持續(xù)部署過渡到GitOps 期間。還值得一提的是,SOPS 與Flux無縫集成,F(xiàn)lux是基于 GitOps Toolkit 的最流行的持續(xù)交付解決方案之一。