Add With-helper for supplemental gid support

Can be used to conform to Docker engine behavior of adding additional
GIDs to spec when found in /etc/group of image filesystem

Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com>
This commit is contained in:
Phil Estes 2018-09-10 15:34:25 -04:00
parent 1597270d04
commit 78e61af47a
No known key found for this signature in database
GPG Key ID: 0F386284C03A1162

View File

@ -634,6 +634,66 @@ func WithUsername(username string) SpecOpts {
} }
} }
// WithAdditionalGIDs sets the OCI spec's additionalGids array to any additional groups listed
// for a particular user in the /etc/groups file of the image's root filesystem
func WithAdditionalGIDs(username string) SpecOpts {
return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) {
setProcess(s)
if c.Snapshotter == "" && c.SnapshotKey == "" {
if !isRootfsAbs(s.Root.Path) {
return errors.Errorf("rootfs absolute path is required")
}
gids, err := getSupplementalGroupsFromPath(s.Root.Path, func(g user.Group) bool {
// we only want supplemental groups
if g.Name == username {
return false
}
for _, entry := range g.List {
if entry == username {
return true
}
}
return false
})
if err != nil {
return err
}
s.Process.User.AdditionalGids = gids
return nil
}
if c.Snapshotter == "" {
return errors.Errorf("no snapshotter set for container")
}
if c.SnapshotKey == "" {
return errors.Errorf("rootfs snapshot not created for container")
}
snapshotter := client.SnapshotService(c.Snapshotter)
mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey)
if err != nil {
return err
}
return mount.WithTempMount(ctx, mounts, func(root string) error {
gids, err := getSupplementalGroupsFromPath(root, func(g user.Group) bool {
// we only want supplemental groups
if g.Name == username {
return false
}
for _, entry := range g.List {
if entry == username {
return true
}
}
return false
})
if err != nil {
return err
}
s.Process.User.AdditionalGids = gids
return nil
})
}
}
// WithCapabilities sets Linux capabilities on the process // WithCapabilities sets Linux capabilities on the process
func WithCapabilities(caps []string) SpecOpts { func WithCapabilities(caps []string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
@ -715,6 +775,26 @@ func getGIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err
return uint32(g.Gid), nil return uint32(g.Gid), nil
} }
func getSupplementalGroupsFromPath(root string, filter func(user.Group) bool) ([]uint32, error) {
gpath, err := fs.RootPath(root, "/etc/group")
if err != nil {
return []uint32{}, err
}
groups, err := user.ParseGroupFileFilter(gpath, filter)
if err != nil {
return []uint32{}, err
}
if len(groups) == 0 {
// if there are no additional groups; just return an empty set
return []uint32{}, nil
}
addlGids := []uint32{}
for _, grp := range groups {
addlGids = append(addlGids, uint32(grp.Gid))
}
return addlGids, nil
}
func isRootfsAbs(root string) bool { func isRootfsAbs(root string) bool {
return filepath.IsAbs(root) return filepath.IsAbs(root)
} }