在K8S中,如何安全管理Secrets?

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 在K8S中,如何安全管理Secrets?

为何要加密?


在Kubernetes中,Secret是用来帮我们存储敏感信息的,比如密码、证书等,但是在默认的情况下,Secret只是做了简单的base64编码,任何人都可以非常容易的对其进行解密获取到原始数据。


比如通过以下方法生成一个secret对象:


$ echo -n "coolops" | kubectl create secret generic mysecret --dry-run --from-file=secret=/dev/stdin -o yaml > secret.yaml
$ cat secret.yaml 
apiVersion: v1
data:
  secret: Y29vbG9wcw==
kind: Secret
metadata:
  creationTimestamp: null
  name: mysecret


其他人只要拿到secret的值,就可以对其进行解密获取到真实数据,如下:


$ echo "Y29vbG9wcw==" | base64 -d
coolops


这样就非常的不安全,有点"掩耳盗铃"的意思。


在Kubernetes集群中,Etcd是集群数据库,存储着集群所以的资源数据,其中也包括Secrets,所以拿下了这个数据库就等于拿下了整个集群,所以在生产环境中对其进行加密是非常有必要的。


如何进行加密?


静态加密


kubernetes 1.13版本之后,提供静态加密方式,其主要是通过kube-apiserver来控制Secrets的加解密,而在Etcd中存储的是加密后的信息,所以攻击者拿下了etcd,也无法轻易的拿到Secrets保存的敏感数据。


!! 当前集群是使用kubeadm安装,版本1.18.9


(1)创建加密配置文件,保存到master节点/etc/kubernetes/pki/static-secret-encryption.yaml中


apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
    - secrets
    providers:
    - aescbc:
        keys:
        - name: mysecret
          secret: DJqYaMMpY2DNlHz+HYrFYOUSh5SXKWiVOwLf6nQX9ss=
    - identity: {}


其中secret是加密密钥,使用如下命令生成:


$ head -c 32 /dev/urandom | base64


(2)修改kube-apiserver启动参数,位置/etc/kubernetes/manifests/kube-apiserver.yaml


......
spec:
  containers:
  - command:
    - kube-apiserver
    - --encryption-provider-config=/etc/kubernetes/pki/static-secret-encryption.yaml
......


!! 注意:kube-apiserver的加密参数,在1.14之后是--encryption-provider-config


(3)重启kube-apiserver


(4)验证加密


首先创建一个secret资源,如下:


$ kubectl create secret generic secret1 -n default --from-literal=mykey=mydata


然后查看etcd中的数据


$ ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key get /registry/secrets/default/secret1  | hexdump -C
00000000  2f 72 65 67 69 73 74 72  79 2f 73 65 63 72 65 74  |/registry/secret|
00000010  73 2f 64 65 66 61 75 6c  74 2f 73 65 63 72 65 74  |s/default/secret|
00000020  31 0a 6b 38 73 3a 65 6e  63 3a 61 65 73 63 62 63  |1.k8s:enc:aescbc|
00000030  3a 76 31 3a 6d 79 73 65  63 72 65 74 3a b6 90 7d  |:v1:mysecret:..}|
00000040  b3 40 9b 4d 63 eb 71 cf  ca 16 52 a0 91 82 c3 69  |.@.Mc.q...R....i|
00000050  2b 6f e5 1c ae 88 58 0d  4f 08 c9 29 57 69 f5 e6  |+o....X.O..)Wi..|
00000060  e2 7c 42 79 bb 84 22 3a  90 54 5e d4 ac f6 a6 a6  |.|By..":.T^.....|
00000070  47 e2 b2 67 29 d8 c4 c6  61 9e 84 62 9d 3c 7c b0  |G..g)...a..b.<|.|
00000080  6c 5f 5e f3 da 08 34 17  ef a3 a7 9c 76 31 02 98  |l_^...4.....v1..|
00000090  54 5c 21 05 af 8d a8 dc  39 04 4d 84 bf a8 d1 f6  |T\!.....9.M.....|
000000a0  58 f4 90 30 22 46 14 a5  e6 19 3a 51 48 86 99 a7  |X..0"F....:QH...|
000000b0  ed f1 5f 8e 4a 1c 30 cb  5f ec ba 3d e2 0a 1d 93  |.._.J.0._..=....|
000000c0  7c 57 68 6b d2 01 51 49  fd 81 56 72 6d ca 98 e6  ||Whk..QI..Vrm...|
000000d0  99 59 84 15 bc 5d 7d f7  95 75 b2 cb 4f ff 8d d1  |.Y...]}..u..O...|
000000e0  ae 29 0d 27 df fa 59 b4  e2 37 2c 33 83 9e e4 73  |.).'..Y..7,3...s|
000000f0  55 ce 89 cc c0 5f 3d e4  df 90 8d 70 91 f9 81 b1  |U...._=....p....|
00000100  e7 0c ee 71 cf 81 22 6f  6c 45 74 51 0c f7 5f 4d  |...q.."olEtQ.._M|
00000110  1f 9a be 51 05 cd fd b2  74 0b 29 30 e2 24 ea 57  |...Q....t.)0.$.W|
00000120  0e 8a cb 1f 55 7a 2e 4c  0e 1a 4e 09 c6 0a        |....Uz.L..N...|
0000012e


