From 8530bc9468306daaa23395c400e1575e504b3175 Mon Sep 17 00:00:00 2001 From: Andrei Natanael Cosma Date: Sat, 26 Nov 2022 04:17:37 +0100 Subject: [PATCH] Fixes secret (un)marshaling for kube play. Merges stringData into data for secrets as in k8s. Fixes e2e tests, remove '\n' from base64 encoded data. Correct test to check that data in secret mounted file is decoded. Closes #16269 Closes #16625 Signed-off-by: Andrei Natanael Cosma --- pkg/domain/infra/abi/play.go | 11 ++++- pkg/specgen/generate/kube/play_test.go | 68 ++++++++++++++++++++++++++ pkg/specgen/generate/kube/volume.go | 27 ++-------- test/e2e/play_kube_test.go | 26 ++++++++-- 4 files changed, 105 insertions(+), 27 deletions(-) diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index e73bf6614d60..b561f7b62d29 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -3,6 +3,7 @@ package abi import ( "bytes" "context" + "encoding/json" "errors" "fmt" "io" @@ -1213,7 +1214,15 @@ func (ic *ContainerEngine) playKubeSecret(secret *v1.Secret) (*entities.SecretCr return nil, err } - data, err := yaml.Marshal(secret) + if len(secret.StringData) > 0 { + if secret.Data == nil { + secret.Data = make(map[string][]byte) + } + for key, val := range secret.StringData { + secret.Data[key] = []byte(val) + } + } + data, err := json.Marshal(secret.Data) if err != nil { return nil, err } diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go index 3ad80f8b1eb1..0f3abe46ff88 100644 --- a/pkg/specgen/generate/kube/play_test.go +++ b/pkg/specgen/generate/kube/play_test.go @@ -34,6 +34,14 @@ func createSecrets(t *testing.T, d string) *secrets.SecretsManager { } for _, s := range k8sSecrets { + if len(s.StringData) > 0 { + if s.Data == nil { + s.Data = make(map[string][]byte) + } + for key, val := range s.StringData { + s.Data[key] = []byte(val) + } + } data, err := json.Marshal(s.Data) assert.NoError(t, err) @@ -345,6 +353,42 @@ func TestEnvVarsFrom(t *testing.T) { "myvar": "foo", }, }, + { + "SecretExistsMultipleDataEntries", + v1.EnvFromSource{ + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "multi-data", + }, + }, + }, + CtrSpecGenOptions{ + SecretsManager: secretsManager, + }, + true, + map[string]string{ + "myvar": "foo", + "myvar1": "foo1", + }, + }, + { + "SecretExistsMultipleStringDataEntries", + v1.EnvFromSource{ + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "multi-stringdata", + }, + }, + }, + CtrSpecGenOptions{ + SecretsManager: secretsManager, + }, + true, + map[string]string{ + "myvar": "foo", + "myvar1": "foo1", + }, + }, { "SecretDoesNotExist", v1.EnvFromSource{ @@ -1087,6 +1131,30 @@ var ( "myvar": []byte("foo"), }, }, + { + TypeMeta: v12.TypeMeta{ + Kind: "Secret", + }, + ObjectMeta: v12.ObjectMeta{ + Name: "multi-data", + }, + Data: map[string][]byte{ + "myvar": []byte("foo"), + "myvar1": []byte("foo1"), + }, + }, + { + TypeMeta: v12.TypeMeta{ + Kind: "Secret", + }, + ObjectMeta: v12.ObjectMeta{ + Name: "multi-stringdata", + }, + StringData: map[string]string{ + "myvar": string("foo"), + "myvar1": string("foo1"), + }, + }, } cpuInt = 4 diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go index 4e98305c5d32..2e9f3705c0a0 100644 --- a/pkg/specgen/generate/kube/volume.go +++ b/pkg/specgen/generate/kube/volume.go @@ -1,6 +1,7 @@ package kube import ( + "encoding/json" "errors" "fmt" "os" @@ -9,10 +10,8 @@ import ( "github.com/containers/common/pkg/secrets" "github.com/containers/podman/v4/libpod" v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1" - metav1 "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/sirupsen/logrus" - "gopkg.in/yaml.v3" ) const ( @@ -137,24 +136,8 @@ func VolumeFromSecret(secretSource *v1.SecretVolumeSource, secretsManager *secre return nil, err } - // unmarshaling directly into a v1.secret creates type mismatch errors - // use a more friendly, string only secret struct. - type KubeSecret struct { - metav1.TypeMeta `json:",inline"` - // +optional - metav1.ObjectMeta `json:"metadata,omitempty"` - // +optional - Immutable *bool `json:"immutable,omitempty"` - Data map[string]string `json:"data,omitempty"` - // +optional - StringData map[string]string `json:"stringData,omitempty"` - // +optional - Type string `json:"type,omitempty"` - } - - data := &KubeSecret{} - - err = yaml.Unmarshal(secretByte, data) + data := make(map[string][]byte) + err = json.Unmarshal(secretByte, &data) if err != nil { return nil, err } @@ -166,8 +149,8 @@ func VolumeFromSecret(secretSource *v1.SecretVolumeSource, secretsManager *secre kv.Items = make(map[string][]byte) // add key: value pairs to the items array - for key, entry := range data.Data { - kv.Items[key] = []byte(entry) + for key, entry := range data { + kv.Items[key] = entry } return kv, nil } diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index 7fbc9305fcbe..c07ee00234c9 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -3,6 +3,7 @@ package integration import ( "bytes" "context" + "encoding/base64" "encoding/json" "fmt" "net" @@ -48,9 +49,11 @@ metadata: name: newsecrettwo type: Opaque data: - username: Y2RvZXJuCg== + username: Y2RvZXJu password: dGVzdGluZ3Rlc3RpbmcK note: a3ViZSBzZWNyZXRzIGFyZSBjb29sIQo= +stringData: + plain_note: This is a test ` var secretPodYaml = ` @@ -89,6 +92,9 @@ spec: - name: bar mountPath: /etc/bar readOnly: true + - name: baz + mountPath: /etc/baz + readOnly: true volumes: - name: foo secret: @@ -98,6 +104,10 @@ spec: secret: secretName: newsecrettwo optional: false + - name: baz + secret: + secretName: newsecrettwo + optional: false ` var unknownKindYaml = ` @@ -4220,7 +4230,8 @@ ENV OPENJ9_JAVA_OPTIONS=%q exec := podmanTest.Podman([]string{"exec", "-it", "mypod-myctr", "cat", "/etc/foo/username"}) exec.WaitWithDefaultTimeout() Expect(exec).Should(Exit(0)) - Expect(exec.OutputToString()).Should(ContainSubstring("dXNlcg==")) + username, _ := base64.StdEncoding.DecodeString("dXNlcg==") + Expect(exec.OutputToString()).Should(ContainSubstring(string(username))) secretRm := podmanTest.Podman([]string{"secret", "rm", "newsecret"}) secretRm.WaitWithDefaultTimeout() @@ -4258,12 +4269,19 @@ ENV OPENJ9_JAVA_OPTIONS=%q exec = podmanTest.Podman([]string{"exec", "-it", "mypod2-myctr", "cat", "/etc/foo/username"}) exec.WaitWithDefaultTimeout() Expect(exec).Should(Exit(0)) - Expect(exec.OutputToString()).Should(ContainSubstring("dXNlcg==")) + username, _ = base64.StdEncoding.DecodeString("dXNlcg==") + Expect(exec.OutputToString()).Should(ContainSubstring(string(username))) exec = podmanTest.Podman([]string{"exec", "-it", "mypod2-myctr", "cat", "/etc/bar/username"}) exec.WaitWithDefaultTimeout() Expect(exec).Should(Exit(0)) - Expect(exec.OutputToString()).Should(ContainSubstring("Y2RvZXJuCg==")) + username, _ = base64.StdEncoding.DecodeString("Y2RvZXJu") + Expect(exec.OutputToString()).Should(ContainSubstring(string(username))) + + exec = podmanTest.Podman([]string{"exec", "-it", "mypod2-myctr", "cat", "/etc/baz/plain_note"}) + exec.WaitWithDefaultTimeout() + Expect(exec).Should(Exit(0)) + Expect(exec.OutputToString()).Should(ContainSubstring("This is a test")) })