[management,client] Take the debug-bundle upload destination from management

The debug-bundle paths that upload without a human picking a destination
compiled the vendor endpoint in: the mobile clients and the desktop UI hold
`https://upload.debug.netbird.io/upload-url` as a constant, the CLI defaults its
flag to it, and the remote job falls back to it when nothing else is set. A
self-hosted deployment therefore shipped peer logs, routes, DNS and firewall
state to NetBird-run infrastructure without its operator ever configuring that,
and had no way to point those paths anywhere else. #7147 and #7153 gave the
remote job a per-job URL and an MDM override, but neither reaches the mobile,
UI or CLI paths, and both fail open when unset.

Publish the destination from the management server instead, on the channel that
already carries stun/turn/signal/relay/flow/metrics:

- `NetbirdConfig.debug.upload_url`, sourced from the new account setting
  `debug_bundle_upload_url` (REST + dashboard) and falling back to the new
  `DebugUpload.URL` in the management server config, which a self-hosted install
  can set once so a fresh account is not left on the vendor default. Both are
  validated as https-with-host where they are written; a change fans out to
  connected peers rather than waiting for the next login.
- One resolver on the client, `debug.ResolveUploadURL`, used by every path:
  MDM override > explicitly named URL > destination published by management >
  the NetBird service, but only for a peer enrolled with NetBird's cloud.
  Anything else fails closed with ErrNoUploadDestination and the bundle stays
  local, which is the behaviour change: a self-hosted deployment that names no
  upload service no longer uploads at all.
- The engine keeps the published value (`Engine.DebugUploadURL`) so the bundle
  paths, which run off the engine loop, do not have to read it back out of the
  opt-in sync-response store.
- The daemon request grows `upload`, so "upload to wherever this deployment
  says" is expressible; an empty `uploadURL` no longer has to mean "no upload".
  The privilege gate is unchanged and still applies only to a URL the local
  caller named — a destination published by management is the operator naming
  their own service.
- The desktop UI stops carrying a vendor URL of its own and sends the intent.

Reported privately as GHSA-hf99-43rj-h577.
This commit is contained in:
riccardom
2026-09-10 16:38:41 +02:00
parent 08718d072c
commit 9f6d17b9e8
34 changed files with 1923 additions and 1319 deletions
+8
View File
@@ -383,6 +383,14 @@ components:
description: Enables or disables client metrics push for all peers in the account
type: boolean
example: false
debug_bundle_upload_url:
description: |
Upload service the peers of this account send debug bundles to. A bundle carries peer logs, routes, DNS and
firewall state, so setting this keeps that data inside infrastructure the account controls instead of the
upload service NetBird runs. Must be an https URL with a host. Empty falls back to the deployment-wide value
configured on the management server; with neither, only peers enrolled with NetBird's cloud upload at all.
type: string
example: "https://upload.example.com/upload-url"
agent_network_only:
description: Limits the dashboard to the Agent Network surface for this account. Set for accounts created via netbird.ai signups and can be disabled later. Enabling this requires dashboard_features.agent_network to be true in the same request.
type: boolean
+6
View File
@@ -1686,6 +1686,12 @@ type AccountSettings struct {
// DashboardFeatures Per-account dashboard section visibility overrides. Omitted keys follow the default dashboard behavior.
DashboardFeatures *AccountDashboardFeatures `json:"dashboard_features,omitempty"`
// DebugBundleUploadUrl Upload service the peers of this account send debug bundles to. A bundle carries peer logs, routes, DNS and
// firewall state, so setting this keeps that data inside infrastructure the account controls instead of the
// upload service NetBird runs. Must be an https URL with a host. Empty falls back to the deployment-wide value
// configured on the management server; with neither, only peers enrolled with NetBird's cloud upload at all.
DebugBundleUploadUrl *string `json:"debug_bundle_upload_url,omitempty"`
// DnsDomain Allows to define a custom dns domain for the account
DnsDomain *string `json:"dns_domain,omitempty"`
@@ -15,4 +15,5 @@ type AccountSettingsInfo struct {
AutoUpdateVersion string
AutoUpdateAlways bool
MetricsPushEnabled bool
DebugBundleUploadURL string
}
File diff suppressed because it is too large Load Diff
+15
View File
@@ -337,6 +337,8 @@ message NetbirdConfig {
FlowConfig flow = 5;
MetricsConfig metrics = 6;
DebugConfig debug = 7;
}
// HostConfig describes connection properties of some server (e.g. STUN, Signal, Management)
@@ -379,6 +381,19 @@ message MetricsConfig {
bool enabled = 1;
}
// DebugConfig carries the deployment-wide debug settings the operator of this
// management server publishes to its peers.
message DebugConfig {
// upload_url is the debug-bundle upload service this peer's account uses,
// taken from the account settings or, failing that, from the management
// server config. Publishing it keeps a self-hosted deployment's bundles inside
// its own control sphere instead of falling back to the upload service NetBird
// runs. An empty value means no destination is published: the peer then
// uploads only when it is enrolled with NetBird's cloud, and otherwise keeps
// the bundle local.
string upload_url = 1;
}
// JWTConfig represents JWT authentication configuration for validating tokens.
message JWTConfig {
string issuer = 1;