Merge pull request #2009 from crosbymichael/user-path

Support getting uid/gid from rootfs path
This commit is contained in:
Phil Estes 2018-01-17 10:48:59 -05:00 committed by GitHub
commit aaf930eaf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -257,7 +257,24 @@ func WithUIDGID(uid, gid uint32) SpecOpts {
// uid, and not returns error. // uid, and not returns error.
func WithUserID(uid uint32) SpecOpts { func WithUserID(uid uint32) SpecOpts {
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) { return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) {
// TODO: support non-snapshot rootfs if c.Snapshotter == "" && c.SnapshotKey == "" {
if !isRootfsAbs(s.Root.Path) {
return errors.Errorf("rootfs absolute path is required")
}
uuid, ugid, err := getUIDGIDFromPath(s.Root.Path, func(u user.User) bool {
return u.Uid == int(uid)
})
if err != nil {
if os.IsNotExist(err) || err == errNoUsersFound {
s.Process.User.UID, s.Process.User.GID = uid, uid
return nil
}
return err
}
s.Process.User.UID, s.Process.User.GID = uuid, ugid
return nil
}
if c.Snapshotter == "" { if c.Snapshotter == "" {
return errors.Errorf("no snapshotter set for container") return errors.Errorf("no snapshotter set for container")
} }
@ -269,33 +286,18 @@ func WithUserID(uid uint32) SpecOpts {
if err != nil { if err != nil {
return err return err
} }
return mount.WithTempMount(ctx, mounts, func(root string) error { return mount.WithTempMount(ctx, mounts, func(root string) error {
ppath, err := fs.RootPath(root, "/etc/passwd") uuid, ugid, err := getUIDGIDFromPath(root, func(u user.User) bool {
if err != nil {
return err
}
f, err := os.Open(ppath)
if err != nil {
if os.IsNotExist(err) {
s.Process.User.UID, s.Process.User.GID = uid, uid
return nil
}
return err
}
defer f.Close()
users, err := user.ParsePasswdFilter(f, func(u user.User) bool {
return u.Uid == int(uid) return u.Uid == int(uid)
}) })
if err != nil { if err != nil {
return err if os.IsNotExist(err) || err == errNoUsersFound {
}
if len(users) == 0 {
s.Process.User.UID, s.Process.User.GID = uid, uid s.Process.User.UID, s.Process.User.GID = uid, uid
return nil return nil
} }
u := users[0] return err
s.Process.User.UID, s.Process.User.GID = uint32(u.Uid), uint32(u.Gid) }
s.Process.User.UID, s.Process.User.GID = uuid, ugid
return nil return nil
}) })
} }
@ -306,8 +308,20 @@ func WithUserID(uid uint32) SpecOpts {
// does not exist, or the username is not found in /etc/passwd, // does not exist, or the username is not found in /etc/passwd,
// it returns error. // it returns error.
func WithUsername(username string) SpecOpts { func WithUsername(username string) SpecOpts {
// TODO: support non-snapshot rootfs
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) { return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) {
if c.Snapshotter == "" && c.SnapshotKey == "" {
if !isRootfsAbs(s.Root.Path) {
return errors.Errorf("rootfs absolute path is required")
}
uid, gid, err := getUIDGIDFromPath(s.Root.Path, func(u user.User) bool {
return u.Name == username
})
if err != nil {
return err
}
s.Process.User.UID, s.Process.User.GID = uid, gid
return nil
}
if c.Snapshotter == "" { if c.Snapshotter == "" {
return errors.Errorf("no snapshotter set for container") return errors.Errorf("no snapshotter set for container")
} }
@ -320,27 +334,41 @@ func WithUsername(username string) SpecOpts {
return err return err
} }
return mount.WithTempMount(ctx, mounts, func(root string) error { return mount.WithTempMount(ctx, mounts, func(root string) error {
ppath, err := fs.RootPath(root, "/etc/passwd") uid, gid, err := getUIDGIDFromPath(root, func(u user.User) bool {
if err != nil {
return err
}
f, err := os.Open(ppath)
if err != nil {
return err
}
defer f.Close()
users, err := user.ParsePasswdFilter(f, func(u user.User) bool {
return u.Name == username return u.Name == username
}) })
if err != nil { if err != nil {
return err return err
} }
if len(users) == 0 { s.Process.User.UID, s.Process.User.GID = uid, gid
return errors.Errorf("no users found for %s", username)
}
u := users[0]
s.Process.User.UID, s.Process.User.GID = uint32(u.Uid), uint32(u.Gid)
return nil return nil
}) })
} }
} }
var errNoUsersFound = errors.New("no users found")
func getUIDGIDFromPath(root string, filter func(user.User) bool) (uid, gid uint32, err error) {
ppath, err := fs.RootPath(root, "/etc/passwd")
if err != nil {
return 0, 0, err
}
f, err := os.Open(ppath)
if err != nil {
return 0, 0, err
}
defer f.Close()
users, err := user.ParsePasswdFilter(f, filter)
if err != nil {
return 0, 0, err
}
if len(users) == 0 {
return 0, 0, errNoUsersFound
}
u := users[0]
return uint32(u.Uid), uint32(u.Gid), nil
}
func isRootfsAbs(root string) bool {
return filepath.IsAbs(root)
}