From 832a69b0bee6ec289521fbd59ddd480372493ee3 Mon Sep 17 00:00:00 2001 From: Ashley Cui Date: Fri, 15 Jan 2021 01:27:23 -0500 Subject: Implement Secrets Implement podman secret create, inspect, ls, rm Implement podman run/create --secret Secrets are blobs of data that are sensitive. Currently, the only secret driver supported is filedriver, which means creating a secret stores it in base64 unencrypted in a file. After creating a secret, a user can use the --secret flag to expose the secret inside the container at /run/secrets/[secretname] This secret will not be commited to an image on a podman commit Signed-off-by: Ashley Cui --- test/apiv2/50-secrets.at | 36 +++++++++ test/e2e/commit_test.go | 25 ++++++ test/e2e/common_test.go | 15 ++++ test/e2e/run_test.go | 26 +++++- test/e2e/secret_test.go | 202 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 test/apiv2/50-secrets.at create mode 100644 test/e2e/secret_test.go (limited to 'test') diff --git a/test/apiv2/50-secrets.at b/test/apiv2/50-secrets.at new file mode 100644 index 000000000..1ef43381a --- /dev/null +++ b/test/apiv2/50-secrets.at @@ -0,0 +1,36 @@ +# -*- sh -*- +# +# secret-related tests +# + +# secret create +t POST secrets/create '"Name":"mysecret","Data":"c2VjcmV0"' 200\ + .ID~.* \ + +# secret create unsupported labels +t POST secrets/create '"Name":"mysecret","Data":"c2VjcmV0","Labels":{"fail":"fail"}' 400 + +# secret create name already in use +t POST secrets/create '"Name":"mysecret","Data":"c2VjcmV0"' 409 + +# secret inspect +t GET secrets/mysecret 200\ + .Spec.Name=mysecret + +# secret inspect non-existent secret +t GET secrets/bogus 404 + +# secret list +t GET secrets 200\ + length=1 + +# secret list unsupported filters +t GET secrets?filters=%7B%22name%22%3A%5B%22foo1%22%5D%7D 400 + +# secret rm +t DELETE secrets/mysecret 204 +# secret rm non-existent secret +t DELETE secrets/bogus 404 + +# secret update not implemented +t POST secrets/mysecret/update "" 501 diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index 3c7bbca66..8760978fd 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -279,4 +279,29 @@ var _ = Describe("Podman commit", func() { data := check.InspectImageJSON() Expect(data[0].ID).To(Equal(string(id))) }) + + It("podman commit should not commit secret", func() { + secretsString := "somesecretdata" + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte(secretsString), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"run", "--secret", "mysecret", "--name", "secr", ALPINE, "cat", "/run/secrets/mysecret"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal(secretsString)) + + session = podmanTest.Podman([]string{"commit", "secr", "foobar.com/test1-image:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"run", "foobar.com/test1-image:latest", "cat", "/run/secrets/mysecret"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Not(Equal(0))) + + }) }) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 54d801e12..53810d882 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -491,6 +491,21 @@ func (p *PodmanTestIntegration) CleanupVolume() { p.Cleanup() } +// CleanupSecret cleans up the temporary store +func (p *PodmanTestIntegration) CleanupSecrets() { + // Remove all containers + session := p.Podman([]string{"secret", "rm", "-a"}) + session.Wait(90) + + // Stop remove service on secret cleanup + p.StopRemoteService() + + // Nuke tempdir + if err := os.RemoveAll(p.TempDir); err != nil { + fmt.Printf("%q\n", err) + } +} + // InspectContainerToJSON takes the session output of an inspect // container and returns json func (s *PodmanSessionIntegration) InspectContainerToJSON() []define.InspectContainerData { diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index caeaf190e..76d362288 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -668,8 +668,8 @@ USER bin` Expect(session.ExitCode()).To(Equal(0)) }) - It("podman run with secrets", func() { - SkipIfRemote("--default-mounts-file option is not supported in podman-remote") + It("podman run with subscription secrets", func() { + SkipIfRemote("--default-mount-file option is not supported in podman-remote") containersDir := filepath.Join(podmanTest.TempDir, "containers") err := os.MkdirAll(containersDir, 0755) Expect(err).To(BeNil()) @@ -1448,4 +1448,26 @@ WORKDIR /madethis` Expect(session.ExitCode()).To(Equal(0)) Expect(session.OutputToString()).To(ContainSubstring(hostnameEnv)) }) + + It("podman run --secret", func() { + secretsString := "somesecretdata" + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte(secretsString), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"run", "--secret", "mysecret", "--name", "secr", ALPINE, "cat", "/run/secrets/mysecret"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal(secretsString)) + + session = podmanTest.Podman([]string{"inspect", "secr", "--format", " {{(index .Config.Secrets 0).Name}}"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("mysecret")) + + }) }) diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go new file mode 100644 index 000000000..6dad605c5 --- /dev/null +++ b/test/e2e/secret_test.go @@ -0,0 +1,202 @@ +package integration + +import ( + "io/ioutil" + "os" + "path/filepath" + + . "github.com/containers/podman/v2/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman secret", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() + podmanTest.SeedImages() + }) + + AfterEach(func() { + podmanTest.CleanupSecrets() + f := CurrentGinkgoTestDescription() + processTestResult(f) + + }) + + It("podman secret create", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session.WaitWithDefaultTimeout() + secrID := session.OutputToString() + Expect(session.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.ID}}", secrID}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(Equal(secrID)) + }) + + It("podman secret create bad name should fail", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "?!", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Not(Equal(0))) + }) + + It("podman secret inspect", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session.WaitWithDefaultTimeout() + secrID := session.OutputToString() + Expect(session.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"secret", "inspect", secrID}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.IsJSONOutputValid()).To(BeTrue()) + }) + + It("podman secret inspect with --format", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session.WaitWithDefaultTimeout() + secrID := session.OutputToString() + Expect(session.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.ID}}", secrID}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(Equal(secrID)) + }) + + It("podman secret inspect multiple secrets", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session.WaitWithDefaultTimeout() + secrID := session.OutputToString() + Expect(session.ExitCode()).To(Equal(0)) + + session2 := podmanTest.Podman([]string{"secret", "create", "b", secretFilePath}) + session2.WaitWithDefaultTimeout() + secrID2 := session2.OutputToString() + Expect(session2.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"secret", "inspect", secrID, secrID2}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.IsJSONOutputValid()).To(BeTrue()) + }) + + It("podman secret inspect bogus", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + inspect := podmanTest.Podman([]string{"secret", "inspect", "bogus"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Not(Equal(0))) + + }) + + It("podman secret ls", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + list := podmanTest.Podman([]string{"secret", "ls"}) + list.WaitWithDefaultTimeout() + Expect(list.ExitCode()).To(Equal(0)) + Expect(len(list.OutputToStringArray())).To(Equal(2)) + + }) + + It("podman secret ls with Go template", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + list := podmanTest.Podman([]string{"secret", "ls", "--format", "table {{.Name}}"}) + list.WaitWithDefaultTimeout() + + Expect(list.ExitCode()).To(Equal(0)) + Expect(len(list.OutputToStringArray())).To(Equal(2), list.OutputToString()) + }) + + It("podman secret rm", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session.WaitWithDefaultTimeout() + secrID := session.OutputToString() + Expect(session.ExitCode()).To(Equal(0)) + + removed := podmanTest.Podman([]string{"secret", "rm", "a"}) + removed.WaitWithDefaultTimeout() + Expect(removed.ExitCode()).To(Equal(0)) + Expect(removed.OutputToString()).To(Equal(secrID)) + + session = podmanTest.Podman([]string{"secret", "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(Equal(1)) + }) + + It("podman secret rm --all", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"secret", "create", "b", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + removed := podmanTest.Podman([]string{"secret", "rm", "-a"}) + removed.WaitWithDefaultTimeout() + Expect(removed.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"secret", "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(Equal(1)) + }) + +}) -- cgit v1.2.3-54-g00ecf