成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

關(guān)于 Kubernetes 的 Secret 并不安全這件事

系統(tǒng) Linux
Secret 其實并不安全,稍微用 kubectl 查看過 Secret 的人都知道,我們可以非常方便的看到 Secret 的原文,只要有相關(guān)的權(quán)限即可,盡管它的內(nèi)容是 base64 編碼的,這基本上等同于明文。

 K8s 提供了 Secret 資源供我們來保存、設置一些敏感信息,比如 API endpoint 地址,各種用戶密碼或 token 之類的信息。在沒有使用 K8s 的時候,這些信息可能是通過配置文件或者環(huán)境變量在部署的時候設置的。

不過,Secret 其實并不安全,稍微用 kubectl 查看過 Secret 的人都知道,我們可以非常方便的看到 Secret 的原文,只要有相關(guān)的權(quán)限即可,盡管它的內(nèi)容是 base64 編碼的,這基本上等同于明文。

所以說,K8s 原生的 Secret 是非常簡單的,不是特別適合在大型公司里直接使用,對 RBAC 的挑戰(zhàn)也比較大,很多不該看到明文信息的人可能都能看到。

尤其是現(xiàn)在很多公司采用了所謂的 GitOps 理念,很多東西都需要放到 VCS,比如 git 中,這一問題就更日益突出,因為 VCS 也得需要設置必要的權(quán)限。

問題

簡單來說,大概有幾個地方都可以讓不應該看到 Secret 內(nèi)容的人獲得 Secret 內(nèi)容:

  •  etcd 存儲
  •  通過 API server
  •  在 node 上直接查看文件

這里我們以這個例子來看一下 Secret 在 K8s 中的使用情況。

Secret 定義, 用戶名和密碼分別為 admin 和 hello-secret: 

  1. apiVersion: v1  
  2. kind: Secret  
  3. metadata:  
  4.   name: mysecret  
  5. type: Opaque  
  6. data:  
  7.   username: YWRtaW4 
  8.   passwordaGVsbG8tc2VjcmV0Cg== 

Pod 定義,這里我們將 Secret 作為 volume mount 到容器中。 

  1. apiVersion: v1  
  2. kind: Pod  
  3. metadata:  
  4.   name: mypod  
  5. spec:  
  6.   containers:  
  7.   - name: mypod  
  8.     image: docker.io/containerstack/alpine-stress  
  9.     command:  
  10.       - top  
  11.     volumeMounts:  
  12.     - name: foo  
  13.       mountPath: "/etc/foo"  
  14.       readOnly: true  
  15.   volumes:  
  16.   - name: foo  
  17.     secret:  
  18.       secretName: mysecret 

Pod 啟動后,我們可以到容器中來查看 Secret 作為 volume mount 到容器后的文件內(nèi)容。 

  1. $ kubectl exec -it mypod sh  
  2. / # cd /etc/foo/  
  3. /etc/foo # ls -tal  
  4. total 4  
  5. drwxr-xr-x    1 root     root          4096 Apr 14 08:55 ..  
  6. drwxrwxrwt    3 root     root           120 Apr 14 08:55 .  
  7. drwxr-xr-x    2 root     root            80 Apr 14 08:55 ..2021_04_14_08_55_54.401661151  
  8. lrwxrwxrwx    1 root     root            31 Apr 14 08:55 ..data -> ..2021_04_14_08_55_54.401661151  
  9. lrwxrwxrwx    1 root     root            15 Apr 14 08:55 password -> ..data/password  
  10. lrwxrwxrwx    1 root     root            15 Apr 14 08:55 username -> ..data/username  
  11. /etc/foo # ls -tal ..2021_04_14_08_55_54.401661151  
  12. total 8  
  13. drwxr-xr-x    2 root     root            80 Apr 14 08:55 .  
  14. drwxrwxrwt    3 root     root           120 Apr 14 08:55 ..  
  15. -rw-r--r--    1 root     root            13 Apr 14 08:55 password  
  16. -rw-r--r--    1 root     root             5 Apr 14 08:55 username  
  17. /etc/foo # cat password  
  18. hello-secret  
  19. /etc/foo #  

