Encryption at REST-API
Kubernetes stores key value pair data inside etcd
in plain text format which can be easily comprehended by anyone who has access to to it.
We can enable encryption at kubernetes API that will encrypt the resource data entering into etcd
. For example, we can configure to encrypt only Secret resource.
Before enabling encryption
Let’s see how etcd
stores secrets data when no api level encryption is enabled. Following describes the steps to do so.
- We would need
etcdctl
client tool installed on our system.
sudo apt install etcd-client
- We required to locate the necessary certificate and key files.
etcdctl
requires...etcd/ca.crt
,...etcd/server.crt
,...etcd/server.key
to get the data frometcd
.
In my case, I was using minikube. I could find this files inside control node at path /var/lib/minikube/certs/etcd
.
- Run the command to get the data from
etcd
.
ETCDCTL_API=3 etcdctl \
--cacert=ca.crt \
--cert=server.crt \
--key=server.key \
get /registry/secrets/<namespace>/<secret-name>
You may face issues with permissions to access these certificates and key file and provide to command, it’s better to copy paste where there is no permission issue and use that path. (and delete afterwards obviously)
It should show something like below.
/registry/secrets/learning/mysql-db-secret
k8s
v1Secret
mysql-db-secrelearning"*$6866e01b-df74-4a98-9511-d0b52d6773cf2qB
kubectl-createUpdatevFieldsV1:=
;{"f:data":{".":{},"f:PASSWORD":{},"f:USER":{}},"f:type":{}}B
PASSWORDuser
USERuserOpaque"
It clearly shows the data inside secret mysql-db-secret
in namespace learning
.
That is the problem!
Enable encryption at rest
So we need to enable encryption at kube-apiserver
pod. Here we need two things, kube-apiserver.yaml
pod file and encryption resource file that will create.
Encryption Resource file
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
- configmaps
- pandas.awesome.bears.example
providers:
- aescbc:
keys:
- name: key1
secret: <BASE 64 ENCODED SECRET>
- identity: {}
resources.resources
lists the kubernetes resources we need to enable the encryption for. providers
lists the encryption algorithms. First item in providers
is used for encryption and rest for fallbacks if any provider is enable to encrypt/decrypt. This is a list of available providers here.
Key secret has to be base64
encoded that we can generated as follows
This is method is for linux.
head -c 32 /dev/urandom | base64
So Encryption resource file for our case can be like following.
/etc/kubernetes/enc/enc.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: er+42Uj8deiLT9sUFFwycEqLPW+Egt0EDVTWPsF3MDM=
- identity: {}
Using Encryption Resource file
We need to use this resource file inside kube-apiserver
pod. We can achieve by providing --encryption-provider-config
parameter with value as path to encryption resource yaml file, while creating the kube-apiserver
pod.
kube-apiserver.yaml
can be located at path /etc/kubernetes/manifests/kube-apiserver.yaml
.
We need to do two things here.
- Provide
--encryption-provider-config
parameter incommand
section ofcontainers
.
Code snippet of kube-apiserver.yaml
.
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.76.2
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/var/lib/minikube/certs/ca.crt
- --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,Validat
ingAdmissionWebhook,ResourceQuota
- --enable-bootstrap-token-auth=true
..........
- --tls-cert-file=/var/lib/minikube/certs/apiserver.crt
- --tls-private-key-file=/var/lib/minikube/certs/apiserver.key
- --encryption-provider-config=/etc/kubernetes/enc/enc.yaml
- Mount the path to pod where it can find
/etc/kubernetes/enc/enc.yaml
.
Code snippet of kube-apiserver.yaml
.
spec:
containers:
- ...
volumeMounts:
- mountPath: /etc/ssl/certs
name: ca-certs
readOnly: true
....
- mountPath: /etc/kubernetes/enc
name: enc
readOnly: true
volumes:
- hostPath:
path: /etc/ssl/certs
type: DirectoryOrCreate
name: ca-certs
.....
- name: enc
hostPath:
path: /etc/kubernetes/enc
type: DirectoryOrCreate
So /etc/kubernetes/enc
is mounted to pod path /etc/kubernetes/enc
. Encryption resource file should be present at /etc/kubernetes/enc/enc.yaml
at host.
Updating the kube-apiserver.yaml
would restart the api server automatically and any further creation of secret should be encrypted.