diff options
-rw-r--r-- | pkg/secrets/secrets.go | 88 | ||||
-rw-r--r-- | test/e2e/run_test.go | 16 |
2 files changed, 101 insertions, 3 deletions
diff --git a/pkg/secrets/secrets.go b/pkg/secrets/secrets.go index 8227499e5..be825d906 100644 --- a/pkg/secrets/secrets.go +++ b/pkg/secrets/secrets.go @@ -3,11 +3,11 @@ package secrets import ( "bufio" "fmt" + "io/ioutil" "os" "path/filepath" "strings" - "github.com/containers/storage/pkg/chrootarchive" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" @@ -23,6 +23,82 @@ var ( OverrideMountsFile = "/etc/containers/mounts.conf" ) +// secretData stores the name of the file and the content read from it +type secretData struct { + name string + data []byte +} + +// saveTo saves secret data to given directory +func (s secretData) saveTo(dir string) error { + path := filepath.Join(dir, s.name) + if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil && !os.IsExist(err) { + return err + } + return ioutil.WriteFile(path, s.data, 0700) +} + +func readAll(root, prefix string) ([]secretData, error) { + path := filepath.Join(root, prefix) + + data := []secretData{} + + files, err := ioutil.ReadDir(path) + if err != nil { + if os.IsNotExist(err) { + return data, nil + } + + return nil, err + } + + for _, f := range files { + fileData, err := readFile(root, filepath.Join(prefix, f.Name())) + if err != nil { + // If the file did not exist, might be a dangling symlink + // Ignore the error + if os.IsNotExist(err) { + continue + } + return nil, err + } + data = append(data, fileData...) + } + + return data, nil +} + +func readFile(root, name string) ([]secretData, error) { + path := filepath.Join(root, name) + + s, err := os.Stat(path) + if err != nil { + return nil, err + } + + if s.IsDir() { + dirData, err := readAll(root, name) + if err != nil { + return nil, err + } + return dirData, nil + } + bytes, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + return []secretData{{name: name, data: bytes}}, nil +} + +func getHostSecretData(hostDir string) ([]secretData, error) { + var allSecrets []secretData + hostSecrets, err := readAll(hostDir, "") + if err != nil { + return nil, errors.Wrapf(err, "failed to read secrets from %q", hostDir) + } + return append(allSecrets, hostSecrets...), nil +} + func getMounts(filePath string) []string { file, err := os.Open(filePath) if err != nil { @@ -84,8 +160,14 @@ func SecretMounts(filePath, mountLabel, containerWorkingDir string) ([]rspec.Mou return nil, err } - if err = chrootarchive.NewArchiver(nil).CopyWithTar(hostDir, ctrDirOnHost); err != nil && !os.IsNotExist(err) { - return nil, errors.Wrapf(err, "error getting host secret data") + data, err := getHostSecretData(hostDir) + if err != nil { + return nil, errors.Wrapf(err, "getting host secret data failed") + } + for _, s := range data { + if err := s.saveTo(ctrDirOnHost); err != nil { + return nil, errors.Wrapf(err, "error saving data to container filesystem on host %q", ctrDirOnHost) + } } err = label.Relabel(ctrDirOnHost, mountLabel, false) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 17b61533b..94a1fef57 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -278,10 +278,26 @@ var _ = Describe("Podman run", func() { err = ioutil.WriteFile(secretsFile, []byte(secretsString), 0755) Expect(err).To(BeNil()) + targetDir := "/tmp/symlink/target" + err = os.MkdirAll(targetDir, 0755) + Expect(err).To(BeNil()) + keyFile := filepath.Join(targetDir, "key.pem") + err = ioutil.WriteFile(keyFile, []byte(mountString), 0755) + Expect(err).To(BeNil()) + execSession := podmanTest.SystemExec("ln", []string{"-s", targetDir, filepath.Join(secretsDir, "mysymlink")}) + execSession.WaitWithDefaultTimeout() + Expect(execSession.ExitCode()).To(Equal(0)) + session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/run/secrets/test.txt"}) session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) Expect(session.OutputToString()).To(Equal(secretsString)) + session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "ls", "/run/secrets/mysymlink"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("key.pem")) + err = os.RemoveAll(containersDir) Expect(err).To(BeNil()) }) |