注意在数据头部出现k8s:enc:aescbc:v1:,说明数据已经被正确加密,使用的是aescbc算法,使用的密钥为mysecret


接下来查看读取的时候能否正常被解密,如下:


$ kubectl get secrets secret1 -o yaml
apiVersion: v1
data:
  mykey: bXlkYXRh
kind: Secret
metadata:
  creationTimestamp: "2021-01-22T02:27:48Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:mykey: {}
      f:type: {}
    manager: kubectl
    operation: Update
    time: "2021-01-22T02:27:48Z"
  name: secret1
  namespace: default
  resourceVersion: "26907503"
  selfLink: /api/v1/namespaces/default/secrets/secret1
  uid: 9020c914-3785-404f-a7b2-0743ff49c19d
type: Opaque
$ echo "bXlkYXRh" | base64 -d
mydata


可以发现能否正常解密。


不知道你有没有发现,只有存在etcd里的数据被加密了,我们在集群使用kubectl get secrets secret1 -o yaml获取到的仍然只是简单的进行了base64转码,所以一旦我们的节点被攻破,secrets也就暴露在外面了。


密钥管理服务KMS plugin


KMS 加密驱动使用封套加密模型来加密 etcd 中的数据。数据使用数据加密秘钥(DEK)加密;每次加密都生成一个新的 DEK。这些 DEK 经一个秘钥加密秘钥(KEK)加密后在一个远端的 KMS 中存储和管理。KMS 驱动使用 gRPC 与一个特定的 KMS 插件通信。这个 KMS 插件作为一个 gRPC 服务器被部署在 Kubernetes 主服务器的同一个主机上,负责与远端 KMS 的通信。


现在基本云厂商都提供KMS服务。这里以阿里云为例。


(1)开通密钥管理服务


640.png


(2)创建密钥


640.png


(3)然后部署kms-plugin


apiVersion: apps/v1
kind: Deployment 
metadata:
  name: ack-kms-plugin
  namespace: kube-system
spec:
  selector:
   matchLabels:
     name: ack-kms-plugin
  template:
   metadata:
     labels:
       name: ack-kms-plugin
   spec:
     affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - preference: {}
              weight: 100
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: node
                    operator: In
                    values:
                      - master
     restartPolicy: Always
     tolerations:
     - key: node-role.kubernetes.io/master
       effect: NoSchedule
     volumes:
     - name: kmssocket
       hostPath:
         path: /var/run/kmsplugin
         type: DirectoryOrCreate
     containers:
     - name: ack-kms-plugin
       image: registry.{{ .Region }}.aliyuncs.com/acs/ack-kms-plugin:v1.0.2
       imagePullPolicy: Always
       command:
       - ack-kms-plugin
       - --gloglevel=5
       - --key-id={{ .KeyId }}
       - --path-to-unix-socket=/var/run/kmsplugin/grpc.sock
       livenessProbe:
         exec:
           command:
           - ack-kms-plugin
           - health
           - --path-to-unix-socket=/var/run/kmsplugin/grpc.sock
         initialDelaySeconds: 30
         failureThreshold: 3
         timeoutSeconds: 5
         periodSeconds: 300
       env:
         - name: ACCESS_KEY_ID    #not required if you want plugin help to pull the sts credentials
           value: {{ .AK }}
         - name: ACCESS_KEY_SECRET   #not required if you want plugin help to pull the sts credentials
           value: {{ .AK_Secret }}
         - name: CREDENTIAL_INTERVAL   #not required if you want plugin help to pull the sts credentials
           value: {{ .Credential_Interval }}
       volumeMounts:
       - name: kmssocket
         mountPath: /var/run/kmsplugin
         readOnly: false


其中需要更改的地方:


  • {{ .Region }}:阿里巴巴云区域 ID, 如果您的群集部署在 ECS 上, 您可以通过curl http://100.100.100.200/latest/meta-data/region-id
  • {{ .KeyId }}:Kms 服务列表中用于秘密加密的阿里云 Kms 密钥 ID
  • {{ .AK }}:授权的角色ID
  • {{ .AK_Secret }}:授权的角色密钥
  • {{ .Credential_Interval }}:凭据轮询间隔


(4)创建kms插件配置文件/etc/kubernetes/kmsplugin/encryptionconfig.yaml


apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
    - secrets
    providers:
    - kms:
        name: grpc-kms-provider
        endpoint: unix:///var/run/kmsplugin/grpc.sock
        cachesize: 1000
        timeout: 3s
    - identity: {}


(5)修改kube-apiserver配置清单文件/etc/kubernetes/manifests/kube-apiserver.yaml


在启动参数里加入:


......
spec:
  containers:
  - command:
    - kube-apiserver
    - --encryption-provider-config=/etc/kubernetes/kmsplugin/encryptionconfig.yaml
......


然后再配置挂载,如下:


