diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index 4598e535db..d73fa653f9 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -201,6 +201,20 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(envFlagName, completion.AutocompleteNone) + unsetenvFlagName := "unsetenv" + createFlags.StringArrayVar( + &cf.UnsetEnv, + unsetenvFlagName, []string{}, + "Unset environment default variables in container", + ) + _ = cmd.RegisterFlagCompletionFunc(unsetenvFlagName, completion.AutocompleteNone) + + createFlags.BoolVar( + &cf.UnsetEnvAll, + "unsetenv-all", false, + "Unset all default environment variables in container", + ) + if !registry.IsRemote() { createFlags.BoolVar( &cf.EnvHost, diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index 6283eb28e1..aacdfd2748 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -297,6 +297,8 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c Systemd: "true", // podman default TmpFS: parsedTmp, TTY: cc.Config.Tty, + UnsetEnv: cc.UnsetEnv, + UnsetEnvAll: cc.UnsetEnvAll, User: cc.Config.User, UserNS: string(cc.HostConfig.UsernsMode), UTS: string(cc.HostConfig.UTSMode), diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index b0d7b8f123..811d16880a 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -1047,6 +1047,18 @@ Remote connections use local containers.conf for defaults Set the umask inside the container. Defaults to `0022`. Remote connections use local containers.conf for defaults +#### **--unsetenv**=*env* + +Unset default environment variables for the container. Default environment +variables include variables provided natively by Podman, environment variables +configured by the image, and environment variables from containers.conf. + +#### **--unsetenv-all**=*true|false* + +Unset all default environment variables for the container. Default environment +variables include variables provided natively by Podman, environment variables +configured by the image, and environment variables from containers.conf. + #### **--uidmap**=*container_uid*:*from_uid*:*amount* Run the container in a new user namespace using the supplied mapping. This diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 0fdd47a785..3d908444bd 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -1117,6 +1117,18 @@ Remote connections use local containers.conf for defaults Set the umask inside the container. Defaults to `0022`. Remote connections use local containers.conf for defaults +#### **--unsetenv**=*env* + +Unset default environment variables for the container. Default environment +variables include variables provided natively by Podman, environment variables +configured by the image, and environment variables from containers.conf. + +#### **--unsetenv-all**=*true|false* + +Unset all default environment variables for the container. Default environment +variables include variables provided natively by Podman, environment variables +configured by the image, and environment variables from containers.conf. + #### **--uidmap**=*container_uid*:*from_uid*:*amount* Run the container in a new user namespace using the supplied mapping. This diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 277c3b9606..0dae810dee 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -300,8 +300,7 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp ctrConfig.User = c.config.User if spec.Process != nil { ctrConfig.Tty = spec.Process.Terminal - ctrConfig.Env = []string{} - ctrConfig.Env = append(ctrConfig.Env, spec.Process.Env...) + ctrConfig.Env = append([]string{}, spec.Process.Env...) ctrConfig.WorkingDir = spec.Process.Cwd } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 4a15d495fb..fbe8d8e7e2 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -709,18 +709,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { g.AddAnnotation(annotations.ContainerManager, annotations.ContainerManagerLibpod) } - // Only add container environment variable if not already present - foundContainerEnv := false - for _, env := range g.Config.Process.Env { - if strings.HasPrefix(env, "container=") { - foundContainerEnv = true - break - } - } - if !foundContainerEnv { - g.AddProcessEnv("container", "libpod") - } - cgroupPath, err := c.getOCICgroupPath() if err != nil { return nil, err diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 35120a1a55..f850db3d8c 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -116,6 +116,8 @@ type CreateContainerConfig struct { dockerContainer.Config // desired container configuration HostConfig dockerContainer.HostConfig // host dependent configuration for container NetworkingConfig dockerNetwork.NetworkingConfig // network configuration for container + UnsetEnv []string // unset specified default environment variables + UnsetEnvAll bool // unset all default environment variables } // swagger:model IDResponse diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index 70d2be1e6a..b255785c25 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -248,6 +248,8 @@ type ContainerCreateOptions struct { TTY bool Timezone string Umask string + UnsetEnv []string + UnsetEnvAll bool UIDMap []string Ulimit []string User string diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 002b4ace32..40a18a6ac8 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -88,9 +88,6 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat if err != nil { return nil, errors.Wrap(err, "error parsing fields in containers.conf") } - if defaultEnvs["container"] == "" { - defaultEnvs["container"] = "podman" - } var envs map[string]string // Image Environment defaults @@ -101,9 +98,16 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat if err != nil { return nil, errors.Wrap(err, "Env fields from image failed to parse") } - defaultEnvs = envLib.Join(defaultEnvs, envs) + defaultEnvs = envLib.Join(envLib.DefaultEnvVariables(), envLib.Join(defaultEnvs, envs)) + } + + for _, e := range s.UnsetEnv { + delete(defaultEnvs, e) } + if s.UnsetEnvAll { + defaultEnvs = make(map[string]string) + } // First transform the os env into a map. We need it for the labels later in // any case. osEnv, err := envLib.ParseSlice(os.Environ()) diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index beccd9fc2a..1b022b9122 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -298,7 +298,6 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt for key, val := range s.Annotations { g.AddAnnotation(key, val) } - g.AddProcessEnv("container", "podman") g.Config.Linux.Resources = s.ResourceLimits // Devices @@ -332,6 +331,7 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g) + g.ClearProcessEnv() for name, val := range s.Env { g.AddProcessEnv(name, val) } diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index d777287d7e..cde456ad09 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -194,6 +194,13 @@ type ContainerBasicConfig struct { // The execution domain system allows Linux to provide limited support // for binaries compiled under other UNIX-like operating systems. Personality *spec.LinuxPersonality `json:"personality,omitempty"` + // UnsetEnv unsets the specified default environment variables from the image or from buildin or containers.conf + // Optional. + UnsetEnv []string `json:"unsetenv,omitempty"` + // UnsetEnvAll unsetall default environment variables from the image or from buildin or containers.conf + // UnsetEnvAll unsets all default environment variables from the image or from buildin + // Optional. + UnsetEnvAll bool `json:"unsetenvall,omitempty"` } // ContainerStorageConfig contains information on the storage configuration of a diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 04d3add324..aa59b0a8d0 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -711,6 +711,8 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions s.Umask = c.Umask s.PidFile = c.PidFile s.Volatile = c.Rm + s.UnsetEnv = c.UnsetEnv + s.UnsetEnvAll = c.UnsetEnvAll // Initcontainers s.InitContainerType = c.InitContainerType diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 2c8d08b999..ba21cd21d2 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -736,4 +736,26 @@ EOF is "$output" "$random_1" "output matches STDIN" } +@test "podman run defaultenv" { + run_podman run --rm $IMAGE printenv + is "$output" ".*TERM=xterm" "output matches TERM" + is "$output" ".*container=podman" "output matches container=podman" + + run_podman run --unsetenv=TERM --rm $IMAGE printenv + is "$output" ".*container=podman" "output matches container=podman" + run grep TERM <<<$output + is "$output" "" "unwanted TERM environment variable despite --unsetenv=TERM" + + run_podman run --unsetenv-all --rm $IMAGE /bin/printenv + run grep TERM <<<$output + is "$output" "" "unwanted TERM environment variable despite --unsetenv-all" + run grep container <<<$output + is "$output" "" "unwanted container environment variable despite --unsetenv-all" + run grep PATH <<<$output + is "$output" "" "unwanted PATH environment variable despite --unsetenv-all" + + run_podman run --unsetenv-all --env TERM=abc --rm $IMAGE /bin/printenv + is "$output" ".*TERM=abc" "missing TERM environment variable despite TERM being set on commandline" +} + # vim: filetype=sh diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index 1c778a5e3f..e997ab6f9c 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -174,10 +174,14 @@ function check_listen_env() { if is_remote; then is "$output" "$stdenv" "LISTEN Environment did not pass: $context" else - is "$output" "$stdenv + out=$(for o in $output; do echo $o; done| sort) + std=$(echo "$stdenv LISTEN_PID=1 LISTEN_FDS=1 -LISTEN_FDNAMES=listen_fdnames" "LISTEN Environment passed: $context" +LISTEN_FDNAMES=listen_fdnames" | sort) + echo "<$out>" + echo "<$std>" + is "$out" "$std" "LISTEN Environment passed: $context" fi }