Kubernetes 中的 Secret加密存储

前言

在使用Kubernetes的时候,我们常常会通过configmap、secret等原生资源来配置一些环境变量等,以便同代码一起用于git版本管理。如果是用于存储一般信息还行,但是某些时候我们可能需要用这些资源来配置一些账号密码等敏感信息,虽然secrets具备加密性质,但是因为其本身的加密方式是基于base64的,所以对于稍微有点相关知识的人来说,等同于明文。

在很多公司研发部门的管理中,生产环境的很多账户密码是不允许被除管理员之外的人员获知的(比如数据库密码),如果不对相关信息进行加密存储,直接在git中进行版本管理,对相关人员来说,无异于裸奔。所以此处介绍一款K8S的开源资源类型sealed-secrets

sealed-secrets是什么

官方地址:bitnami-labs/sealed-secrets: A Kubernetes controller and tool for one-way encrypted Secrets (github.com)

Problem: “I can manage all my K8s config in git, except Secrets.”

Solution: Encrypt your Secret into a SealedSecret, which is safe to store - even inside a public repository. The SealedSecret can be decrypted only by the controller running in the target cluster and nobody else (not even the original author) is able to obtain the original Secret from the SealedSecret.

官方文档中的这一问一答,清晰明了的表达了sealed-secrets的作用,他就是为了让我们可以放心的把secret共享存储和使用,而避免加密信息被破解。

安装部署

Sealed Secrets由两部分组成:

  • 服务器端的控制器
  • 客户端工具:kubeseal

kubeseal使用非对称加密来加密数据,只有服务端的控制器才能解密数据,这些加密数据被编码在SealedSecret资源中。

安装kubeseal

1.登录Releases · bitnami-labs/sealed-secrets (github.com),找到最新版本,选择适合你系统的版本下载
在这里插入图片描述
2.将压缩包解压后将工具放到/usr/local/bin/目录下

tar -zxvf kubeseal-0.19.3-linux-amd64.tar.gz
install -m 755 kubeseal /usr/local/bin/kubeseal
##验证一下
[root@master sealed-secrets]# kubeseal --version
kubeseal version: 0.19.3

安装控制器

1.下载

登录github,下载相应资源文件Releases · bitnami-labs/sealed-secrets (github.com)
在这里插入图片描述
2.部署

kubectl apply -f controller.yaml

3.查看pod

