-
Notifications
You must be signed in to change notification settings - Fork 233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add encryption providers proposal #1213
Merged
kubermatic-bot
merged 4 commits into
kubermatic:master
from
moelsayed:encryption_providers
Feb 11, 2021
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# Encryption Providers for encrypted secrets at rest | ||
|
||
**Auther**: Mohamed Elsayed (@moelsayed) | ||
**Status**: Draft | ||
|
||
|
||
## Abstract | ||
|
||
By default, all Kubernetes secret objects are stored on disk in plain text inside etcd. The [Encryption Providers](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/ | ||
) feature was added to Kubernets starting with version 1.13. | ||
|
||
At rest data encryption is a requirement for security compliance and adds an additional layer of security for secret data, especially when etcd nodes are separated from the control plan and in off-node backups. | ||
|
||
KubeOne needs to support this feature natively. Meaning the user should be able to enable, disable the feature and rotate keys when needed without having to apply any actions manually. | ||
|
||
## Goals | ||
|
||
* Provide a safe path to enable/disable Encryption Providers. | ||
* Support atomic(?) rotation for existing keys. | ||
* Rewriting all secret resources (no just secrets) after enable/disable/rotate operations. | ||
|
||
## Non-Goals | ||
|
||
* Deploy External KMS. | ||
* Safely manage (disable/enable/rotate) configuration when a custom configuration file is used. | ||
|
||
## Challenges | ||
|
||
The feature has a lot of moving parts; as it requires performing a specific sequence of actions, including changing the KubeAPI configuration, restarting KubeAPI and rewriting all secret resources to apply the encryption. This requires the implementation to be as idempotent as possible with ability to rollback on failure, with out breaking the cluster. | ||
|
||
## Implementation | ||
|
||
Unfortunately, it's not possible to simply update the KubeAPI configuration and expect the configuration to reconcile. KubeOne will have to _read_ the _current_ configuration on the cluster, _mutate_ it based on the _required_ state and then apply it. Additionally, KubeOne will have to be able to revert changes on any errors and recover safely if the process is interrupted at any point. | ||
|
||
The configuration for this will be added under `features` in the KubeOneCluster spec: | ||
|
||
```yaml | ||
apiVersion: kubeone.io/v1beta1 | ||
kind: KubeOneCluster | ||
features: | ||
encryptionProviders: | ||
enabled: true | ||
customProvidersFile: | | ||
apiVersion: apiserver.config.k8s.io/v1 | ||
kind: EncryptionConfiguration | ||
resources: | ||
- resources: | ||
- secrets | ||
providers: | ||
- identity: {} | ||
- aescbc: | ||
keys: | ||
- name: key1 | ||
secret: <BASE 64 ENCODED SECRET> | ||
``` | ||
|
||
To allow users to rotate the keys, a new flag will be added to the `apply` command: | ||
|
||
```bash | ||
--rotate-encryption-key automatically rotate encryption provider key | ||
``` | ||
|
||
### pre-flight checks | ||
|
||
* Cluster is healthy. | ||
* Current Encryption Providers state/configuration is valid and identical on all control plane nodes. | ||
|
||
### Enable Encryption Providers for new cluster | ||
|
||
* Generate a valid configuration file with the `identity` provider set last. | ||
* Sync the configuration file to all Control Plane nodes. | ||
* Set the required KubeAPI configuration and deploy KubeAPI. | ||
|
||
### Enable Encryption Providers for existing cluster | ||
|
||
* Ensure there is no Encryption Provider Config (manually added by the user, broken previous enable process, etc..) present. | ||
* Generate a valid configuration file with the `identity` provider set last. | ||
* Sync the configuration file to all Control Plane nodes. | ||
* Update and restart KubeAPI on all nodes. | ||
* Rewrite secrets to ensure they are encrypted successfully. | ||
|
||
### Disable Encryption Providers for existing cluster | ||
|
||
* Read the current active Encryption Provider configuration from control plane nodes. | ||
* Mutate the configuration to add `identity` provider first and the active provider last. | ||
* Sync the configuration file to all Control Plane nodes. | ||
* Restart KubeAPI on all control plane nodes. | ||
* Rewrite secrets to ensure they are decrypted successfully. | ||
* Update KubeAPI configuration to remove the Encryption Provider configuration and restart KubeAPI on all control plane nodes. | ||
* Remove the old configuration file from all control plane nodes. | ||
|
||
### Rotate Encryption Provider Key for existing cluster | ||
|
||
* Read the current active Encryption Provider configuration from control plane nodes. | ||
* Generate a new encryption key. | ||
* Mutate the configuration file to include the new key first, current key second and `identity` last. | ||
* Sync the updated configuration file to all control plane nodes and restart KubeAPI. | ||
* Rewrite all secrets to ensure they are encrypted with the new key. | ||
* Mutate the configuration file again to remove the old key. | ||
* Sync the updated configuration file to all control plane nodes and restart KubeAPI. | ||
|
||
### Apply Custom Encryption Provider file | ||
This use case is useful for users who would like to utilize an external KMS provider or specify resources other than secrets for encryption. In this case, KubeOne will not manage the content of the file, it will only validate it to make sure it's syntactically valid. Additionally, KubeOne will not rewrite the resources in this case. | ||
|
||
* Ensure the configuration file is valid. | ||
* Sync the configuration file to all control plane nodes. | ||
* Restart KubeAPI on all nodes. | ||
kron4eg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Tasks & effort | ||
|
||
* Implement the needed pre-flight checks. | ||
* Implement validation for Encryption Provider configuration files. | ||
* Implement the workflow for each use case. | ||
* Add e2e tests for each workflow. | ||
* Add documentation for the feature. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping in mind future API extensions that will be inevitably required, simple boolean flag is not enough. Flags are needed per provider type, and not only flags but possible config options too.
So we are looking at 3 possible providers:
Those should be expressed as additional objects inside
encryptionProviders
, likeAlternatively, we could not reimplement parts of what's already done in upstream and "just" provide the
Given that second option, we can actually extract the
endpoint
from KMS providers and automatically mount them to the kube-apiserver pod ( with extra mounts in kubeadm config).Provided that we can detect changes in
encryptionConfiguration
(compare actual file to encryptionConfiguration`, we can automate and orchestrate kubeapi pod restarts.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Providing ONLY
encryptionConfiguration
we could give all encryption options to the end user, including KMS support in one shot.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with what @kron4eg said, but in that case, I'd leave the
enable
field in the API and implement it like @moelsayed initially proposed. For example:The difference between the originally proposed API and this API is that I've removed the
rotate
field. Instead of therotate
field, we would keep the CLI flag as it's currently proposed.enable
is set tofalse
enable
is set totrue
:customProviderFile
is not set, generate it ourselves and handle key managementcustomProviderFile
is set, upload it to the instance. Additionally, if KMS is configured, create the appropriate volumes on the API server podsNote: if
customProviderFile
is set and the CLI flag is set, KubeOne would either show a warning or fail.In this case, we can quickly implement support for all setups. Technically, users could use Terraform/Ansible to deploy KMS and with such API, they could actually use it in their clusters. I think that it wouldn't require too much additional effort on our side, but we could solve everything (besides deploying KMS, which should be discussed) in a single run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kron4eg @xmudrii I updated the proposal accordingly. Please check.
For the initial implementation, I will stop at implementing the the custom config basic functionality. I will create a new issue/PR to address deploying the KMS and creating the required volume mounts for the API server. I am considering that out of scope for the initial implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@moelsayed Can you create an Epic for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xmudrii there is already an epic to track the proposal and the implementation: #769
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@moelsayed I was thinking about an Epic for addressing the KMS deployment and the volume creation. You can also extend the current Epic. I only see issues relevant to the initial implementation in the Epic, but please correct me if I'm wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if:
enable: true
, but nocustomProviderFile
is given (e.g. it's empty)?enable: true
, but nocustomProviderFile
is given and install/apply is run, and thencustomProviderFile
becomes defined?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We manage everything automatically. A new config file is created and pushed to the nodes. In this case key rotation is supported.
K1 should push the defined custom file but it will refuse to the rotate the keys if the rotate flag is set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xmudrii I updated the epic with an issue to add KMS #1242.