Files
netbird/client/internal/profilemanager/config_json_test.go
T
riccardom 155ced4ab9 [client] Refuse a serialized config that carries no peer identity
ConfigFromJSON still promised a "fully initialized" config after this PR
moved key generation out of apply() into EnsureIdentity, but identity stopped
being one of the defaults it applies. Its two callers both connect with what
they get back: the iOS SDK's Client.SetConfigFromJSON keeps it as the
preloaded config Run() uses on tvOS, and Auth.SetConfigFromJSON as the config
it authenticates with.

No caller feeds it a document without keys today — every stored document
comes from Auth.GetConfigJSON, whose config is provisioned by
DirectUpdateOrCreateConfig or CreateInMemoryConfig, and the tvOS app only
ever edits fields of a document it already has. This is a safety net for the
next caller, not a live bug.

Provisioning the identity here would be the wrong net. Neither caller can
hand a generated key back to the store the document came from — Client
exports no config at all — so the peer would connect under an identity
nothing persists and register anew on every launch, which is the failure the
EnsureIdentity split exists to prevent. A document with no identity means
nobody has logged in yet, and saying so is the only useful answer.

Both keys are required because both are dead ends when missing: an empty
WireGuard key fails the management login on its size, and an empty SSH key
fails ssh.GeneratePublicKey in ConnectClient before the engine starts.
2026-09-08 09:20:11 +02:00

50 lines
1.7 KiB
Go

package profilemanager
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
)
// The serialized form is how the tvOS SDK stores a profile, and its callers
// connect with whatever comes back. A document with no identity used to be
// completed by apply() minting keys, which meant connecting as a peer nothing
// could persist; it is now refused, since the only honest answer to "restore
// this config" for a config that was never logged in is to say so.
func TestConfigFromJSONRefusesADocumentWithoutAnIdentity(t *testing.T) {
path := filepath.Join(t.TempDir(), "exported.json")
stored, err := UpdateOrCreateConfig(ConfigInput{ConfigPath: path, ManagementURL: DefaultManagementURL})
require.NoError(t, err)
require.NotEmpty(t, stored.PrivateKey, "a provisioned config is the fixture this test needs")
require.NotEmpty(t, stored.SSHKey)
exported, err := ConfigToJSON(stored)
require.NoError(t, err)
restored, err := ConfigFromJSON(exported)
require.NoError(t, err, "a config exported after a login must load")
require.Equal(t, stored.PrivateKey, restored.PrivateKey, "the restored peer is not the stored one")
require.Equal(t, stored.SSHKey, restored.SSHKey)
for _, missing := range []struct {
name string
strip func(*Config)
}{
{"no WireGuard key", func(c *Config) { c.PrivateKey = "" }},
{"no SSH key", func(c *Config) { c.SSHKey = "" }},
{"no keys at all", func(c *Config) { c.PrivateKey = ""; c.SSHKey = "" }},
} {
t.Run(missing.name, func(t *testing.T) {
incomplete := stored.clone()
missing.strip(incomplete)
document, err := ConfigToJSON(incomplete)
require.NoError(t, err)
_, err = ConfigFromJSON(document)
require.ErrorIs(t, err, ErrConfigWithoutIdentity)
})
}
}