Skip to content

Commit 78e61af

Browse files
committed
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 <[email protected]>
1 parent 1597270 commit 78e61af

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

oci/spec_opts.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,66 @@ func WithUsername(username string) SpecOpts {
634634
}
635635
}
636636

637+
// WithAdditionalGIDs sets the OCI spec's additionalGids array to any additional groups listed
638+
// for a particular user in the /etc/groups file of the image's root filesystem
639+
func WithAdditionalGIDs(username string) SpecOpts {
640+
return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) {
641+
setProcess(s)
642+
if c.Snapshotter == "" && c.SnapshotKey == "" {
643+
if !isRootfsAbs(s.Root.Path) {
644+
return errors.Errorf("rootfs absolute path is required")
645+
}
646+
gids, err := getSupplementalGroupsFromPath(s.Root.Path, func(g user.Group) bool {
647+
// we only want supplemental groups
648+
if g.Name == username {
649+
return false
650+
}
651+
for _, entry := range g.List {
652+
if entry == username {
653+
return true
654+
}
655+
}
656+
return false
657+
})
658+
if err != nil {
659+
return err
660+
}
661+
s.Process.User.AdditionalGids = gids
662+
return nil
663+
}
664+
if c.Snapshotter == "" {
665+
return errors.Errorf("no snapshotter set for container")
666+
}
667+
if c.SnapshotKey == "" {
668+
return errors.Errorf("rootfs snapshot not created for container")
669+
}
670+
snapshotter := client.SnapshotService(c.Snapshotter)
671+
mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey)
672+
if err != nil {
673+
return err
674+
}
675+
return mount.WithTempMount(ctx, mounts, func(root string) error {
676+
gids, err := getSupplementalGroupsFromPath(root, func(g user.Group) bool {
677+
// we only want supplemental groups
678+
if g.Name == username {
679+
return false
680+
}
681+
for _, entry := range g.List {
682+
if entry == username {
683+
return true
684+
}
685+
}
686+
return false
687+
})
688+
if err != nil {
689+
return err
690+
}
691+
s.Process.User.AdditionalGids = gids
692+
return nil
693+
})
694+
}
695+
}
696+
637697
// WithCapabilities sets Linux capabilities on the process
638698
func WithCapabilities(caps []string) SpecOpts {
639699
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
715775
return uint32(g.Gid), nil
716776
}
717777

778+
func getSupplementalGroupsFromPath(root string, filter func(user.Group) bool) ([]uint32, error) {
779+
gpath, err := fs.RootPath(root, "/etc/group")
780+
if err != nil {
781+
return []uint32{}, err
782+
}
783+
groups, err := user.ParseGroupFileFilter(gpath, filter)
784+
if err != nil {
785+
return []uint32{}, err
786+
}
787+
if len(groups) == 0 {
788+
// if there are no additional groups; just return an empty set
789+
return []uint32{}, nil
790+
}
791+
addlGids := []uint32{}
792+
for _, grp := range groups {
793+
addlGids = append(addlGids, uint32(grp.Gid))
794+
}
795+
return addlGids, nil
796+
}
797+
718798
func isRootfsAbs(root string) bool {
719799
return filepath.IsAbs(root)
720800
}

0 commit comments

Comments
 (0)