etcd 存儲

API server 中的資源都保存在 etcd 中,我們可以直接從文件看到相關(guān)內(nèi)容: 

  1. # hexdump -C /var/lib/etcd/member/snap/db | grep -A 5 -B 5 hello  
  2. 00043640  12 00 1a 07 64 65 66 61  75 6c 74 22 00 2a 24 32  |....default".*$2|  
  3. 00043650  35 66 37 35 38 30 38 2d  37 33 31 33 2d 34 38 64  |5f75808-7313-48d|  
  4. 00043660  39 2d 39 61 38 65 2d 38  61 35 66 66 32 32 63 64  |9-9a8e-8a5ff22cd|  
  5. 00043670  64 35 39 32 00 38 00 42  08 08 98 dc da 83 06 10  |d592.8.B........|  
  6. 00043680  00 7a 00 12 19 0a 08 70  61 73 73 77 6f 72 64 12  |.z.....password.|  
  7. 00043690  0d 68 65 6c 6c 6f 2d 73  65 63 72 65 74 0a 12 11  |.hello-secret...|  
  8. 000436a0  0a 08 75 73 65 72 6e 61  6d 65 12 05 61 64 6d 69  |..username..admi|  
  9. 000436b0  6e 1a 06 4f 70 61 71 75  65 1a 00 22 00 00 00 00  |n..Opaque.."....|  
  10. 000436c0  00 00 00 08 95 5f 00 00  00 00 00 00 00 00 0a 37  |....._.........7|  
  11. 000436d0  2f 72 65 67 69 73 74 72  79 2f 73 65 72 76 69 63  |/registry/servic|  
  12. 000436e0  65 73 2f 65 6e 64 70 6f  69 6e 74 73 2f 6b 75 62  |es/endpoints/kub| 

可以看到,基本 yaml 中的內(nèi)容都是明文存放的,而且是進行 base64 解碼之后的內(nèi)容。

使用下面的命令也可以獲得類似的結(jié)果。 

  1. ETCDCTL_API=3 etcdctl get --prefix /registry/secrets/default/mysecret | hexdump -C 

etcd 本來存儲的是明文數(shù)據(jù),這個好像已經(jīng)從 1.7 開始支持加密存儲了,而且直接訪問 etcd 從物理上來說也不是那么容易。

API server

通過 API server 則簡單的多,只要有權(quán)限就可以從任何節(jié)點上通過訪問 API server 來得到 secret 的明文內(nèi)容。 

  1. $ kubectl get secret mysecret -o yaml  
  2. apiVersion: v1  
  3. data:  
  4.   password: aGVsbG8tc2VjcmV0Cg==  
  5.   username: YWRtaW4 
  6. kind: Secret  
  7. metadata:  
  8.   creationTimestamp: "2021-04-14T08:55:52Z"  
  9.   name: mysecret  
  10.   namespace: default  
  11.   resourceVersion: "2196"  
  12.   selfLink: /api/v1/namespaces/default/secrets/mysecret  
  13.   uid: 25f75808-7313-48d9-9a8e-8a5ff22cdd59  
  14. type: Opaque 

節(jié)點上

在節(jié)點上也可以看到 Secret 文件的內(nèi)容。

查找 foo volume 的掛載點: 

  1. # mount | grep foo   
  2. tmpfs on /var/lib/kubelet/pods/280451e8-512b-489c-b5dd-df2b1a3c9b29/volumes/kubernetes.io~secret/foo type tmpfs (rw,relatime)  

