Skip to content

FalcoSuessgott/vault-kubernetes-kms

Repository files navigation

vault-kms-plugin

Important

as of v1.0.0 vault-kubernetes-kms is considered stable and production-grade

A Kubernetes KMS Plugin that uses HashiCorp Vaults Transit Engine for securely encrypting Secrets, Config Maps and other Kubernetes Objects in etcd at Rest (on disk).

E2E drawing drawing drawing

Why

HashiCorp Vault already offers useful Kubernetes integrations, such as the Vault Secrets Operator for populating Kubernetes secrets from Vault Secrets or the Vault Agent Injector for injecting Vault secrets into a Pod using a sidecar container approach.

Wouldn't it be nice if you could also use your Vault server to encrypt Kubernetes secrets before they are written into etcd? The vault-kubernetes-kms plugin does exactly this!

Since the key used for encrypting secrets is not stored in Kubernetes, an attacker who intends to get unauthorized access to the plaintext values would need to compromise etcd and the Vault server.

How does it work?

img

vault-kubernetes-kms is supposed to run as a static pod on every control plane node or on that node where the kube-apiserver will run.

vault-kubernetes-kms will start a UNIX domain socket and listens for encryption requests from the kube-apiserver. The plugin will then use the specified Vault transit encryption key to encrypt the data and send it back to the kube-apiserver, who will then store the encrypted response in etcd.

