diff --git a/orbit/changes/14698-macos-desktop-err b/orbit/changes/14698-macos-desktop-err new file mode 100644 index 0000000000..cd2b93536f --- /dev/null +++ b/orbit/changes/14698-macos-desktop-err @@ -0,0 +1,2 @@ +- Fixed issue on MacOS with starting Fleet Desktop for the first time. MacOS would return an error + if a user is not logged in via the GUI. \ No newline at end of file diff --git a/orbit/cmd/orbit/orbit.go b/orbit/cmd/orbit/orbit.go index 174789c17f..76f1979f5e 100644 --- a/orbit/cmd/orbit/orbit.go +++ b/orbit/cmd/orbit/orbit.go @@ -33,6 +33,7 @@ import ( "github.com/fleetdm/fleet/v4/orbit/pkg/token" "github.com/fleetdm/fleet/v4/orbit/pkg/update" "github.com/fleetdm/fleet/v4/orbit/pkg/update/filestore" + "github.com/fleetdm/fleet/v4/orbit/pkg/user" "github.com/fleetdm/fleet/v4/pkg/certificate" "github.com/fleetdm/fleet/v4/pkg/file" retrypkg "github.com/fleetdm/fleet/v4/pkg/retry" @@ -1307,6 +1308,19 @@ func (d *desktopRunner) execute() error { for { // First retry logic to start fleet-desktop. if done := retry(30*time.Second, false, d.interruptCh, func() bool { + // On MacOS, if we attempt to run Fleet Desktop while the user is not logged in through + // the GUI, MacOS returns an error. See https://github.com/fleetdm/fleet/issues/14698 + // for more details. + loggedInGui, err := user.IsUserLoggedInViaGui() + if err != nil { + log.Debug().Err(err).Msg("desktop.IsUserLoggedInGui") + return true + } + + if !loggedInGui { + return true + } + // Orbit runs as root user on Unix and as SYSTEM (Windows Service) user on Windows. // To be able to run the desktop application (mostly to register the icon in the system tray) // we need to run the application as the login user. diff --git a/orbit/pkg/user/user_darwin.go b/orbit/pkg/user/user_darwin.go new file mode 100644 index 0000000000..90089ef603 --- /dev/null +++ b/orbit/pkg/user/user_darwin.go @@ -0,0 +1,30 @@ +//go:build darwin +// +build darwin + +package user + +import ( + "errors" + "os/exec" + "strings" +) + +// IsUserLoggedInViaGui returns whether or not a user is logged into the machine via the GUI. +func IsUserLoggedInViaGui() (bool, error) { + output, err := exec.Command("/usr/bin/stat", "-f", "%Su", "/dev/console").Output() + if err != nil { + var ee *exec.ExitError + if errors.As(err, &ee) && len(ee.Stderr) > 0 { + return false, errors.Join(err, errors.New(string(ee.Stderr))) + } + + return false, err + } + + // If no user is logged in via GUI, the command line returns "root". + if strings.TrimSpace(string(output)) == "root" { + return false, nil + } + + return true, nil +} diff --git a/orbit/pkg/user/user_notdarwin.go b/orbit/pkg/user/user_notdarwin.go new file mode 100644 index 0000000000..d7be4fe41c --- /dev/null +++ b/orbit/pkg/user/user_notdarwin.go @@ -0,0 +1,11 @@ +//go:build !darwin +// +build !darwin + +package user + +// IsUserLoggedInViaGui returns whether or not a user is logged into the machine via the GUI. This +// function is only relevant on MacOS, where it is used to prevent errors when launching Fleet +// Desktop. We assume yes (effectively a no-op) on all other platforms. +func IsUserLoggedInViaGui() (bool, error) { + return true, nil +}