ipn/ipnlocal: always tx TKA sync after enablement

By always firing off a sync after enablement, the control plane should know the node's TKA head
at all times.

Signed-off-by: Tom DNetto <tom@tailscale.com>
pull/6447/head
Tom DNetto 2 years ago committed by Tom
parent 0f7da5c7dc
commit ed1fae6c73

@ -115,6 +115,7 @@ func (b *LocalBackend) tkaSyncIfNeeded(nm *netmap.NetworkMap, prefs ipn.PrefsVie
isEnabled := b.tka != nil isEnabled := b.tka != nil
wantEnabled := nm.TKAEnabled wantEnabled := nm.TKAEnabled
didJustEnable := false
if isEnabled != wantEnabled { if isEnabled != wantEnabled {
var ourHead tka.AUMHash var ourHead tka.AUMHash
if b.tka != nil { if b.tka != nil {
@ -135,6 +136,7 @@ func (b *LocalBackend) tkaSyncIfNeeded(nm *netmap.NetworkMap, prefs ipn.PrefsVie
return fmt.Errorf("bootstrap: %w", err) return fmt.Errorf("bootstrap: %w", err)
} }
isEnabled = true isEnabled = true
didJustEnable = true
} else if !wantEnabled && isEnabled { } else if !wantEnabled && isEnabled {
if err := b.tkaApplyDisablementLocked(bs.DisablementSecret); err != nil { if err := b.tkaApplyDisablementLocked(bs.DisablementSecret); err != nil {
// We log here instead of returning an error (which itself would be // We log here instead of returning an error (which itself would be
@ -149,7 +151,10 @@ func (b *LocalBackend) tkaSyncIfNeeded(nm *netmap.NetworkMap, prefs ipn.PrefsVie
} }
} }
if isEnabled && b.tka.authority.Head() != nm.TKAHead { // We always transmit the sync RPCs if TKA was just enabled.
// This informs the control plane that our TKA state is now
// initialized to the transmitted TKA head hash.
if isEnabled && (b.tka.authority.Head() != nm.TKAHead || didJustEnable) {
if err := b.tkaSyncLocked(ourNodeKey); err != nil { if err := b.tkaSyncLocked(ourNodeKey); err != nil {
return fmt.Errorf("tka sync: %w", err) return fmt.Errorf("tka sync: %w", err)
} }

@ -108,8 +108,30 @@ func TestTKAEnablementFlow(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
case "/machine/tka/sync/offer", "/machine/tka/sync/send": // Sync offer/send endpoints are hit even though the node is up-to-date,
t.Error("node attempted to sync, but should have been up to date") // so we implement enough of a fake that the client doesn't explode.
case "/machine/tka/sync/offer":
head, err := a1.Head().MarshalText()
if err != nil {
t.Fatal(err)
}
w.WriteHeader(200)
if err := json.NewEncoder(w).Encode(tailcfg.TKASyncOfferResponse{
Head: string(head),
}); err != nil {
t.Fatal(err)
}
case "/machine/tka/sync/send":
head, err := a1.Head().MarshalText()
if err != nil {
t.Fatal(err)
}
w.WriteHeader(200)
if err := json.NewEncoder(w).Encode(tailcfg.TKASyncSendResponse{
Head: string(head),
}); err != nil {
t.Fatal(err)
}
default: default:
t.Errorf("unhandled endpoint path: %v", r.URL.Path) t.Errorf("unhandled endpoint path: %v", r.URL.Path)

Loading…
Cancel
Save