Skip to content
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

Custom resource encryption #113015

Merged
merged 1 commit into from Oct 26, 2022
Merged

Conversation

ritazh
Copy link
Member

@ritazh ritazh commented Oct 12, 2022

What type of PR is this?

/kind bug

What this PR does / why we need it:

Enable encryption of custom resources in ETCD

Which issue(s) this PR fixes:

Fixes #104165

Special notes for your reviewer:

Does this PR introduce a user-facing change?

kube-apiserver: APIs backed by CustomResourceDefinitions can now be specified in the `--encryption-provider-config` file; when specified, the data for those custom resources can now be encrypted in etcd.

Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:

Custom resources can now be encrypted in ETCD

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. release-note Denotes a PR that will be considered when it comes time to generate release notes. kind/bug Categorizes issue or PR as related to a bug. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. do-not-merge/contains-merge-commits Indicates a PR which contains merge commits. labels Oct 12, 2022
@ritazh ritazh changed the title Crencryption Customer resource encryption Oct 12, 2022
@ritazh ritazh marked this pull request as draft October 12, 2022 15:33
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 12, 2022
@k8s-ci-robot k8s-ci-robot added area/apiserver area/test sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. sig/testing Categorizes an issue or PR as relevant to SIG Testing. and removed do-not-merge/needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels Oct 12, 2022
@leilajal
Copy link
Contributor

/remove-sig api-machinery

@k8s-ci-robot k8s-ci-robot removed the sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. label Oct 13, 2022
@aramase
Copy link
Member

aramase commented Oct 13, 2022

/cc

@k8s-ci-robot k8s-ci-robot added needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. labels Oct 13, 2022
@ritazh ritazh changed the title Customer resource encryption Custom resource encryption Oct 14, 2022
@k8s-ci-robot k8s-ci-robot removed needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. do-not-merge/contains-merge-commits Indicates a PR which contains merge commits. labels Oct 14, 2022
@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 18, 2022
@enj
Copy link
Member

enj commented Oct 18, 2022

New integration test from 0c2357af6aa40ec0f6b5cae1fc60c748eec997a1 applied to master fails as expected, with proper subtest breakdown:

=== RUN   TestEncryptSupportedForAllResourceTypes
    testserver.go:244: runtime-config=map[api/all:true]
    testserver.go:245: Starting kube-apiserver on port 36789...
    testserver.go:265: Waiting for /healthz to be ok...
=== RUN   TestEncryptSupportedForAllResourceTypes/configmaps
=== PAUSE TestEncryptSupportedForAllResourceTypes/configmaps
=== RUN   TestEncryptSupportedForAllResourceTypes/customresourcedefinitions
=== PAUSE TestEncryptSupportedForAllResourceTypes/customresourcedefinitions
=== RUN   TestEncryptSupportedForAllResourceTypes/pandas
=== PAUSE TestEncryptSupportedForAllResourceTypes/pandas
=== RUN   TestEncryptSupportedForAllResourceTypes/apiservices
=== PAUSE TestEncryptSupportedForAllResourceTypes/apiservices
=== RUN   TestEncryptSupportedForAllResourceTypes/pods
=== PAUSE TestEncryptSupportedForAllResourceTypes/pods
=== CONT  TestEncryptSupportedForAllResourceTypes/configmaps
=== CONT  TestEncryptSupportedForAllResourceTypes/apiservices
=== CONT  TestEncryptSupportedForAllResourceTypes/pandas
=== CONT  TestEncryptSupportedForAllResourceTypes/customresourcedefinitions
=== CONT  TestEncryptSupportedForAllResourceTypes/pods
=== CONT  TestEncryptSupportedForAllResourceTypes/customresourcedefinitions
    transformation_testcase.go:194: Get object with dynamic client
=== CONT  TestEncryptSupportedForAllResourceTypes/apiservices
    transformation_testcase.go:194: Get object with dynamic client
=== CONT  TestEncryptSupportedForAllResourceTypes/pandas
    transformation_testcase.go:135: expected data to be prefixed with k8s:enc:aescbc:v1:key1:, but got {"apiVersion":"awesome.bears.com/v1","kind":"Panda","metadata":{"creationTimestamp":"2022-10-18T12:39:44Z","generation":1,"managedFields":[{"apiVersion":"awesome.bears.com/v1","fieldsType":"FieldsV1","fieldsV1":{"f:spec":{".":{},"f:replicas":{}}},"manager":"transformation.test","operation":"Update","time":"2022-10-18T12:39:44Z"}],"name":"cr3panda","uid":"9e9d63b3-d206-4905-b539-cda35cc44f5b"},"spec":{"replicas":100}}
