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

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

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

    1. apiVersion: apiserver.config.k8s.io/v1
    2. kind: EncryptionConfiguration
    3. resources:
    4. - resources:
    5. - secrets
    6. providers:
    7. - aescbc:
    8. keys:
    9. - name: mysecret
    10. secret: DJqYaMMpY2DNlHz+HYrFYOUSh5SXKWiVOwLf6nQX9ss=
    11. - identity: {}

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

    1. $ head -c 32 /dev/urandom | base64

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

    1. ......
    2. spec:
    3. containers:
    4. - command:
    5. - kube-apiserver
    6. - --encryption-provider-config=/etc/kubernetes/pki/static-secret-encryption.yaml
    7. ......

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

    (3)重启kube-apiserver
    (4)验证加密
    首先创建一个secret资源,如下:

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

    然后查看etcd中的数据

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

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

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

    1. $ kubectl get secrets secret1 -o yaml
    2. apiVersion: v1
    3. data:
    4. mykey: bXlkYXRh
    5. kind: Secret
    6. metadata:
    7. creationTimestamp: "2021-01-22T02:27:48Z"
    8. managedFields:
    9. - apiVersion: v1
    10. fieldsType: FieldsV1
    11. fieldsV1:
    12. f:data:
    13. .: {}
    14. f:mykey: {}
    15. f:type: {}
    16. manager: kubectl
    17. operation: Update
    18. time: "2021-01-22T02:27:48Z"
    19. name: secret1
    20. namespace: default
    21. resourceVersion: "26907503"
    22. selfLink: /api/v1/namespaces/default/secrets/secret1
    23. uid: 9020c914-3785-404f-a7b2-0743ff49c19d
    24. type: Opaque
    25. $ echo "bXlkYXRh" | base64 -d
    26. mydata

    可以发现能否正常解密。

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