* [client,management] Skip route firewall rule computation when no firewall
A peer that runs with the firewall disabled has no ACL manager and no
firewall to program, so nothing ever reads RoutesFirewallRules: the only
consumers are acl.Manager, which is reached solely when e.acl is set, and
the legacy-management probe in updateNetworkMap, which is guarded by a
non-nil firewall.
Building those rules is the most expensive part of a sync on a peer that
routes many network resources. On a 15k-peer deployment a debug bundle
showed getPeerNetworkResourceFirewallRules accounting for 62% of the
allocations of Calculate, and Calculate for effectively all of the
allocations of handleSync, which was taking 3.2s on average and holding
the engine lock for the duration.
Let the caller ask Calculate to leave the rules out. The client passes
its existing DisableFirewall setting; the management server keeps the
default and still produces them.
RoutesFirewallRulesIsEmpty is set from the resulting empty list, so a
receiver that would otherwise infer legacy management from an empty rule
set does not misread the skip.
* [client,management] Cover the skip flag through the envelope
Review feedback on #7624.
The components test compared only the length of the peer firewall rules, so
a change to their content would have passed while the message claimed they
came out unchanged. Compare the slices.
The skip path was also only exercised by setting the field directly on the
components, which bypasses the envelope conversion where
RoutesFirewallRulesIsEmpty is derived. That bit is what keeps the client from
reading skipped rules as a legacy management server, so it gets a test that
goes through EnvelopeToNetworkMap with the flag set.
* [management] Give the router a peer ACL so the rule comparison bites
Review feedback on #7624.
peer-router-1 appears in no peer ACL in the shared fixture, so its
FirewallRules came out empty and the equality assertion compared two empty
slices — it would have passed even if the peer rules were dropped entirely.
Add a policy covering the router and require the baseline to be non-empty
before comparing.
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.
* Support per-peer lazy connection state and default proxy peers to lazy
* Classify forward targets from incoming config in lazy exclusion
* Set IsUserspaceBind mock so lazy manager starts in engine test
* Skip lazy exclude reconciliation when the set is unchanged
* Keep cached lazy flag when a sync carries no peer config