--- FAIL: TestEncryptSupportedForAllResourceTypes (6.39s)
    --- PASS: TestEncryptSupportedForAllResourceTypes/configmaps (0.03s)
    --- PASS: TestEncryptSupportedForAllResourceTypes/customresourcedefinitions (0.03s)
    --- PASS: TestEncryptSupportedForAllResourceTypes/pods (0.03s)
    --- PASS: TestEncryptSupportedForAllResourceTypes/apiservices (0.03s)
    --- FAIL: TestEncryptSupportedForAllResourceTypes/pandas (2.06s)
FAIL
FAIL	k8s.io/kubernetes/test/integration/controlplane/transformation	8.627s
FAIL

@enj
Copy link
Member

enj commented Oct 18, 2022

/milestone v1.26
/triage accepted
/priority important-soon
/sig auth

@k8s-ci-robot k8s-ci-robot added the triage/accepted Indicates an issue or PR is ready to be actively worked on. label Oct 18, 2022
@k8s-ci-robot k8s-ci-robot added this to the v1.26 milestone Oct 18, 2022
@k8s-ci-robot k8s-ci-robot added priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. sig/auth Categorizes an issue or PR as relevant to SIG Auth. and removed needs-priority Indicates a PR lacks a `priority/foo` label and requires one. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels Oct 18, 2022
@@ -161,6 +216,23 @@ func (e *transformTest) getETCDPath() string {
return fmt.Sprintf("/%s/secrets/%s/%s", e.storageConfig.Prefix, e.ns.Name, e.secret.Name)
}

