mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 21:27:31 +00:00
ipn/{localapi, ipnlocal}: forget the prior exit node when localAPI is used to zero the ExitNodeID (#11681)
Updates tailscale/corp#18724 When localAPI clients directly set ExitNodeID to "", the expected behaviour is that the prior exit node also gets zero'd - effectively setting the UI state back to 'no exit node was ever selected' The IntenalExitNodePrior has been changed to be a non-opaque type, as it is read by the UI to render the users last selected exit node, and must be concrete. Future-us can either break this, or deprecate it and replace it with something more interesting. Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
This commit is contained in:
@@ -3096,7 +3096,7 @@ func (b *LocalBackend) SetUseExitNodeEnabled(v bool) (ipn.PrefsView, error) {
|
||||
mp.ExitNodeIDSet = true
|
||||
mp.ExitNodeID = ""
|
||||
mp.InternalExitNodePriorSet = true
|
||||
mp.InternalExitNodePrior = string(p0.ExitNodeID())
|
||||
mp.InternalExitNodePrior = p0.ExitNodeID()
|
||||
}
|
||||
return b.editPrefsLockedOnEntry(mp, unlock)
|
||||
}
|
||||
@@ -3105,6 +3105,13 @@ func (b *LocalBackend) EditPrefs(mp *ipn.MaskedPrefs) (ipn.PrefsView, error) {
|
||||
if mp.SetsInternal() {
|
||||
return ipn.PrefsView{}, errors.New("can't set Internal fields")
|
||||
}
|
||||
|
||||
// Zeroing the ExitNodeId via localAPI must also zero the prior exit node.
|
||||
if mp.ExitNodeIDSet && mp.ExitNodeID == "" {
|
||||
mp.InternalExitNodePrior = ""
|
||||
mp.InternalExitNodePriorSet = true
|
||||
}
|
||||
|
||||
unlock := b.lockAndGetUnlock()
|
||||
defer unlock()
|
||||
return b.editPrefsLockedOnEntry(mp, unlock)
|
||||
|
@@ -458,6 +458,44 @@ func TestLazyMachineKeyGeneration(t *testing.T) {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
|
||||
func TestZeroExitNodeViaLocalAPI(t *testing.T) {
|
||||
lb := newTestLocalBackend(t)
|
||||
|
||||
// Give it an initial exit node in use.
|
||||
if _, err := lb.EditPrefs(&ipn.MaskedPrefs{
|
||||
ExitNodeIDSet: true,
|
||||
Prefs: ipn.Prefs{
|
||||
ExitNodeID: "foo",
|
||||
},
|
||||
}); err != nil {
|
||||
t.Fatalf("enabling first exit node: %v", err)
|
||||
}
|
||||
|
||||
// SetUseExitNodeEnabled(false) "remembers" the prior exit node.
|
||||
if _, err := lb.SetUseExitNodeEnabled(false); err != nil {
|
||||
t.Fatal("expected failure")
|
||||
}
|
||||
|
||||
// Zero the exit node
|
||||
pv, err := lb.EditPrefs(&ipn.MaskedPrefs{
|
||||
ExitNodeIDSet: true,
|
||||
Prefs: ipn.Prefs{
|
||||
ExitNodeID: "",
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("enabling first exit node: %v", err)
|
||||
}
|
||||
|
||||
// We just set the internal exit node to the empty string, so InternalExitNodePrior should
|
||||
// also be zero'd
|
||||
if got, want := pv.InternalExitNodePrior(), tailcfg.StableNodeID(""); got != want {
|
||||
t.Fatalf("unexpected InternalExitNodePrior %q, want: %q", got, want)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSetUseExitNodeEnabled(t *testing.T) {
|
||||
lb := newTestLocalBackend(t)
|
||||
|
||||
@@ -488,7 +526,7 @@ func TestSetUseExitNodeEnabled(t *testing.T) {
|
||||
if g, w := prefs.ExitNodeID(), tailcfg.StableNodeID(""); g != w {
|
||||
t.Fatalf("unexpected exit node ID %q; want %q", g, w)
|
||||
}
|
||||
if g, w := prefs.InternalExitNodePrior(), "foo"; g != w {
|
||||
if g, w := prefs.InternalExitNodePrior(), tailcfg.StableNodeID("foo"); g != w {
|
||||
t.Fatalf("unexpected exit node prior %q; want %q", g, w)
|
||||
}
|
||||
}
|
||||
@@ -500,7 +538,7 @@ func TestSetUseExitNodeEnabled(t *testing.T) {
|
||||
if g, w := prefs.ExitNodeID(), tailcfg.StableNodeID("foo"); g != w {
|
||||
t.Fatalf("unexpected exit node ID %q; want %q", g, w)
|
||||
}
|
||||
if g, w := prefs.InternalExitNodePrior(), "foo"; g != w {
|
||||
if g, w := prefs.InternalExitNodePrior(), tailcfg.StableNodeID("foo"); g != w {
|
||||
t.Fatalf("unexpected exit node prior %q; want %q", g, w)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user