Add --unsetenv & --unsetenv-all to remove def environment variables

Podman adds a few environment variables by default, and
currently there is no way to get rid of them from your container.
This option will allow  you to specify which defaults you don't
want.

--unsetenv-all will remove all default environment variables.

Default environment variables can come from podman builtin,
containers.conf or from the container image.

Fixes: https://github.com/containers/podman/issues/11836

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh 2021-10-26 12:16:21 -04:00
parent 230f0b622e
commit 44d1618dd7
No known key found for this signature in database
GPG Key ID: A2DF901DABE2C028
14 changed files with 91 additions and 21 deletions

View File

@ -201,6 +201,20 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
) )
_ = cmd.RegisterFlagCompletionFunc(envFlagName, completion.AutocompleteNone) _ = 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() { if !registry.IsRemote() {
createFlags.BoolVar( createFlags.BoolVar(
&cf.EnvHost, &cf.EnvHost,

View File

@ -297,6 +297,8 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c
Systemd: "true", // podman default Systemd: "true", // podman default
TmpFS: parsedTmp, TmpFS: parsedTmp,
TTY: cc.Config.Tty, TTY: cc.Config.Tty,
UnsetEnv: cc.UnsetEnv,
UnsetEnvAll: cc.UnsetEnvAll,
User: cc.Config.User, User: cc.Config.User,
UserNS: string(cc.HostConfig.UsernsMode), UserNS: string(cc.HostConfig.UsernsMode),
UTS: string(cc.HostConfig.UTSMode), UTS: string(cc.HostConfig.UTSMode),

View File

@ -1047,6 +1047,18 @@ Remote connections use local containers.conf for defaults
Set the umask inside the container. Defaults to `0022`. Set the umask inside the container. Defaults to `0022`.
Remote connections use local containers.conf for defaults 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* #### **--uidmap**=*container_uid*:*from_uid*:*amount*
Run the container in a new user namespace using the supplied mapping. This Run the container in a new user namespace using the supplied mapping. This

View File

@ -1117,6 +1117,18 @@ Remote connections use local containers.conf for defaults
Set the umask inside the container. Defaults to `0022`. Set the umask inside the container. Defaults to `0022`.
Remote connections use local containers.conf for defaults 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* #### **--uidmap**=*container_uid*:*from_uid*:*amount*
Run the container in a new user namespace using the supplied mapping. This Run the container in a new user namespace using the supplied mapping. This

View File

@ -300,8 +300,7 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp
ctrConfig.User = c.config.User ctrConfig.User = c.config.User
if spec.Process != nil { if spec.Process != nil {
ctrConfig.Tty = spec.Process.Terminal ctrConfig.Tty = spec.Process.Terminal
ctrConfig.Env = []string{} ctrConfig.Env = append([]string{}, spec.Process.Env...)
ctrConfig.Env = append(ctrConfig.Env, spec.Process.Env...)
ctrConfig.WorkingDir = spec.Process.Cwd ctrConfig.WorkingDir = spec.Process.Cwd
} }

View File

@ -709,18 +709,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
g.AddAnnotation(annotations.ContainerManager, annotations.ContainerManagerLibpod) 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() cgroupPath, err := c.getOCICgroupPath()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -116,6 +116,8 @@ type CreateContainerConfig struct {
dockerContainer.Config // desired container configuration dockerContainer.Config // desired container configuration
HostConfig dockerContainer.HostConfig // host dependent configuration for container HostConfig dockerContainer.HostConfig // host dependent configuration for container
NetworkingConfig dockerNetwork.NetworkingConfig // network 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 // swagger:model IDResponse

View File

@ -248,6 +248,8 @@ type ContainerCreateOptions struct {
TTY bool TTY bool
Timezone string Timezone string
Umask string Umask string
UnsetEnv []string
UnsetEnvAll bool
UIDMap []string UIDMap []string
Ulimit []string Ulimit []string
User string User string

View File

@ -88,9 +88,6 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
if err != nil { if err != nil {
return nil, errors.Wrap(err, "error parsing fields in containers.conf") return nil, errors.Wrap(err, "error parsing fields in containers.conf")
} }
if defaultEnvs["container"] == "" {
defaultEnvs["container"] = "podman"
}
var envs map[string]string var envs map[string]string
// Image Environment defaults // Image Environment defaults
@ -101,9 +98,16 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Env fields from image failed to parse") 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 // First transform the os env into a map. We need it for the labels later in
// any case. // any case.
osEnv, err := envLib.ParseSlice(os.Environ()) osEnv, err := envLib.ParseSlice(os.Environ())

View File

@ -298,7 +298,6 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
for key, val := range s.Annotations { for key, val := range s.Annotations {
g.AddAnnotation(key, val) g.AddAnnotation(key, val)
} }
g.AddProcessEnv("container", "podman")
g.Config.Linux.Resources = s.ResourceLimits g.Config.Linux.Resources = s.ResourceLimits
// Devices // 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) BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g)
g.ClearProcessEnv()
for name, val := range s.Env { for name, val := range s.Env {
g.AddProcessEnv(name, val) g.AddProcessEnv(name, val)
} }

View File

@ -194,6 +194,13 @@ type ContainerBasicConfig struct {
// The execution domain system allows Linux to provide limited support // The execution domain system allows Linux to provide limited support
// for binaries compiled under other UNIX-like operating systems. // for binaries compiled under other UNIX-like operating systems.
Personality *spec.LinuxPersonality `json:"personality,omitempty"` 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 // ContainerStorageConfig contains information on the storage configuration of a

View File

@ -711,6 +711,8 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
s.Umask = c.Umask s.Umask = c.Umask
s.PidFile = c.PidFile s.PidFile = c.PidFile
s.Volatile = c.Rm s.Volatile = c.Rm
s.UnsetEnv = c.UnsetEnv
s.UnsetEnvAll = c.UnsetEnvAll
// Initcontainers // Initcontainers
s.InitContainerType = c.InitContainerType s.InitContainerType = c.InitContainerType

View File

@ -736,4 +736,26 @@ EOF
is "$output" "$random_1" "output matches STDIN" 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 # vim: filetype=sh

View File

@ -174,10 +174,14 @@ function check_listen_env() {
if is_remote; then if is_remote; then
is "$output" "$stdenv" "LISTEN Environment did not pass: $context" is "$output" "$stdenv" "LISTEN Environment did not pass: $context"
else else
is "$output" "$stdenv out=$(for o in $output; do echo $o; done| sort)
std=$(echo "$stdenv
LISTEN_PID=1 LISTEN_PID=1
LISTEN_FDS=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 fi
} }