Kubernetes 使用KMS驅(qū)動(dòng)進(jìn)行數(shù)據(jù)加密

2022-06-07 10:01 更新

使用 KMS 驅(qū)動(dòng)進(jìn)行數(shù)據(jù)加密

本頁(yè)展示了如何配置秘鑰管理服務(wù)—— Key Management Service (KMS) 驅(qū)動(dòng)和插件以啟用 Secret 數(shù)據(jù)加密。

在開(kāi)始之前

  • 你必須擁有一個(gè) Kubernetes 的集群,同時(shí)你的 Kubernetes 集群必須帶有 kubectl 命令行工具。 建議在至少有兩個(gè)節(jié)點(diǎn)的集群上運(yùn)行本教程,且這些節(jié)點(diǎn)不作為控制平面主機(jī)。 如果你還沒(méi)有集群,你可以通過(guò) Minikube 構(gòu)建一個(gè)你自己的集群,或者你可以使用下面任意一個(gè) Kubernetes 工具構(gòu)建:
  • 需要 Kubernetes 1.10.0 或更新版本
  • 需要 etcd v3 或更新版本

FEATURE STATE: Kubernetes v1.12 [beta]

KMS 加密驅(qū)動(dòng)使用封套加密模型來(lái)加密 etcd 中的數(shù)據(jù)。 數(shù)據(jù)使用數(shù)據(jù)加密秘鑰(DEK)加密;每次加密都生成一個(gè)新的 DEK。 這些 DEK 經(jīng)一個(gè)秘鑰加密秘鑰(KEK)加密后在一個(gè)遠(yuǎn)端的 KMS 中存儲(chǔ)和管理。 KMS 驅(qū)動(dòng)使用 gRPC 與一個(gè)特定的 KMS 插件通信。這個(gè) KMS 插件作為一個(gè) gRPC 服務(wù)器被部署在 Kubernetes 主服務(wù)器的同一個(gè)主機(jī)上,負(fù)責(zé)與遠(yuǎn)端 KMS 的通信。

配置 KMS 驅(qū)動(dòng)

為了在 API 服務(wù)器上配置 KMS 驅(qū)動(dòng),在加密配置文件中的驅(qū)動(dòng)數(shù)組中加入一個(gè)類(lèi)型為 ?kms ?的驅(qū)動(dòng),并設(shè)置下列屬性:

  • ?name?: KMS 插件的顯示名稱(chēng)。
  • ?endpoint?: gRPC 服務(wù)器(KMS 插件)的監(jiān)聽(tīng)地址。該端點(diǎn)是一個(gè) UNIX 域套接字。
  • ?cachesize?: 以明文緩存的數(shù)據(jù)加密秘鑰(DEKs)的數(shù)量。一旦被緩存, 就可以直接使用 DEKs 而無(wú)需另外調(diào)用 KMS;而未被緩存的 DEKs 需要調(diào)用一次 KMS 才能解包。
  • ?timeout?: 在返回一個(gè)錯(cuò)誤之前,kube-apiserver 等待 kms-plugin 響應(yīng)的時(shí)間(默認(rèn)是 3 秒)。

實(shí)現(xiàn) KMS 插件

為實(shí)現(xiàn)一個(gè) KMS 插件,你可以開(kāi)發(fā)一個(gè)新的插件 gRPC 服務(wù)器或啟用一個(gè)由你的云服務(wù)驅(qū)動(dòng)提供的 KMS 插件。 你可以將這個(gè)插件與遠(yuǎn)程 KMS 集成,并把它部署到 Kubernetes 的主服務(wù)器上。

啟用由云服務(wù)驅(qū)動(dòng)支持的 KMS

有關(guān)啟用云服務(wù)驅(qū)動(dòng)特定的 KMS 插件的說(shuō)明,請(qǐng)咨詢你的云服務(wù)驅(qū)動(dòng)商。

開(kāi)發(fā) KMS 插件 gRPC 服務(wù)器

你可以使用 Go 語(yǔ)言的存根文件開(kāi)發(fā) KMS 插件 gRPC 服務(wù)器。 對(duì)于其他語(yǔ)言,你可以用 proto 文件創(chuàng)建可以用于開(kāi)發(fā) gRPC 服務(wù)器代碼的存根文件。

  • 使用 Go:使用存根文件 service.pb.go 中的函數(shù)和數(shù)據(jù)結(jié)構(gòu)開(kāi)發(fā) gRPC 服務(wù)器代碼。
  • 使用 Go 以外的其他語(yǔ)言:用 protoc 編譯器編譯 proto 文件: service.proto 為指定語(yǔ)言生成存根文件。

然后使用存根文件中的函數(shù)和數(shù)據(jù)結(jié)構(gòu)開(kāi)發(fā)服務(wù)器代碼。

注意:

  • kms 插件版本:?v1beta1 ?
  • 作為對(duì)過(guò)程調(diào)用 Version 的響應(yīng),兼容的 KMS 插件應(yīng)把 v1beta1 作為 VersionResponse.version 返回

  • 消息版本:?v1beta1 ?
  • 所有來(lái)自 KMS 驅(qū)動(dòng)的消息都把 version 字段設(shè)置為當(dāng)前版本 v1beta1

  • 協(xié)議:UNIX 域套接字 (?unix?)
  • gRPC 服務(wù)器應(yīng)監(jiān)聽(tīng) UNIX 域套接字

