Change:
This is a Feature Request <!-- Please only use this template for submitting feature/enhancement requests --<!-- See for guidance on writing an actionable issue description. --What would you like to be Within add a new generated page that documents the format for an encryption configuration. Update to hyperlink to that new reference Why is this needed Within , there is a configuration format for the API server, EncryptionConfiguration. At the moment that format is not documented in Readers may want to look up what that format covers. Comments /sig api-machinery /sig auth /kind feature /language en
/triage accepted
/assign This file is already generated in the generator. All we need to do is to copy it to the website repo.

Discussion:
* [kube-apiserver configuration (v1)](/docs/reference/config-api/apiserver-config.v1/) <ins> * [kube-apiserver encryption (v1)](/docs/reference/config-api/apiserver-encryption.v1/) </ins> * [kubelet configuration (v1alpha1)](/docs/reference/config-api/kubelet-config.v1alpha1/) and [kubelet configuration (v1beta1)](/docs/reference/config-api/kubelet-config.v1beta1/) * [kube-scheduler configuration (v1beta2)](/docs/reference/config-api/kube-scheduler-config.v1beta2/) and

<ins> --- title: kube-apiserver Encryption Configuration (v1) content_type: tool-reference package: apiserver.config.k8s.io/v1 auto_generated: true --- <p>Package v1 is the v1 version of the API.</p> ## Resource Types - [EncryptionConfiguration](#apiserver-config-k8s-io-v1-EncryptionConfiguration) ## `EncryptionConfiguration`     {#apiserver-config-k8s-io-v1-EncryptionConfiguration} <p>EncryptionConfiguration stores the complete configuration for encryption providers.</p> <table class="table"> <thead><tr><th width="30%">Field</th><th>Description</th></tr></thead> <tbody> <tr><td><code>apiVersion</code><br/>string</td><td><code>apiserver.config.k8s.io/v1</code></td></tr> <tr><td><code>kind</code><br/>string</td><td><code>EncryptionConfiguration</code></td></tr> <tr><td><code>resources</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-ResourceConfiguration"><code>[]ResourceConfiguration</code></a> </td> <td> <p>resources is a list containing resources, and their corresponding encryption providers.</p> </td> </tr> </tbody> </table> ## `AESConfiguration`     {#apiserver-config-k8s-io-v1-AESConfiguration} **Appears in:** - [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) <p>AESConfiguration contains the API configuration for an AES transformer.</p> <table class="table"> <thead><tr><th width="30%">Field</th><th>Description</th></tr></thead> <tbody> <tr><td><code>keys</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-Key"><code>[]Key</code></a> </td> <td> <p>keys is a list of keys to be used for creating the AES transformer. Each key has to be 32 bytes long for AES-CBC and 16, 24 or 32 bytes for AES-GCM.</p> </td> </tr> </tbody> </table> ## `IdentityConfiguration`     {#apiserver-config-k8s-io-v1-IdentityConfiguration} **Appears in:** - [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) <p>IdentityConfiguration is an empty struct to allow identity transformer in provider configuration.</p> ## `KMSConfiguration`     {#apiserver-config-k8s-io-v1-KMSConfiguration} **Appears in:** - [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) <p>KMSConfiguration contains the name, cache size and path to configuration file for a KMS based envelope transformer.</p> <table class="table"> <thead><tr><th width="30%">Field</th><th>Description</th></tr></thead> <tbody> <tr><td><code>name</code> <B>[Required]</B><br/> <code>string</code> </td> <td> <p>name is the name of the KMS plugin to be used.</p> </td> </tr> <tr><td><code>cachesize</code><br/> <code>int32</code> </td> <td> <p>cachesize is the maximum number of secrets which are cached in memory. The default value is 1000. Set to a negative value to disable caching.</p> </td> </tr> <tr><td><code>endpoint</code> <B>[Required]</B><br/> <code>string</code> </td> <td> <p>endpoint is the gRPC server listening address, for example &quot;unix:///var/run/kms-provider.sock&quot;.</p> </td> </tr> <tr><td><code>timeout</code><br/> <a href="https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration"><code>meta/v1.Duration</code></a> </td> <td> <p>timeout for gRPC calls to kms-plugin (ex. 5s). The default is 3 seconds.</p> </td> </tr> </tbody> </table> ## `Key`     {#apiserver-config-k8s-io-v1-Key} **Appears in:** - [AESConfiguration](#apiserver-config-k8s-io-v1-AESConfiguration) - [SecretboxConfiguration](#apiserver-config-k8s-io-v1-SecretboxConfiguration) <p>Key contains name and secret of the provided key for a transformer.</p> <table class="table"> <thead><tr><th width="30%">Field</th><th>Description</th></tr></thead> <tbody> <tr><td><code>name</code> <B>[Required]</B><br/> <code>string</code> </td> <td> <p>name is the name of the key to be used while storing data to disk.</p> </td> </tr> <tr><td><code>secret</code> <B>[Required]</B><br/> <code>string</code> </td> <td> <p>secret is the actual key, encoded in base64.</p> </td> </tr> </tbody> </table> ## `ProviderConfiguration`     {#apiserver-config-k8s-io-v1-ProviderConfiguration} **Appears in:** - [ResourceConfiguration](#apiserver-config-k8s-io-v1-ResourceConfiguration) <p>ProviderConfiguration stores the provided configuration for an encryption provider.</p> <table class="table"> <thead><tr><th width="30%">Field</th><th>Description</th></tr></thead> <tbody> <tr><td><code>aesgcm</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-AESConfiguration"><code>AESConfiguration</code></a> </td> <td> <p>aesgcm is the configuration for the AES-GCM transformer.</p> </td> </tr> <tr><td><code>aescbc</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-AESConfiguration"><code>AESConfiguration</code></a> </td> <td> <p>aescbc is the configuration for the AES-CBC transformer.</p> </td> </tr> <tr><td><code>secretbox</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-SecretboxConfiguration"><code>SecretboxConfiguration</code></a> </td> <td> <p>secretbox is the configuration for the Secretbox based transformer.</p> </td> </tr> <tr><td><code>identity</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-IdentityConfiguration"><code>IdentityConfiguration</code></a> </td> <td> <p>identity is the (empty) configuration for the identity transformer.</p> </td> </tr> <tr><td><code>kms</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-KMSConfiguration"><code>KMSConfiguration</code></a> </td> <td> <p>kms contains the name, cache size and path to configuration file for a KMS based envelope transformer.</p> </td> </tr> </tbody> </table> ## `ResourceConfiguration`     {#apiserver-config-k8s-io-v1-ResourceConfiguration} **Appears in:** - [EncryptionConfiguration](#apiserver-config-k8s-io-v1-EncryptionConfiguration) <p>ResourceConfiguration stores per resource configuration.</p> <table class="table"> <thead><tr><th width="30%">Field</th><th>Description</th></tr></thead> <tbody> <tr><td><code>resources</code> <B>[Required]</B><br/> <code>[]string</code> </td> <td> <p>resources is a list of kubernetes resources which have to be encrypted.</p> </td> </tr> <tr><td><code>providers</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-ProviderConfiguration"><code>[]ProviderConfiguration</code></a> </td> <td> <p>providers is a list of transformers to be used for reading and writing the resources to disk. eg: aesgcm, aescbc, secretbox, identity.</p> </td> </tr> </tbody> </table> ## `SecretboxConfiguration`     {#apiserver-config-k8s-io-v1-SecretboxConfiguration} **Appears in:** - [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) <p>SecretboxConfiguration contains the API configuration for an Secretbox transformer.</p> <table class="table"> <thead><tr><th width="30%">Field</th><th>Description</th></tr></thead> <tbody> <tr><td><code>keys</code> <B>[Required]</B><br/> <a href="#apiserver-config-k8s-io-v1-Key"><code>[]Key</code></a> </td> <td> <p>keys is a list of keys to be used for creating the Secretbox transformer. Each key has to be 32 bytes long.</p> </td> </tr> </tbody> </table> </ins>