[root@master sealed-secrets]# kubectl get pods -n kube-system -l name=sealed-secrets-controller
NAME                                         READY   STATUS    RESTARTS   AGE
sealed-secrets-controller-8645675c65-jtrc2   1/1     Running   0          10d
[root@master sealed-secrets]# kubectl logs sealed-secrets-controller-8645675c65-jtrc2 -n kube-system 
controller version: 0.19.3
2022/12/23 09:15:22 Starting sealed-secrets controller version: 0.19.3
2022/12/23 09:15:22 Searching for existing private keys
2022/12/23 09:15:24 New key written to kube-system/sealed-secrets-keymrkx6
2022/12/23 09:15:24 Certificate is 
-----BEGIN CERTIFICATE-----
MIIEzTCCArWgAwIBAgIRAONV9p03jyrJuRrGUwyJJ2AwDQYJKoZIhvcNAQELBQAw
ADAeFw0yMjEyMjMwOTE1MjRaFw0zMjEyMjAwOTE1MjRaMAAwggIiMA0GCSqGSIb3
DQEBAQUAA4ICDwAwggIKAoICAQDMkPndKm9g0XpgdNMuHvZ2qWsSGlET3pGyiSSs
APWDPT8FJEOcO1d4SrevrBCfWLxsd+CMyl4SE6Os1zqGXNMPAWJuag0JJBqcONgi
k3yWpma3h3g0fY21T7MUoAO16a+uMBJEPZAfzjfb3Oz8q26mWi8Ct96DKsvZkdZs
Xt1PL6nCKvj8DuAqH9+VzDiW/z66TeOCd8RsvJkMjGpyBZR+puIiDdDZ0dY/bS5l
0p3Ri72cTKnTBToLr3tM91einiJ0vhaMMVEdCED84rautJtbyBk/Km15g+D9ojW+
LcL5z8qKtDn13Hxo/2RRuUt4gsucuqrBWYUwKj8qoQZ/+iHAs6Ym+Y3A94qNFxNQ
udAbu/7HVIEOIU5G64HY5dqiQN5LJRqM7zlUjip65Rrr/Ysk/t0kNULKDX1060/k
EaVC8pPYa5hQLcWmyRBWstQTSNYGHO2ANevBIOT+O4wjrmEyC9dMuVRomdkqSkBi
NJsIYc3JATiGWcDax6H1G2V+QYmjg0PlH008e/n2wbJmAfHIxxBgMHGL0FPUFthX
rNhMHAirDrB7I1yW/OaoIm/YRJM+PMmJOk4IkJ66a6pVHDuRfY8lwDiH8vJaYk6y
oDS6T9qJ1bKTFDZtPg4rna+C36/px57BW/bTADHNckefuPFtAGbflEabeGr0TcoC
sU/ATQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAAEwDwYDVR0TAQH/BAUwAwEB/zAd
BgNVHQ4EFgQULw16NueVc/9IABCb1k6GGESJVJkwDQYJKoZIhvcNAQELBQADggIB
ACXaJ318/8KLv8MOzqtA0dhzQsqZkdrC+jm+Sf+nAmGFP1K/MsSQa8Ggyw/o8t/E
c+q2UYBF8CeP5hDRWlTavvkJISjQTyGJlhuhwA9EefFgcX4hIJhXrLqOGL7tJplr
oVyCoqDbeWuR4M3Nr2z44AQqbo0L9QFkEW4fHHOtIjjt9535yGgB5ApuryM/Crad
7Y3dC1Uohn7oW/4xO0EIjn1blOh9XFc4a862frTiQP54gZ3yU9/JhieSLlNFkReT
ZHcIIGKvNp52mw1hVJATClWKF3JljK4YLG+lHd1NGiuBLDvI6s/9x/3Fih8S37Tv
V3AFz1F0yb5xbFALmhzhgi744vK2lXt2/Gp6SzLq4cIQFi10wYNrW7I2dlpJczs3
p0PmCEJa1r2WEBLvlS+85FkJy7CXrCc9te4vHGIqY2kBG5u2VUUm/gl21HHrTYDt
P5HalOefSq+ve02Tiyyye8STz1sr0bN0db47DOhylnkzJPgHWMCuOq0KNZBry2N9
euPDbGlhga3USPWOyKV6eingIFFT7ug9Fc5vLBh+mD8FQjDOAJ4Cl0MbkIDuQy+x
wYf9W21fxfKQnBgjYvjcNb5no7wKp2KsWshXWDkoih/05icJMfTSkwQ/Qzu4dbDw
6IifuAQn4SzIUd6y+0sVNjZK9XQ3ve+NYYBvM01OhfUA
-----END CERTIFICATE-----

4.查看公钥/私钥信息

kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml

测试

1.创建一个secret文件

kubectl create secret generic mysecret --from-literal=username=admin --from-literal=password=123456 --dry-run -o yaml > mysecret.yaml

# 查看生成的文件
[root@master sealed-secrets]# cat mysecret.yaml 
apiVersion: v1
data:
  password: MTIzNDU2
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: null
  name: mysecret

2.使用kubeseal对mysercret.yaml进行加密转换

kubeseal --format=yaml < mysecret.yaml > mysecret-sealed.yaml
### kubeseal输出的默认格式是json,此处使用--format将格式转为yaml,这一步是kubeseal从Kubernetes集群获取公钥并使用该公钥加密数据

##查看转换后的SealedSecret
[root@master sealed-secrets]# cat mysecret-sealed.yaml 
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: mysecret
  namespace: default