將 KMS 插件與遠(yuǎn)程 KMS 整合

KMS 插件可以用任何受 KMS 支持的協(xié)議與遠(yuǎn)程 KMS 通信。 所有的配置數(shù)據(jù),包括 KMS 插件用于與遠(yuǎn)程 KMS 通信的認(rèn)證憑據(jù),都由 KMS 插件獨(dú)立地存儲(chǔ)和管理。 KMS 插件可以用額外的元數(shù)據(jù)對(duì)密文進(jìn)行編碼,這些元數(shù)據(jù)是在把它發(fā)往 KMS 進(jìn)行解密之前可能要用到的。

部署 KMS 插件 

確保 KMS 插件與 Kubernetes 主服務(wù)器運(yùn)行在同一主機(jī)上。

使用 KMS 驅(qū)動(dòng)加密數(shù)據(jù)

為了加密數(shù)據(jù):

  1. 使用 ?kms ?驅(qū)動(dòng)的相應(yīng)的屬性創(chuàng)建一個(gè)新的加密配置文件:
  2. kind: EncryptionConfiguration
    apiVersion: apiserver.config.k8s.io/v1
    resources:
      - resources:
        - secrets
        providers:
        - kms:
            name: myKmsPlugin
            endpoint: unix:///tmp/socketfile.sock
            cachesize: 100
            timeout: 3s
        - identity: {}
  3. 設(shè)置 kube-apiserver 的 ?--encryption-provider-config? 參數(shù)指向配置文件的位置。
  4. 重啟 API 服務(wù)器。

驗(yàn)證數(shù)據(jù)已經(jīng)加密 

寫(xiě)入 etcd 時(shí)數(shù)據(jù)被加密。重啟 kube-apiserver 后,任何新建或更新的 Secret 在存儲(chǔ)時(shí)應(yīng)該已被加密。 要驗(yàn)證這點(diǎn),你可以用 etcdctl 命令行程序獲取 Secret 內(nèi)容。

  1. 在默認(rèn)的命名空間里創(chuàng)建一個(gè)名為 secret1 的 Secret:
  2. kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
    
  3. 用 etcdctl 命令行,從 etcd 讀取出 Secret:
  4. ETCDCTL_API=3 etcdctl get /kubernetes.io/secrets/default/secret1 [...] | hexdump -C
    

    其中 ?[...]? 是用于連接 etcd 服務(wù)器的額外參數(shù)。

  5. 驗(yàn)證保存的 Secret 是否是以 ?k8s:enc:kms:v1:? 開(kāi)頭的,這表明 ?kms ?驅(qū)動(dòng)已經(jīng)對(duì)結(jié)果數(shù)據(jù)加密。
  6. 驗(yàn)證 Secret 在被 API 獲取時(shí)已被正確解密:
  7. kubectl describe secret secret1 -n default
    

    結(jié)果應(yīng)該是 ?mykey: mydata?。

確保所有 Secret 都已被加密

因?yàn)?nbsp;Secret 是在寫(xiě)入時(shí)被加密的,所以在更新 Secret 時(shí)也會(huì)加密該內(nèi)容。

下列命令讀取所有 Secret 并更新它們以便應(yīng)用服務(wù)器端加密。如果因?yàn)閷?xiě)入沖突導(dǎo)致錯(cuò)誤發(fā)生, 請(qǐng)重試此命令。對(duì)較大的集群,你可能希望根據(jù)命名空間或腳本更新去細(xì)分 Secret 內(nèi)容。

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

從本地加密驅(qū)動(dòng)切換到 KMS 驅(qū)動(dòng) 

為了從本地加密驅(qū)動(dòng)切換到 ?kms ?驅(qū)動(dòng)并重新加密所有 Secret 內(nèi)容:

  1. 在配置文件中加入 ?kms ?驅(qū)動(dòng)作為第一個(gè)條目,如下列樣例所示
  2. kind: EncryptionConfiguration
    apiVersion: apiserver.config.k8s.io/v1
    resources:
      - resources:
        - secrets
        providers:
        - kms:
            name : myKmsPlugin
            endpoint: unix:///tmp/socketfile.sock
            cachesize: 100
        - aescbc:
             keys:
             - name: key1
               secret: <BASE 64 ENCODED SECRET>
  3. 重啟所有 kube-apiserver 進(jìn)程。
  4. 運(yùn)行下列命令使用 ?kms ?驅(qū)動(dòng)強(qiáng)制重新加密所有 Secret。
  5. kubectl get secrets --all-namespaces -o json| kubectl replace -f -
    

禁用靜態(tài)數(shù)據(jù)加密

要禁用靜態(tài)數(shù)據(jù)加密:

  1. 將 ?identity ?驅(qū)動(dòng)作為配置文件中的第一個(gè)條目:
  2. kind: EncryptionConfiguration
    apiVersion: apiserver.config.k8s.io/v1
    resources:
      - resources:
        - secrets
        providers:
        - identity: {}
        - kms:
            name : myKmsPlugin
            endpoint: unix:///tmp/socketfile.sock
            cachesize: 100
  3. 重啟所有 kube-apiserver 進(jìn)程。
  4. 運(yùn)行下列命令強(qiáng)制重新加密所有 Secret。
  5. kubectl get secrets --all-namespaces -o json | kubectl replace -f -
    


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)