To do so, you will have to enable Data at Rest encryption, by configuring the kube-apiserver to use a EncryptionConfiguration (See https://falcosuessgott.github.io/vault-kubernetes-kms/configuration/ for more details).

⚠️ As a result of that, the kube-apiserver requires the vault-kubernetes-kms plugin to be up & running before the kube-apiserver starts. To ensure this, setting a priority class in the plugins manifest ("priorityClassName: system-node-critical") is recommended. ⚠️

Following the scenario that vault-kubernetes-kms is deployed as a static pod, then your Vault server has to reside outside of your Kubernetes cluster, as it is recommended. If you decide to deploy the plugin not as a static pod, then theoretically the Vault server can be deployed on the same cluster, you then would have to patch the kube-apiserver after startup to find its EncryptionProviderConfig.

Check out the official documentation

Features

Without a KMS Provider

# create any secret
$> kubectl create secret generic secret-unencrypted -n default --from-literal=key=value

# proof that k8s secrets are stored unencrypted on disk in etctd
$> kubectl -n kube-system exec etcd-minikube -- sh -c "ETCDCTL_API=3 etcdctl \
    --endpoints=https://127.0.0.1:2379 \
    --cert /var/lib/minikube/certs/etcd/server.crt \
    --key /var/lib/minikube/certs/etcd/server.key \
    --cacert /var/lib/minikube/certs/etcd/ca.crt \
    get /registry/secrets/default/secret-unencrypted" | 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  2d 75 6e 65 6e 63 72 79  70 74 65 64 0a 6b 38 73  |-unencrypted.k8s|
00000030  00 0a 0c 0a 02 76 31 12  06 53 65 63 72 65 74 12  |.....v1..Secret.|
00000040  d1 01 0a b8 01 0a 12 73  65 63 72 65 74 2d 75 6e  |.......secret-un|
00000050  65 6e 63 72 79 70 74 65  64 12 00 1a 07 64 65 66  |encrypted....def|
00000060  61 75 6c 74 22 00 2a 24  33 62 31 66 34 34 31 32  |ault".*$3b1f4412|
00000070  2d 37 61 39 34 2d 34 38  62 35 2d 61 38 36 39 2d  |-7a94-48b5-a869-|
00000080  38 62 66 36 62 35 33 39  63 38 36 34 32 00 38 00  |8bf6b539c8642.8.|
00000090  42 08 08 fc 92 e9 ad 06  10 00 8a 01 60 0a 0e 6b  |B...........`..k|
000000a0  75 62 65 63 74 6c 2d 63  72 65 61 74 65 12 06 55  |ubectl-create..U|
000000b0  70 64 61 74 65 1a 02 76  31 22 08 08 fc 92 e9 ad  |pdate..v1"......|
000000c0  06 10 00 32 08 46 69 65  6c 64 73 56 31 3a 2c 0a  |...2.FieldsV1:,.|
000000d0  2a 7b 22 66 3a 64 61 74  61 22 3a 7b 22 2e 22 3a  |*{"f:data":{".":|
000000e0  7b 7d 2c 22 66 3a 6b 65  79 22 3a 7b 7d 7d 2c 22  |{},"f:key":{}},"|  # secret keys unencrypted
000000f0  66 3a 74 79 70 65 22 3a  7b 7d 7d 42 00 12 0c 0a  |f:type":{}}B....|
00000100  03 6b 65 79 12 05 76 61  6c 75 65 1a 06 4f 70 61  |.key..value..Opa|  # secret values unencrypted
00000110  7

After configuring a KMS Provider

# create any k8s secret
$> kubectl create secret generic secret-encrypted -n default --from-literal=key=value

# proof that now secrets are stored encrypted on disk in etctd
$> kubectl -n kube-system exec etcd-minikube -- sh -c "ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
    --cert /var/lib/minikube/certs/etcd/server.crt \
    --key /var/lib/minikube/certs/etcd/server.key \
    --cacert /var/lib/minikube/certs/etcd/ca.crt \
    get /registry/secrets/default/secret-encrypted" | 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  2d 65 6e 63 72 79 70 74  65 64 0a 6b 38 73 3a 65  |-encrypted.k8s:e|
00000030  6e 63 3a 6b 6d 73 3a 76  32 3a 76 61 75 6c 74 3a  |nc:kms:v2:vault:|
00000040  0a 84 02 54 b2 35 ef 01  ca 9a 3b 00 00 00 00 9e  |...T.5....;.....|
00000050  c6 26 2a e6 23 f0 c0 b7  22 3a 99 d8 36 81 07 af  |.&*.#...":..6...|
00000060  ae d7 33 62 3f 99 62 ed  b1 f0 10 f9 47 05 46 0e  |..3b?.b.....G.F.|
00000070  c4 4f b5 63 aa 7d e5 3b  44 fd 9e 6d e7 42 2f 8f  |.O.c.}.;D..m.B/.|
00000080  44 27 57 f6 ee 62 69 9b  49 6b 00 bb d3 38 d4 85  |D'W..bi.Ik...8..|
00000090  ce 57 b6 fa 95 4b 88 ea  9c de 1f c9 e0 05 48 a5  |.W...K........H.|
000000a0  5f 08 01 c4 c9 f2 3d 5d  35 e6 0e e7 0a 89 18 ab  |_.....=]5.......|
000000b0  72 f2 ba 2b 3e cb 20 bf  cd 9a 0f 97 78 d4 79 05  |r..+>. .....x.y.|
000000c0  77 52 1b ba bd 55 2b 9f  e0 f1 af dc 04 3a b0 a9  |wR...U+......:..|
000000d0  70 8e 7a 97 10 8f b4 41  75 4b b8 24 dc 6f 10 04  |p.z....AuK.$.o..|
000000e0  4b b9 a0 fc a5 cc 02 e9  53 6e 1a be 31 c2 2b 38  |K.......Sn..1.+8|
000000f0  d3 d9 07 6f ee 40 9d 20  dc d6 68 29 e0 20 3f 8f  |...o.@. ..h). ?.|
00000100  0a 1c a0 03 4f bf 9f 4b  8a 76 9b 8c 06 5b 4f c8  |....O..K.v...[O.|
00000110  75 b7 a1 a3 d1 4e b2 00  81 53 ed 6a b2 d9 03 88  |u....N...S.j....|
00000120  cb 3c 3d bb 12 b4 88 d3  e0 c7 a7 e1 31 0c 18 55  |.<=.........1..U|
00000130  26 fb 38 86 5b fb 5c bc  2b e0 8b f3 56 84 78 b2  |&.8.[.\.+...V.x.|
00000140  ae fc 11 98 1e a7 b9 12  0a 31 37 31 30 37 34 34  |.........1710744|
00000150  32 30 33 1a 59 76 61 75  6c 74 3a 76 31 3a 30 4f  |203.Yvault:v1:0O| # encrypted secret stored in etcd on disk
00000160  31 7a 58 5a 31 54 34 33  37 70 53 59 7a 69 58 41  |1zXZ1T437pSYziXA|
00000170  32 30 62 4a 44 58 48 62  4a 31 55 65 50 75 6b 61  |20bJDXHbJ1UePuka|
00000180  70 70 47 4f 4f 54 51 65  6b 61 61 7a 6e 32 76 73  |ppGOOTQekaazn2vs|
00000190  35 4f 41 54 56 66 65 2b  31 63 75 7a 76 6a 64 6a  |5OATVfe+1cuzvjdj|
000001a0  41 43 2b 6f 31 45 61 6a  57 72 32 53 6c 57 0a     |AC+o1EajWr2SlW.|
000001af