WIP: rebase for 2026-05-18 #7

Draft
codinget wants to merge 234 commits from rebase/2026-05-18 into webnet
8 changed files with 126 additions and 273 deletions
Showing only changes of commit d6ffc0d986 - Show all commits
+2 -5
View File
@@ -22,15 +22,12 @@ func TestHandleC2NDebugTKA(t *testing.T) {
return nil, nil
}
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
signerKey := key.NewNLPrivate()
key1 := tka.Key{Kind: tka.Key25519, Public: signerKey.Public().Verifier(), Votes: 2}
state := tka.CreateStateForTest(key1)
chonk := tka.ChonkMem()
authority, _, err := tka.Create(chonk, tka.State{
Keys: []tka.Key{key1},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
}, signerKey)
authority, _, err := tka.Create(chonk, state, signerKey)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
+68 -199
View File
@@ -84,7 +84,29 @@ func fakeNoiseServer(t *testing.T, handler http.HandlerFunc) (*httptest.Server,
return ts, client
}
// newLocalBackendForTKA creates a new instance of [LocalBackend] for testing
// Tailnet Lock, in particular setting the tka field.
func newLocalBackendForTKA(t *testing.T, varRoot string, client *http.Client, pm *profileManager, authority *tka.Authority, chonk tka.CompactableChonk) LocalBackend {
t.Helper()
cc := fakeControlClient(t, client)
return LocalBackend{
varRoot: varRoot,
cc: cc,
ccAuto: cc,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
tka: &tkaState{
profile: pm.CurrentProfile().ID(),
authority: authority,
storage: chonk,
},
pm: pm,
store: pm.Store(),
}
}
func setupProfileManager(t *testing.T, nodePriv key.NodePrivate, nlPriv key.NLPrivate) *profileManager {
t.Helper()
pm := must.Get(newProfileManager(new(mem.Store), t.Logf, health.NewTracker(eventbustest.NewBus(t))))
must.Do(pm.SetPrefs((&ipn.Prefs{
Persist: &persist.Persist{
@@ -95,6 +117,18 @@ func setupProfileManager(t *testing.T, nodePriv key.NodePrivate, nlPriv key.NLPr
return pm
}
// setupChonkStorage creates a new [tka.FS] in a temporary folder.
func setupChonkStorage(t *testing.T, pm *profileManager) (varRoot string, chonk *tka.FS) {
varRoot = t.TempDir()
tkaPath := filepath.Join(varRoot, "tka-profile", string(pm.CurrentProfile().ID()))
os.Mkdir(tkaPath, 0755)
chonk, err := tka.ChonkDir(tkaPath)
if err != nil {
t.Fatal(err)
}
return varRoot, chonk
}
func TestTKAEnablementFlow(t *testing.T) {
nodePriv := key.NewNode()
@@ -102,11 +136,9 @@ func TestTKAEnablementFlow(t *testing.T) {
// our mock server can communicate.
nlPriv := key.NewNLPrivate()
key := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
state := tka.CreateStateForTest(key)
chonk := tka.ChonkMem()
a1, genesisAUM, err := tka.Create(chonk, tka.State{
Keys: []tka.Key{key},
DisablementValues: [][]byte{bytes.Repeat([]byte{0xa5}, 32)},
}, nlPriv)
a1, genesisAUM, err := tka.Create(chonk, state, nlPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
@@ -188,13 +220,7 @@ func TestTKADisablementFlow(t *testing.T) {
pm := setupProfileManager(t, nodePriv, nlPriv)
temp := t.TempDir()
tkaPath := filepath.Join(temp, "tka-profile", string(pm.CurrentProfile().ID()))
os.Mkdir(tkaPath, 0755)
chonk, err := tka.ChonkDir(tkaPath)
if err != nil {
t.Fatal(err)
}
varRoot, chonk := setupChonkStorage(t, pm)
authority, _, err := tka.Create(chonk, tka.State{
Keys: []tka.Key{key},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
@@ -239,20 +265,7 @@ func TestTKADisablementFlow(t *testing.T) {
}))
defer ts.Close()
cc := fakeControlClient(t, client)
b := LocalBackend{
varRoot: temp,
cc: cc,
ccAuto: cc,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
tka: &tkaState{
authority: authority,
storage: chonk,
},
pm: pm,
store: pm.Store(),
}
b := newLocalBackendForTKA(t, varRoot, client, pm, authority, chonk)
// Test that the wrong disablement secret does not shut down the authority.
returnWrongSecret = true
@@ -289,8 +302,6 @@ func TestTKASync(t *testing.T) {
someKeyPriv := key.NewNLPrivate()
someKey := tka.Key{Kind: tka.Key25519, Public: someKeyPriv.Public().Verifier(), Votes: 1}
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
type tkaSyncScenario struct {
name string
// controlAUMs is called (if non-nil) to get any AUMs which the tka state
@@ -369,10 +380,8 @@ func TestTKASync(t *testing.T) {
// Setup the tka authority on the control plane.
key := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
controlStorage := tka.ChonkMem()
controlAuthority, bootstrap, err := tka.Create(controlStorage, tka.State{
Keys: []tka.Key{key, someKey},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
}, nlPriv)
controlState := tka.CreateStateForTest(key, someKey)
controlAuthority, bootstrap, err := tka.Create(controlStorage, controlState, nlPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
@@ -382,14 +391,8 @@ func TestTKASync(t *testing.T) {
}
}
temp := t.TempDir()
tkaPath := filepath.Join(temp, "tka-profile", string(pm.CurrentProfile().ID()))
os.Mkdir(tkaPath, 0755)
// Setup the TKA authority on the node.
nodeStorage, err := tka.ChonkDir(tkaPath)
if err != nil {
t.Fatal(err)
}
varRoot, nodeStorage := setupChonkStorage(t, pm)
nodeAuthority, err := tka.Bootstrap(nodeStorage, bootstrap)
if err != nil {
t.Fatalf("tka.Bootstrap() failed: %v", err)
@@ -424,20 +427,7 @@ func TestTKASync(t *testing.T) {
defer ts.Close()
// Setup the client.
cc := fakeControlClient(t, client)
b := LocalBackend{
varRoot: temp,
cc: cc,
ccAuto: cc,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
pm: pm,
store: pm.Store(),
tka: &tkaState{
authority: nodeAuthority,
storage: nodeStorage,
},
}
b := newLocalBackendForTKA(t, varRoot, client, pm, nodeAuthority, nodeStorage)
// Finally, let's trigger a sync.
err = b.tkaSyncIfNeeded(&netmap.NetworkMap{
@@ -463,8 +453,6 @@ func TestTKASyncTriggersCompact(t *testing.T) {
someKeyPriv := key.NewNLPrivate()
someKey := tka.Key{Kind: tka.Key25519, Public: someKeyPriv.Public().Verifier(), Votes: 1}
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
nodePriv := key.NewNode()
nlPriv := key.NewNLPrivate()
pm := setupProfileManager(t, nodePriv, nlPriv)
@@ -480,10 +468,8 @@ func TestTKASyncTriggersCompact(t *testing.T) {
key := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
controlStorage := tka.ChonkMem()
controlStorage.SetClock(clock)
controlAuthority, bootstrap, err := tka.Create(controlStorage, tka.State{
Keys: []tka.Key{key, someKey},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
}, nlPriv)
controlState := tka.CreateStateForTest(key, someKey)
controlAuthority, bootstrap, err := tka.Create(controlStorage, controlState, nlPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
@@ -542,19 +528,8 @@ func TestTKASyncTriggersCompact(t *testing.T) {
defer ts.Close()
// Setup the client.
cc := fakeControlClient(t, client)
b := LocalBackend{
cc: cc,
ccAuto: cc,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
pm: pm,
store: pm.Store(),
tka: &tkaState{
authority: nodeAuthority,
storage: nodeStorage,
},
}
varRoot := ""
b := newLocalBackendForTKA(t, varRoot, client, pm, nodeAuthority, nodeStorage)
// Trigger a sync.
err = b.tkaSyncIfNeeded(&netmap.NetworkMap{
@@ -610,11 +585,9 @@ func TestTKASyncTriggersCompact(t *testing.T) {
func TestTKAFilterNetmap(t *testing.T) {
nlPriv := key.NewNLPrivate()
nlKey := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
state := tka.CreateStateForTest(nlKey)
storage := tka.ChonkMem()
authority, _, err := tka.Create(storage, tka.State{
Keys: []tka.Key{nlKey},
DisablementValues: [][]byte{bytes.Repeat([]byte{0xa5}, 32)},
}, nlPriv)
authority, _, err := tka.Create(storage, state, nlPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
@@ -764,17 +737,11 @@ func TestTKADisable(t *testing.T) {
// Make a fake TKA authority, to seed local state.
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
nlPriv := key.NewNLPrivate()
key := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
pm := setupProfileManager(t, nodePriv, nlPriv)
temp := t.TempDir()
tkaPath := filepath.Join(temp, "tka-profile", string(pm.CurrentProfile().ID()))
os.Mkdir(tkaPath, 0755)
key := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
chonk, err := tka.ChonkDir(tkaPath)
if err != nil {
t.Fatal(err)
}
temp, chonk := setupChonkStorage(t, pm)
authority, _, err := tka.Create(chonk, tka.State{
Keys: []tka.Key{key},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
@@ -821,21 +788,7 @@ func TestTKADisable(t *testing.T) {
}))
defer ts.Close()
cc := fakeControlClient(t, client)
b := LocalBackend{
varRoot: temp,
cc: cc,
ccAuto: cc,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
tka: &tkaState{
profile: pm.CurrentProfile().ID(),
authority: authority,
storage: chonk,
},
pm: pm,
store: pm.Store(),
}
b := newLocalBackendForTKA(t, temp, client, pm, authority, chonk)
// Test that we get an error for an incorrect disablement secret.
if err := b.NetworkLockDisable([]byte{1, 2, 3, 4}); err == nil || err.Error() != "incorrect disablement secret" {
@@ -854,20 +807,11 @@ func TestTKASign(t *testing.T) {
pm := setupProfileManager(t, nodePriv, nlPriv)
// Make a fake TKA authority, to seed local state.
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
key := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
state := tka.CreateStateForTest(key)
temp := t.TempDir()
tkaPath := filepath.Join(temp, "tka-profile", string(pm.CurrentProfile().ID()))
os.Mkdir(tkaPath, 0755)
chonk, err := tka.ChonkDir(tkaPath)
if err != nil {
t.Fatal(err)
}
authority, _, err := tka.Create(chonk, tka.State{
Keys: []tka.Key{key},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
}, nlPriv)
varRoot, chonk := setupChonkStorage(t, pm)
authority, _, err := tka.Create(chonk, state, nlPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
@@ -887,20 +831,8 @@ func TestTKASign(t *testing.T) {
}
}))
defer ts.Close()
cc := fakeControlClient(t, client)
b := LocalBackend{
varRoot: temp,
cc: cc,
ccAuto: cc,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
tka: &tkaState{
authority: authority,
storage: chonk,
},
pm: pm,
store: pm.Store(),
}
b := newLocalBackendForTKA(t, varRoot, client, pm, authority, chonk)
if err := b.NetworkLockSign(toSign.Public(), nil); err != nil {
t.Errorf("NetworkLockSign() failed: %v", err)
@@ -911,23 +843,14 @@ func TestTKAForceDisable(t *testing.T) {
nodePriv := key.NewNode()
// Make a fake TKA authority, to seed local state.
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
nlPriv := key.NewNLPrivate()
key := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
state := tka.CreateStateForTest(key)
pm := setupProfileManager(t, nodePriv, nlPriv)
temp := t.TempDir()
tkaPath := filepath.Join(temp, "tka-profile", string(pm.CurrentProfile().ID()))
os.Mkdir(tkaPath, 0755)
chonk, err := tka.ChonkDir(tkaPath)
if err != nil {
t.Fatal(err)
}
authority, genesis, err := tka.Create(chonk, tka.State{
Keys: []tka.Key{key},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
}, nlPriv)
temp, chonk := setupChonkStorage(t, pm)
authority, genesis, err := tka.Create(chonk, state, nlPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
@@ -1002,20 +925,11 @@ func TestTKAAffectedSigs(t *testing.T) {
pm := setupProfileManager(t, nodePriv, nlPriv)
// Make a fake TKA authority, to seed local state.
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
tkaKey := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
state := tka.CreateStateForTest(tkaKey)
temp := t.TempDir()
tkaPath := filepath.Join(temp, "tka-profile", string(pm.CurrentProfile().ID()))
os.Mkdir(tkaPath, 0755)
chonk, err := tka.ChonkDir(tkaPath)
if err != nil {
t.Fatal(err)
}
authority, _, err := tka.Create(chonk, tka.State{
Keys: []tka.Key{tkaKey},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
}, nlPriv)
varRoot, chonk := setupChonkStorage(t, pm)
authority, _, err := tka.Create(chonk, state, nlPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
@@ -1084,20 +998,7 @@ func TestTKAAffectedSigs(t *testing.T) {
}
}))
defer ts.Close()
cc := fakeControlClient(t, client)
b := LocalBackend{
varRoot: temp,
cc: cc,
ccAuto: cc,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
tka: &tkaState{
authority: authority,
storage: chonk,
},
pm: pm,
store: pm.Store(),
}
b := newLocalBackendForTKA(t, varRoot, client, pm, authority, chonk)
sigs, err := b.NetworkLockAffectedSigs(nlPriv.KeyID())
switch {
@@ -1130,22 +1031,13 @@ func TestTKARecoverCompromisedKeyFlow(t *testing.T) {
pm := setupProfileManager(t, nodePriv, nlPriv)
// Make a fake TKA authority, to seed local state.
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
key := tka.Key{Kind: tka.Key25519, Public: nlPriv.Public().Verifier(), Votes: 2}
cosignKey := tka.Key{Kind: tka.Key25519, Public: cosignPriv.Public().Verifier(), Votes: 2}
compromisedKey := tka.Key{Kind: tka.Key25519, Public: compromisedPriv.Public().Verifier(), Votes: 1}
state := tka.CreateStateForTest(key, compromisedKey, cosignKey)
temp := t.TempDir()
tkaPath := filepath.Join(temp, "tka-profile", string(pm.CurrentProfile().ID()))
os.Mkdir(tkaPath, 0755)
chonk, err := tka.ChonkDir(tkaPath)
if err != nil {
t.Fatal(err)
}
authority, _, err := tka.Create(chonk, tka.State{
Keys: []tka.Key{key, compromisedKey, cosignKey},
DisablementValues: [][]byte{tka.DisablementKDF(disablementSecret)},
}, nlPriv)
varRoot, chonk := setupChonkStorage(t, pm)
authority, _, err := tka.Create(chonk, state, nlPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
@@ -1170,20 +1062,7 @@ func TestTKARecoverCompromisedKeyFlow(t *testing.T) {
}
}))
defer ts.Close()
cc := fakeControlClient(t, client)
b := LocalBackend{
varRoot: temp,
cc: cc,
ccAuto: cc,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
tka: &tkaState{
authority: authority,
storage: chonk,
},
pm: pm,
store: pm.Store(),
}
b := newLocalBackendForTKA(t, varRoot, client, pm, authority, chonk)
aum, err := b.NetworkLockGenerateRecoveryAUM([]tkatype.KeyID{compromisedPriv.KeyID()}, tka.AUMHash{})
if err != nil {
@@ -1193,17 +1072,7 @@ func TestTKARecoverCompromisedKeyFlow(t *testing.T) {
// Cosign using the cosigning key.
{
pm := setupProfileManager(t, nodePriv, cosignPriv)
b := LocalBackend{
varRoot: temp,
logf: t.Logf,
health: health.NewTracker(eventbustest.NewBus(t)),
tka: &tkaState{
authority: authority,
storage: chonk,
},
pm: pm,
store: pm.Store(),
}
b := newLocalBackendForTKA(t, varRoot, client, pm, authority, chonk)
if aum, err = b.NetworkLockCosignRecoveryAUM(aum); err != nil {
t.Fatalf("NetworkLockCosignRecoveryAUM() failed: %v", err)
}
+14 -28
View File
@@ -27,12 +27,10 @@ func (s signer25519) SignAUM(sigHash tkatype.AUMSigHash) ([]tkatype.Signature, e
func TestAuthorityBuilderAddKey(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
state := CreateStateForTest(key)
storage := ChonkMem()
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
a, _, err := Create(storage, state, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
@@ -61,12 +59,10 @@ func TestAuthorityBuilderAddKey(t *testing.T) {
func TestAuthorityBuilderMaxKey(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
state := CreateStateForTest(key)
storage := ChonkMem()
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
a, _, err := Create(storage, state, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
@@ -108,12 +104,10 @@ func TestAuthorityBuilderRemoveKey(t *testing.T) {
key := Key{Kind: Key25519, Public: pub, Votes: 2}
pub2, _ := testingKey25519(t, 2)
key2 := Key{Kind: Key25519, Public: pub2, Votes: 1}
state := CreateStateForTest(key, key2)
storage := ChonkMem()
a, _, err := Create(storage, State{
Keys: []Key{key, key2},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
a, _, err := Create(storage, state, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
@@ -154,12 +148,10 @@ func TestAuthorityBuilderRemoveKey(t *testing.T) {
func TestAuthorityBuilderSetKeyVote(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
state := CreateStateForTest(key)
storage := ChonkMem()
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
a, _, err := Create(storage, state, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
@@ -190,12 +182,10 @@ func TestAuthorityBuilderSetKeyVote(t *testing.T) {
func TestAuthorityBuilderSetKeyMeta(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2, Meta: map[string]string{"a": "b"}}
state := CreateStateForTest(key)
storage := ChonkMem()
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
a, _, err := Create(storage, state, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
@@ -226,12 +216,10 @@ func TestAuthorityBuilderSetKeyMeta(t *testing.T) {
func TestAuthorityBuilderMultiple(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
state := CreateStateForTest(key)
storage := ChonkMem()
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
a, _, err := Create(storage, state, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
@@ -274,12 +262,10 @@ func TestAuthorityBuilderMultiple(t *testing.T) {
func TestAuthorityBuilderCheckpointsAfterXUpdates(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
state := CreateStateForTest(key)
storage := ChonkMem()
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
a, _, err := Create(storage, state, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
+2 -4
View File
@@ -321,10 +321,8 @@ func optTemplate(name string, template AUM) testchainOpt {
}
func genesisTemplate(key Key) testchainOpt {
return optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}})
state := CreateStateForTest(key)
return optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &state})
}
func checkpointTemplate() testchainOpt {
+2 -4
View File
@@ -72,10 +72,8 @@ func TestNLPrivate(t *testing.T) {
// Test that key.NLPrivate implements Signer by making a new
// authority.
k := Key{Kind: Key25519, Public: pub.Verifier(), Votes: 1}
_, aum, err := Create(ChonkMem(), State{
Keys: []Key{k},
DisablementValues: [][]byte{bytes.Repeat([]byte{1}, 32)},
}, p)
state := CreateStateForTest(k)
_, aum, err := Create(ChonkMem(), state, p)
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
+16
View File
@@ -13,6 +13,7 @@ import (
"golang.org/x/crypto/argon2"
"tailscale.com/types/tkatype"
"tailscale.com/util/testenv"
)
// ErrNoSuchKey is returned if the key referenced by a KeyID does not exist.
@@ -313,3 +314,18 @@ func (s *State) staticValidateCheckpoint() error {
}
return nil
}
// CreateStateForTest creates a [State] that marks the given keys as trusted
// with an arbitrary disablement value.
//
// This is only for use in tests, and will panic if called outside a test.
func CreateStateForTest(keys ...Key) State {
testenv.AssertInTest()
disablementSecret := bytes.Repeat([]byte{0xa5}, 32)
return State{
Keys: keys,
DisablementValues: [][]byte{DisablementKDF(disablementSecret)},
}
}
+2 -4
View File
@@ -597,12 +597,10 @@ func TestCompactLongButYoung(t *testing.T) {
ourPriv := key.NewNLPrivate()
ourKey := Key{Kind: Key25519, Public: ourPriv.Public().Verifier(), Votes: 1}
someOtherKey := Key{Kind: Key25519, Public: key.NewNLPrivate().Public().Verifier(), Votes: 1}
state := CreateStateForTest(ourKey, someOtherKey)
storage := ChonkMem()
auth, _, err := Create(storage, State{
Keys: []Key{ourKey, someOtherKey},
DisablementValues: [][]byte{DisablementKDF(bytes.Repeat([]byte{0xa5}, 32))},
}, ourPriv)
auth, _, err := Create(storage, state, ourPriv)
if err != nil {
t.Fatalf("tka.Create() failed: %v", err)
}
+20 -29
View File
@@ -197,6 +197,7 @@ func TestComputeStateAt(t *testing.T) {
// for tests you want one AUM to be 'lower' than another, so that
// that chain is taken based on fork resolution rules).
func fakeAUM(t *testing.T, template any, parent *AUMHash) (AUM, AUMHash) {
t.Helper()
if seed, ok := template.(int); ok {
a := AUM{MessageKind: AUMNoOp, KeyID: []byte{byte(seed)}}
if parent != nil {
@@ -299,12 +300,17 @@ func TestAuthorityHead(t *testing.T) {
func TestAuthorityValidDisablement(t *testing.T) {
pub, _ := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
disablementSecret := []byte{1, 2, 3}
state := State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF(disablementSecret)},
}
c := newTestchain(t, `
G1 -> L1
G1.template = genesis
`,
genesisTemplate(key),
optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &state}),
)
a, _ := Open(c.Chonk())
@@ -317,10 +323,7 @@ func TestCreateBootstrapAuthority(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
a1, genesisAUM, err := Create(ChonkMem(), State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
a1, genesisAUM, err := Create(ChonkMem(), CreateStateForTest(key), signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
}
@@ -349,10 +352,7 @@ func TestBootstrapChonkMustBeEmpty(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
state := State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}
state := CreateStateForTest(key)
// Bootstrap our chonk for the first time, which should succeed.
_, _, err := Create(chonk, state, signer25519(priv))
@@ -412,7 +412,7 @@ func TestAuthorityInformNonLinear(t *testing.T) {
| -> L4 -> L5
G1.template = genesis
L1.hashSeed = 3
L1.hashSeed = 2
L2.hashSeed = 2
L4.hashSeed = 2
`,
@@ -445,6 +445,8 @@ func TestAuthorityInformNonLinear(t *testing.T) {
}
if a.Head() != c.AUMHashes["L3"] {
t.Logf("a.Head() = %s", a.Head())
t.Logf("auMHashes = %v", c.AUMHashes)
t.Fatal("authority did not converge to correct AUM")
}
}
@@ -495,21 +497,12 @@ func TestInteropWithNLKey(t *testing.T) {
pub2 := key.NewNLPrivate().Public()
pub3 := key.NewNLPrivate().Public()
a, _, err := Create(ChonkMem(), State{
Keys: []Key{
{
Kind: Key25519,
Votes: 1,
Public: pub1.KeyID(),
},
{
Kind: Key25519,
Votes: 1,
Public: pub2.KeyID(),
},
},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, priv1)
state := CreateStateForTest(
Key{Kind: Key25519, Votes: 1, Public: pub1.KeyID()},
Key{Kind: Key25519, Votes: 1, Public: pub2.KeyID()},
)
a, _, err := Create(ChonkMem(), state, priv1)
if err != nil {
t.Errorf("tka.Create: %v", err)
return
@@ -529,6 +522,7 @@ func TestInteropWithNLKey(t *testing.T) {
func TestAuthorityCompact(t *testing.T) {
pub, priv := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
state := CreateStateForTest(key)
c := newTestchain(t, `
G -> A -> B -> C -> D -> E
@@ -537,10 +531,7 @@ func TestAuthorityCompact(t *testing.T) {
C.template = checkpoint2
`,
genesisTemplate(key),
optTemplate("checkpoint2", AUM{MessageKind: AUMCheckpoint, State: &State{
Keys: []Key{key},
DisablementValues: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}}),
optTemplate("checkpoint2", AUM{MessageKind: AUMCheckpoint, State: &state}),
optKey("key", key, priv),
optSignAllUsing("key"))