This feature is in an early stage and considered a preview feature. It is not recommended to enable this for production environments due to potential data loss.
To secure sensitive data stored in Kubernetes resources (e.g. Secrets
), that data can be encrypted at rest. In Kubernetes this means that data is encrypted while stored in etcd and is only decrypted when the resource is requested via a Kubernetes API request.
Data will either be encrypted with static encryption keys or via envelope encryption based on cloud provider KMS services (see Configuring Encryption at Rest). This feature is based on the Kubernetes upstream feature for encrypting data at rest.
Important Notes
- Data is only encrypted at rest and not when requested by users with sufficient RBAC to access it. This means that the output of
kubectl get secret <secret> -o yaml
(or similar commands/actions) remains unencrypted and is only base64-encoded. Proper RBAC management is mandatory to secure secret data at all stages. - Due to multiple revisions of data existing in etcd, etcd backups might contain previous revisions of a resource that are unencrypted if the etcd backup is taken less than five minutes after data has been encrypted. Previous revisions are compacted every five minutes by
kube-apiserver
.
Configuring Encryption at Rest
Encryption at rest can be configured by updating an existing Cluster
resource via kubectl edit cluster <Cluster ID>
. At the moment, a feature gate is required on the cluster to enable the feature. Here is an example of what spec.encryptionConfiguration
can look like:
# only a snippet, not valid on its own!
spec:
features:
encryptionAtRest: true
encryptionConfiguration:
enabled: true
resources:
- secrets
secretbox:
keys:
- name: encryption-key-2022-01
secretRef:
name: encryption-key-2022-01
key: key
Check out the Kubermatic CRD documentation for a full overview of the configuration options.
Encrypted Resources
While most users might want to encrypt their Secret
resources at rest, the encryption at rest feature is flexible enough to expand to other resource types. This can be useful if you have CRDs for custom resources that store sensitive data. A list of encrypted resources can be passed via spec.encryptionConfiguration.resources
. At the moment, the list of resources is static and cannot be changed once encryption at rest is enabled. You will need to disable encryption at rest before re-configuring it. This might change in future versions of the feature.
Resource types should be passed in their plural form, all lowercase.
Currently Available Encryption Providers
At the moment, the following encryption providers/schemes/methods are available:
Secretbox
The Secretbox encryption scheme can be configured via spec.encryptionConfiguration.secretbox
. It takes static keys used for symmetric encryption using XSalsa20 and Poly1305.
Each key needs to be 32-byte long and needs to be base64-encoded. A key can be generated via head -c 32 /dev/urandom | base64
on Linux, for example. Consider your IT security guidelines for a sufficiently secure way to generate such keys. Keys can be configured directly via spec.encryptionConfiguration.secretbox.keys[].value
, which can be problematic when Cluster
resources are stored in git or several people have access to Cluster
resources. For those situations, spec.encryptionConfiguration.secretbox.keys[].secretRef
allows to reference a Secret
resource in the Cluster
’s control plane namespace (usually cluster-<Cluster ID>
).
# snippet for directly passing a key
spec:
encryptionConfiguration:
enabled: true
resources:
- secrets
secretbox:
keys:
- name: encryption-key-2022-01
value: ynCl8otobs5NuHu$3TLghqwFXVpv6N//SE6ZVTimYok=
# snippet for referencing a secret
spec:
encryptionConfiguration:
enabled: true
resources:
- secrets
secretbox:
keys:
- name: encryption-key-2022-01
secretRef:
name: encryption-key-2022-01
key: key
If a key is referenced by a secretRef
, KKP does not react to updates to the key Secret
after it has been used for configuring encryption at rest. Follow the key rotation process with a new Secret
if you want to update the active encryption key.
Disabling Encryption at Rest
Once configured, encryption at rest can be disabled via setting spec.encryptionConfiguration.enabled
to false
or removing spec.encryptionConfiguration
from the Cluster specification. KKP will reconfigure Kubernetes components and run a decryption job for existing resources.
Querying Encryption Status
Since encryption at rest needs to reconfigure the control plane and re-encrypt existing data in a user cluster, applying changes to the encryption configuration can take a while. Encryption status can be queried via kubectl
:
$ kubectl get cluster <Cluster ID> -o jsonpath="{.status.encryption.phase}"
Active
Only “Active” means that the configured encryption is fully applied.
Rotating Encryption Keys
Occasionally, it might be necessary to rotate encryption keys for data encrypted at rest, for example on a regular basis as a good security practice or when a key has been compromised.
Key rotation can be facilitated by first adding a secondary key to the respective encryption provider that is configured (rotating between different providers is not supported). For example for Secretbox, you would reconfigure the example given earlier to include a secondary key:
# only a snippet, not valid on its own!
spec:
encryptionConfiguration:
enabled: true
resources:
- secrets
secretbox:
keys:
- name: encryption-key-2022-01
secretRef:
name: encryption-key-2022-01
key: key
- name: encryption-key-2022-02
secretRef:
name: encryption-key-2022-02
key: key
This will configure the contents of encryption-key-2022-02
as secondary encryption key. Secondary keys allow to decrypt data that is not encrypted with the primary key. This needs to be done so all control plane components can decrypt data once the key is rotated to be the primary key and is thus used to encrypt resources. KKP will rotate involved components, but will not run a re-encryption job, as data in etcd does not need to be encrypted again for this update.
After control plane components have been rotated, switch the position of the two keys in the keys
array. The given example will look like this:
# only a snippet, not valid on its own!
spec:
encryptionConfiguration:
enabled: true
resources:
- secrets
secretbox:
keys:
- name: encryption-key-2022-02
secretRef:
name: encryption-key-2022-02
key: key
- name: encryption-key-2022-01
secretRef:
name: encryption-key-2022-01
key: key
The secondary key now becomes the primary key. Data in etcd can still be read because the old key is still configured as a secondary key. KKP will reconfigure control plane components and launch a data re-encryption job for existing resources.
After data has been re-encrypted (check encryption status as per Querying Encryption Status) the old key can be removed from the configuration. Make sure to not remove it before that, as that will make data in etcd unreadable.