87 lines
1.6 KiB
Go
87 lines
1.6 KiB
Go
|
package oci
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"os"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/containerd/containerd/fs"
|
||
|
"github.com/opencontainers/runc/libcontainer/user"
|
||
|
)
|
||
|
|
||
|
func GetUser(ctx context.Context, root, username string) (uint32, uint32, error) {
|
||
|
// fast path from uid/gid
|
||
|
if uid, gid, err := ParseUser(username); err == nil {
|
||
|
return uid, gid, nil
|
||
|
}
|
||
|
|
||
|
passwdPath, err := user.GetPasswdPath()
|
||
|
if err != nil {
|
||
|
return 0, 0, err
|
||
|
}
|
||
|
groupPath, err := user.GetGroupPath()
|
||
|
if err != nil {
|
||
|
return 0, 0, err
|
||
|
}
|
||
|
passwdFile, err := openUserFile(root, passwdPath)
|
||
|
if err == nil {
|
||
|
defer passwdFile.Close()
|
||
|
}
|
||
|
groupFile, err := openUserFile(root, groupPath)
|
||
|
if err == nil {
|
||
|
defer groupFile.Close()
|
||
|
}
|
||
|
|
||
|
execUser, err := user.GetExecUser(username, nil, passwdFile, groupFile)
|
||
|
if err != nil {
|
||
|
return 0, 0, err
|
||
|
}
|
||
|
|
||
|
return uint32(execUser.Uid), uint32(execUser.Gid), nil
|
||
|
}
|
||
|
|
||
|
func ParseUser(str string) (uid uint32, gid uint32, err error) {
|
||
|
if str == "" {
|
||
|
return 0, 0, nil
|
||
|
}
|
||
|
parts := strings.SplitN(str, ":", 2)
|
||
|
for i, v := range parts {
|
||
|
switch i {
|
||
|
case 0:
|
||
|
uid, err = parseUID(v)
|
||
|
if err != nil {
|
||
|
return 0, 0, err
|
||
|
}
|
||
|
if len(parts) == 1 {
|
||
|
gid = uid
|
||
|
}
|
||
|
case 1:
|
||
|
gid, err = parseUID(v)
|
||
|
if err != nil {
|
||
|
return 0, 0, err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func openUserFile(root, p string) (*os.File, error) {
|
||
|
p, err := fs.RootPath(root, p)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return os.Open(p)
|
||
|
}
|
||
|
|
||
|
func parseUID(str string) (uint32, error) {
|
||
|
if str == "root" {
|
||
|
return 0, nil
|
||
|
}
|
||
|
uid, err := strconv.ParseUint(str, 10, 32)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
return uint32(uid), nil
|
||
|
}
|