Skip to content

Commit

Permalink
exposes table desktop process info in checkpoint and in kolide_deskto…
Browse files Browse the repository at this point in the history
…p_procs table (#1240)

* exposes table desktop process info in checkpoint and in kolide_desktop_procs table
* bump scutil timeout for determining console users for desktop process
  • Loading branch information
James-Pickett authored Jun 30, 2023
1 parent 145d28e commit fa27bbf
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 15 deletions.
49 changes: 36 additions & 13 deletions ee/desktop/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,23 @@ func WithUsersFilesRoot(usersFilesRoot string) desktopUsersProcessesRunnerOption
}
}

var instance *DesktopUsersProcessesRunner
var instanceSet = &sync.Once{}

func setInstance(r *DesktopUsersProcessesRunner) {
instanceSet.Do(func() {
instance = r
})
}

func InstanceDesktopProcessRecords() map[string]processRecord {
if instance == nil {
return nil
}

return instance.uidProcs
}

// DesktopUsersProcessesRunner creates a launcher desktop process each time it detects
// a new console (GUI) user. If the current console user's desktop process dies, it
// will create a new one.
Expand Down Expand Up @@ -119,9 +136,10 @@ type DesktopUsersProcessesRunner struct {
// If, for example, a user logs out, the process record will remain until the
// user logs in again and it is replaced.
type processRecord struct {
process *os.Process
path string
socketPath string
Process *os.Process
StartTime, LastHealthCheck time.Time
path string
socketPath string
}

// New creates and returns a new DesktopUsersProcessesRunner runner and initializes all required fields
Expand Down Expand Up @@ -166,6 +184,7 @@ func New(k types.Knapsack, opts ...desktopUsersProcessesRunnerOption) (*DesktopU
}
}()

setInstance(runner)
return runner, nil
}

