mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
098a44c07f
Finish the refactor which was partially completed with commit
34536c498d
, passing around IdentityMapping structs instead of pairs of
[]IDMap slices.
Existing code which uses []IDMap relies on zero-valued fields to be
valid, empty mappings. So in order to successfully finish the
refactoring without introducing bugs, their replacement therefore also
needs to have a useful zero value which represents an empty mapping.
Change IdentityMapping to be a pass-by-value type so that there are no
nil pointers to worry about.
The functionality provided by the deprecated NewIDMappingsFromMaps
function is required by unit tests to to construct arbitrary
IdentityMapping values. And the daemon will always need to access the
mappings to pass them to the Linux kernel. Accommodate these use cases
by exporting the struct fields instead. BuildKit currently depends on
the UIDs and GIDs methods so we cannot get rid of them yet.
Signed-off-by: Cory Snider <csnider@mirantis.com>
88 lines
2.8 KiB
Go
88 lines
2.8 KiB
Go
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/pkg/idtools"
|
|
"github.com/moby/sys/symlink"
|
|
lcUser "github.com/opencontainers/runc/libcontainer/user"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
|
|
var userStr, grpStr string
|
|
parts := strings.Split(chown, ":")
|
|
if len(parts) > 2 {
|
|
return idtools.Identity{}, errors.New("invalid chown string format: " + chown)
|
|
}
|
|
if len(parts) == 1 {
|
|
// if no group specified, use the user spec as group as well
|
|
userStr, grpStr = parts[0], parts[0]
|
|
} else {
|
|
userStr, grpStr = parts[0], parts[1]
|
|
}
|
|
|
|
passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath)
|
|
if err != nil {
|
|
return idtools.Identity{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
|
|
}
|
|
groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath)
|
|
if err != nil {
|
|
return idtools.Identity{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
|
|
}
|
|
uid, err := lookupUser(userStr, passwdPath)
|
|
if err != nil {
|
|
return idtools.Identity{}, errors.Wrapf(err, "can't find uid for user "+userStr)
|
|
}
|
|
gid, err := lookupGroup(grpStr, groupPath)
|
|
if err != nil {
|
|
return idtools.Identity{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
|
|
}
|
|
|
|
// convert as necessary because of user namespaces
|
|
chownPair, err := identityMapping.ToHost(idtools.Identity{UID: uid, GID: gid})
|
|
if err != nil {
|
|
return idtools.Identity{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
|
|
}
|
|
return chownPair, nil
|
|
}
|
|
|
|
func lookupUser(userStr, filepath string) (int, error) {
|
|
// if the string is actually a uid integer, parse to int and return
|
|
// as we don't need to translate with the help of files
|
|
uid, err := strconv.Atoi(userStr)
|
|
if err == nil {
|
|
return uid, nil
|
|
}
|
|
users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool {
|
|
return u.Name == userStr
|
|
})
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if len(users) == 0 {
|
|
return 0, errors.New("no such user: " + userStr)
|
|
}
|
|
return users[0].Uid, nil
|
|
}
|
|
|
|
func lookupGroup(groupStr, filepath string) (int, error) {
|
|
// if the string is actually a gid integer, parse to int and return
|
|
// as we don't need to translate with the help of files
|
|
gid, err := strconv.Atoi(groupStr)
|
|
if err == nil {
|
|
return gid, nil
|
|
}
|
|
groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool {
|
|
return g.Name == groupStr
|
|
})
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if len(groups) == 0 {
|
|
return 0, errors.New("no such group: " + groupStr)
|
|
}
|
|
return groups[0].Gid, nil
|
|
}
|