Skip to content

Commit 19735b5

Browse files
committed
Add With-helper for supplemental gid support
[Backported to release/1.1] 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 <[email protected]>
1 parent db009b3 commit 19735b5

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

oci/spec_opts_unix.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,66 @@ func WithUsername(username string) SpecOpts {
443443
}
444444
}
445445

446+
// WithAdditionalGIDs sets the OCI spec's additionalGids array to any additional groups listed
447+
// for a particular user in the /etc/groups file of the image's root filesystem
448+
func WithAdditionalGIDs(username string) SpecOpts {
449+
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) {
450+
setProcess(s)
451+
if c.Snapshotter == "" && c.SnapshotKey == "" {
452+
if !isRootfsAbs(s.Root.Path) {
453+
return errors.Errorf("rootfs absolute path is required")
454+
}
455+
gids, err := getSupplementalGroupsFromPath(s.Root.Path, func(g user.Group) bool {
456+
// we only want supplemental groups
457+
if g.Name == username {
458+
return false
459+
}
460+
for _, entry := range g.List {
461+
if entry == username {
462+
return true
463+
}
464+
}
465+
return false
466+
})
467+
if err != nil {
468+
return err
469+
}
470+
s.Process.User.AdditionalGids = gids
471+
return nil
472+
}
473+
if c.Snapshotter == "" {
474+
return errors.Errorf("no snapshotter set for container")
475+
}
476+
if c.SnapshotKey == "" {
477+
return errors.Errorf("rootfs snapshot not created for container")
478+
}
479+
snapshotter := client.SnapshotService(c.Snapshotter)
480+
mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey)
481+
if err != nil {
482+
return err
483+
}
484+
return mount.WithTempMount(ctx, mounts, func(root string) error {
485+
gids, err := getSupplementalGroupsFromPath(root, func(g user.Group) bool {
486+
// we only want supplemental groups
487+
if g.Name == username {
488+
return false
489+
}
490+
for _, entry := range g.List {
491+
if entry == username {
492+
return true
493+
}
494+
}
495+
return false
496+
})
497+
if err != nil {
498+
return err
499+
}
500+
s.Process.User.AdditionalGids = gids
501+
return nil
502+
})
503+
}
504+
}
505+
446506
// WithCapabilities sets Linux capabilities on the process
447507
func WithCapabilities(caps []string) SpecOpts {
448508
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
@@ -512,6 +572,26 @@ func getGIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err
512572
return uint32(g.Gid), nil
513573
}
514574

575+
func getSupplementalGroupsFromPath(root string, filter func(user.Group) bool) ([]uint32, error) {
576+
gpath, err := fs.RootPath(root, "/etc/group")
577+
if err != nil {
578+
return []uint32{}, err
579+
}
580+
groups, err := user.ParseGroupFileFilter(gpath, filter)
581+
if err != nil {
582+
return []uint32{}, err
583+
}
584+
if len(groups) == 0 {
585+
// if there are no additional groups; just return an empty set
586+
return []uint32{}, nil
587+
}
588+
addlGids := []uint32{}
589+
for _, grp := range groups {
590+
addlGids = append(addlGids, uint32(grp.Gid))
591+
}
592+
return addlGids, nil
593+
}
594+
515595
func isRootfsAbs(root string) bool {
516596
return filepath.IsAbs(root)
517597
}

0 commit comments

Comments
 (0)