--- <ins> title: Encrypting Secret Data at Rest </ins> reviewers: - smarterclayton <del> title: Encrypting Secret Data at Rest </del> content_type: task min-kubernetes-server-version: 1.13 ---

<!-- overview --> This page shows how to enable and configure encryption of secret data at rest. ## {{% heading "prerequisites" %}} * {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} * etcd v3.0 or later is required <!-- steps --> ## Configuration and determining whether encryption at rest is already enabled The `kube-apiserver` process accepts an argument `--encryption-provider-config` <del> that controls how API data is encrypted in etcd. An example configuration is provided below. </del> <ins> that controls how API data is encrypted in etcd. The configuration is provided as an API named [`EncryptionConfiguration`](/docs/reference/config-api/apiserver-encryption.v1/). An example configuration is provided below. </ins> {{< caution >}} <del> **IMPORTANT:** For multi-master configurations (with two or more control plane nodes) the encryption configuration file must be the same! Otherwise, the kube-apiserver can't decrypt data stored inside the key-value store. </del> <ins> **IMPORTANT:** For high-availability configurations (with two or more control plane nodes), the encryption configuration file must be the same! Otherwise, the `kube-apiserver` component cannot decrypt data stored in the etcd. </ins> {{< /caution >}} ## Understanding the encryption at rest configuration.