spec:
  encryptedData:
    password: AgBPYXyfWoN6YH/Dls8+L8uIQbHEfVmd6T4bOe3Y0W7d4wL9YPCLDS4fNpjJMPGx7nnR2nJkL2nWcr8xqepkLuIgn5cIZxQ5+EV624nzDIrm/PWE/3GNgb6oCQmpbcW2fIYVbicG6xpz3KHsPKHgxXQCGUJD9wB6bb1wWw5UZOGmihjHanzqbWZhdicDyfKdkyGHPiVi83xgdRmCaScgz9f1EQOfNsD5IkjD3gyLp3ZoMJUBprx0vvKDfZcoIL7vBJLHke9SrvDFtPdfmIneL2yJ7Gew4DJazlUct/U9FnMczl7Wr1Y6YAOFNNV9ysCRVC+C1bmrwr5r21G17KeES+GWLyXIy/epKoCpmtWcHJ22YNhSEtR0RGHWHCwSPeXbr2SdQegZ0Pk64X9QAYrEBO7IhF2gA1JA045DwFMXJjrKzDW+4ogslDXT2a5cIcVKVdrCGk8ajSsXQeOFq5GIcWLPeXs/LRu5SYyj7nr+xjyrPUtV7vxbNUmBCoFJ5TvWnO5yKE6wGQuTUxCOiIRf44KZqy03XZD2nsxe5UW/tyLJHXp1VL8hYHcoSfVSMHsTVPCNpDDUxCnZRnncfRHAXUyPnI2Cpx7uKsg8zu7M6TKklm8g1Ow+P8XBjzTY5vAr441oTad86REHQ6FVdBw8IKtZHYy2kxaTrThnWB3L+3ckk7ZhM3kbIDUdbXkFTkEx82A76ucXSLc=
    username: AgCwYrUhSKTgBZ5rf8DTToyB6yztH1+4P5tCv3mSCXt0dJ4L5sCso38JwBQJW6IRgw9nHqXdNwdZKpZW7Yjjr/LpsKUrs/9XkO+rgyf68uXi5tqNSHpsCza3e9Jx9qUI7k3WjHFHtRt5IsaO4OH7tUEmVlnCeuegXZ51HJfnmsZIgzGqDhnHWt6Z9FUOMvyd8jpro58p8tjjZIEBgrIRlMJdGSuUuSP0o3x30/4oPO7+yqbeV9B7OOp7i+sk4LBNfclmjLgySbCww6bc6wHr45NIt/bhIYkiKwk/IWh5e5LBqmZh+klkWA+GcltDTXi7+wv2UMAJXBmPhg4x41/unZUDhsljMvkPC92xWjivp4SMcMrRnjzKYI5UiTi5czS3uqRjH23q6U5/QM0o9IqVRojbSsnF9RmAAsfvZSoToHMgxOyS5ApF+4K/p9LI5t+vz3h7SQ+QhwYyyCcA3JRoK8a0ZFa3fz6bSMFMR+ANC7JtNez7Kiem9WjFhP+FB99UJCGdPmVHWL44uThtRZf/B3hO2hb/oXNHfZiUdjvXdB6Ee56yCUZrurkfjGd0ElnTy7a2CpEHjk2KIETv47qXnL4R6hRbd7nwdprjEg/0hawa0xhwat2PA4Vt+ZG2VbWYIgqc8TgDHJObb6IPn0HEoPvaZCGK1GzXspsbslNMdWrHu5bmbimVDrl7VUAKMWQe7uOy1PHy9A==
  template:
    metadata:
      creationTimestamp: null
      name: mysecret
      namespace: default

3.部署mysecret-sealed.yaml

kubectl apply -f mysecret-sealed.yaml
##查看部署后的文件
[root@master sealed-secrets]# kubectl get secrets mysecret -o yaml
apiVersion: v1
data:
  password: MTIzNDU2
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2022-12-23T09:24:38Z"
  name: mysecret
  namespace: default
  ownerReferences:
  - apiVersion: bitnami.com/v1alpha1
    controller: true
    kind: SealedSecret
    name: mysecret
    uid: af66d9ea-3ce3-4894-a1b5-0c3396ffb8d3
  resourceVersion: "2935007"
  uid: ed797abd-4390-4fc3-bda0-56c36c531d37