查看這個 volume 下面的文件內(nèi)容: 

  1. # ls -tal /var/lib/kubelet/pods/280451e8-512b-489c-b5dd-df2b1a3c9b29/volumes/kubernetes.io~secret/foo  
  2. total 4  
  3. drwxrwxrwt 3 root root  120 4月  14 16:55 .  
  4. drwxr-xr-x 2 root root   80 4月  14 16:55 ..2021_04_14_08_55_54.401661151  
  5. lrwxrwxrwx 1 root root   31 4月  14 16:55 ..data -> ..2021_04_14_08_55_54.401661151  
  6. lrwxrwxrwx 1 root root   15 4月  14 16:55 password -> ..data/password  
  7. lrwxrwxrwx 1 root root   15 4月  14 16:55 username -> ..data/username  
  8. drwxr-xr-x 4 root root 4096 4月  14 16:55 ..  
  9. # cat /var/lib/kubelet/pods/280451e8-512b-489c-b5dd-df2b1a3c9b29/volumes/kubernetes.io~secret/foo/password  
  10. hello-secret 

第三方方案

針對上面提到的可能泄露 Secret 的幾點,大概解決方案不難想到如下幾種:

  •  etcd 加密
  •  API server 嚴格進行權(quán)限設計
  •  強化 node 節(jié)點用戶權(quán)限管理和系統(tǒng)安全

不過,要相關(guān)確保 Secret 的絕對安全,上面這幾種方案都是必須,缺一不可,缺少了那一個都相當于在墻上留了一個洞。

社區(qū)和公有云提供商都有一些產(chǎn)品和方案,我們可以參考一下。

  •  shyiko/kubesec: Secure Secret management for Kubernetes (with gpg, Google Cloud KMS and AWS KMS backends)
  •  bitnami-labs/sealed-secrets: A Kubernetes controller and tool for one-way encrypted Secrets
  •  Vault by HashiCorp
  •  mozilla/sops
  •  Kubernetes External Secrets
  •  Kamus

shyiko/kubesec

kubesec 只對 Secret 中數(shù)據(jù)進行加密/解密,支持如下 key 管理服務或軟件:

  •  AWS Key Management Service
  •  Google Cloud KMS
  •  GnuPG

bitnami-labs/sealed-secrets

Bitnami 在 K8s 領(lǐng)域也是一家人人知曉的公司,輸出了很多技術(shù)和最佳實踐。

本圖來自 Sealed Secrets: Protecting your passwords before they reach Kubernetes

SealeSecret 將 secret 資源整個加密保存為 SealedSecret 資源,而解密只能由該集群中的 controller 進行。

SealeSecret 提供了一個 kubeseal 工具來對 secret 資源進行加密,這個過程需要一個公開 key(公鑰),這個公開 key 就是從 SealeSecret controller 拿到的。

不過,只從從說明文檔來看, SealeSecret controller 加密解密所依賴的 key,也是通過普通的 Secret 來保存的,這難道不是一個問題?同時也增加了 SealeSecret controller 的運維成本。

mozilla/sops

嚴格來說, sops 跟 K8s 并沒有什么必然關(guān)系,它只是一個支持 YAML/JSON/ENV/INI 等文件格式的加密文件編輯器,它支持 AWS KMS, GCP KMS, Azure Key Vault, age, 和 PGP 等服務與應用。

如果有有興趣可以看它的主頁。

Kubernetes External Secrets

Kubernetes External Secrets 是知名域名服務提供商 godaddy 開發(fā)的開源軟件,它可以直接將保存在外部 KMS 中的機密信息傳給 K8s 。目前支持的 KSM 包括:

  •  AWS Secrets Manager
  •  AWS System Manager
  •  Hashicorp Vault
  •  Azure Key Vault
  •  GCP Secret Manager
  • Alibaba Cloud KMS Secret Manager

它通過自定義 controller 和 CRD 來實現(xiàn),具體架構(gòu)圖如下:

具體來說用戶需要創(chuàng)建一個 ExternalSecret 類型的資源,來將外部 KMS 的數(shù)據(jù)映射到 K8s 的 Secret 上。

不過,這種方式大概只有兩點好處:

  • 統(tǒng)一 key 的管理,或者沿用既有 key 資產(chǎn)
  • key 信息不想放到 VCS 等

對于防止 Sercet 信息泄露,作用不大,因為其明文資源還是可以在 API server/etcd 上看到。

或者說,External Secrets 真正做的事情,也就是從外部 KMS 中的 key ,映射成 K8s 中的 Secret 資源而已,對保證在 K8s 集群中數(shù)據(jù)的安全性用處不大。

