mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-27 03:55:36 +00:00
e985c6e58f
Since the tailscaled binaries that we distribute are static and don't link cgo, we previously wouldn't fetch group IDs that are returned via NSS. Try shelling out to the 'id' command, similar to how we call 'getent', to detect such cases. Updates #11682 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: I9bdc938bd76c71bc130d44a97cc2233064d64799
51 lines
1.3 KiB
Go
51 lines
1.3 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 != "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 strings.Split(string(out), "\x00"), nil
|
|
}
|