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

關于 Kubernetes 的 Secret 并不安全這件事

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

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

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

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

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

問題

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

  •  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 到容器后的文件內容。 

  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 中,我們可以直接從文件看到相關內容: 

  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 中的內容都是明文存放的,而且是進行 base64 解碼之后的內容。

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

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

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

API server

通過 API server 則簡單的多,只要有權限就可以從任何節點上通過訪問 API server 來得到 secret 的明文內容。 

  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 

節點上

在節點上也可以看到 Secret 文件的內容。

查找 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 下面的文件內容: 

  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 嚴格進行權限設計
  •  強化 node 節點用戶權限管理和系統安全

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

社區和公有云提供商都有一些產品和方案,我們可以參考一下。

  •  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 中數據進行加密/解密,支持如下 key 管理服務或軟件:

  •  AWS Key Management Service
  •  Google Cloud KMS
  •  GnuPG

bitnami-labs/sealed-secrets

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

本圖來自 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 并沒有什么必然關系,它只是一個支持 YAML/JSON/ENV/INI 等文件格式的加密文件編輯器,它支持 AWS KMS, GCP KMS, Azure Key Vault, age, 和 PGP 等服務與應用。

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

Kubernetes External Secrets

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

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

它通過自定義 controller 和 CRD 來實現,具體架構圖如下:

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

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

  • 統一 key 的管理,或者沿用既有 key 資產
  • key 信息不想放到 VCS 等

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

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

Kamus

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

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 來實現:定義一個 基于內存的 emptyDir ,業務容器和 init 容器使用同一個 volume, init 容器解密后,將數據存放到該 volume 下,之后業務容器就可以使用解密后的 secret 數據了。

Vault by HashiCorp

HashiCorp 公司就不多說,在云計算/DevOps領域也算是數一數二的公司了。

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

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

Agent Sidecar Injector

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

  •  Mutation webhook:

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

  •  agent-sidecar:

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

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

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

這是官方 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] 

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

Vault CSI Provider

這部分可以參考下面的社區方案部分。

社區方案

當然,社區沒有理由意識不到原生 secret 的問題,因此社區也有 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 啟動之后,就可以確認解密后的數據了: 

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

總結

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

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

 

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

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

2018-07-10 08:56:19

編程程序員開發

2023-10-19 10:43:38

2012-04-16 10:12:54

Java線程

2020-11-03 12:32:25

影子物聯網物聯網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技術棧公眾號

主站蜘蛛池模板: 国产高清在线观看 | 国产免费一区 | 成人免费在线观看 | 成人在线视频网站 | 狠狠狠干| 欧美成年人 | 日韩欧美成人一区二区三区 | 中文字幕av一区 | 国内自拍视频在线观看 | 久久久亚洲综合 | 日韩和的一区二区 | 亚洲精品99久久久久久 | 中文字幕在线剧情 | 国产精品免费看 | 亚洲综合视频 | 成人动漫视频网站 | 久久久久九九九九 | 亚洲va欧美va天堂v国产综合 | 中文字幕免费视频 | 中文字幕在线播放第一页 | 色偷偷人人澡人人爽人人模 | 蜜月va乱码一区二区三区 | 在线播放国产视频 | 天天操天天天干 | 日韩欧美大片在线观看 | 国产男女视频网站 | 福利视频网站 | 麻豆一区一区三区四区 | 九九综合九九 | www.一区二区| 欧美区在线 | 精品久久久久久国产 | 日日夜夜精品 | 免费在线观看成人 | 九九热在线视频免费观看 | 精品国产精品国产偷麻豆 | 成人av激情| 欧美久久久电影 | 精品欧美乱码久久久久久 | 精品视频一二区 | 日本午夜网站 |