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
Support encryption-at-rest for the kube-apiserver #3368
Support encryption-at-rest for the kube-apiserver #3368
Conversation
@georgebuckerfield: Your pull request title starts with "WIP", so the do-not-merge/work-in-progress label will be added. This label will ensure that your pull request will not be merged. Remove the prefix from your pull request title to trigger the removal of the label and allow for your pull request to be merged. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Hi @georgebuckerfield. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
cmd/kops/create_cluster.go
Outdated
@@ -299,6 +300,9 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command { | |||
cmd.Flags().StringVar(&options.VSphereCoreDNSServer, "vsphere-coredns-server", options.VSphereCoreDNSServer, "vsphere-coredns-server is required for vSphere.") | |||
cmd.Flags().StringVar(&options.VSphereDatastore, "vsphere-datastore", options.VSphereDatastore, "vsphere-datastore is required for vSphere. Set a valid datastore in which to store dynamic provision volumes.") | |||
} | |||
if featureflag.EnableEtcdEncryption.Enabled() { |
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.
Not sure the feature flag or cli option is really required; i'm tempted to say we shouldn't encourage creating clusters via cli options, but push for creation via config instead; @justinsb @chrislovecnm .. I'm also guessing the feature requires more config than bool to be useful, i.e. keys ... I think we should drop the reference to etcd as well
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 @gambol99, let's not have a cli option, and remove the etcd verbadge. The users can use manifests or do an edit on the cluster after a create.
I am on the side of not having a featureflag as well.
nodeup/pkg/model/encryption.go
Outdated
) | ||
|
||
// EncryptionBuilder builds the encryption-at-rest config | ||
type EncryptionBuilder struct { |
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.
can we not wrap all this logic into the kube_apisever builder itself?
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.
Agreed
nodeup/pkg/model/encryption.go
Outdated
var _ fi.ModelBuilder = &EncryptionBuilder{} | ||
|
||
// Build is responsible for building the config file | ||
func (b *EncryptionBuilder) Build(c *fi.ModelBuilderContext) error { |
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 noticed your add the build here .. there doesn't appear to be a conditional on the role though? .. does the file need to be on masters and nodes?
nodeup/pkg/model/encryption.go
Outdated
import ( | ||
"fmt" | ||
|
||
"k8s.io/apiserver/pkg/server/options/encryptionconfig" |
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 think a general convention ... std lib, local imports and then external .. Could we drop the encryptionconfig import down
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 can change this, but it doesn't seem to be consistent with the rest of the repo. The convention seems to be: std lib, k8s.io libraries, external libraries e.g. in nodeup/pkg/model/kubeapiserver.go
, nodeup/pkg/model/kubecontrollermanager.go
etc. Happy to modify if I'm wrong though!
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.
The imports formatting is not consistent through the project ;( But yes @gambol99 has it correct
nodeup/pkg/model/encryption.go
Outdated
|
||
func (b *EncryptionBuilder) buildEncryptionConfig() (*encryptionconfig.EncryptionConfig, error) { | ||
resources := b.Cluster.Spec.KubeEtcdEncryptionConfig.Resources | ||
config := &encryptionconfig.EncryptionConfig{ |
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.
this could probably be a oneliner
return &encryptionconfig.EncryptionConfig{
Kind: "EncryptionConfig",
APIVersion: "v1",
Resources: b.Cluster.Spec.KubeEtcdEncryptionConfig.Resources,
}, nil
pkg/apis/kops/encryption.go
Outdated
) | ||
|
||
// KubeEtcdEncryptionConfig holds the etcd encryption config | ||
type KubeEtcdEncryptionConfig struct { |
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 think we can keep this in the componentconfig.go
pkg/apis/kops/v1alpha1/encryption.go
Outdated
) | ||
|
||
// KubeEtcdEncryptionConfig holds the etcd encryption config | ||
type KubeEtcdEncryptionConfig struct { |
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.
same as above
pkg/model/components/apiserver.go
Outdated
@@ -204,6 +204,11 @@ func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error { | |||
c.InsecurePort = 8080 | |||
} | |||
|
|||
// Set the path for the encryption-at-rest config | |||
if *clusterSpec.KubeEtcdEncryptionConfig.Enabled { |
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.
does this not cause a panic if not set? .. should we check for a nil
pkg/featureflag/featureflag.go
Outdated
@@ -55,6 +55,9 @@ var EnableExternalDNS = New("EnableExternalDNS", Bool(false)) | |||
// SpecOverrideFlag allows setting spec values on create | |||
var SpecOverrideFlag = New("SpecOverrideFlag", Bool(false)) | |||
|
|||
// EnableEtcdEncryption if will enable encryption-at-rest for etcd. | |||
var EnableEtcdEncryption = New("EnableDataEncryption", Bool(false)) |
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.
dependent on @justinsb and @chrislovecnm if a feature flag is required
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 can pull it
upup/pkg/fi/nodeup/command.go
Outdated
@@ -220,6 +220,9 @@ func (c *NodeUpCommand) Run(out io.Writer) error { | |||
} else { | |||
loader.Builders = append(loader.Builders, &model.KubeRouterBuilder{NodeupModelContext: modelContext}) | |||
} | |||
if *c.cluster.Spec.KubeEtcdEncryptionConfig.Enabled { | |||
loader.Builders = append(loader.Builders, &model.EncryptionBuilder{NodeupModelContext: modelContext}) |
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.
tempted to say we wrap this into the KubeAPIServerBuilder
Thanks for the review @gambol99, I'll start addressing these tonight. Going to try and get some tests added as well. |
/ok-to-test |
/retest |
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.
You have taken in a great, but complex piece of work. Thanks for the help! Appreciate your patience with the PR review process.
Question for yah
- aescbc: | ||
keys: | ||
- name: key1 | ||
secret: c2VjcmV0IGlzIHNlY3VyQ== |
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 is this secret used for? Should we have this in a kops secret?
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.
That secret is used by the apiserver to encrypt/decrypt the data, so ideally I think it should be a secret/obscured somehow. What makes it tricky is users can specify an arbitrary number of keys for each provider (the apiserver will try them each in order when decrypting), so I'm not quite sure how that will work with kops secrets? I suppose users could create multiple secrets with kops secret create aescbckey key1 c2Vj...
, kops secret create aescbckey key1 nf9D...
, or something similar. We could then swap in the actual secrets when nodeup runs?
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.
Or actually, just store the entire encryptionconfig in a secret? That might simplify things a bit.
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 would store the encryptionconfig in a secret. We just had a PR for docker login perms. Let me find it.
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.
Ok, so I've refactored this. The process for enabling encryption for a cluster would now be:
I'm completely open to renaming the |
@gambol99 can you give a review, please? Many changes have been made. |
@georgebuckerfield looks good, if @gambol99 does not get back to you, please reach out. But @gambol99 if available will give it a look. Again appreciate your patience with this, as this PR went through a few cycles |
Cheers @chrislovecnm, appreciate your help getting this through! |
@georgebuckerfield @chrislovecnm ... lgtm |
/lgtm |
Sorry, @georgebuckerfield ... can we squash the git commits into reasonable chunks of work or just one commit? One last thing. |
- add a new kops secret command to store encryption config - add the experimential-encryption-provider-config flag to the kube-apiserver - add functionality to nodeup to create the stored encryption config in the correct path
Yep, @chrislovecnm, I'm working on that now. I've made it slightly complicated for myself by merging in upstream updates halfway through (to resolve a conflict), just sorting that out now. |
e472e4d
to
da36425
Compare
/retest |
@georgebuckerfield restarted the travis build for you |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: chrislovecnm The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
/test all [submit-queue is verifying that this PR is safe to merge] |
Automatic merge from submit-queue. . |
Unless I'm miserably failing at searching, I could not find any documentation on how the config file should look like when executing Is there any example available somewhere? |
Because people will find @elisiano's question and not an answer : https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/ covers creating that config.yaml file. |
Thank you @iMartyn ! |
This PR adds support for enabling encryption-at-rest for data in etcd, via the kube-apiserver (as per https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data).
I've put the functionality behind a feature flag,
+EnableDataEncryption
. It can then be enabled per-cluster by using--enable-encryption-config
on the command line, or by adding akubeEncryptionConfig
section to the cluster spec. This is passed through to the kube-apiserver by the nodeup process. I'm not sure if this is the best way of doing it right now, but it is working.Fixes #3356.