7
securejoin "github.com/cyphar/filepath-securejoin"
8
"github.com/moby/sys/user"
9
"github.com/sirupsen/logrus"
13
etcpasswd = "/etc/passwd"
14
etcgroup = "/etc/group"
17
// Overrides allows you to override defaults in GetUserGroupInfo.
18
type Overrides struct {
19
DefaultUser *user.ExecUser
20
ContainerEtcPasswdPath string
21
ContainerEtcGroupPath string
24
// GetUserGroupInfo takes string forms of the container's mount path and the container user and
25
// returns an ExecUser with uid, gid, sgids, and home. And override can be provided for defaults.
26
func GetUserGroupInfo(containerMount, containerUser string, override *Overrides) (*user.ExecUser, error) {
28
passwdDest, groupDest string
29
defaultExecUser *user.ExecUser
34
// Check for an override /etc/passwd path
35
if override.ContainerEtcPasswdPath != "" {
36
passwdDest = override.ContainerEtcPasswdPath
38
// Check for an override for /etc/group path
39
if override.ContainerEtcGroupPath != "" {
40
groupDest = override.ContainerEtcGroupPath
45
// Make sure the /etc/passwd destination is not a symlink to something naughty
46
if passwdDest, err = securejoin.SecureJoin(containerMount, etcpasswd); err != nil {
52
// Make sure the /etc/group destination is not a symlink to something naughty
53
if groupDest, err = securejoin.SecureJoin(containerMount, etcgroup); err != nil {
59
// Check for an override default user
60
if override != nil && override.DefaultUser != nil {
61
defaultExecUser = override.DefaultUser
63
// Define a default container user
64
// defaultExecUser = &user.ExecUser{
71
return user.GetExecUserPath(containerUser, defaultExecUser, passwdDest, groupDest)
74
// GetContainerGroups uses securejoin to get a list of numerical groupids from a container. Per the runc
75
// function it calls: If a group name cannot be found, an error will be returned. If a group id cannot be found,
76
// or the given group data is nil, the id will be returned as-is provided it is in the legal range.
77
func GetContainerGroups(groups []string, containerMount string, override *Overrides) ([]uint32, error) {
84
if override != nil && override.ContainerEtcGroupPath != "" {
85
groupPath = override.ContainerEtcGroupPath
88
if groupDest, err = securejoin.SecureJoin(containerMount, groupPath); err != nil {
93
gids, err := user.GetAdditionalGroupsPath(groups, groupDest)
97
uintgids := make([]uint32, 0, len(gids))
98
// For libpod, we want []uint32s
99
for _, gid := range gids {
100
uintgids = append(uintgids, uint32(gid))
105
// GetUser takes a containermount path and user name or ID and returns
106
// a matching User structure from /etc/passwd. If it cannot locate a user
107
// with the provided information, an ErrNoPasswdEntries is returned.
108
// When the provided user name was an ID, a User structure with Uid
109
// set is returned along with ErrNoPasswdEntries.
110
func GetUser(containerMount, userIDorName string) (*user.User, error) {
112
uid, err := strconv.Atoi(userIDorName)
116
passwdDest, err := securejoin.SecureJoin(containerMount, etcpasswd)
120
users, err := user.ParsePasswdFileFilter(passwdDest, func(u user.User) bool {
122
return u.Name == userIDorName
126
if err != nil && !os.IsNotExist(err) {
130
return &users[0], nil
133
return &user.User{Uid: uid}, user.ErrNoPasswdEntries
135
return nil, user.ErrNoPasswdEntries
138
// GetGroup takes a containermount path and a group name or ID and returns
139
// a match Group struct from /etc/group. If it cannot locate a group,
140
// an ErrNoGroupEntries error is returned. When the provided group name
141
// was an ID, a Group structure with Gid set is returned along with
143
func GetGroup(containerMount, groupIDorName string) (*user.Group, error) {
145
gid, err := strconv.Atoi(groupIDorName)
150
groupDest, err := securejoin.SecureJoin(containerMount, etcgroup)
155
groups, err := user.ParseGroupFileFilter(groupDest, func(g user.Group) bool {
157
return g.Name == groupIDorName
161
if err != nil && !os.IsNotExist(err) {
165
return &groups[0], nil
168
return &user.Group{Gid: gid}, user.ErrNoGroupEntries
170
return nil, user.ErrNoGroupEntries