mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-20 15:31:30 +02:00
Continuous MDM enforcement — MDM always wins over user/OS state, so a policy pushed AFTER the fresh-install decision still takes effect. If the admin later lifts the policy, autostart stays off until the user re-enables it in Settings (accepted trade-off vs tracking user intent separately).
122 lines
3.9 KiB
Go
122 lines
3.9 KiB
Go
//go:build !android && !ios && !freebsd && !js
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/netbirdio/netbird/client/internal/profilemanager"
|
|
"github.com/netbirdio/netbird/client/mdm"
|
|
"github.com/netbirdio/netbird/client/ui/preferences"
|
|
"github.com/netbirdio/netbird/client/ui/services"
|
|
)
|
|
|
|
// autostartDefaultState carries the guard inputs of the one-time autostart
|
|
// default decision so the decision itself stays a pure, testable function.
|
|
type autostartDefaultState struct {
|
|
supported bool
|
|
mdmDisabled bool
|
|
priorInstall bool
|
|
}
|
|
|
|
// shouldEnableAutostartDefault applies the first-run guards in order and
|
|
// returns whether autostart may be enabled, plus the reason when it may not.
|
|
func shouldEnableAutostartDefault(s autostartDefaultState) (bool, string) {
|
|
switch {
|
|
case !s.supported:
|
|
return false, "autostart not supported on this platform"
|
|
case s.mdmDisabled:
|
|
return false, "autostart disabled by MDM policy"
|
|
case s.priorInstall:
|
|
return false, "existing NetBird installation"
|
|
}
|
|
return true, ""
|
|
}
|
|
|
|
// autostartDisabledByMDM reports whether the MDM policy manages the
|
|
// disableAutostart key in a way that must suppress the default. An
|
|
// unparseable managed value is treated as disabled to stay on the safe side.
|
|
func autostartDisabledByMDM(policy *mdm.Policy) bool {
|
|
if !policy.HasKey(mdm.KeyDisableAutostart) {
|
|
return false
|
|
}
|
|
disabled, ok := policy.GetBool(mdm.KeyDisableAutostart)
|
|
return !ok || disabled
|
|
}
|
|
|
|
// netbirdFootprintExists reports whether the machine already carries NetBird
|
|
// daemon config or state, meaning this is not a genuinely fresh install. It is
|
|
// the update-safety gate for the autostart default: upgrading users always
|
|
// have a footprint, so an update can never trigger a login-item write.
|
|
func netbirdFootprintExists() bool {
|
|
candidates := []string{
|
|
profilemanager.DefaultConfigPath,
|
|
filepath.Join(profilemanager.DefaultConfigPathDir, "config.json"),
|
|
filepath.Join(profilemanager.DefaultConfigPathDir, "state.json"),
|
|
}
|
|
for _, path := range candidates {
|
|
if path != "" && fileExists(path) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// applyAutostartDefault runs the one-time launch-on-login default for genuinely
|
|
// fresh installs. The autostartInitialized marker is persisted before any
|
|
// enable attempt so a crash mid-flow degrades to "never enabled" instead of
|
|
// retrying login-item writes on every launch. A user's later disable in
|
|
// Settings is never overridden: the marker guarantees at-most-once, ever.
|
|
func applyAutostartDefault(ctx context.Context, autostart *services.Autostart, prefs *preferences.Store, prefsFileExisted bool) {
|
|
mdmDisabled := autostartDisabledByMDM(mdm.LoadPolicy())
|
|
|
|
if mdmDisabled {
|
|
if enabled, err := autostart.IsEnabled(ctx); err != nil {
|
|
log.Warnf("MDM disableAutostart: read autostart state: %v", err)
|
|
} else if enabled {
|
|
if err := autostart.SetEnabled(ctx, false); err != nil {
|
|
log.Warnf("MDM disableAutostart: force off failed: %v", err)
|
|
} else {
|
|
log.Info("MDM disableAutostart enforced: autostart turned off")
|
|
}
|
|
}
|
|
}
|
|
|
|
priorFootprint := netbirdFootprintExists() || prefsFileExisted
|
|
|
|
if prefs.Get().AutostartInitialized {
|
|
return
|
|
}
|
|
if err := prefs.SetAutostartInitialized(true); err != nil {
|
|
log.Warnf("persist autostart marker, skipping autostart default: %v", err)
|
|
return
|
|
}
|
|
|
|
state := autostartDefaultState{
|
|
supported: autostart.Supported(ctx),
|
|
mdmDisabled: mdmDisabled,
|
|
priorInstall: priorFootprint,
|
|
}
|
|
enable, reason := shouldEnableAutostartDefault(state)
|
|
if !enable {
|
|
log.Debugf("skipping autostart default: %s", reason)
|
|
return
|
|
}
|
|
|
|
if err := autostart.SetEnabled(ctx, true); err != nil {
|
|
log.Warnf("enable autostart on fresh install: %v", err)
|
|
return
|
|
}
|
|
log.Info("autostart enabled by default on fresh install")
|
|
}
|
|
|
|
// fileExists reports whether path exists.
|
|
func fileExists(path string) bool {
|
|
_, err := os.Stat(path)
|
|
return err == nil
|
|
}
|