mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-02 10:58:40 -04:00
## Describe your changes `applyAutostartDefault` gated all MDM enforcement behind the one-time `AutostartInitialized` marker, so MDM `disableAutostart` only affected fresh installs — a policy pushed after autostart had been enabled could not revoke the OS login-item. The PR adds follow-up MDM enforcements at the top of the function: if at any time MDM sets `disableAutostart=true` and the OS registration is present, force `SetEnabled(false)` to align it. Trade-off: once the admin lifts the policy, autostart stays off until the user re-toggles in Settings — consistent with "MDM always wins" behavior of the other managed keys. ## Issue ticket number and link Follow-up to PR https://github.com/netbirdio/netbird/pull/6738 (introduced the `disableAutostart` MDM key with fresh-install-only semantics). ## Stack <!-- branch-stack --> ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [ ] It is a refactor - [ ] Created tests that fail without the change (if possible) > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [x] I added/updated documentation for this change - [ ] Documentation is **not needed** for this change (explain why) ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: <https://github.com/netbirdio/docs/pull/855> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added an administrative policy to disable client autostart (“Disable Autostart”). - Added support for configuring this policy via macOS MDM, Windows Group Policy (ADMX/ADML), and registry settings. - When enforced, the client prevents new autostart registration on fresh installs and removes existing autostart on the next GUI launch, keeping it disabled until the policy is lifted. - **Bug Fixes** - Improved enforcement logic for managed autostart defaults so policy state is applied consistently during startup and first-run setup. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
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 autostart entry 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 autostart entry 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
|
|
}
|