aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/containers/run.go4
-rwxr-xr-xcontrib/cirrus/setup_environment.sh5
-rw-r--r--docs/source/markdown/podman-run.1.md5
-rw-r--r--libpod/container_config.go2
-rw-r--r--libpod/container_inspect.go2
-rw-r--r--libpod/container_internal_linux.go63
-rw-r--r--libpod/define/container_inspect.go2
-rw-r--r--libpod/options.go11
-rw-r--r--pkg/api/handlers/libpod/containers_create.go6
-rw-r--r--pkg/api/handlers/utils/images.go2
-rw-r--r--pkg/domain/entities/containers.go1
-rw-r--r--pkg/domain/infra/abi/containers.go1
-rw-r--r--pkg/specgen/generate/container_create.go3
-rw-r--r--pkg/specgen/specgen.go2
-rw-r--r--pkg/specgenutil/specgen.go3
-rw-r--r--test/e2e/run_passwd_test.go12
-rw-r--r--test/python/docker/compat/test_images.py1
-rw-r--r--test/system/030-run.bats10
18 files changed, 106 insertions, 29 deletions
diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go
index cfb89ce57..b9a2c3bb5 100644
--- a/cmd/podman/containers/run.go
+++ b/cmd/podman/containers/run.go
@@ -83,6 +83,9 @@ func runFlags(cmd *cobra.Command) {
_ = cmd.RegisterFlagCompletionFunc(gpuFlagName, completion.AutocompleteNone)
_ = flags.MarkHidden("gpus")
+ passwdFlagName := "passwd"
+ flags.BoolVar(&runOpts.Passwd, passwdFlagName, true, "add entries to /etc/passwd and /etc/group")
+
if registry.IsRemote() {
_ = flags.MarkHidden("preserve-fds")
_ = flags.MarkHidden("conmon-pidfile")
@@ -191,6 +194,7 @@ func run(cmd *cobra.Command, args []string) error {
return err
}
s.RawImageName = rawImageName
+ s.Passwd = &runOpts.Passwd
runOpts.Spec = s
if _, err := createPodIfNecessary(cmd, s, cliVals.Net); err != nil {
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 8f535c7e7..43c709228 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -118,6 +118,11 @@ fi
case "$OS_RELEASE_ID" in
ubuntu) ;;
fedora)
+ # Force a crun version that has this fix: https://github.com/containers/crun/pull/819
+ # FIXME: Remove once a fixed crun made its way into Fedora
+ if test "$OS_RELEASE_VER" == "35"; then
+ yum upgrade -y https://kojipkgs.fedoraproject.org//work/tasks/684/80280684/crun-1.3-2.fc35.x86_64.rpm
+ fi
if ((CONTAINER==0)); then
# All SELinux distros need this for systemd-in-a-container
msg "Enabling container_manage_cgroup"
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index a6687e656..55642d5b3 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -762,6 +762,11 @@ Tune the host's OOM preferences for containers (accepts values from **-1000** to
#### **--os**=*OS*
Override the OS, defaults to hosts, of the image to be pulled. For example, `windows`.
+#### **--passwd**
+
+Allow Podman to add entries to /etc/passwd and /etc/group when used in conjunction with the --user option.
+This is used to override the Podman provided user setup in favor of entrypoint configurations such as libnss-extrausers.
+
#### **--personality**=*persona*
Personality sets the execution domain via Linux personality(2).
diff --git a/libpod/container_config.go b/libpod/container_config.go
index adc585fa1..db65063b5 100644
--- a/libpod/container_config.go
+++ b/libpod/container_config.go
@@ -163,6 +163,8 @@ type ContainerRootFSConfig struct {
// Volatile specifies whether the container storage can be optimized
// at the cost of not syncing all the dirty files in memory.
Volatile bool `json:"volatile,omitempty"`
+ // Passwd allows to user to override podman's passwd/group file setup
+ Passwd *bool `json:"passwd,omitempty"`
}
// ContainerSecurityConfig is an embedded sub-config providing security configuration
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 439328ea8..b065dd1f9 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -377,6 +377,8 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp
ctrConfig.Umask = c.config.Umask
}
+ ctrConfig.Passwd = c.config.Passwd
+
return ctrConfig
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index c2ec02e57..edebe2393 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1735,11 +1735,9 @@ func (c *Container) makeBindMounts() error {
}
if !c.config.UseImageHosts {
- newHosts, err := c.generateHosts("/etc/hosts")
- if err != nil {
+ if err := c.updateHosts("/etc/hosts"); err != nil {
return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
}
- c.state.BindMounts["/etc/hosts"] = newHosts
}
}
@@ -1756,32 +1754,32 @@ func (c *Container) makeBindMounts() error {
}
} else {
if !c.config.UseImageHosts && c.state.BindMounts["/etc/hosts"] == "" {
- newHosts, err := c.generateHosts("/etc/hosts")
- if err != nil {
+ if err := c.updateHosts("/etc/hosts"); err != nil {
return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
}
- c.state.BindMounts["/etc/hosts"] = newHosts
}
}
// SHM is always added when we mount the container
c.state.BindMounts["/dev/shm"] = c.config.ShmDir
- newPasswd, newGroup, err := c.generatePasswdAndGroup()
- if err != nil {
- return errors.Wrapf(err, "error creating temporary passwd file for container %s", c.ID())
- }
- if newPasswd != "" {
- // Make /etc/passwd
- // If it already exists, delete so we can recreate
- delete(c.state.BindMounts, "/etc/passwd")
- c.state.BindMounts["/etc/passwd"] = newPasswd
- }
- if newGroup != "" {
- // Make /etc/group
- // If it already exists, delete so we can recreate
- delete(c.state.BindMounts, "/etc/group")
- c.state.BindMounts["/etc/group"] = newGroup
+ if c.config.Passwd != nil && *c.config.Passwd {
+ newPasswd, newGroup, err := c.generatePasswdAndGroup()
+ if err != nil {
+ return errors.Wrapf(err, "error creating temporary passwd file for container %s", c.ID())
+ }
+ if newPasswd != "" {
+ // Make /etc/passwd
+ // If it already exists, delete so we can recreate
+ delete(c.state.BindMounts, "/etc/passwd")
+ c.state.BindMounts["/etc/passwd"] = newPasswd
+ }
+ if newGroup != "" {
+ // Make /etc/group
+ // If it already exists, delete so we can recreate
+ delete(c.state.BindMounts, "/etc/group")
+ c.state.BindMounts["/etc/group"] = newGroup
+ }
}
// Make /etc/hostname
@@ -2048,18 +2046,29 @@ func (c *Container) generateResolvConf() (string, error) {
return destPath, nil
}
-// generateHosts creates a containers hosts file
-func (c *Container) generateHosts(path string) (string, error) {
+// updateHosts updates the container's hosts file
+func (c *Container) updateHosts(path string) error {
+ var hosts string
+
orig, err := ioutil.ReadFile(path)
if err != nil {
- return "", err
+ // Ignore if the path does not exist
+ if !os.IsNotExist(err) {
+ return err
+ }
+ } else {
+ hosts = string(orig)
}
- hosts := string(orig)
- hosts += c.getHosts()
+ hosts += c.getHosts()
hosts = c.appendLocalhost(hosts)
- return c.writeStringToRundir("hosts", hosts)
+ newHosts, err := c.writeStringToRundir("hosts", hosts)
+ if err != nil {
+ return err
+ }
+ c.state.BindMounts["/etc/hosts"] = newHosts
+ return nil
}
// based on networking mode we may want to append the localhost
diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go
index a4d9bcf4f..ba73e4196 100644
--- a/libpod/define/container_inspect.go
+++ b/libpod/define/container_inspect.go
@@ -68,6 +68,8 @@ type InspectContainerConfig struct {
Timeout uint `json:"Timeout"`
// StopTimeout is time before container is stopped when calling stop
StopTimeout uint `json:"StopTimeout"`
+ // Passwd determines whether or not podman can add entries to /etc/passwd and /etc/group
+ Passwd *bool `json:"Passwd,omitempty"`
}
// InspectRestartPolicy holds information about the container's restart policy.
diff --git a/libpod/options.go b/libpod/options.go
index e6fa987a8..85d7b4689 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1794,6 +1794,17 @@ func WithHostDevice(dev []specs.LinuxDevice) CtrCreateOption {
}
}
+// WithSelectedPasswordManagement makes it so that the container either does or does not setup /etc/passwd or /etc/group
+func WithSelectedPasswordManagement(passwd *bool) CtrCreateOption {
+ return func(c *Container) error {
+ if c.valid {
+ return define.ErrCtrFinalized
+ }
+ c.config.Passwd = passwd
+ return nil
+ }
+}
+
// Pod Creation Options
// WithPodCreateCommand adds the full command plus arguments of the current
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index 77bfe7b50..d1841769a 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -19,11 +19,15 @@ import (
func CreateContainer(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
var sg specgen.SpecGenerator
+
if err := json.NewDecoder(r.Body).Decode(&sg); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
-
+ if sg.Passwd == nil {
+ t := true
+ sg.Passwd = &t
+ }
warn, err := generate.CompleteSpec(r.Context(), runtime, &sg)
if err != nil {
utils.InternalServerError(w, err)
diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go
index d874165e3..3f3f48193 100644
--- a/pkg/api/handlers/utils/images.go
+++ b/pkg/api/handlers/utils/images.go
@@ -35,7 +35,7 @@ func NormalizeToDockerHub(r *http.Request, nameOrID string) (string, error) {
if errors.Cause(err) != storage.ErrImageUnknown {
return "", fmt.Errorf("normalizing name for compat API: %v", err)
}
- } else if strings.HasPrefix(img.ID(), nameOrID) {
+ } else if strings.HasPrefix(img.ID(), strings.TrimPrefix(nameOrID, "sha256:")) {
return img.ID(), nil
}
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 1677c067f..ae441b7f3 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -341,6 +341,7 @@ type ContainerRunOptions struct {
Rm bool
SigProxy bool
Spec *specgen.SpecGenerator
+ Passwd bool
}
// ContainerRunReport describes the results of running
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index d1af4a479..bf4dcff62 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -927,6 +927,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
for _, w := range warn {
fmt.Fprintf(os.Stderr, "%s\n", w)
}
+
rtSpec, spec, optsN, err := generate.MakeContainer(ctx, ic.Libpod, opts.Spec)
if err != nil {
return nil, err
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 577a67bbe..1debf6c0e 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -489,5 +489,8 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
if s.PidFile != "" {
options = append(options, libpod.WithPidFile(s.PidFile))
}
+
+ options = append(options, libpod.WithSelectedPasswordManagement(s.Passwd))
+
return options, nil
}
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index e650c1966..5a1cc1144 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -201,6 +201,8 @@ type ContainerBasicConfig struct {
// UnsetEnvAll unsets all default environment variables from the image or from buildin
// Optional.
UnsetEnvAll bool `json:"unsetenvall,omitempty"`
+ // Passwd is a container run option that determines if we are validating users/groups before running the container
+ Passwd *bool `json:"manage_password,omitempty"`
}
// ContainerStorageConfig contains information on the storage configuration of a
diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go
index 123c0073b..9a91b2893 100644
--- a/pkg/specgenutil/specgen.go
+++ b/pkg/specgenutil/specgen.go
@@ -698,6 +698,9 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
// Initcontainers
s.InitContainerType = c.InitContainerType
+
+ t := true
+ s.Passwd = &t
return nil
}
diff --git a/test/e2e/run_passwd_test.go b/test/e2e/run_passwd_test.go
index 6d1d26914..2207a50a8 100644
--- a/test/e2e/run_passwd_test.go
+++ b/test/e2e/run_passwd_test.go
@@ -125,4 +125,16 @@ USER 1000`, ALPINE)
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(Not(ContainSubstring("/etc/group")))
})
+
+ It("podman run --no-manage-passwd flag", func() {
+ run := podmanTest.Podman([]string{"run", "--user", "1234:1234", ALPINE, "cat", "/etc/passwd"})
+ run.WaitWithDefaultTimeout()
+ Expect(run).Should(Exit(0))
+ Expect(run.OutputToString()).To(ContainSubstring("1234:1234"))
+
+ run = podmanTest.Podman([]string{"run", "--passwd=false", "--user", "1234:1234", ALPINE, "cat", "/etc/passwd"})
+ run.WaitWithDefaultTimeout()
+ Expect(run).Should(Exit(0))
+ Expect(run.OutputToString()).NotTo((ContainSubstring("1234:1234")))
+ })
})
diff --git a/test/python/docker/compat/test_images.py b/test/python/docker/compat/test_images.py
index 1e2b531b7..485a0e419 100644
--- a/test/python/docker/compat/test_images.py
+++ b/test/python/docker/compat/test_images.py
@@ -79,6 +79,7 @@ class TestImages(unittest.TestCase):
# Add more images
self.client.images.pull(constant.BB)
self.assertEqual(len(self.client.images.list()), 2)
+ self.assertEqual(len(self.client.images.list(all=True)), 2)
# List images with filter
self.assertEqual(len(self.client.images.list(filters={"reference": "alpine"})), 1)
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 6f1fa600a..55514305b 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -756,4 +756,14 @@ EOF
is "$output" ".*TERM=abc" "missing TERM environment variable despite TERM being set on commandline"
}
+@test "podman run - no /etc/hosts" {
+ skip_if_rootless "cannot move /etc/hosts file as a rootless user"
+ tmpfile=$PODMAN_TMPDIR/hosts
+ mv /etc/hosts $tmpfile
+ run_podman '?' run --rm --add-host "foo.com:1.2.3.4" $IMAGE cat "/etc/hosts"
+ mv $tmpfile /etc/hosts
+ is "$status" 0 "podman run without /etc/hosts file should work"
+ is "$output" "1.2.3.4 foo.com.*" "users can add hosts even without /etc/hosts"
+}
+
# vim: filetype=sh