Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor runAsUser into tablehelper package #1653

Merged
merged 10 commits into from
Mar 25, 2024
7 changes: 1 addition & 6 deletions ee/tables/homebrew/upgradeable.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,9 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
return results, fmt.Errorf("kolide_brew_upgradeable requires at least one user id to be specified")
}

cmd, err := allowedcmd.Brew(ctx, "outdated", "--json")
if err != nil {
return results, fmt.Errorf("creating brew outdated command: %w", err)
}

for _, uid := range uids {
for _, dataQuery := range tablehelpers.GetConstraints(queryContext, "query", tablehelpers.WithDefaults("*")) {
output, err := tablehelpers.RunCmdAsUser(cmd, uid)
output, err := tablehelpers.Exec(ctx, t.slogger, 30, allowedcmd.Brew, []string{"outdated", "--json"}, true, tablehelpers.WithUid(uid))
if err != nil {
t.slogger.Log(ctx, slog.LevelInfo, "failure querying user brew installed packages", "err", err, "target_uid", uid)
continue
Expand Down
8 changes: 2 additions & 6 deletions ee/tables/nix_env/upgradeable/upgradeable.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,10 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
return results, fmt.Errorf("kolide_nix_upgradeable requires at least one user id to be specified")
}

cmd, err := allowedcmd.NixEnv(ctx, "--query", "--installed", "-c", "--xml")
if err != nil {
return results, fmt.Errorf("creating nix-env package query command: %w", err)
}

for _, uid := range uids {
for _, dataQuery := range tablehelpers.GetConstraints(queryContext, "query", tablehelpers.WithDefaults("*")) {
output, err := tablehelpers.RunCmdAsUser(cmd, uid)
// Nix takes a while to load, so leaving a minute timeout here to give enough time. More might be needed.
output, err := tablehelpers.Exec(ctx, t.slogger, 60, allowedcmd.NixEnv, []string{"--query", "--installed", "-c", "--xml"}, true, tablehelpers.WithUid(uid))
if err != nil {
t.slogger.Log(ctx, slog.LevelInfo, "failure querying user installed packages", "err", err, "target_uid", uid)
continue
Expand Down
51 changes: 50 additions & 1 deletion ee/tables/tablehelpers/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,57 @@
"fmt"
"log/slog"
"os"
"os/exec"
"os/user"
"path/filepath"
"strconv"
"syscall"
"time"

"github.com/kolide/launcher/ee/allowedcmd"
"github.com/kolide/launcher/pkg/traces"
"go.opentelemetry.io/otel/attribute"
)

type execOps func(*exec.Cmd) error

func WithUid(uid string) execOps {
return func(cmd *exec.Cmd) error {
currentUser, err := user.Current()
if err != nil {
return fmt.Errorf("getting current user: %w", err)
}

runningUser, err := user.LookupId(uid)
if err != nil {
return fmt.Errorf("looking up user with uid %s: %w", uid, err)
}

if currentUser.Uid != "0" && currentUser.Uid != runningUser.Uid {
return fmt.Errorf("current user %s is not root and can't start process for other user %s", currentUser.Uid, uid)
}

runningUserUid, err := strconv.ParseUint(runningUser.Uid, 10, 32)
if err != nil {
return fmt.Errorf("converting uid %s to int: %w", runningUser.Uid, err)
}

runningUserGid, err := strconv.ParseUint(runningUser.Gid, 10, 32)
if err != nil {
return fmt.Errorf("converting gid %s to int: %w", runningUser.Gid, err)
}

cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{

Check failure on line 50 in ee/tables/tablehelpers/exec.go

View workflow job for this annotation

GitHub Actions / govulncheck (windows-latest)

undefined: syscall.Credential

Check failure on line 50 in ee/tables/tablehelpers/exec.go

View workflow job for this annotation

GitHub Actions / govulncheck (windows-latest)

unknown field Credential in struct literal of type syscall.SysProcAttr

Check failure on line 50 in ee/tables/tablehelpers/exec.go

View workflow job for this annotation

GitHub Actions / launcher (windows-latest)

unknown field Credential in struct literal of type syscall.SysProcAttr

Check failure on line 50 in ee/tables/tablehelpers/exec.go

View workflow job for this annotation

GitHub Actions / launcher (windows-latest)

undefined: syscall.Credential

Check failure on line 50 in ee/tables/tablehelpers/exec.go

View workflow job for this annotation

GitHub Actions / launcher (windows-latest)

unknown field Credential in struct literal of type syscall.SysProcAttr

Check failure on line 50 in ee/tables/tablehelpers/exec.go

View workflow job for this annotation

GitHub Actions / launcher (windows-latest)

undefined: syscall.Credential
Micah-Kolide marked this conversation as resolved.
Show resolved Hide resolved
Uid: uint32(runningUserUid),
Gid: uint32(runningUserGid),
},
}

return nil
}
}

// Exec is a wrapper over exec.CommandContext. It does a couple of
// additional things to help with table usage:
// 1. It enforces a timeout.
Expand All @@ -26,7 +69,7 @@
// `possibleBins` can be either a list of command names, or a list of paths to commands.
// Where reasonable, `possibleBins` should be command names only, so that we can perform
// lookup against PATH.
func Exec(ctx context.Context, slogger *slog.Logger, timeoutSeconds int, execCmd allowedcmd.AllowedCommand, args []string, includeStderr bool) ([]byte, error) {
func Exec(ctx context.Context, slogger *slog.Logger, timeoutSeconds int, execCmd allowedcmd.AllowedCommand, args []string, includeStderr bool, opts ...execOps) ([]byte, error) {
ctx, span := traces.StartSpan(ctx)
defer span.End()

Expand All @@ -41,6 +84,12 @@
return nil, fmt.Errorf("creating command: %w", err)
}

for _, opt := range opts {
if err := opt(cmd); err != nil {
return nil, err
}
}

span.SetAttributes(attribute.String("exec.path", cmd.Path))
span.SetAttributes(attribute.String("exec.binary", filepath.Base(cmd.Path)))
span.SetAttributes(attribute.StringSlice("exec.args", args))
Expand Down
66 changes: 0 additions & 66 deletions ee/tables/tablehelpers/run_cmd_as_user_posix.go

This file was deleted.

Loading