kind: EncryptionConfiguration resources: - resources: <del> - secrets </del> <ins> - secrets </ins> providers: <del> - identity: {} - aesgcm: keys: - name: key1 secret: c2VjcmV0IGlzIHNlY3VyZQ== - name: key2 secret: dGhpcyBpcyBwYXNzd29yZA== - aescbc: keys: - name: key1 secret: c2VjcmV0IGlzIHNlY3VyZQ== - name: key2 secret: dGhpcyBpcyBwYXNzd29yZA== - secretbox: keys: - name: key1 secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY= </del> <ins> - identity: {} - aesgcm: keys: - name: key1 secret: c2VjcmV0IGlzIHNlY3VyZQ== - name: key2 secret: dGhpcyBpcyBwYXNzd29yZA== - aescbc: keys: - name: key1 secret: c2VjcmV0IGlzIHNlY3VyZQ== - name: key2 secret: dGhpcyBpcyBwYXNzd29yZA== - secretbox: keys: - name: key1 secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY= </ins> ``` Each `resources` array item is a separate config and contains a complete configuration. The `resources.resources` field is an array of Kubernetes resource names (`resource` or `resource.group`) that should be encrypted. The `providers` array is an ordered list of the possible encryption <del> providers. Only one provider type may be specified per entry (`identity` or `aescbc` may be provided, but not both in the same item). </del> <ins> providers. </ins> <del> The first provider in the list is used to encrypt resources going into storage. When reading resources from storage each provider that matches the stored data attempts to decrypt the data in order. If no provider can read the stored data due to a mismatch in format or secret key, an error </del> <ins> Only one provider type may be specified per entry (`identity` or `aescbc` may be provided, but not both in the same item). The first provider in the list is used to encrypt resources written into the storage. When reading resources from storage, each provider that matches the stored data attempts in order to decrypt the data. If no provider can read the stored data due to a mismatch in format or secret key, an error </ins> is returned which prevents clients from accessing that resource. <ins> For more detailed information about the `EncryptionConfiguration` struct, please refer to the [encryption configuration API](/docs/reference/config-api/apiserver-encryption.v1/). </ins> {{< caution >}} <del> **IMPORTANT:** If any resource is not readable via the encryption config (because keys were changed), </del> <ins> If any resource is not readable via the encryption config (because keys were changed), </ins> the only recourse is to delete that key from the underlying etcd directly. Calls that attempt to read that resource will fail until it is deleted or a valid decryption key is provided. {{< /caution >}}

Each provider supports multiple keys - the keys are tried in order for decryption, and if the provider is the first provider, the first key is used for encryption. <del> __Storing the raw encryption key in the EncryptionConfig only moderately improves your security posture, compared to no encryption. Please use `kms` provider for additional security.__ By default, the `identity` provider is used to protect secrets in etcd, which provides no encryption. `EncryptionConfiguration` was introduced to encrypt secrets locally, with a locally managed key. Encrypting secrets with a locally managed key protects against an etcd compromise, but it fails to protect against a host compromise. Since the encryption keys are stored on the host in the EncryptionConfig YAML file, a skilled attacker can access that file and extract the encryption keys. </del> <ins> {{< caution >}} Storing the raw encryption key in the EncryptionConfig only moderately improves your security posture, compared to no encryption.  Please use `kms` provider for additional security. {{< /caution >}} By default, the `identity` provider is used to protect Secrets in etcd, which provides no encryption. `EncryptionConfiguration` was introduced to encrypt Secrets locally, with a locally managed key. </ins> <del> Envelope encryption creates dependence on a separate key, not stored in Kubernetes. In this case, an attacker would need to compromise etcd, the kubeapi-server, and the third-party KMS provider to retrieve the plaintext values, providing a higher level of security than locally-stored encryption keys. </del> <ins> Encrypting Secrets with a locally managed key protects against an etcd compromise, but it fails to protect against a host compromise. Since the encryption keys are stored on the host in the EncryptionConfiguration YAML file, a skilled attacker can access that file and extract the encryption keys. Envelope encryption creates dependence on a separate key, not stored in Kubernetes. In this case, an attacker would need to compromise etcd, the `kubeapi-server`, and the third-party KMS provider to retrieve the plaintext values, providing a higher level of security than locally stored encryption keys. </ins> ## Encrypting your data

kind: EncryptionConfiguration resources: - resources: <del> - secrets </del> <ins> - secrets </ins> providers: <del> - aescbc: keys: - name: key1 secret: <BASE 64 ENCODED SECRET> - identity: {} </del> <ins> - aescbc: keys: - name: key1 secret: <BASE 64 ENCODED SECRET> - identity: {} </ins> ``` <del> To create a new secret perform the following steps: </del> <ins> To create a new Secret, perform the following steps: </ins> <del> 1. Generate a 32 byte random key and base64 encode it. If you're on Linux or macOS, run the following command: </del> <ins> 1. Generate a 32-byte random key and base64 encode it. If you're on Linux or macOS, run the following command: </ins> ```shell head -c 32 /dev/urandom | base64 ``` <del> 2. Place that value in the secret field. 3. Set the `--encryption-provider-config` flag on the `kube-apiserver` to point to the location of the config file. 4. Restart your API server. </del> <ins> 1. Place that value in the `secret` field of the `EncryptionConfiguration` struct. 1. Set the `--encryption-provider-config` flag on the `kube-apiserver` to point to the location of the config file. 1. Restart your API server. </ins> {{< caution >}} <del> Your config file contains keys that can decrypt content in etcd, so you must properly restrict permissions on your masters so only the user who runs the kube-apiserver can read it. </del> <ins> Your config file contains keys that can decrypt the contents in etcd, so you must properly restrict permissions on your control-plane nodes so only the user who runs the `kube-apiserver` can read it. </ins> {{< /caution >}} ## Verifying that data is encrypted Data is encrypted when written to etcd. After restarting your `kube-apiserver`, any newly created or <del> updated secret should be encrypted when stored. To check, you can use the `etcdctl` command line program to retrieve the contents of your secret. </del> <ins> updated Secret should be encrypted when stored. To check this, you can use the `etcdctl` command line program to retrieve the contents of your Secret. </ins> <del> 1. Create a new secret called `secret1` in the `default` namespace: </del> <ins> 1. Create a new Secret called `secret1` in the `default` namespace: </ins> ```shell kubectl create secret generic secret1 -n default --from-literal=mykey=mydata ``` <del> 2. Using the etcdctl commandline, read that secret out of etcd: </del> <ins> 1. Using the `etcdctl` command line, read that Secret out of etcd: </ins> `ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C` where `[...]` must be the additional arguments for connecting to the etcd server. <del> 3. Verify the stored secret is prefixed with `k8s:enc:aescbc:v1:` which indicates the `aescbc` provider has encrypted the resulting data. </del> <ins> 1. Verify the stored Secret is prefixed with `k8s:enc:aescbc:v1:` which indicates the `aescbc` provider has encrypted the resulting data. </ins> <del> 4. Verify the secret is correctly decrypted when retrieved via the API: </del> <ins> 1. Verify the Secret is correctly decrypted when retrieved via the API: </ins> ```shell kubectl describe secret secret1 -n default ``` <del> should match `mykey: bXlkYXRh`, mydata is encoded, check [decoding a secret](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret) to completely decode the secret. </del> <ins> The output should contain `mykey: bXlkYXRh`, with contents of `mydata` encoded, check [decoding a Secret](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret) to completely decode the Secret. </ins> <del> ## Ensure all secrets are encrypted </del> <ins> ## Ensure all Secrets are encrypted </ins> <del> Since secrets are encrypted on write, performing an update on a secret will encrypt that content. </del> <ins> Since Secrets are encrypted on write, performing an update on a Secret will encrypt that content. </ins> ```shell kubectl get secrets --all-namespaces -o json | kubectl replace -f - ``` <del> The command above reads all secrets and then updates them to apply server side encryption. </del> <ins> The command above reads all Secrets and then updates them to apply server side encryption. </ins> {{< note >}} If an error occurs due to a conflicting write, retry the command. For larger clusters, you may wish to subdivide the secrets by namespace or script an update. {{< /note >}} ## Rotating a decryption key <del> Changing the secret without incurring downtime requires a multi step operation, especially in the presence of a highly available deployment where multiple `kube-apiserver` processes are running. </del> <ins> Changing a Secret without incurring downtime requires a multi-step operation, especially in the presence of a highly-available deployment where multiple `kube-apiserver` processes are running. </ins> 1. Generate a new key and add it as the second key entry for the current provider on all servers <del> 2. Restart all `kube-apiserver` processes to ensure each server can decrypt using the new key 3. Make the new key the first entry in the `keys` array so that it is used for encryption in the config 4. Restart all `kube-apiserver` processes to ensure each server now encrypts using the new key 5. Run `kubectl get secrets --all-namespaces -o json | kubectl replace -f -` to encrypt all existing secrets with the new key 6. Remove the old decryption key from the config after you back up etcd with the new key in use and update all secrets With a single `kube-apiserver`, step 2 may be skipped. </del> <ins> 1. Restart all `kube-apiserver` processes to ensure each server can decrypt using the new key 1. Make the new key the first entry in the `keys` array so that it is used for encryption in the config 1. Restart all `kube-apiserver` processes to ensure each server now encrypts using the new key 1. Run `kubectl get secrets --all-namespaces -o json | kubectl replace -f -` to encrypt all existing Secrets with the new key 1. Remove the old decryption key from the config after you have backed up etcd with the new key in use and updated all Secrets When running a single `kube-apiserver` instance, step 2 may be skipped. </ins> ## Decrypting all data <del> To disable encryption at rest place the `identity` provider as the first entry in the config: </del> <ins> To disable encryption at rest, place the `identity` provider as the first entry in the config and restart all `kube-apiserver` processes. </ins> ```yaml apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration resources: - resources: <del> - secrets </del> <ins> - secrets </ins> providers: <del> - identity: {} - aescbc: keys: - name: key1 secret: <BASE 64 ENCODED SECRET> </del> <ins> - identity: {} - aescbc: keys: - name: key1 secret: <BASE 64 ENCODED SECRET> </ins> ``` <del> and restart all `kube-apiserver` processes. Then run: </del> <ins> Then run the following command to force decrypt all Secrets: </ins> ```shell kubectl get secrets --all-namespaces -o json | kubectl replace -f - ``` <del> to force all secrets to be decrypted. </del> <ins> ## {{% heading "whatsnext" %}} * Learn more about the [EncryptionConfiguration configuration API (v1)](/docs/reference/config-api/apiserver-encryption.v1/). </ins>