Expand Down Expand Up @@ -239,7 +258,7 @@ func (r *DesktopUsersProcessesRunner) killDesktopProcesses() {
level.Error(r.logger).Log(
"msg", "error sending shutdown command to user desktop process",
"uid", uid,
"pid", proc.process.Pid,
"pid", proc.Process.Pid,
"path", proc.path,
"err", err,
)
Expand All @@ -265,11 +284,11 @@ func (r *DesktopUsersProcessesRunner) killDesktopProcesses() {
if !r.processExists(processRecord) {
continue
}
if err := processRecord.process.Kill(); err != nil {
if err := processRecord.Process.Kill(); err != nil {
level.Error(r.logger).Log(
"msg", "error killing desktop process",
"uid", uid,
"pid", processRecord.process.Pid,
"pid", processRecord.Process.Pid,
"path", processRecord.path,
"err", err,
)
Expand Down Expand Up @@ -368,7 +387,7 @@ func (r *DesktopUsersProcessesRunner) refreshMenu() {
level.Error(r.logger).Log(
"msg", "error sending refresh command to desktop process",
"uid", uid,
"pid", proc.process.Pid,
"pid", proc.Process.Pid,
"path", proc.path,
"err", err,
)
Expand Down Expand Up @@ -445,7 +464,7 @@ func (r *DesktopUsersProcessesRunner) runConsoleUserDesktop() error {
return fmt.Errorf("determining executable path: %w", err)
}

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

consoleUsers, err := consoleuser.CurrentUids(ctx)
Expand Down Expand Up @@ -527,7 +546,8 @@ func (r *DesktopUsersProcessesRunner) addProcessTrackingRecordForUser(uid string
}

r.uidProcs[uid] = processRecord{
process: osProcess,
Process: osProcess,
StartTime: time.Now().UTC(),
path: path,
socketPath: socketPath,
}
Expand Down Expand Up @@ -583,14 +603,17 @@ func (r *DesktopUsersProcessesRunner) userHasDesktopProcess(uid string) bool {
if !r.processExists(proc) {
level.Info(r.logger).Log(
"msg", "found existing desktop process dead for console user",
"pid", r.uidProcs[uid].process.Pid,
"pid", r.uidProcs[uid].Process.Pid,
"process_path", r.uidProcs[uid].path,
"uid", uid,
)

return false
}

proc.LastHealthCheck = time.Now().UTC()
r.uidProcs[uid] = proc

// have running process
return true
}
Expand All @@ -600,11 +623,11 @@ func (r *DesktopUsersProcessesRunner) processExists(processRecord processRecord)
defer cancel()

// the call to process.NewProcessWithContext ensures process exists
proc, err := process.NewProcessWithContext(ctx, int32(processRecord.process.Pid))
proc, err := process.NewProcessWithContext(ctx, int32(processRecord.Process.Pid))
if err != nil {
level.Info(r.logger).Log(
"msg", "looking up existing desktop process",
"pid", processRecord.process.Pid,
"pid", processRecord.Process.Pid,
"process_path", processRecord.path,
"err", err,
)
Expand All @@ -615,7 +638,7 @@ func (r *DesktopUsersProcessesRunner) processExists(processRecord processRecord)
if err != nil || path != processRecord.path {
level.Info(r.logger).Log(
"msg", "error or path mismatch checking existing desktop process path",
"pid", processRecord.process.Pid,
"pid", processRecord.Process.Pid,
"process_record_path", processRecord.path,
"err", err,
"found_path", path,
Expand Down
4 changes: 2 additions & 2 deletions ee/desktop/runner/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func TestDesktopUserProcessRunner_Execute(t *testing.T) {
user, err := user.Current()
require.NoError(t, err)
r.uidProcs[user.Uid] = processRecord{
process: &os.Process{},
Process: &os.Process{},
path: "test",
}
},
Expand Down Expand Up @@ -176,7 +176,7 @@ func TestDesktopUserProcessRunner_Execute(t *testing.T) {
// intentionally ignoring the error here
// CI will intermittently fail with "wait: no child processes" due runner.go also calling process.Wait()
// racing with this code to remove the child process
p.process.Wait()
p.Process.Wait()
}
})
})
Expand Down
6 changes: 6 additions & 0 deletions pkg/log/checkpoint/checkpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/go-kit/kit/log"
"github.com/kolide/kit/version"
"github.com/kolide/launcher/ee/desktop/runner"
"github.com/kolide/launcher/pkg/agent"
"github.com/kolide/launcher/pkg/agent/types"
)
Expand Down Expand Up @@ -107,6 +108,11 @@ func (c *checkPointer) logCheckPoint() {
c.logger.Log("notary versions", notaryVersions)
}
c.logServerProvidedData()
c.logDesktopProcs()
}

func (c *checkPointer) logDesktopProcs() {
c.logger.Log("user_desktop_processes", runner.InstanceDesktopProcessRecords())
}

func (c *checkPointer) logDbSize() {
Expand Down
2 changes: 2 additions & 0 deletions pkg/osquery/table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/kolide/launcher/pkg/agent/types"
"github.com/kolide/launcher/pkg/osquery/tables/cryptoinfotable"
"github.com/kolide/launcher/pkg/osquery/tables/dataflattentable"
"github.com/kolide/launcher/pkg/osquery/tables/desktopprocs"
"github.com/kolide/launcher/pkg/osquery/tables/dev_table_tooling"
"github.com/kolide/launcher/pkg/osquery/tables/firefox_preferences"
"github.com/kolide/launcher/pkg/osquery/tables/launcher_db"
Expand All @@ -29,6 +30,7 @@ func LauncherTables(k types.Knapsack) []osquery.OsqueryPlugin {
osquery_instance_history.TablePlugin(),
tufinfo.TufReleaseVersionTable(k),
launcher_db.TablePlugin("kolide_tuf_autoupdater_errors", k.AutoupdateErrorsStore()),
desktopprocs.TablePlugin(),
}
}

Expand Down
36 changes: 36 additions & 0 deletions pkg/osquery/tables/desktopprocs/desktopprocs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package desktopprocs

import (
"context"
"fmt"

"github.com/kolide/launcher/ee/desktop/runner"
"github.com/osquery/osquery-go/plugin/table"
)

func TablePlugin() *table.Plugin {
columns := []table.ColumnDefinition{
table.TextColumn("uid"),
table.TextColumn("pid"),
table.TextColumn("start_time"),
table.TextColumn("last_health_check"),
}
return table.NewPlugin("kolide_desktop_procs", columns, generate())
}

func generate() table.GenerateFunc {
return func(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
results := []map[string]string{}

for k, v := range runner.InstanceDesktopProcessRecords() {
results = append(results, map[string]string{
"uid": k,
"pid": fmt.Sprint(v.Process.Pid),
"start_time": fmt.Sprint(v.StartTime),
"last_health_check": fmt.Sprint(v.LastHealthCheck),
})
}

return results, nil
}
}

0 comments on commit fa27bbf

Please sign in to comment.