Modify --user flag for podman create and run

If an integer is passed into the --user flag, i.e --user=1234
don't look up the user in /etc/passwd, just assign the integer as the uid.

Signed-off-by: umohnani8 <umohnani@redhat.com>

Closes: #652
Approved by: mheon
This commit is contained in:
umohnani8
2018-04-20 09:44:37 -04:00
committed by Atomic Bot
parent e76caee338
commit cf41dc70b3
4 changed files with 46 additions and 7 deletions

View File

@ -9,7 +9,6 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@ -956,17 +955,17 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return nil, errors.Wrapf(ErrCtrStateInvalid, "container %s must be mounted in order to add additional groups", c.ID()) return nil, errors.Wrapf(ErrCtrStateInvalid, "container %s must be mounted in order to add additional groups", c.ID())
} }
for _, group := range c.config.Groups { for _, group := range c.config.Groups {
_, gid, err := chrootuser.GetUser(c.state.Mountpoint, strconv.Itoa(int(g.Spec().Process.User.UID))+":"+group) gid, err := chrootuser.GetGroup(c.state.Mountpoint, group)
if err != nil { if err != nil {
return nil, err return nil, err
} }
g.AddProcessAdditionalGid(uint32(gid)) g.AddProcessAdditionalGid(gid)
} }
} }
// Look up and add groups the user belongs to // Look up and add groups the user belongs to
groups, err := chrootuser.GetAdditionalGroupsForUser(c.state.Mountpoint, uint64(g.Spec().Process.User.UID)) groups, err := chrootuser.GetAdditionalGroupsForUser(c.state.Mountpoint, uint64(g.Spec().Process.User.UID))
if err != nil { if err != nil && err != chrootuser.ErrNoSuchUser {
return nil, err return nil, err
} }
for _, gid := range groups { for _, gid := range groups {

View File

@ -37,8 +37,8 @@ func GetUser(rootdir, userspec string) (uint32, uint32, error) {
userspec = name userspec = name
} else { } else {
// Leave userspec alone, but swallow the error and just // Leave userspec alone, but swallow the error and just
// use GID 0. // use GID == UID.
gid64 = 0 gid64 = uid64
gerr = nil gerr = nil
} }
} }
@ -70,6 +70,21 @@ func GetUser(rootdir, userspec string) (uint32, uint32, error) {
return 0, 0, err return 0, 0, err
} }
// GetGroup returns the gid by looking it up in the /etc/passwd file
// groupspec format [ group | gid ]
func GetGroup(rootdir, groupspec string) (uint32, error) {
gid64, gerr := strconv.ParseUint(groupspec, 10, 32)
if gerr != nil {
// The group couldn't be parsed as a number, so look up
// the group's GID.
gid64, gerr = lookupGroupInContainer(rootdir, groupspec)
}
if gerr != nil {
return 0, errors.Wrapf(gerr, "error looking up group for gid %q", groupspec)
}
return uint32(gid64), nil
}
// GetAdditionalGroupsForUser returns a list of gids that userid is associated with // GetAdditionalGroupsForUser returns a list of gids that userid is associated with
func GetAdditionalGroupsForUser(rootdir string, userid uint64) ([]uint32, error) { func GetAdditionalGroupsForUser(rootdir string, userid uint64) ([]uint32, error) {
return lookupAdditionalGroupsForUIDInContainer(rootdir, userid) return lookupAdditionalGroupsForUIDInContainer(rootdir, userid)

View File

@ -4,6 +4,7 @@ package chrootuser
import ( import (
"bufio" "bufio"
"errors"
"flag" "flag"
"fmt" "fmt"
"io" "io"
@ -78,6 +79,9 @@ func openChrootedFile(rootdir, filename string) (*exec.Cmd, io.ReadCloser, error
var ( var (
lookupUser, lookupGroup sync.Mutex lookupUser, lookupGroup sync.Mutex
// ErrNoSuchUser indicates that the user provided by the caller does not
// exist in /etc/passws
ErrNoSuchUser = errors.New("user does not exist in /etc/passwd")
) )
type lookupPasswdEntry struct { type lookupPasswdEntry struct {
@ -207,7 +211,7 @@ func lookupGroupForUIDInContainer(rootdir string, userid uint64) (username strin
return pwd.name, pwd.gid, nil return pwd.name, pwd.gid, nil
} }
return "", 0, user.UnknownUserError(fmt.Sprintf("error looking up user with UID %d", userid)) return "", 0, ErrNoSuchUser
} }
func lookupAdditionalGroupsForUIDInContainer(rootdir string, userid uint64) (gid []uint32, err error) { func lookupAdditionalGroupsForUIDInContainer(rootdir string, userid uint64) (gid []uint32, err error) {

View File

@ -330,6 +330,27 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).To(Equal("uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),18(audio),20(dialout),26(tape),27(video),777,65533(nogroup)")) Expect(session.OutputToString()).To(Equal("uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),18(audio),20(dialout),26(tape),27(video),777,65533(nogroup)"))
}) })
It("podman run with user (default)", func() {
session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)"))
})
It("podman run with user (integer)", func() {
session := podmanTest.Podman([]string{"run", "--rm", "--user=1234", ALPINE, "id"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("uid=1234 gid=1234"))
})
It("podman run with user (username)", func() {
session := podmanTest.Podman([]string{"run", "--rm", "--user=mail", ALPINE, "id"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=12(mail) groups=12(mail)"))
})
It("podman run with attach stdin outputs container ID", func() { It("podman run with attach stdin outputs container ID", func() {
session := podmanTest.Podman([]string{"run", "--attach", "stdin", ALPINE, "printenv"}) session := podmanTest.Podman([]string{"run", "--attach", "stdin", ALPINE, "printenv"})
session.WaitWithDefaultTimeout() session.WaitWithDefaultTimeout()