[client] Gate remote jobs behind an admin opt-in with MDM support

Remote jobs (debug bundles requested by the management server) run on the
peer with no local consent. This makes them an explicit opt-in, mirroring
the SSH-server opt-in: an --allow-remote-jobs flag persisted in the client
config, defaulting off. Enabling it off->on crosses the user-to-root
boundary and is refused for unprivileged IPC callers by the daemon gate,
the same way enabling the SSH server is. When disabled, the job-stream
handler refuses every job before doing any work.

Because the flag is admin-controlled, it is also MDM-managed: the
allowRemoteJobs policy key can enable or lock it, and a user SetConfig that
diverges from an enforced value is rejected like the other managed fields.

A second MDM key, debugBundleUploadURL, overrides the debug-bundle upload
service for remote jobs, taking precedence over the management-supplied
value (MDM > management > default). This lets an operator pin uploads to a
trusted host regardless of what management requests. The override is
validated as an https URL with a host, the same as the management value.

Defaulting the opt-in off is a behavior change: existing deployments that
rely on management-triggered debug bundles must opt in (flag or MDM) before
they work again.
This commit is contained in:
mlsmaycon
2026-08-13 02:12:47 +09:00
committed by Maycon Santos
parent d32573020a
commit 7da4127c7d
15 changed files with 227 additions and 27 deletions
+3
View File
@@ -35,6 +35,7 @@ import (
"github.com/netbirdio/netbird/client/internal/statemanager"
"github.com/netbirdio/netbird/client/internal/updater"
"github.com/netbirdio/netbird/client/proto"
"github.com/netbirdio/netbird/util"
"github.com/netbirdio/netbird/util/capture"
"github.com/netbirdio/netbird/version"
)
@@ -553,6 +554,7 @@ func (s *Server) setConfigInputFromRequest(msg *proto.SetConfigRequest) (profile
config.RosenpassPermissive = msg.RosenpassPermissive
config.DisableAutoConnect = msg.DisableAutoConnect
config.ServerSSHAllowed = msg.ServerSSHAllowed
config.RemoteJobsAllowed = msg.RemoteJobsAllowed
config.NetworkMonitor = msg.NetworkMonitor
config.DisableClientRoutes = msg.DisableClientRoutes
config.DisableServerRoutes = msg.DisableServerRoutes
@@ -2107,6 +2109,7 @@ func (s *Server) GetConfig(ctx context.Context, req *proto.GetConfigRequest) (*p
Mtu: int64(cfg.MTU),
DisableAutoConnect: cfg.DisableAutoConnect,
ServerSSHAllowed: *cfg.ServerSSHAllowed,
RemoteJobsAllowed: util.ReturnBoolWithDefaultFalse(cfg.RemoteJobsAllowed),
RosenpassEnabled: cfg.RosenpassEnabled,
RosenpassPermissive: cfg.RosenpassPermissive,
BlockInbound: cfg.BlockInbound,