Kamus

Kamus 同樣提供了加密 key 的方法(一個命令行工具),同時只有通過 K8s 中的 controller 才能對這個 key 進行解密。不過它 保存在 K8s 中的 Secret 是加密的狀態(tài),用戶不能像 External Secrets 那樣直接獲得 Secret 的明文內(nèi)容。

Kamus 由 3 個組件組成,分別是:

  •  Encrypt API
  •  Decrypt API
  •  Key Management System (KMS)

KMS 是一個外部加密服務的封裝,目前支持如下服務:- AES - AWS KMS - Azure KeyVault - Google Cloud KMS

Kamus 以 service account 為單位對 secret 進行加密,之后 Pod 會通過 service account 來請求 Kamus 的解密服務來對該 secret 進行解密。

對 K8s 來說,解密 secret 可以通過 init container 來實現(xiàn):定義一個 基于內(nèi)存的 emptyDir ,業(yè)務容器和 init 容器使用同一個 volume, init 容器解密后,將數(shù)據(jù)存放到該 volume 下,之后業(yè)務容器就可以使用解密后的 secret 數(shù)據(jù)了。

Vault by HashiCorp

HashiCorp 公司就不多說,在云計算/DevOps領(lǐng)域也算是數(shù)一數(shù)二的公司了。

Vault 本身就是一個 KMS 類似的服務,用于管理機密數(shù)據(jù)。對于 K8s 的原生 secret ,大概提供了如下兩種方式的支持:

  •  Agent Sidecar Injector/vault-k8s
  •  Vault CSI Provider

Agent Sidecar Injector

這種方式和上面的 Kamus 類似,也是需要兩個組件:

  •  Mutation webhook:

          負責修改 pod 定義,注入init/sidecar

  •  agent-sidecar:

           負責獲取和解密數(shù)據(jù),將數(shù)據(jù)保存到指定的 volume/路徑下

Vault agent sidecar injector 不僅提供了 init container 來初始化 secret ,還通過 sidecar 來定期更新 secret ,這樣就非常接近原生 secret 的實現(xiàn)了。

應用程序則只需要在文件系統(tǒng)上讀取指定的文件就可以了,而不必關(guān)系如何從外部獲取加密信息。

這是官方 blog 中的一個示例:

Pod 信息: 

  1. spec:  
  2.   template:  
  3.     metadata:  
  4.       annotations:  
  5.         vault.hashicorp.com/agent-inject: "true"  
  6.         vault.hashicorp.com/agent-inject-secret-helloworld: "secrets/helloworld"  
  7.         vault.hashicorp.com/role: "myapp" 

這個定義中,vault-k8s 會對該 pod 注入 vault agent,并使用 secrets/helloworld 來初始化。Pod 運行后,可以在 /vault/secrets 下找到一個名為 helloworld 的文件。 

  1. $ kubectl exec -ti app-XXXXXXXXX -c app -- cat /vault/secrets/helloworld  
  2. data: map[password:foobarbazpass username:foobaruser]  
  3. metadata: map[created_time:2019-12-16T01:01:58.869828167Z deletion_time: destroyed:false version:1] 

當然這個數(shù)據(jù)是raw data,沒有經(jīng)過格式化。如果想指定輸出到文件中的格式,可以使用 vault 的模板功能。

Vault CSI Provider

這部分可以參考下面的社區(qū)方案部分。

社區(qū)方案

當然,社區(qū)沒有理由意識不到原生 secret 的問題,因此社區(qū)也有 Kubernetes Secrets Store CSI Driver ,一種通過 CSI 接口將 Secret 集成到 K8s 的方案。

Secrets Store CSI driver(secrets-store.csi.k8s.io)可以讓 K8s mount 多個 secret 以 volume 的形式,從外部 KMS mount 到 Pod 里。

