mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-14 10:49:07 +02:00
pushNewTURNTokens and pushNewRelayTokens send a SyncResponse whose NetbirdConfig carries only Turns and Relay. handleDebugUploadUpdate read the absent Debug as an empty destination and stored it, so every TURN credential refresh — every few minutes — silently dropped the operator's choice and the next bundle went to the service NetBird runs. That is the exact failure this branch exists to prevent. A nil DebugConfig now carries no information and is left alone. To keep an operator's clear reaching the peer, toNetbirdConfig always emits Debug on the full config it builds, empty URL included, so the peer can tell "cleared" from "not mentioned". Reported by cubic on #7514.
65 lines
2.6 KiB
Go
65 lines
2.6 KiB
Go
package internal
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
mgmProto "github.com/netbirdio/netbird/shared/management/proto"
|
|
)
|
|
|
|
// TestValidateBundleUploadURL covers the sanity check applied to a
|
|
// management-supplied upload URL before a remote debug bundle is generated.
|
|
func TestValidateBundleUploadURL(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
raw string
|
|
wantErr bool
|
|
}{
|
|
{name: "empty defers to the deployment destination", raw: ""},
|
|
{name: "https with host", raw: "https://upload.debug.netbird.io/upload"},
|
|
{name: "https self-hosted host", raw: "https://upload.example.com"},
|
|
{name: "plaintext rejected", raw: "http://upload.example.com", wantErr: true},
|
|
{name: "missing host rejected", raw: "https:///upload", wantErr: true},
|
|
{name: "port-only authority rejected", raw: "https://:443", wantErr: true},
|
|
{name: "non-url scheme rejected", raw: "ftp://upload.example.com", wantErr: true},
|
|
{name: "garbage rejected", raw: "://not a url", wantErr: true},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
err := validateBundleUploadURL(tc.raw)
|
|
if tc.wantErr {
|
|
require.Error(t, err, "an invalid upload URL must be rejected")
|
|
return
|
|
}
|
|
assert.NoError(t, err, "a valid or empty upload URL must be accepted")
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestEngineDebugUploadURL covers the destination the management server
|
|
// publishes: the engine keeps the last value it saw so the bundle paths, which
|
|
// run off the engine loop, do not have to re-read a sync response.
|
|
func TestEngineDebugUploadURL(t *testing.T) {
|
|
e := &Engine{}
|
|
assert.Empty(t, e.DebugUploadURL(), "a peer that never synced publishes no destination")
|
|
|
|
e.handleDebugUploadUpdate(nil)
|
|
assert.Empty(t, e.DebugUploadURL(), "a management server predating the field publishes none")
|
|
|
|
e.handleDebugUploadUpdate(&mgmProto.DebugConfig{UploadUrl: "https://upload.example.com/upload-url"})
|
|
assert.Equal(t, "https://upload.example.com/upload-url", e.DebugUploadURL())
|
|
|
|
// The partial updates that refresh TURN and relay credentials carry a
|
|
// NetbirdConfig with no Debug at all. Treating that as "no destination"
|
|
// would drop the operator's choice on every credential refresh.
|
|
e.handleDebugUploadUpdate(nil)
|
|
assert.Equal(t, "https://upload.example.com/upload-url", e.DebugUploadURL(),
|
|
"a partial config update must not clear the published destination")
|
|
|
|
// An operator that removes the destination sends an empty UploadUrl on a
|
|
// full config, and that does reach the peer.
|
|
e.handleDebugUploadUpdate(&mgmProto.DebugConfig{})
|
|
assert.Empty(t, e.DebugUploadURL())
|
|
}
|