@@ -875,6 +875,63 @@ func WithAdditionalGIDs(userstr string) SpecOpts {
875875 }
876876}
877877
878+ // WithAppendAdditionalGroups append additional groups within the container.
879+ // The passed in groups can be either a gid or a groupname.
880+ func WithAppendAdditionalGroups (groups ... string ) SpecOpts {
881+ return func (ctx context.Context , client Client , c * containers.Container , s * Spec ) (err error ) {
882+ // For LCOW or on Darwin additional GID's are not supported
883+ if s .Windows != nil || runtime .GOOS == "darwin" {
884+ return nil
885+ }
886+ setProcess (s )
887+ setAdditionalGids := func (root string ) error {
888+ gpath , err := fs .RootPath (root , "/etc/group" )
889+ if err != nil {
890+ return err
891+ }
892+ ugroups , err := user .ParseGroupFile (gpath )
893+ if err != nil {
894+ return err
895+ }
896+ groupMap := make (map [string ]user.Group )
897+ for _ , group := range ugroups {
898+ groupMap [group .Name ] = group
899+ groupMap [strconv .Itoa (group .Gid )] = group
900+ }
901+ var gids []uint32
902+ for _ , group := range groups {
903+ g , ok := groupMap [group ]
904+ if ! ok {
905+ return fmt .Errorf ("unable to find group %s" , group )
906+ }
907+ gids = append (gids , uint32 (g .Gid ))
908+ }
909+ s .Process .User .AdditionalGids = append (s .Process .User .AdditionalGids , gids ... )
910+ return nil
911+ }
912+ if c .Snapshotter == "" && c .SnapshotKey == "" {
913+ if ! filepath .IsAbs (s .Root .Path ) {
914+ return errors .New ("rootfs absolute path is required" )
915+ }
916+ return setAdditionalGids (s .Root .Path )
917+ }
918+ if c .Snapshotter == "" {
919+ return errors .New ("no snapshotter set for container" )
920+ }
921+ if c .SnapshotKey == "" {
922+ return errors .New ("rootfs snapshot not created for container" )
923+ }
924+ snapshotter := client .SnapshotService (c .Snapshotter )
925+ mounts , err := snapshotter .Mounts (ctx , c .SnapshotKey )
926+ if err != nil {
927+ return err
928+ }
929+
930+ mounts = tryReadonlyMounts (mounts )
931+ return mount .WithTempMount (ctx , mounts , setAdditionalGids )
932+ }
933+ }
934+
878935// WithCapabilities sets Linux capabilities on the process
879936func WithCapabilities (caps []string ) SpecOpts {
880937 return func (_ context.Context , _ Client , _ * containers.Container , s * Spec ) error {
@@ -979,7 +1036,7 @@ func UserFromPath(root string, filter func(user.User) bool) (user.User, error) {
9791036// ErrNoGroupsFound can be returned from GIDFromPath
9801037var ErrNoGroupsFound = errors .New ("no groups found" )
9811038
982- // GIDFromPath inspects the GID using /etc/passwd in the specified rootfs.
1039+ // GIDFromPath inspects the GID using /etc/group in the specified rootfs.
9831040// filter can be nil.
9841041func GIDFromPath (root string , filter func (user.Group ) bool ) (gid uint32 , err error ) {
9851042 gpath , err := fs .RootPath (root , "/etc/group" )
0 commit comments