csi-driver-spiffe
csi-driver-spiffe 是一個 Kubernetes 的容器儲存介面 (CSI) 驅動程式外掛,設計為與 cert-manager 協同運作。
它以透明的方式將 SPIFFE SVID(以 X.509 憑證金鑰對的形式)傳遞給掛載的 Kubernetes Pod。
最終結果是,Kubernetes 中運行的任何和所有 Pod 都可以透過最少的配置,安全地從信任網域請求 SPIFFE 身分證明文件。
這些文件依序具有以下屬性
- 自動續約 ✔️
- 私鑰永遠不會離開節點的虛擬記憶體 ✔️
- 每個 Pod 的文件都是唯一的 ✔️
- 該文件與 Pod 共享相同的生命週期,並在 Pod 終止時銷毀 ✔️
- 在信任網域內啟用 mTLS ✔️
...volumeMounts:- mountPath: "/var/run/secrets/spiffe.io"name: spiffevolumes:- name: spiffecsi:driver: spiffe.csi.cert-manager.ioreadOnly: true
元件
該專案分為兩個元件:驅動程式和批准者。
CSI 驅動程式
CSI 驅動程式以 DaemonSet 形式在叢集上運行,負責產生、請求和掛載憑證和私鑰到其管理的節點上的 Pod。CSI 驅動程式會建立並管理一個 tmpfs 目錄。
當使用 CSI 磁碟區配置建立 Pod 時,驅動程式會在本地產生一個私鑰,並在與 Pod 相同的命名空間中建立一個 cert-manager CertificateRequest。
驅動程式使用 CSI 權杖請求。這表示正在建立的 Pod 的權杖會傳遞給驅動程式。
此權杖的詳細資訊會用於建立代表 Pod 身分的 SPIFFE ID,而該權杖則會用於建立 SVID 的實際 CertificateRequest。
一旦憑證由已配置的 cert-manager 發行者簽署,驅動程式會將私鑰和憑證掛載到 Pod 的磁碟區中,並監看憑證以根據憑證的到期日續約憑證和私鑰。
批准者
一個獨立的 cert-manager 批准者部署負責管理 csi-driver-spiffe CertificateRequests 的批准和拒絕。
批准者確保請求具有
- 可接受的金鑰用法 (金鑰加密、數位簽章、用戶端驗證、伺服器驗證);
- 與強制持續時間 (預設為 1 小時) 相符的請求持續時間;
- 沒有 SAN 或其他可識別屬性,但單一 URI SAN 除外;
- 一個 URI SAN,它是建立 CertificateRequest 的 ServiceAccount 的 SPIFFE 身分;
- 與啟動時配置的相符的 SPIFFE ID 信任網域。
批准者只會考慮具有 spiffe.csi.cert-manager.io/identity
註釋的 CertificateRequests,該註釋由 csi-driver-spiffe 新增到其建立的所有請求。
安裝
請參閱安裝指南,以取得有關如何安裝 csi-driver-spiffe 的說明。
安全考量
csi-driver-spiffe 處理應該保密的極有價值的憑證。使用 Kubernetes CSI 磁碟區的設計使得可以輕鬆地將存取權限限制為僅限掛載 CSI 磁碟區的 Pod,但仍應小心不要洩露 csi-driver-spiffe 建立的私鑰。
csi-driver-spiffe 一律使用它正在簽發的 Pod 的權杖,來建立其建立的 SVID 的 CertificateRequest 資源。這表示
- 在簽發期間,csi-driver-spiffe 能夠執行 Pod 可以執行的任何操作;請注意,遭入侵的 csi-driver-spiffe Pod 可能會濫用這些權限,儘管在正常運作中僅使用 CertificateRequest 權限。
- 重要的是:所有使用 csi-driver-spiffe 的 Pod 都必須擁有建立 CertificateRequest 資源的權限。
Pod 必須擁有建立 CertificateRequests 權限的要求具有重要的安全含義。如果具有這些權限的 Pod 遭到入侵,它可以建立任意 CertificateRequest 資源,這些資源可能會參考叢集中的任意發行者。
由於 csi-driver-spiffe 要求在叢集內使用批准,因此此風險會透過批准來減輕。
不過,重要的是,叢集中的任何其他形式的批准(例如 approver-policy)都要仔細配置,以免與 csi-driver-spiffe 批准者重疊,並限制對其他發行者的存取。
例如,如果一個允許任何 Pod 使用 ACME (Let's Encrypt) 發行者發行的 approver-policy CertificateRequestPolicy
資源,可能會允許遭入侵的 Pod 發行公開信任的憑證,前提是該 Pod 使用 csi-driver-spiffe,因此擁有建立 CertificateRequest 資源的權限。
安全地使用 csi-driver-spiffe 表示要考慮叢集中有哪些可用的批准方法,並仔細配置這些批准者,以確保 Pod 無法鎖定它們不應該使用的發行者。
用法
一旦驅動程式成功安裝,Pod 就可以開始請求和掛載其金鑰和 SPIFFE 憑證。由於在建立 CertificateRequests 時會模擬 Pod 的 ServiceAccount,因此每個打算使用此磁碟區的 ServiceAccount 都必須擁有該權限。
具有虛擬部署的範例資訊清單
kubectl apply -f https://raw.githubusercontent.com/cert-manager/csi-driver-spiffe/ed646ccf28b1ecdf63f628bf16f1d350a9b850c1/deploy/example/example-app.yamlkubectl exec -n sandbox \$(kubectl get pod -n sandbox -l app=my-csi-app -o jsonpath='{.items[0].metadata.name}') \-- \cat /var/run/secrets/spiffe.io/tls.crt | \openssl x509 --noout --text | \grep "Issuer:"# expected output: Issuer: CN = csi-driver-spiffe-cakubectl exec -n sandbox \$(kubectl get pod -n sandbox -l app=my-csi-app -o jsonpath='{.items[0].metadata.name}') \-- \cat /var/run/secrets/spiffe.io/tls.crt | \openssl x509 --noout --text | \grep "URI:"# expected output: URI:spiffe://foo.bar/ns/sandbox/sa/example-app
執行階段設定
如果 csi-driver-spiffe 在啟用了執行階段設定的情況下安裝,它將監看一個名為 ConfigMap 的發行者配置。如果該 ConfigMap 存在且包含有效的發行者參考,則該發行者將用於所有建立的 CertificateRequest 資源。
如果 ConfigMap 已刪除或不包含有效的發行者參考,則會被忽略。如果在安裝時指定了預設發行者,則該預設值將用作後備。如果沒有提供有效的執行階段設定,也沒有指定預設發行者,則在配置有效發行者之前,將會失敗發行(以及因此 Pod 的建立)。
執行階段設定 ConfigMap 的名稱是在安裝時使用 app.runtimeIssuanceConfigMap
Helm 值設定的。有效的 ConfigMap 必須包含 issuer-name
、issuer-kind
和 issuer-group
金鑰。
以下是建立一個名為 my-issuer-name
的 ClusterIssuer 的 ConfigMap 範例
kubectl create configmap spiffe-issuer -n cert-manager \--from-literal=issuer-name=my-issuer-name \--from-literal=issuer-kind=ClusterIssuer \--from-literal=issuer-group=cert-manager.io
FS-群組
當以指定的用戶或群組執行 Pod 時,由於基於 Unix 的檔案系統權限,預設情況下磁碟區將無法讀取。可以使用以下磁碟區屬性指定掛載的磁碟區檔案群組
...securityContext:runAsUser: 123runAsGroup: 456volumes:- name: spiffecsi:driver: spiffe.csi.cert-manager.ioreadOnly: truevolumeAttributes:spiffe.csi.cert-manager.io/fs-group: "456"
kubectl apply -f https://raw.githubusercontent.com/cert-manager/csi-driver-spiffe/ed646ccf28b1ecdf63f628bf16f1d350a9b850c1/deploy/example/fs-group-app.yamlkubectl exec -n sandbox $(kubectl get pod -n sandbox -l app=my-csi-app-fs-group -o jsonpath='{.items[0].metadata.name}') -- cat /var/run/secrets/spiffe.io/tls.crt | openssl x509 --noout --text | grep URI:# expected output: URI:spiffe://foo.bar/ns/sandbox/sa/fs-group-app
根 CA 捆綁包
⚠️ 此功能的功能遠不如 trust-manager,而且更難以使用和更新。建議改用 trust-manager。
預設情況下,CSI 驅動程式只會掛載 Pod 的私鑰和已簽署的憑證。csi-driver-spiffe 可以選擇配置為也從將寫入所有 Pod 磁碟區的磁碟區掛載靜態定義的 CA 捆綁包。
如果 CSI 驅動程式偵測到此捆綁包已變更(透過覆寫、續約等),新的捆綁包將寫入所有現有的磁碟區。
以下範例掛載 Trust Domain ClusterIssuer 使用的 CA 憑證。
helm upgrade -i -n cert-manager cert-manager-csi-driver-spiffe jetstack/cert-manager-csi-driver-spiffe --wait \--set "app.logLevel=1" \--set "app.trustDomain=my.trust.domain" \\--set "app.runtimeIssuanceConfigMap=spiffe-issuer"--set "app.issuer.name=csi-driver-spiffe-ca" \--set "app.issuer.kind=ClusterIssuer" \--set "app.issuer.group=cert-manager.io" \\--set "app.driver.volumes[0].name=root-cas" \--set "app.driver.volumes[0].secret.secretName=csi-driver-spiffe-ca" \--set "app.driver.volumeMounts[0].name=root-cas" \--set "app.driver.volumeMounts[0].mountPath=/var/run/secrets/cert-manager-csi-driver-spiffe" \--set "app.driver.sourceCABundle=/var/run/secrets/cert-manager-csi-driver-spiffe/ca.crt"kubectl rollout restart deployment -n sandbox my-csi-appkubectl exec -it -n sandbox $(kubectl get pod -n sandbox -l app=my-csi-app -o jsonpath='{.items[0].metadata.name}') -- ls /var/run/secrets/spiffe.io/# expected output: ca.crt tls.crt tls.key