Revert "control/controlclient: continue map poll during key expiry to receive extensions" (#20257)

* Revert "control/controlclient: continue map poll during key expiry to receive extensions"

This reverts commit 6a822dcc36. This commit
has caused test failures in the corp repo by unexpected changing the login
behaviour when nodes have a valid node key.

Updates tailscale/corp#43705
Updates #19326

Signed-off-by: Alex Chan <alexc@tailscale.com>

* Revert "tsnet: test key extension after server restart"

This reverts commit 317201375f. This test
relies on changes in 317201375f, which is
also being reverted because it causes test failures in corp.

Updates tailscale/corp#43705
Updates #19326

Signed-off-by: Alex Chan <alexc@tailscale.com>

---------

Signed-off-by: Alex Chan <alexc@tailscale.com>
This commit is contained in:
Alex Chan
2026-06-25 15:24:12 -07:00
committed by GitHub
parent 6e1de5b651
commit 9169b206be
4 changed files with 12 additions and 772 deletions
-129
View File
@@ -3884,132 +3884,3 @@ func TestListenMultipleEphemeralPorts(t *testing.T) {
testMultipleEphemeral(t, lt)
})
}
// TestKeyExtensionAfterRestart verifies that a tsnet client with an expired node key
// that has launched into an interactive login after a restart recovers when the old
// key gets extended.
//
// See https://github.com/tailscale/tailscale/issues/19326.
func TestKeyExtensionAfterRestart(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel()
controlURL, control := startControl(t)
control.RequireAuth = true
tmp := filepath.Join(t.TempDir(), "s1")
os.MkdirAll(tmp, 0755)
newServer := func() *Server {
s := &Server{
Dir: tmp,
ControlURL: controlURL,
Hostname: "s1",
Logf: tstest.WhileTestRunningLogger(t),
}
t.Cleanup(func() { s.Close() })
return s
}
// Start a node as tsnet instance s1.
s1 := newServer()
if err := s1.Start(); err != nil {
t.Fatalf("s1.Start: %v", err)
}
upErrCh := make(chan error, 1)
go func() { _, err := s1.Up(ctx); upErrCh <- err }()
var initialAuthURL string
if err := tstest.WaitFor(20*time.Second, func() error {
url := s1.lb.StatusWithoutPeers().AuthURL
if url == "" {
return errors.New("no AuthURL yet")
}
initialAuthURL = url
return nil
}); err != nil {
t.Fatalf("waiting for initial AuthURL: %v", err)
}
if !control.CompleteAuth(initialAuthURL) {
t.Fatal("failed to complete initial AuthURL")
}
select {
case err := <-upErrCh:
if err != nil {
t.Fatalf("s1.Up: %v", err)
}
case <-time.After(20 * time.Second):
t.Fatalf("timed out waiting for s1.Up to return, s1.lb.State()=%v", s1.lb.State())
}
nodePub := s1.lb.StatusWithoutPeers().Self.PublicKey
// Expire s1's node key.
serverNode := control.Node(nodePub)
if serverNode == nil {
t.Fatalf("node %v not in control", nodePub)
}
serverNode.KeyExpiry = time.Now().Add(-time.Minute)
control.UpdateNode(serverNode)
// Wait for s1 to transition away from the Running state.
if err := tstest.WaitFor(20*time.Second, func() error {
if got := s1.lb.State(); got == ipn.Running {
return errors.New("still Running")
}
return nil
}); err != nil {
t.Fatalf("waiting to transition away from Running: %v", err)
}
if err := s1.Close(); err != nil {
t.Fatalf("s1.Close: %v", err)
}
// Restart the node as tsnet instance s2.
s2 := newServer()
if err := s2.Start(); err != nil {
t.Fatalf("s2.Start: %v", err)
}
s2UpErrCh := make(chan error, 1)
go func() { _, err := s2.Up(ctx); s2UpErrCh <- err }()
// Wait for s2 to transition into the NeedsLogin state.
var secondAuthURL string
if err := tstest.WaitFor(20*time.Second, func() error {
u := s2.lb.StatusWithoutPeers().AuthURL
if u == "" {
return errors.New("no AuthURL yet")
}
secondAuthURL = u
return nil
}); err != nil {
t.Fatalf("waiting for s2 AuthURL: %v", err)
}
// We deliberately do not complete the auth.
_ = secondAuthURL
// Extend the old node key.
serverNode.KeyExpiry = time.Now().Add(24 * time.Hour)
control.UpdateNode(serverNode)
// Wait for s2 to receive the netmap with the key extension info
// and transition to Running.
if err := tstest.WaitFor(20*time.Second, func() error {
if got := s2.lb.State(); got != ipn.Running {
return fmt.Errorf("in state %v; want Running", got)
}
return nil
}); err != nil {
t.Fatalf("waiting to return to Running after key extension: %v", err)
}
select {
case err := <-s2UpErrCh:
if err != nil {
t.Fatalf("s2.Up: %v", err)
}
case <-time.After(20 * time.Second):
t.Fatalf("timed out waiting for s2.Up to return, s2.lb.State()=%v", s2.lb.State())
}
}