mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-10-31 08:11:32 +01:00 
			
		
		
		
	Updates #5794 Change-Id: I7b05cd29ec02085cb503bbcd0beb61bf455002ac Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
		
			
				
	
	
		
			59 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			59 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) Tailscale Inc & AUTHORS
 | |
| // SPDX-License-Identifier: BSD-3-Clause
 | |
| 
 | |
| package osuser
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"os/exec"
 | |
| 	"os/user"
 | |
| 	"runtime"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	"tailscale.com/version/distro"
 | |
| )
 | |
| 
 | |
| // GetGroupIds returns the list of group IDs that the user is a member of, or
 | |
| // an error. It will first try to use the 'id' command to get the group IDs,
 | |
| // and if that fails, it will fall back to the user.GroupIds method.
 | |
| func GetGroupIds(user *user.User) ([]string, error) {
 | |
| 	if runtime.GOOS == "plan9" {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	if runtime.GOOS != "linux" {
 | |
| 		return user.GroupIds()
 | |
| 	}
 | |
| 
 | |
| 	if distro.Get() == distro.Gokrazy {
 | |
| 		// Gokrazy is a single-user appliance with ~no userspace.
 | |
| 		// There aren't users to look up (no /etc/passwd, etc)
 | |
| 		// so rather than fail below, just hardcode root.
 | |
| 		// TODO(bradfitz): fix os/user upstream instead?
 | |
| 		return []string{"0"}, nil
 | |
| 	}
 | |
| 
 | |
| 	if ids, err := getGroupIdsWithId(user.Username); err == nil {
 | |
| 		return ids, nil
 | |
| 	}
 | |
| 	return user.GroupIds()
 | |
| }
 | |
| 
 | |
| func getGroupIdsWithId(usernameOrUID string) ([]string, error) {
 | |
| 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | |
| 	defer cancel()
 | |
| 
 | |
| 	cmd := exec.CommandContext(ctx, "id", "-Gz", usernameOrUID)
 | |
| 	out, err := cmd.Output()
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("running 'id' command: %w", err)
 | |
| 	}
 | |
| 	return parseGroupIds(out), nil
 | |
| }
 | |
| 
 | |
| func parseGroupIds(cmdOutput []byte) []string {
 | |
| 	return strings.Split(strings.Trim(string(cmdOutput), "\n\x00"), "\x00")
 | |
| }
 |