Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into becca/windows-hello
Browse files Browse the repository at this point in the history
  • Loading branch information
RebeccaMahany committed Sep 23, 2024
2 parents 4a8e67b + fb6d91a commit c6ad847
Show file tree
Hide file tree
Showing 23 changed files with 321 additions and 33 deletions.
3 changes: 2 additions & 1 deletion cmd/launcher/desktop.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ func runDesktop(_ *multislogger.MultiSlogger, args []string) error {
)
}

runGroup := rungroup.NewRunGroup(slogger)
runGroup := rungroup.NewRunGroup()
runGroup.SetSlogger(slogger)

// listen for signals
runGroup.Add("desktopSignalListener", func() error {
Expand Down
6 changes: 5 additions & 1 deletion cmd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func runLauncher(ctx context.Context, cancel func(), multiSlogger, systemMultiSl
}

// create a rungroup for all the actors we create to allow for easy start/stop
runGroup := rungroup.NewRunGroup(slogger)
runGroup := rungroup.NewRunGroup()

// Need to set up the log shipper so that we can get the logger early
// and pass it to the various systems.
Expand Down Expand Up @@ -246,6 +246,10 @@ func runLauncher(ctx context.Context, cancel func(), multiSlogger, systemMultiSl
startupSpan.AddEvent("log_shipper_init_completed")
}

// Now that log shipping is set up, set the slogger on the rungroup so that rungroup logs
// will also be shipped.
runGroup.SetSlogger(k.Slogger())

startupSettingsWriter, err := startupsettings.OpenWriter(ctx, k)
if err != nil {
return fmt.Errorf("creating startup db: %w", err)
Expand Down
12 changes: 12 additions & 0 deletions ee/agent/flags/flag_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -657,3 +657,15 @@ func (fc *FlagController) LocalDevelopmentPath() string {
WithDefaultString(fc.cmdLineOpts.LocalDevelopmentPath),
).get(nil)
}

func (fc *FlagController) Identifier() string {
identifier := NewStringFlagValue(
WithDefaultString(fc.cmdLineOpts.Identifier),
).get(nil)

if strings.TrimSpace(identifier) == "" {
identifier = launcher.DefaultLauncherIdentifier
}

return identifier
}
13 changes: 12 additions & 1 deletion ee/agent/timemachine/timemachine_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,17 @@ func AddExclusions(ctx context.Context, k types.Knapsack) {
launcher.pid
*/

exclusionPatterns := []string{
exclusionPatternsFirstBatch := []string{
"*.json",
"*.json.gz",
"*.db",
}

addExclusionsFromPathPatterns(ctx, k, exclusionPatternsFirstBatch)

// Attempting to run this with a single tmutil call we see a lot of tmutil failures logged with error "argument list too long".
// To avoid this we run in two separate batches, attempting to cut the post-glob argument list roughly in half
exclusionPatternsSecondBatch := []string{
"*.sqlite",
"desktop_*",
"*.pid",
Expand All @@ -45,6 +52,10 @@ func AddExclusions(ctx context.Context, k types.Knapsack) {
"osquery*",
}

addExclusionsFromPathPatterns(ctx, k, exclusionPatternsSecondBatch)
}

func addExclusionsFromPathPatterns(ctx context.Context, k types.Knapsack, exclusionPatterns []string) {
var exclusionPaths []string
for _, pattern := range exclusionPatterns {
matches, err := filepath.Glob(filepath.Join(k.RootDirectory(), pattern))
Expand Down
3 changes: 3 additions & 0 deletions ee/agent/types/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,7 @@ type Flags interface {
// SystrayRestartEnabled controls whether launcher's desktop runner will restart systray on error
SetSystrayRestartEnabled(enabled bool) error
SystrayRestartEnabled() bool

// Identifier is the package build identifier used to namespace our paths and service names
Identifier() string
}
20 changes: 19 additions & 1 deletion ee/agent/types/mocks/flags.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion ee/agent/types/mocks/knapsack.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions ee/allowedcmd/cmd_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ func Brew(ctx context.Context, arg ...string) (*exec.Cmd, error) {
return validatedCmd, nil
}

func Coredumpctl(ctx context.Context, arg ...string) (*exec.Cmd, error) {
return validatedCommand(ctx, "/usr/bin/coredumpctl", arg...)
}

func Cryptsetup(ctx context.Context, arg ...string) (*exec.Cmd, error) {
for _, p := range []string{"/usr/sbin/cryptsetup", "/sbin/cryptsetup"} {
validatedCmd, err := validatedCommand(ctx, p, arg...)
Expand Down
1 change: 1 addition & 0 deletions ee/debug/checkups/checkups.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ func checkupsFor(k types.Knapsack, target targetBits) []checkupInt {
{&osqRestartCheckup{k: k}, doctorSupported | flareSupported},
{&uninstallHistoryCheckup{k: k}, flareSupported},
{&desktopMenu{k: k}, flareSupported},
{&coredumpCheckup{}, doctorSupported | flareSupported},
}

checkupsToRun := make([]checkupInt, 0)
Expand Down
144 changes: 144 additions & 0 deletions ee/debug/checkups/coredump_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//go:build linux
// +build linux

package checkups

import (
"archive/zip"
"context"
"fmt"
"io"
"os"
"path/filepath"
"strings"

"github.com/kolide/launcher/ee/agent"
"github.com/kolide/launcher/ee/allowedcmd"
)

type coredumpCheckup struct {
status Status
summary string
data map[string]any
}

func (c *coredumpCheckup) Name() string {
return "Coredump Report"
}

func (c *coredumpCheckup) Run(ctx context.Context, extraWriter io.Writer) error {
c.data = make(map[string]any)

c.status = Passing
for _, binaryName := range []string{"launcher", "osqueryd"} {
coredumpListRaw, err := c.coredumpList(ctx, binaryName)
if err != nil {
c.summary += fmt.Sprintf("could not get coredump data for %s; ", binaryName)
c.data[binaryName] = fmt.Sprintf("listing coredumps: %v", err)
continue
}

if coredumpListRaw == nil {
c.summary += fmt.Sprintf("%s does not have any coredumps; ", binaryName)
c.data[binaryName] = "N/A"
continue
}

// At least one coredump exists for at least one binary
c.status = Warning
c.summary += fmt.Sprintf("%s has at least one coredump; ", binaryName)
c.data[binaryName] = strings.TrimSpace(string(coredumpListRaw))
}
c.summary = strings.TrimSuffix(strings.TrimSpace(c.summary), ";")

if extraWriter == io.Discard || c.status == Passing {
// Either not a flare, or we don't have any coredumps to grab info about
return nil
}

// Gather extra information about the coredumps
extraZip := zip.NewWriter(extraWriter)
defer extraZip.Close()
for _, binaryName := range []string{"launcher", "osqueryd"} {
if c.data[binaryName] == "N/A" {
continue
}
if err := c.writeCoredumpInfo(ctx, binaryName, extraZip); err != nil {
fmt.Fprintf(extraWriter, "Writing coredump info for %s: %v", binaryName, err)
}
}

return nil
}

func (c *coredumpCheckup) coredumpList(ctx context.Context, binaryName string) ([]byte, error) {
coredumpctlListCmd, err := allowedcmd.Coredumpctl(ctx, "--no-pager", "--no-legend", "--json=short", "list", binaryName)
if err != nil {
return nil, fmt.Errorf("could not create coredumpctl command: %w", err)
}

out, err := coredumpctlListCmd.CombinedOutput()
if strings.Contains(string(out), "No coredumps found") {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("running coredumpctl list %s: out `%s`; %w", binaryName, string(out), err)
}

return out, nil
}

func (c *coredumpCheckup) writeCoredumpInfo(ctx context.Context, binaryName string, z *zip.Writer) error {
// Print info about all matching coredumps
coredumpctlInfoCmd, err := allowedcmd.Coredumpctl(ctx, "--no-pager", "info", binaryName)
if err != nil {
return fmt.Errorf("could not create coredumpctl info command: %w", err)
}
infoOut, err := coredumpctlInfoCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("running coredumpctl info %s: out `%s`; %w", binaryName, string(infoOut), err)
}
coredumpctlInfoFile, err := z.Create(filepath.Join(".", fmt.Sprintf("coredumpctl-info-%s.txt", binaryName)))
if err != nil {
return fmt.Errorf("creating coredumpctl-info.txt for %s in zip: %w", binaryName, err)
}
if _, err := coredumpctlInfoFile.Write(infoOut); err != nil {
return fmt.Errorf("writing coredumpctl-info.txt in %s zip: %w", binaryName, err)
}

// Now, try to get a coredump -- this will grab the most recent one
tempDir, err := agent.MkdirTemp("coredump-flare")
if err != nil {
return fmt.Errorf("making temporary directory for coredump from %s: %w", binaryName, err)
}
defer os.RemoveAll(tempDir)
tempDumpFile := filepath.Join(tempDir, fmt.Sprintf("coredump-%s.dump", binaryName))
coredumpctlDumpCmd, err := allowedcmd.Coredumpctl(ctx, "--no-pager", fmt.Sprintf("--output=%s", tempDumpFile), "dump", binaryName)
if err != nil {
return fmt.Errorf("could not create coredumpctl dump command: %w", err)
}
if err := coredumpctlDumpCmd.Run(); err != nil {
return fmt.Errorf("running coredumpctl dump %s: %w", binaryName, err)
}
if err := addFileToZip(z, tempDumpFile); err != nil {
return fmt.Errorf("adding coredumpctl dump %s output file to zip: %w", binaryName, err)
}

return nil
}

func (c *coredumpCheckup) ExtraFileName() string {
return "coredumps.zip"
}

func (c *coredumpCheckup) Status() Status {
return c.status
}

func (c *coredumpCheckup) Summary() string {
return c.summary
}

func (c *coredumpCheckup) Data() any {
return c.data
}
36 changes: 36 additions & 0 deletions ee/debug/checkups/coredump_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//go:build !linux
// +build !linux

package checkups

import (
"context"
"io"
)

type coredumpCheckup struct {
}

func (c *coredumpCheckup) Name() string {
return ""
}

func (c *coredumpCheckup) ExtraFileName() string {
return ""
}

func (c *coredumpCheckup) Run(_ context.Context, _ io.Writer) error {
return nil
}

func (c *coredumpCheckup) Status() Status {
return Informational
}

func (c *coredumpCheckup) Summary() string {
return ""
}

func (c *coredumpCheckup) Data() any {
return nil
}
10 changes: 10 additions & 0 deletions ee/secureenclavesigner/secureenclavesigner_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ func (ses *secureEnclaveSigner) Public() crypto.PublicKey {
return nil
}

// currentConsoleUserKey may return no error and a nil pointer where the inability
// to get the key is expected (see logic around calling firstConsoleUser). In this case,
// k will be a "typed" nil, as an uninitialized pointer to a ecdsa.PublicKey. We're returning
// this typed nil assigned as the crypto.PublicKey interface. This means that the interface's value
// will be nil, but it's underlying type will not be - so it will pass nil checks but panic
// when typecasted later. Explicitly return an untyped nil in this case to prevent confusion and panics later
if k == nil {
return nil
}

return k
}

Expand Down
6 changes: 3 additions & 3 deletions ee/tuf/library_lookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ func CheckOutLatest(ctx context.Context, binary autoupdatableBinary, rootDirecto

// If we can't find the specific release version that we should be on, then just return the executable
// with the most recent version in the library
return mostRecentVersion(ctx, binary, updateDirectory, channel)
return mostRecentVersion(ctx, slogger, binary, updateDirectory, channel)
}

// findExecutable looks at our local TUF repository to find the release for our
Expand Down Expand Up @@ -270,12 +270,12 @@ func findExecutable(ctx context.Context, binary autoupdatableBinary, tufReposito

// mostRecentVersion returns the path to the most recent, valid version available in the library for the
// given binary, along with its version.
func mostRecentVersion(ctx context.Context, binary autoupdatableBinary, baseUpdateDirectory, channel string) (*BinaryUpdateInfo, error) {
func mostRecentVersion(ctx context.Context, slogger *slog.Logger, binary autoupdatableBinary, baseUpdateDirectory, channel string) (*BinaryUpdateInfo, error) {
ctx, span := traces.StartSpan(ctx)
defer span.End()

// Pull all available versions from library
validVersionsInLibrary, _, err := sortedVersionsInLibrary(ctx, binary, baseUpdateDirectory)
validVersionsInLibrary, _, err := sortedVersionsInLibrary(ctx, slogger, binary, baseUpdateDirectory)
if err != nil {
return nil, fmt.Errorf("could not get sorted versions in library for %s: %w", binary, err)
}
Expand Down
Loading

0 comments on commit c6ad847

Please sign in to comment.