tka: truncate long rotation signature chains

When a rotation signature chain reaches a certain size, remove the
oldest rotation signature from the chain before wrapping it in a new
rotation signature.

Since all previous rotation signatures are signed by the same wrapping
pubkey (node's own tailnet lock key), the node can re-construct the
chain, re-signing previous rotation signatures. This will satisfy the
existing certificate validation logic.

Updates #13185

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
This commit is contained in:
Anton Tolchanov
2024-08-19 19:32:14 +01:00
committed by Anton Tolchanov
parent bcc47d91ca
commit fd6686d81a
4 changed files with 221 additions and 11 deletions
+25
View File
@@ -667,6 +667,31 @@ func TestTKAFilterNetmap(t *testing.T) {
if diff := cmp.Diff(want, nm.Peers, nodePubComparer); diff != "" {
t.Errorf("filtered netmap differs (-want, +got):\n%s", diff)
}
// Confirm that repeated rotation works correctly.
for range 100 {
n5Rotated, n5RotatedSig = resign(n5nl, n5RotatedSig)
}
n51, n51Sig := resign(n5nl, n5RotatedSig)
nm = &netmap.NetworkMap{
Peers: nodeViews([]*tailcfg.Node{
{ID: 1, Key: n1.Public(), KeySignature: n1GoodSig.Serialize()},
{ID: 5, Key: n5Rotated.Public(), KeySignature: n5RotatedSig}, // rotated
{ID: 51, Key: n51.Public(), KeySignature: n51Sig},
}),
}
b.tkaFilterNetmapLocked(nm)
want = nodeViews([]*tailcfg.Node{
{ID: 1, Key: n1.Public(), KeySignature: n1GoodSig.Serialize()},
{ID: 51, Key: n51.Public(), KeySignature: n51Sig},
})
if diff := cmp.Diff(want, nm.Peers, nodePubComparer); diff != "" {
t.Errorf("filtered netmap differs (-want, +got):\n%s", diff)
}
}
func TestTKADisable(t *testing.T) {