type: Opaque

可以看到,mysecret-sealed.yaml被还原为secret并进行部署

我们可以通过日志看到转换过程:控制器拦截了请求,并解密来自SealedSecret的加密数据,然后创建Secret对象

kubectl logs sealed-secrets-controller-8645675c65-jtrc2 -n kube-system
....
2022/12/23 09:24:38 WARNING: Empty API version & kind, filling it...
2022/12/23 09:24:38 Updating default/mysecret
2022/12/23 09:24:38 Event(v1.ObjectReference{Kind:"SealedSecret", Namespace:"default", Name:"mysecret", UID:"af66d9ea-3ce3-4894-a1b5-0c3396ffb8d3", APIVersion:"bitnami.com/v1alpha1", ResourceVersion:"2935006", FieldPath:""}): type: 'Normal' reason: 'Unsealed' SealedSecret unsealed successfully
....

安装web-ui

在很多情况下(比如全流程devops),集群管理员与业务运维等并非同一权限,因此这种命令行操作的方式并不能适用所有情况,这时就会需要一个WEB-UI界面来完成这个加密过程,很幸运github上开源了secret-sealed对应的web界面

web-ui官网地址

bakito/sealed-secrets-web: A web interface for Sealed Secrets by Bitnami. (github.com)

使用helm直接安装
helm repo add bakito https://charts.bakito.net
helm repo update

helm upgrade --install sealed-secrets-web bakito/sealed-secrets-web

当然,我们可能需要一些自定义的配置

helm upgrade --install sealed-secrets-web bakito/sealed-secrets-web \
  --set sealedSecrets.namespace=sealed-secrets-web \
  --set sealedSecrets.serviceName=sealed-secrets

其他使用方式请参照官方文档

查看部署

[root@master sealed-secrets]# kubectl get all -n sealed-secrets-web 
NAME                                      READY   STATUS    RESTARTS   AGE
pod/sealed-secrets-web-6874bbdfb5-9p5wq   1/1     Running   0          8d

NAME                         TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
service/sealed-secrets-web   ClusterIP   10.1.3.215   <none>        80:/TCP   8d

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/sealed-secrets-web   1/1     1            1           8d

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/sealed-secrets-web-6874bbdfb5   1         1         1       8d

我们将service/sealed-secrets-web以nodeport的方式暴露端口(当然也可以使用ingressgateway的方式):

kubectl edit svc sealed-secrets-web -n sealed-secrets-web ##编辑svc
...
  spec:
    clusterIP: 10.1.3.215
    clusterIPs:
    - 10.1.3.215
    externalTrafficPolicy: Cluster
    internalTrafficPolicy: Cluster
    ipFamilies:
    - IPv4
    ipFamilyPolicy: SingleStack
    ports:
    - name: http
      nodePort: 30088  #------------------新增
      port: 80
      protocol: TCP
      targetPort: http
    selector:
      app.kubernetes.io/instance: sealed-secrets-web
      app.kubernetes.io/name: sealed-secrets-web
    sessionAffinity: None
    type: NodePort   #--------------将ClusterIP修改为NodePort
  status:
    loadBalancer: {
    
    }

...
[root@master sealed-secrets]# kubectl get svc -n sealed-secrets-web 
NAME                 TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
sealed-secrets-web   NodePort   10.1.3.215   <none>        80:30088/TCP   8d

web访问
在这里插入图片描述

  • Encode:Base64 对 stringData 字段中的每个密钥进行秘密编码。

  • Decode:Base64 对数据字段中的每个密钥进行秘密解码。

  • Secrets:返回所有命名空间中所有 Sealed Secrets 的列表。单击 Sealed Secret 即可加载解密的 Kubernetes 机密。

  • Seal:加密 Kubernetes 秘密并创建 Sealed Secret。

缺点

web没有登录认证体系,因此需要自行想办法解决权限问题,比如集成到其他web权限管理下,官方提供了API,可以进行参照改造

猜你喜欢

转载自blog.csdn.net/Mrheiiow/article/details/128530761