...
  volumeMounts:
  - name: kms-sock
    mountPath: /var/run/kmsplugin
  - name: kms-config
    mountPath: /etc/kubernetes/kmsplugin
...
  volumes:
  - name: kms-sock
    hostPath:
      path: /var/run/kmsplugin
  - name: kms-config
    hostPath:
      path: /etc/kubernetes/kmsplugin


(6)重启kube-apiserver


(7)验证


现在,群集应使用信封加密方案,使用阿里云 KMS 的给定密钥加密密钥 (KEK) 对 中的秘密进行加密


1. 创建新机密


$ kubectl create secret generic secret1 -n default --from-literal=mykey=mydata


2. 使用 etcdtl,读取主节点中的 etcd中的机密


ps:[.local-ip] 应替换为主节点 IP 之一。


$ ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.pem --cert=/etc/kubernetes/pki/etcd/etcd-client.pem --key=/etc/kubernetes/pki/etcd/etcd-client-key.pem --endpoints=https://{{.local-ip}}:2379 get /registry/secrets/default/secret1


3. 验证存储的机密是否前缀,指示我们的 kms 提供商已加密生成的数据。

k8s:enc:kms:v1:grpc-kms-provider


4. 验证密钥是否已正确解密:


$ kubectl get secrets secret1 -o yaml


使用第三方插件


还可以使用其他插件,比如sealed-secrets和vault。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
4月前
|
Kubernetes 容器
查看k8s secrets证书有效期
查看k8s secrets证书有效期
|
7月前
|
存储 Kubernetes 安全
加密 K8s Secrets 的几种方案
加密 K8s Secrets 的几种方案
|
存储 Kubernetes 数据安全/隐私保护
k8s-configmap 和 secrets
configmap 使用场景 configmap的定义 configmap的使用 secrets的使用场景 secrets的定义 secrets的使用
|
存储 运维 Kubernetes
云上数据安全实践:一键加密K8s集群Secrets,防止高危机密信息泄露
在Kubernetes集群中,我们通常使用Secrets模型存储和管理业务应用涉及的敏感信息,比如应用密码、TLS证书、Docker镜像下载凭据等敏感信息。Kubernetes会将所有的这些Secrets对象数据存储在集群对应的etcd中。阿里云容器服务Kubernetes版(简称ACK)通过用户指定的KMS主密钥,对K8s集群Secrets进行落盘加密,用户只需要一键配置就可以实现对K8s集群的纵深安全保护。
4825 0
云上数据安全实践:一键加密K8s集群Secrets,防止高危机密信息泄露
|
1天前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
本文源自2024云栖大会苏雅诗的演讲,探讨了K8s集群业务为何需要灾备及其重要性。文中强调了集群与业务高可用配置对稳定性的重要性,并指出人为误操作等风险,建议实施周期性和特定情况下的灾备措施。针对容器化业务,提出了灾备的新特性与需求,包括工作负载为核心、云资源信息的备份,以及有状态应用的数据保护。介绍了ACK推出的备份中心解决方案,支持命名空间、标签、资源类型等维度的备份,并具备存储卷数据保护功能,能够满足GitOps流程企业的特定需求。此外,还详细描述了备份中心的使用流程、控制台展示、灾备难点及解决方案等内容,展示了备份中心如何有效应对K8s集群资源和存储卷数据的灾备挑战。
|
22天前
|
Kubernetes 监控 Cloud Native
Kubernetes集群的高可用性与伸缩性实践
Kubernetes集群的高可用性与伸缩性实践
56 1
|
2月前
|
JSON Kubernetes 容灾
ACK One应用分发上线:高效管理多集群应用
ACK One应用分发上线,主要介绍了新能力的使用场景
|
2月前
|
Kubernetes 持续交付 开发工具
ACK One GitOps:ApplicationSet UI简化多集群GitOps应用管理
ACK One GitOps新发布了多集群应用控制台,支持管理Argo CD ApplicationSet,提升大规模应用和集群的多集群GitOps应用分发管理体验。
|
2月前
|
Kubernetes Ubuntu Linux
Centos7 搭建 kubernetes集群
本文介绍了如何搭建一个三节点的Kubernetes集群,包括一个主节点和两个工作节点。各节点运行CentOS 7系统,最低配置为2核CPU、2GB内存和15GB硬盘。详细步骤包括环境配置、安装Docker、关闭防火墙和SELinux、禁用交换分区、安装kubeadm、kubelet、kubectl,以及初始化Kubernetes集群和安装网络插件Calico或Flannel。
194 4
|
2月前
|
Kubernetes Cloud Native 云计算
云原生之旅:Kubernetes 集群的搭建与实践
【8月更文挑战第67天】在云原生技术日益成为IT行业焦点的今天,掌握Kubernetes已成为每个软件工程师必备的技能。本文将通过浅显易懂的语言和实际代码示例,引导你从零开始搭建一个Kubernetes集群,并探索其核心概念。无论你是初学者还是希望巩固知识的开发者,这篇文章都将为你打开一扇通往云原生世界的大门。
131 17