Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Podman run --passwd #12664

Merged
merged 1 commit into from
Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/podman/containers/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions docs/source/markdown/podman-run.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
2 changes: 2 additions & 0 deletions libpod/container_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions libpod/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
32 changes: 17 additions & 15 deletions libpod/container_internal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1767,21 +1767,23 @@ func (c *Container) makeBindMounts() error {
// 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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this is going to break existing containers - if it is nil we have to run this code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll open a PR to fix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, sorry I missed that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#12685 to fix

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
Expand Down
2 changes: 2 additions & 0 deletions libpod/define/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 11 additions & 0 deletions libpod/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion pkg/api/handlers/libpod/containers_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/entities/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ type ContainerRunOptions struct {
Rm bool
SigProxy bool
Spec *specgen.SpecGenerator
Passwd bool
}

// ContainerRunReport describes the results of running
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/infra/abi/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions pkg/specgen/generate/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,5 +482,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
}
2 changes: 2 additions & 0 deletions pkg/specgen/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions pkg/specgenutil/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,9 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions

// Initcontainers
s.InitContainerType = c.InitContainerType

t := true
s.Passwd = &t
return nil
}

Expand Down
12 changes: 12 additions & 0 deletions test/e2e/run_passwd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"})
cdoern marked this conversation as resolved.
Show resolved Hide resolved
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")))
})
})