mirror of
https://github.com/containers/podman.git
synced 2025-06-17 15:08:08 +08:00
Merge pull request #10221 from ashley-cui/envsec
Add support for environment variable secrets
This commit is contained in:
@ -639,12 +639,16 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
|||||||
}
|
}
|
||||||
s.RestartPolicy = splitRestart[0]
|
s.RestartPolicy = splitRestart[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.Secrets, s.EnvSecrets, err = parseSecrets(c.Secrets)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
s.Remove = c.Rm
|
s.Remove = c.Rm
|
||||||
s.StopTimeout = &c.StopTimeout
|
s.StopTimeout = &c.StopTimeout
|
||||||
s.Timeout = c.Timeout
|
s.Timeout = c.Timeout
|
||||||
s.Timezone = c.Timezone
|
s.Timezone = c.Timezone
|
||||||
s.Umask = c.Umask
|
s.Umask = c.Umask
|
||||||
s.Secrets = c.Secrets
|
|
||||||
s.PidFile = c.PidFile
|
s.PidFile = c.PidFile
|
||||||
s.Volatile = c.Rm
|
s.Volatile = c.Rm
|
||||||
|
|
||||||
@ -773,3 +777,70 @@ func parseThrottleIOPsDevices(iopsDevices []string) (map[string]specs.LinuxThrot
|
|||||||
}
|
}
|
||||||
return td, nil
|
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
|
||||||
|
}
|
||||||
|
@ -2,15 +2,16 @@ package secrets
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/completion"
|
"github.com/containers/common/pkg/completion"
|
||||||
"github.com/containers/podman/v3/cmd/podman/common"
|
"github.com/containers/podman/v3/cmd/podman/common"
|
||||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ var (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
createOpts = entities.SecretCreateOptions{}
|
createOpts = entities.SecretCreateOptions{}
|
||||||
|
env = false
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -43,6 +45,9 @@ func init() {
|
|||||||
driverFlagName := "driver"
|
driverFlagName := "driver"
|
||||||
flags.StringVar(&createOpts.Driver, driverFlagName, "file", "Specify secret driver")
|
flags.StringVar(&createOpts.Driver, driverFlagName, "file", "Specify secret driver")
|
||||||
_ = createCmd.RegisterFlagCompletionFunc(driverFlagName, completion.AutocompleteNone)
|
_ = 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 {
|
func create(cmd *cobra.Command, args []string) error {
|
||||||
@ -52,7 +57,13 @@ func create(cmd *cobra.Command, args []string) error {
|
|||||||
path := args[1]
|
path := args[1]
|
||||||
|
|
||||||
var reader io.Reader
|
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()
|
stat, err := os.Stdin.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -840,7 +840,7 @@ Specify the policy to select the seccomp profile. If set to *image*, Podman will
|
|||||||
|
|
||||||
Note that this feature is experimental and may change in the future.
|
Note that this feature is experimental and may change in the future.
|
||||||
|
|
||||||
#### **\-\-secret**=*secret*
|
#### **\-\-secret**=*secret*[,opt=opt ...]
|
||||||
|
|
||||||
Give the container access to a secret. Can be specified multiple times.
|
Give the container access to a secret. Can be specified multiple times.
|
||||||
|
|
||||||
@ -848,12 +848,17 @@ A secret is a blob of sensitive data which a container needs at runtime but
|
|||||||
should not be stored in the image or in source control, such as usernames and passwords,
|
should not be stored in the image or in source control, such as usernames and passwords,
|
||||||
TLS certificates and keys, SSH keys or other important generic strings or binary content (up to 500 kb in size).
|
TLS certificates and keys, SSH keys or other important generic strings or binary content (up to 500 kb in size).
|
||||||
|
|
||||||
Secrets are copied and mounted into the container when a container is created. If a secret is deleted using
|
When secrets are specified as type `mount`, the secrets are copied and mounted into the container when a container is created.
|
||||||
`podman secret rm`, the container will still have access to the secret. If a secret is deleted and
|
When secrets are specified as type `env`, the secret will be set as an environment variable within the container.
|
||||||
another secret is created with the same name, the secret inside the container will not change; the old
|
Secrets are written in the container at the time of container creation, and modifying the secret using `podman secret` commands
|
||||||
secret value will still remain.
|
after the container is created will not affect the secret inside the container.
|
||||||
|
|
||||||
Secrets are managed using the `podman secret` command.
|
Secrets and its storage are managed using the `podman secret` command.
|
||||||
|
|
||||||
|
Secret Options
|
||||||
|
|
||||||
|
- `type=mount|env` : How the secret will be exposed to the container. Default mount.
|
||||||
|
- `target=target` : Target of secret. Defauts to secret name.
|
||||||
|
|
||||||
#### **\-\-security-opt**=*option*
|
#### **\-\-security-opt**=*option*
|
||||||
|
|
||||||
|
@ -892,7 +892,7 @@ Specify the policy to select the seccomp profile. If set to *image*, Podman will
|
|||||||
|
|
||||||
Note that this feature is experimental and may change in the future.
|
Note that this feature is experimental and may change in the future.
|
||||||
|
|
||||||
#### **\-\-secret**=*secret*
|
#### **\-\-secret**=*secret*[,opt=opt ...]
|
||||||
|
|
||||||
Give the container access to a secret. Can be specified multiple times.
|
Give the container access to a secret. Can be specified multiple times.
|
||||||
|
|
||||||
@ -900,12 +900,17 @@ A secret is a blob of sensitive data which a container needs at runtime but
|
|||||||
should not be stored in the image or in source control, such as usernames and passwords,
|
should not be stored in the image or in source control, such as usernames and passwords,
|
||||||
TLS certificates and keys, SSH keys or other important generic strings or binary content (up to 500 kb in size).
|
TLS certificates and keys, SSH keys or other important generic strings or binary content (up to 500 kb in size).
|
||||||
|
|
||||||
Secrets are copied and mounted into the container when a container is created. If a secret is deleted using
|
When secrets are specified as type `mount`, the secrets are copied and mounted into the container when a container is created.
|
||||||
`podman secret rm`, the container will still have access to the secret. If a secret is deleted and
|
When secrets are specified as type `env`, the secret will be set as an environment variable within the container.
|
||||||
another secret is created with the same name, the secret inside the container will not change; the old
|
Secrets are written in the container at the time of container creation, and modifying the secret using `podman secret` commands
|
||||||
secret value will still remain.
|
after the container is created will not affect the secret inside the container.
|
||||||
|
|
||||||
Secrets are managed using the `podman secret` command
|
Secrets and its storage are managed using the `podman secret` command.
|
||||||
|
|
||||||
|
Secret Options
|
||||||
|
|
||||||
|
- `type=mount|env` : How the secret will be exposed to the container. Default mount.
|
||||||
|
- `target=target` : Target of secret. Defauts to secret name.
|
||||||
|
|
||||||
#### **\-\-security-opt**=*option*
|
#### **\-\-security-opt**=*option*
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@ Secrets will not be committed to an image with `podman commit`, and will not be
|
|||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
|
|
||||||
|
#### **\-\-env**=*false*
|
||||||
|
|
||||||
|
Read secret data from environment variable
|
||||||
|
|
||||||
#### **\-\-driver**=*driver*
|
#### **\-\-driver**=*driver*
|
||||||
|
|
||||||
Specify the secret driver (default **file**, which is unencrypted).
|
Specify the secret driver (default **file**, which is unencrypted).
|
||||||
|
@ -373,4 +373,6 @@ type ContainerMiscConfig struct {
|
|||||||
PidFile string `json:"pid_file,omitempty"`
|
PidFile string `json:"pid_file,omitempty"`
|
||||||
// CDIDevices contains devices that use the CDI
|
// CDIDevices contains devices that use the CDI
|
||||||
CDIDevices []string `json:"cdiDevices,omitempty"`
|
CDIDevices []string `json:"cdiDevices,omitempty"`
|
||||||
|
// EnvSecrets are secrets that are set as environment variables
|
||||||
|
EnvSecrets map[string]*secrets.Secret `json:"secret_env,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/containers/common/pkg/apparmor"
|
"github.com/containers/common/pkg/apparmor"
|
||||||
"github.com/containers/common/pkg/chown"
|
"github.com/containers/common/pkg/chown"
|
||||||
"github.com/containers/common/pkg/config"
|
"github.com/containers/common/pkg/config"
|
||||||
|
"github.com/containers/common/pkg/secrets"
|
||||||
"github.com/containers/common/pkg/subscriptions"
|
"github.com/containers/common/pkg/subscriptions"
|
||||||
"github.com/containers/common/pkg/umask"
|
"github.com/containers/common/pkg/umask"
|
||||||
"github.com/containers/podman/v3/libpod/define"
|
"github.com/containers/podman/v3/libpod/define"
|
||||||
@ -757,6 +758,19 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
|
|||||||
if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil {
|
if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil {
|
||||||
return nil, errors.Wrapf(err, "error setting up OCI Hooks")
|
return nil, errors.Wrapf(err, "error setting up OCI Hooks")
|
||||||
}
|
}
|
||||||
|
if len(c.config.EnvSecrets) > 0 {
|
||||||
|
manager, err := secrets.NewManager(c.runtime.GetSecretsStorageDir())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for name, secr := range c.config.EnvSecrets {
|
||||||
|
_, data, err := manager.LookupSecretData(secr.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
g.AddProcessEnv(name, string(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return g.Config, nil
|
return g.Config, nil
|
||||||
}
|
}
|
||||||
|
@ -1716,6 +1716,28 @@ func WithSecrets(secretNames []string) CtrCreateOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithSecrets adds environment variable secrets to the container
|
||||||
|
func WithEnvSecrets(envSecrets map[string]string) CtrCreateOption {
|
||||||
|
return func(ctr *Container) error {
|
||||||
|
ctr.config.EnvSecrets = make(map[string]*secrets.Secret)
|
||||||
|
if ctr.valid {
|
||||||
|
return define.ErrCtrFinalized
|
||||||
|
}
|
||||||
|
manager, err := secrets.NewManager(ctr.runtime.GetSecretsStorageDir())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for target, src := range envSecrets {
|
||||||
|
secr, err := manager.Lookup(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ctr.config.EnvSecrets[target] = secr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithPidFile adds pidFile to the container
|
// WithPidFile adds pidFile to the container
|
||||||
func WithPidFile(pidFile string) CtrCreateOption {
|
func WithPidFile(pidFile string) CtrCreateOption {
|
||||||
return func(ctr *Container) error {
|
return func(ctr *Container) error {
|
||||||
|
@ -402,6 +402,11 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
|||||||
if len(s.Secrets) != 0 {
|
if len(s.Secrets) != 0 {
|
||||||
options = append(options, libpod.WithSecrets(s.Secrets))
|
options = append(options, libpod.WithSecrets(s.Secrets))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(s.EnvSecrets) != 0 {
|
||||||
|
options = append(options, libpod.WithEnvSecrets(s.EnvSecrets))
|
||||||
|
}
|
||||||
|
|
||||||
if len(s.DependencyContainers) > 0 {
|
if len(s.DependencyContainers) > 0 {
|
||||||
deps := make([]*libpod.Container, 0, len(s.DependencyContainers))
|
deps := make([]*libpod.Container, 0, len(s.DependencyContainers))
|
||||||
for _, ctr := range s.DependencyContainers {
|
for _, ctr := range s.DependencyContainers {
|
||||||
|
@ -180,6 +180,9 @@ type ContainerBasicConfig struct {
|
|||||||
// set tags as `json:"-"` for not supported remote
|
// set tags as `json:"-"` for not supported remote
|
||||||
// Optional.
|
// Optional.
|
||||||
PidFile string `json:"-"`
|
PidFile string `json:"-"`
|
||||||
|
// EnvSecrets are secrets that will be set as environment variables
|
||||||
|
// Optional.
|
||||||
|
EnvSecrets map[string]string `json:"secret_env,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerStorageConfig contains information on the storage configuration of a
|
// ContainerStorageConfig contains information on the storage configuration of a
|
||||||
|
@ -304,4 +304,28 @@ var _ = Describe("Podman commit", func() {
|
|||||||
Expect(session.ExitCode()).To(Not(Equal(0)))
|
Expect(session.ExitCode()).To(Not(Equal(0)))
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman commit should not commit env 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", "source=mysecret,type=env", "--name", "secr", ALPINE, "printenv", "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", "printenv", "mysecret"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.OutputToString()).To(Not(ContainSubstring(secretsString)))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1611,6 +1611,95 @@ WORKDIR /madethis`, BB)
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman run --secret source=mysecret,type=mount", 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", "source=mysecret,type=mount", "--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"))
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman run --secret source=mysecret,type=env", 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", "source=mysecret,type=env", "--name", "secr", ALPINE, "printenv", "mysecret"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(Equal(secretsString))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman run --secret target option", 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))
|
||||||
|
// target with mount type should fail
|
||||||
|
session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=mount,target=anotherplace", "--name", "secr", ALPINE, "cat", "/run/secrets/mysecret"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Not(Equal(0)))
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=env,target=anotherplace", "--name", "secr", ALPINE, "printenv", "anotherplace"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(Equal(secretsString))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman run invalid secret option", 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))
|
||||||
|
|
||||||
|
// Invalid type
|
||||||
|
session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=other", "--name", "secr", ALPINE, "printenv", "mysecret"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Not(Equal(0)))
|
||||||
|
|
||||||
|
// Invalid option
|
||||||
|
session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,invalid=invalid", "--name", "secr", ALPINE, "printenv", "mysecret"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Not(Equal(0)))
|
||||||
|
|
||||||
|
// Option syntax not valid
|
||||||
|
session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type", "--name", "secr", ALPINE, "printenv", "mysecret"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Not(Equal(0)))
|
||||||
|
|
||||||
|
// No source given
|
||||||
|
session = podmanTest.Podman([]string{"run", "--secret", "type=env", "--name", "secr", ALPINE, "printenv", "mysecret"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Not(Equal(0)))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman run --requires", func() {
|
It("podman run --requires", func() {
|
||||||
depName := "ctr1"
|
depName := "ctr1"
|
||||||
depContainer := podmanTest.Podman([]string{"create", "--name", depName, ALPINE, "top"})
|
depContainer := podmanTest.Podman([]string{"create", "--name", depName, ALPINE, "top"})
|
||||||
|
@ -199,4 +199,27 @@ var _ = Describe("Podman secret", func() {
|
|||||||
Expect(len(session.OutputToStringArray())).To(Equal(1))
|
Expect(len(session.OutputToStringArray())).To(Equal(1))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman secret creates from environment variable", func() {
|
||||||
|
// no env variable set, should fail
|
||||||
|
session := podmanTest.Podman([]string{"secret", "create", "--env", "a", "MYENVVAR"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
secrID := session.OutputToString()
|
||||||
|
Expect(session.ExitCode()).To(Not(Equal(0)))
|
||||||
|
|
||||||
|
os.Setenv("MYENVVAR", "somedata")
|
||||||
|
if IsRemote() {
|
||||||
|
podmanTest.RestartRemoteService()
|
||||||
|
}
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"secret", "create", "--env", "a", "MYENVVAR"})
|
||||||
|
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))
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user