mirror of https://github.com/tailscale/tailscale/
ssh/tailssh: try fetching group IDs for user with the 'id' command
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: I9bdc938bd76c71bc130d44a97cc2233064d64799pull/11850/head
parent
9779eb6dba
commit
e985c6e58f
@ -0,0 +1,50 @@
|
||||
// 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
|
||||
}
|
Loading…
Reference in New Issue