要想使用 Secrets Store CSI Driver ,大致過程如下:

  •  定義 SecretProviderClass 
  1. apiVersion: secrets-store.csi.x-k8s.io/v1alpha1  
  2. kind: SecretProviderClass  
  3. metadata:  
  4.   name: my-provider  
  5. spec: 
  6.   provider: vault   # accepted provider options: azure or vault or gcp  
  7.   parameters:       # provider-specific parameters 
  •  為 Pod 配置 Volume 
  1. kind: Pod  
  2. apiVersion: v1  
  3. metadata:  
  4.   name: secrets-store-inline  
  5. spec:  
  6.   containers:  
  7.   - image: k8s.gcr.io/e2e-test-images/busybox:1.29  
  8.     name: busybox  
  9.     command:  
  10.     - "/bin/sleep"  
  11.     - "10000"  
  12.     volumeMounts:  
  13.     - name: secrets-store-inline  
  14.       mountPath: "/mnt/secrets-store"  
  15.       readOnly: true  
  16.   volumes:  
  17.     - name: secrets-store-inline  
  18.       csi:  
  19.         driver: secrets-store.csi.k8s.io  
  20.         readOnly: true  
  21.         volumeAttributes:  
  22.           secretProviderClass: "my-provider" 

Pod 啟動之后,就可以確認解密后的數(shù)據(jù)了: 

  1. $ kubectl exec secrets-store-inline -- ls /mnt/secrets-store/  
  2. foo 

總結(jié)

上面的總結(jié)都是基于互聯(lián)網(wǎng)公開的資料而來,并沒有經(jīng)過親身體驗,因此有些地方可能理解有誤,要想深入了解還需要自己親手確認最好。

不過總體來說,社區(qū)這種方案可能最簡單,部署也不是很麻煩,只是這就和原生的 secret 基本沒什么關(guān)系了。。。 

 

責任編輯:龐桂玉 來源: 奇妙的Linux世界
相關(guān)推薦

2015-05-27 13:19:23

2020-11-13 11:27:04

短信驗證

2015-07-01 14:48:51

2015-07-06 14:32:10

2018-03-12 13:47:27

2023-06-01 19:24:16

2023-10-19 10:43:38

2018-07-10 08:56:19

編程程序員開發(fā)

2012-04-16 10:12:54

Java線程

2020-11-03 12:32:25

影子物聯(lián)網(wǎng)物聯(lián)網(wǎng)IOT

2020-04-22 20:35:02

HashMap線程安全

2021-04-04 23:16:52

安全刷臉銀行

2009-08-03 16:58:59

C#不安全代碼

2024-01-19 08:42:45

Java線程字符串

2023-05-12 17:45:15

MySQL索引排序

2014-04-09 09:37:29

2014-09-12 17:44:23

2020-04-23 10:36:45

容器云安全云計算

2018-01-26 10:49:19

2009-11-12 08:38:34

點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 一区二区三区视频免费看 | 欧美国产精品 | 亚洲高清视频在线观看 | 草久在线视频 | 亚洲一区在线免费观看 | 91精品国产综合久久福利软件 | 成人依人 | 三级av免费 | 免费成人高清在线视频 | 古装三级在线播放 | 欧美一级片久久 | 精精国产xxxx视频在线野外 | 久久精品亚洲精品 | 91午夜在线| 午夜精品视频在线观看 | 日韩中文一区 | 国产精品久久久久久婷婷天堂 | 天天插日日操 | 亚洲网站在线播放 | 中文字幕精品视频 | 久久综合九色综合欧美狠狠 | 国产精品18久久久久久久 | 久久免费观看视频 | 国产成人a亚洲精品 | 欧美在线观看一区 | 欧美人妖网站 | 久久久一二三 | 99久久99久久精品国产片果冰 | 久久国产精品一区二区三区 | 国产精品久久久久久久久久久久午夜片 | 在线观看中文字幕 | 亚洲一区二区三区视频免费观看 | 亚洲一区视频在线播放 | 一区二区三区视频在线观看 | 欧美成人性生活 | 久久69精品久久久久久国产越南 | 一级大片| 国产精品高潮呻吟久久久久 | 欧美色999 | 日韩午夜精品 | 成人午夜免费福利视频 |