From 2634cb234f1500b76a2fd89351b9ad8a737a24ea Mon Sep 17 00:00:00 2001 From: Ashley Cui Date: Wed, 5 May 2021 10:34:13 -0400 Subject: Add support for environment variable secrets Env var secrets are env vars that are set inside the container but not commited to and image. Also support reading from env var when creating a secret. Signed-off-by: Ashley Cui --- cmd/podman/common/specgen.go | 73 +++++++++++++++++++++++++++++++++++++++++++- cmd/podman/secrets/create.go | 15 +++++++-- 2 files changed, 85 insertions(+), 3 deletions(-) (limited to 'cmd/podman') diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 310a07a00..ce7ca2b4b 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -639,11 +639,15 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } s.RestartPolicy = splitRestart[0] } + + s.Secrets, s.EnvSecrets, err = parseSecrets(c.Secrets) + if err != nil { + return err + } s.Remove = c.Rm s.StopTimeout = &c.StopTimeout s.Timezone = c.Timezone s.Umask = c.Umask - s.Secrets = c.Secrets s.PidFile = c.PidFile return nil @@ -771,3 +775,70 @@ func parseThrottleIOPsDevices(iopsDevices []string) (map[string]specs.LinuxThrot } return td, nil } + +func parseSecrets(secrets []string) ([]string, map[string]string, error) { + secretParseError := errors.New("error parsing secret") + var mount []string + envs := make(map[string]string) + for _, val := range secrets { + source := "" + secretType := "" + target := "" + split := strings.Split(val, ",") + + // --secret mysecret + if len(split) == 1 { + source = val + mount = append(mount, source) + continue + } + // --secret mysecret,opt=opt + if !strings.Contains(split[0], "=") { + source = split[0] + split = split[1:] + } + // TODO: implement other secret options + for _, val := range split { + kv := strings.SplitN(val, "=", 2) + if len(kv) < 2 { + return nil, nil, errors.Wrapf(secretParseError, "option %s must be in form option=value", val) + } + switch kv[0] { + case "source": + source = kv[1] + case "type": + if secretType != "" { + return nil, nil, errors.Wrap(secretParseError, "cannot set more tha one secret type") + } + if kv[1] != "mount" && kv[1] != "env" { + return nil, nil, errors.Wrapf(secretParseError, "type %s is invalid", kv[1]) + } + secretType = kv[1] + case "target": + target = kv[1] + default: + return nil, nil, errors.Wrapf(secretParseError, "option %s invalid", val) + } + } + + if secretType == "" { + secretType = "mount" + } + if source == "" { + return nil, nil, errors.Wrapf(secretParseError, "no source found %s", val) + } + if secretType == "mount" { + if target != "" { + return nil, nil, errors.Wrapf(secretParseError, "target option is invalid for mounted secrets") + } + mount = append(mount, source) + } + if secretType == "env" { + if target == "" { + target = source + } + envs[target] = source + } + } + return mount, envs, nil +} diff --git a/cmd/podman/secrets/create.go b/cmd/podman/secrets/create.go index 7374b682b..4204f30b4 100644 --- a/cmd/podman/secrets/create.go +++ b/cmd/podman/secrets/create.go @@ -2,15 +2,16 @@ package secrets import ( "context" - "errors" "fmt" "io" "os" + "strings" "github.com/containers/common/pkg/completion" "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -29,6 +30,7 @@ var ( var ( createOpts = entities.SecretCreateOptions{} + env = false ) func init() { @@ -43,6 +45,9 @@ func init() { driverFlagName := "driver" flags.StringVar(&createOpts.Driver, driverFlagName, "file", "Specify secret driver") _ = createCmd.RegisterFlagCompletionFunc(driverFlagName, completion.AutocompleteNone) + + envFlagName := "env" + flags.BoolVar(&env, envFlagName, false, "Read secret data from environment variable") } func create(cmd *cobra.Command, args []string) error { @@ -52,7 +57,13 @@ func create(cmd *cobra.Command, args []string) error { path := args[1] var reader io.Reader - if path == "-" || path == "/dev/stdin" { + if env { + envValue := os.Getenv(path) + if envValue == "" { + return errors.Errorf("cannot create store secret data: environment variable %s is not set", path) + } + reader = strings.NewReader(envValue) + } else if path == "-" || path == "/dev/stdin" { stat, err := os.Stdin.Stat() if err != nil { return err -- cgit v1.2.3-54-g00ecf