func (e *transformTest) getETCDPathForResource(group, resource, name, namespaceName string) string {
if e.secret != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's pretty hard to follow for state inside transformTest to override params... can we make this a pure function that takes storagePrefix, group, resource, name, namespace params?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, what's the difference between getETCDPathForResource and getETCDPath? can we collapse to a single etcd path computation function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, what's the difference between getETCDPathForResource and getETCDPath? can we collapse to a single etcd path computation function?

I didn't want to touch getETCDPath to minimize changes on existing test files. If you prefer to combine them, then I will go ahead and update kms_transformation_test.go and kmsv2_transformation_test.go. LMK!

Copy link
Member

@liggitt liggitt Oct 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, go ahead and clean up run and getETCDPath... the ripples don't look too bad and I think leave the test package in a less confusing state (mostly just makes the paths that assume they are dealing with secrets explicitly say so)

I got a clean run with this diff:

diff --git a/test/integration/controlplane/transformation/kms_transformation_test.go b/test/integration/controlplane/transformation/kms_transformation_test.go
index 9773296ee29..3db46c22c3b 100644
--- a/test/integration/controlplane/transformation/kms_transformation_test.go
+++ b/test/integration/controlplane/transformation/kms_transformation_test.go
@@ -145,7 +145,7 @@ resources:
 	// Since Data Encryption Key (DEK) is randomly generated (per encryption operation), we need to ask KMS Mock for it.
 	plainTextDEK := pluginMock.LastEncryptRequest()
 
-	secretETCDPath := test.getETCDPath()
+	secretETCDPath := test.getETCDPathForResource("", "secrets", test.secret.Name, test.secret.Namespace)
 	rawEnvelope, err := test.getRawSecretFromETCD()
 	if err != nil {
 		t.Fatalf("failed to read %s from etcd: %v", secretETCDPath, err)
diff --git a/test/integration/controlplane/transformation/kmsv2_transformation_test.go b/test/integration/controlplane/transformation/kmsv2_transformation_test.go
index dfb250a938f..f8b385adb24 100644
--- a/test/integration/controlplane/transformation/kmsv2_transformation_test.go
+++ b/test/integration/controlplane/transformation/kmsv2_transformation_test.go
@@ -154,7 +154,7 @@ resources:
 	// Since Data Encryption Key (DEK) is randomly generated (per encryption operation), we need to ask KMS Mock for it.
 	plainTextDEK := pluginMock.LastEncryptRequest()
 
-	secretETCDPath := test.getETCDPath()
+	secretETCDPath := test.getETCDPathForResource("", "secrets", test.secret.Name, test.secret.Namespace)
 	rawEnvelope, err := test.getRawSecretFromETCD()
 	if err != nil {
 		t.Fatalf("failed to read %s from etcd: %v", secretETCDPath, err)
diff --git a/test/integration/controlplane/transformation/secrets_transformation_test.go b/test/integration/controlplane/transformation/secrets_transformation_test.go
index b899237a937..ccbd86ef0ff 100644
--- a/test/integration/controlplane/transformation/secrets_transformation_test.go
+++ b/test/integration/controlplane/transformation/secrets_transformation_test.go
@@ -95,7 +95,7 @@ func TestSecretsShouldBeTransformed(t *testing.T) {
 		if err != nil {
 			t.Fatalf("Failed to create test secret, error: %v", err)
 		}
-		test.run(tt.unSealFunc, tt.transformerPrefix)
+		test.runResource(test.logger, tt.unSealFunc, tt.transformerPrefix, "", "v1", "secrets", test.secret.Name, test.secret.Namespace)
 		test.cleanUp()
 	}
 }
diff --git a/test/integration/controlplane/transformation/transformation_testcase.go b/test/integration/controlplane/transformation/transformation_testcase.go
index d5ca2b8fcc7..cea83135866 100644
--- a/test/integration/controlplane/transformation/transformation_testcase.go
+++ b/test/integration/controlplane/transformation/transformation_testcase.go
@@ -114,10 +114,6 @@ func (e *transformTest) cleanUp() {
 	e.kubeAPIServer.TearDownFn()
 }
 
-func (e *transformTest) run(unSealSecretFunc unSealSecret, expectedEnvelopePrefix string) {
-	e.runResource(e.logger, unSealSecretFunc, expectedEnvelopePrefix, "", "v1", "secrets", "", "")
-}
-
 func (e *transformTest) runResource(l kubeapiservertesting.Logger, unSealSecretFunc unSealSecret, expectedEnvelopePrefix,
 	group,
 	version,
@@ -212,17 +208,7 @@ func (e *transformTest) benchmark(b *testing.B) {
 	}
 }
 
-func (e *transformTest) getETCDPath() string {
-	return fmt.Sprintf("/%s/secrets/%s/%s", e.storageConfig.Prefix, e.ns.Name, e.secret.Name)
-}
-
 func (e *transformTest) getETCDPathForResource(group, resource, name, namespaceName string) string {
-	if e.secret != nil {
-		group = ""
-		resource = "secrets"
-		name = testSecret
-		namespaceName = testNamespace
-	}
 	groupResource := resource
 	if group != "" {
 		groupResource = fmt.Sprintf("%s/%s", group, resource)
@@ -234,7 +220,7 @@ func (e *transformTest) getETCDPathForResource(group, resource, name, namespaceN
 }
 
 func (e *transformTest) getRawSecretFromETCD() ([]byte, error) {
-	secretETCDPath := e.getETCDPath()
+	secretETCDPath := e.getETCDPathForResource("", "secrets", e.secret.Name, e.ns.Name)
 	etcdResponse, err := e.readRawRecordFromETCD(secretETCDPath)
 	if err != nil {
 		return nil, fmt.Errorf("failed to read %s from etcd: %v", secretETCDPath, err)

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 26, 2022
@liggitt
Copy link
Member

liggitt commented Oct 26, 2022

/approve
squash, then lgtm

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: enj, liggitt, ritazh

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 26, 2022
Signed-off-by: Rita Zhang <rita.z.zhang@gmail.com>
@enj
Copy link
Member

enj commented Oct 26, 2022

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 26, 2022
@k8s-ci-robot k8s-ci-robot merged commit 52f5816 into kubernetes:master Oct 26, 2022
@ritazh ritazh deleted the crencryption branch October 27, 2022 13:19
@sftim
Copy link
Contributor

sftim commented Nov 16, 2022

My suggestion for the changelog text (which can be Markdown):

kube-apiserver: APIs backed by CustomResourceDefinitions can now be specified in the `--encryption-provider-config` file; when specified, the data for those custom resources can now be encrypted in etcd.

I like to put command line arguments inside backticks.

@ritazh
Copy link
Member Author

ritazh commented Nov 16, 2022

Thanks for the suggestion @sftim! I've updated above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/apiserver area/test cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. sig/auth Categorizes an issue or PR as relevant to SIG Auth. sig/testing Categorizes an issue or PR as relevant to SIG Testing. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. triage/accepted Indicates an issue or PR is ready to be actively worked on.
Projects
Status: Done
Archived in project
Development

Successfully merging this pull request may close these issues.

Custom resources don't get encrypted in etcd
7 participants