diff options
-rw-r--r-- | .cirrus.yml | 4 | ||||
-rw-r--r-- | cmd/podman/common/specgen.go | 73 | ||||
-rw-r--r-- | cmd/podman/secrets/create.go | 15 | ||||
-rw-r--r-- | docs/source/markdown/podman-create.1.md | 17 | ||||
-rw-r--r-- | docs/source/markdown/podman-run.1.md | 17 | ||||
-rw-r--r-- | docs/source/markdown/podman-secret-create.1.md | 4 | ||||
-rw-r--r-- | libpod/container_config.go | 2 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 24 | ||||
-rw-r--r-- | libpod/container_path_resolution.go | 2 | ||||
-rw-r--r-- | libpod/options.go | 22 | ||||
-rw-r--r-- | pkg/specgen/generate/container_create.go | 5 | ||||
-rw-r--r-- | pkg/specgen/specgen.go | 3 | ||||
-rw-r--r-- | test/e2e/commit_test.go | 24 | ||||
-rw-r--r-- | test/e2e/common_test.go | 7 | ||||
-rw-r--r-- | test/e2e/play_kube_test.go | 3 | ||||
-rw-r--r-- | test/e2e/run_test.go | 100 | ||||
-rw-r--r-- | test/e2e/secret_test.go | 23 | ||||
-rw-r--r-- | test/system/001-basic.bats | 25 | ||||
-rw-r--r-- | test/system/410-selinux.bats | 13 |
19 files changed, 337 insertions, 46 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index a011c9af5..ebe12ab4a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -539,7 +539,7 @@ rootless_integration_test_task: skip: *branches_and_tags depends_on: - unit_test - matrix: *fedora_vm_axis + matrix: *platform_axis gce_instance: *standardvm timeout_in: 90m env: @@ -614,7 +614,7 @@ rootless_system_test_task: only_if: *not_docs depends_on: - rootless_integration_test - matrix: *fedora_vm_axis + matrix: *platform_axis gce_instance: *standardvm env: TEST_FLAVOR: sys diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 7896ddfc1..5dc2ec864 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -639,12 +639,16 @@ 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.Timeout = c.Timeout s.Timezone = c.Timezone s.Umask = c.Umask - s.Secrets = c.Secrets s.PidFile = c.PidFile s.Volatile = c.Rm @@ -773,3 +777,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 diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index bd2aab4c2..d59793f28 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -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. -#### **\-\-secret**=*secret* +#### **\-\-secret**=*secret*[,opt=opt ...] 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, 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 -`podman secret rm`, the container will still have access to the secret. If a secret is deleted and -another secret is created with the same name, the secret inside the container will not change; the old -secret value will still remain. +When secrets are specified as type `mount`, the secrets are copied and mounted into the container when a container is created. +When secrets are specified as type `env`, the secret will be set as an environment variable within the container. +Secrets are written in the container at the time of container creation, and modifying the secret using `podman secret` commands +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* diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 0c412c2a6..0ab8f04db 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -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. -#### **\-\-secret**=*secret* +#### **\-\-secret**=*secret*[,opt=opt ...] 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, 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 -`podman secret rm`, the container will still have access to the secret. If a secret is deleted and -another secret is created with the same name, the secret inside the container will not change; the old -secret value will still remain. +When secrets are specified as type `mount`, the secrets are copied and mounted into the container when a container is created. +When secrets are specified as type `env`, the secret will be set as an environment variable within the container. +Secrets are written in the container at the time of container creation, and modifying the secret using `podman secret` commands +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* diff --git a/docs/source/markdown/podman-secret-create.1.md b/docs/source/markdown/podman-secret-create.1.md index f5a97a0f3..7aacca3fe 100644 --- a/docs/source/markdown/podman-secret-create.1.md +++ b/docs/source/markdown/podman-secret-create.1.md @@ -20,6 +20,10 @@ Secrets will not be committed to an image with `podman commit`, and will not be ## OPTIONS +#### **\-\-env**=*false* + +Read secret data from environment variable + #### **\-\-driver**=*driver* Specify the secret driver (default **file**, which is unencrypted). diff --git a/libpod/container_config.go b/libpod/container_config.go index a508b96ee..904c03f9b 100644 --- a/libpod/container_config.go +++ b/libpod/container_config.go @@ -373,4 +373,6 @@ type ContainerMiscConfig struct { PidFile string `json:"pid_file,omitempty"` // CDIDevices contains devices that use the CDI CDIDevices []string `json:"cdiDevices,omitempty"` + // EnvSecrets are secrets that are set as environment variables + EnvSecrets map[string]*secrets.Secret `json:"secret_env,omitempty"` } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index f0608e2b2..7d57e8965 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -29,6 +29,7 @@ import ( "github.com/containers/common/pkg/apparmor" "github.com/containers/common/pkg/chown" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/secrets" "github.com/containers/common/pkg/subscriptions" "github.com/containers/common/pkg/umask" "github.com/containers/podman/v3/libpod/define" @@ -377,14 +378,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { case "z": fallthrough case "Z": - if c.MountLabel() != "" { - if c.ProcessLabel() != "" { - if err := label.Relabel(m.Source, c.MountLabel(), label.IsShared(o)); err != nil { - return nil, err - } - } else { - logrus.Infof("Not relabeling volume %q in container %s as SELinux is disabled", m.Source, c.ID()) - } + if err := label.Relabel(m.Source, c.MountLabel(), label.IsShared(o)); err != nil { + return nil, err } default: @@ -763,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 { 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 } diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go index d798963b1..ec7306ca1 100644 --- a/libpod/container_path_resolution.go +++ b/libpod/container_path_resolution.go @@ -128,7 +128,7 @@ func isPathOnVolume(c *Container, containerPath string) bool { if cleanedContainerPath == filepath.Clean(vol.Dest) { return true } - for dest := vol.Dest; dest != "/"; dest = filepath.Dir(dest) { + for dest := vol.Dest; dest != "/" && dest != "."; dest = filepath.Dir(dest) { if cleanedContainerPath == dest { return true } diff --git a/libpod/options.go b/libpod/options.go index 391cf0147..be26ced99 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -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 func WithPidFile(pidFile string) CtrCreateOption { return func(ctr *Container) error { diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index 0090156c9..7682367b7 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -402,6 +402,11 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen. if len(s.Secrets) != 0 { options = append(options, libpod.WithSecrets(s.Secrets)) } + + if len(s.EnvSecrets) != 0 { + options = append(options, libpod.WithEnvSecrets(s.EnvSecrets)) + } + if len(s.DependencyContainers) > 0 { deps := make([]*libpod.Container, 0, len(s.DependencyContainers)) for _, ctr := range s.DependencyContainers { diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 5ef2b0653..2e01d1535 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -180,6 +180,9 @@ type ContainerBasicConfig struct { // set tags as `json:"-"` for not supported remote // Optional. 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 diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index 0d3f2bed7..70a66124a 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -304,4 +304,28 @@ var _ = Describe("Podman commit", func() { 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))) + }) }) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 8530d3dd3..359345096 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -605,13 +605,6 @@ func SkipIfRootlessCgroupsV1(reason string) { } } -func SkipIfUnprivilegedCPULimits() { - info := GetHostDistributionInfo() - if isRootless() && info.Distribution == "fedora" { - ginkgo.Skip("Rootless Fedora doesn't have permission to set CPU limits") - } -} - func SkipIfRootless(reason string) { checkReason(reason) if os.Geteuid() != 0 { diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index d5861e7ba..3908d4075 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -2005,8 +2005,7 @@ VOLUME %s`, ALPINE, hostPathDir+"/") It("podman play kube allows setting resource limits", func() { SkipIfContainerized("Resource limits require a running systemd") - SkipIfRootlessCgroupsV1("Limits require root or cgroups v2") - SkipIfUnprivilegedCPULimits() + SkipIfRootless("CPU limits require root") podmanTest.CgroupManager = "systemd" var ( diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index d8d7dab07..59220cf01 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -921,6 +921,17 @@ USER mail`, BB) Expect(session.OutputToString()).To(ContainSubstring("mail root")) }) + It("podman run with incorect VOLUME", func() { + dockerfile := fmt.Sprintf(`FROM %s +VOLUME ['/etc/foo'] +WORKDIR /etc/foo`, BB) + podmanTest.BuildImage(dockerfile, "test", "false") + session := podmanTest.Podman([]string{"run", "--rm", "test", "echo", "test"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("test")) + }) + It("podman run --volumes-from flag", func() { vol := filepath.Join(podmanTest.TempDir, "vol-test") err := os.MkdirAll(vol, 0755) @@ -1600,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() { depName := "ctr1" depContainer := podmanTest.Podman([]string{"create", "--name", depName, ALPINE, "top"}) diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go index fbee18442..b54b959bf 100644 --- a/test/e2e/secret_test.go +++ b/test/e2e/secret_test.go @@ -199,4 +199,27 @@ var _ = Describe("Podman secret", func() { 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)) + }) + }) diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats index 35107f0a0..5d44c373f 100644 --- a/test/system/001-basic.bats +++ b/test/system/001-basic.bats @@ -10,16 +10,18 @@ function setup() { : } -@test "podman --context emits reasonable output" { - run_podman 125 --context=swarm version - is "$output" "Error: Podman does not support swarm, the only --context value allowed is \"default\"" "--context=default or fail" - - run_podman --context=default version -} +#### DO NOT ADD ANY TESTS HERE! ADD NEW TESTS AT BOTTOM! @test "podman version emits reasonable output" { run_podman version + # FIXME FIXME FIXME: #10248: nasty message on Ubuntu cgroups v1, rootless + if [[ "$output" =~ "overlay test mount with multiple lowers failed" ]]; then + if is_rootless; then + lines=("${lines[@]:1}") + fi + fi + # First line of podman-remote is "Client:<blank>". # Just delete it (i.e. remove the first entry from the 'lines' array) if is_remote; then @@ -41,6 +43,17 @@ function setup() { } +@test "podman --context emits reasonable output" { + # All we care about here is that the command passes + run_podman --context=default version + + # This one must fail + run_podman 125 --context=swarm version + is "$output" \ + "Error: Podman does not support swarm, the only --context value allowed is \"default\"" \ + "--context=default or fail" +} + @test "podman can pull an image" { run_podman pull $IMAGE } diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats index 95233c1e6..f8cee0e59 100644 --- a/test/system/410-selinux.bats +++ b/test/system/410-selinux.bats @@ -198,20 +198,23 @@ function check_label() { skip_if_no_selinux LABEL="system_u:object_r:tmp_t:s0" + RELABEL="system_u:object_r:container_file_t:s0" tmpdir=$PODMAN_TMPDIR/vol touch $tmpdir chcon -vR ${LABEL} $tmpdir ls -Z $tmpdir run_podman run -v $tmpdir:/test $IMAGE cat /proc/self/attr/current - level=$(secon -l $output) run ls -dZ ${tmpdir} is "$output" ${LABEL} "No Relabel Correctly" - run_podman run -v $tmpdir:/test:Z --security-opt label=disable $IMAGE cat /proc/self/attr/current - level=$(secon -l $output) + run_podman run -v $tmpdir:/test:z --security-opt label=disable $IMAGE cat /proc/self/attr/current + run ls -dZ $tmpdir + is "$output" ${RELABEL} "Privileged Relabel Correctly" + + run_podman run -v $tmpdir:/test:z --privileged $IMAGE cat /proc/self/attr/current run ls -dZ $tmpdir - is "$output" ${LABEL} "No Privileged Relabel Correctly" + is "$output" ${RELABEL} "Privileged Relabel Correctly" run_podman run -v $tmpdir:/test:Z $IMAGE cat /proc/self/attr/current level=$(secon -l $output) @@ -220,7 +223,7 @@ function check_label() { run_podman run -v $tmpdir:/test:z $IMAGE cat /proc/self/attr/current run ls -dZ $tmpdir - is "$output" "system_u:object_r:container_file_t:s0" "Shared Relabel Correctly" + is "$output" ${RELABEL} "Shared Relabel Correctly" } # vim: filetype=sh |