|
|
@ -25,6 +25,7 @@ import (
|
|
|
|
"tailscale.com/tka"
|
|
|
|
"tailscale.com/tka"
|
|
|
|
"tailscale.com/types/key"
|
|
|
|
"tailscale.com/types/key"
|
|
|
|
"tailscale.com/types/netmap"
|
|
|
|
"tailscale.com/types/netmap"
|
|
|
|
|
|
|
|
"tailscale.com/types/persist"
|
|
|
|
"tailscale.com/types/tkatype"
|
|
|
|
"tailscale.com/types/tkatype"
|
|
|
|
"tailscale.com/util/mak"
|
|
|
|
"tailscale.com/util/mak"
|
|
|
|
)
|
|
|
|
)
|
|
|
@ -134,7 +135,7 @@ func (b *LocalBackend) tkaSyncIfNeeded(nm *netmap.NetworkMap, prefs ipn.PrefsVie
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if wantEnabled && !isEnabled {
|
|
|
|
if wantEnabled && !isEnabled {
|
|
|
|
if err := b.tkaBootstrapFromGenesisLocked(bs.GenesisAUM); err != nil {
|
|
|
|
if err := b.tkaBootstrapFromGenesisLocked(bs.GenesisAUM, prefs.Persist()); err != nil {
|
|
|
|
return fmt.Errorf("bootstrap: %w", err)
|
|
|
|
return fmt.Errorf("bootstrap: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
isEnabled = true
|
|
|
|
isEnabled = true
|
|
|
@ -278,7 +279,7 @@ func (b *LocalBackend) chonkPathLocked() string {
|
|
|
|
// tailnet key authority, based on the given genesis AUM.
|
|
|
|
// tailnet key authority, based on the given genesis AUM.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// b.mu must be held.
|
|
|
|
// b.mu must be held.
|
|
|
|
func (b *LocalBackend) tkaBootstrapFromGenesisLocked(g tkatype.MarshaledAUM) error {
|
|
|
|
func (b *LocalBackend) tkaBootstrapFromGenesisLocked(g tkatype.MarshaledAUM, persist *persist.Persist) error {
|
|
|
|
if err := b.CanSupportNetworkLock(); err != nil {
|
|
|
|
if err := b.CanSupportNetworkLock(); err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -288,6 +289,19 @@ func (b *LocalBackend) tkaBootstrapFromGenesisLocked(g tkatype.MarshaledAUM) err
|
|
|
|
return fmt.Errorf("reading genesis: %v", err)
|
|
|
|
return fmt.Errorf("reading genesis: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if persist != nil && len(persist.DisallowedTKAStateIDs) > 0 {
|
|
|
|
|
|
|
|
if genesis.State == nil {
|
|
|
|
|
|
|
|
return errors.New("invalid genesis: missing State")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bootstrapStateID := fmt.Sprintf("%d:%d", genesis.State.StateID1, genesis.State.StateID2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, stateID := range persist.DisallowedTKAStateIDs {
|
|
|
|
|
|
|
|
if stateID == bootstrapStateID {
|
|
|
|
|
|
|
|
return fmt.Errorf("TKA with stateID of %q is disallowed on this node", stateID)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chonkDir := b.chonkPathLocked()
|
|
|
|
chonkDir := b.chonkPathLocked()
|
|
|
|
if err := os.Mkdir(filepath.Dir(chonkDir), 0755); err != nil && !os.IsExist(err) {
|
|
|
|
if err := os.Mkdir(filepath.Dir(chonkDir), 0755); err != nil && !os.IsExist(err) {
|
|
|
|
return fmt.Errorf("creating chonk root dir: %v", err)
|
|
|
|
return fmt.Errorf("creating chonk root dir: %v", err)
|
|
|
@ -495,6 +509,31 @@ func (b *LocalBackend) NetworkLockKeyTrustedForTest(keyID tkatype.KeyID) bool {
|
|
|
|
return b.tka.authority.KeyTrusted(keyID)
|
|
|
|
return b.tka.authority.KeyTrusted(keyID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// NetworkLockForceLocalDisable shuts down TKA locally, and denylists the current
|
|
|
|
|
|
|
|
// TKA from being initialized locally in future.
|
|
|
|
|
|
|
|
func (b *LocalBackend) NetworkLockForceLocalDisable() error {
|
|
|
|
|
|
|
|
b.mu.Lock()
|
|
|
|
|
|
|
|
defer b.mu.Unlock()
|
|
|
|
|
|
|
|
if b.tka == nil {
|
|
|
|
|
|
|
|
return errNetworkLockNotActive
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
id1, id2 := b.tka.authority.StateIDs()
|
|
|
|
|
|
|
|
stateID := fmt.Sprintf("%d:%d", id1, id2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newPrefs := b.pm.CurrentPrefs().AsStruct().Clone() // .Persist should always be initialized here.
|
|
|
|
|
|
|
|
newPrefs.Persist.DisallowedTKAStateIDs = append(newPrefs.Persist.DisallowedTKAStateIDs, stateID)
|
|
|
|
|
|
|
|
if err := b.pm.SetPrefs(newPrefs.View()); err != nil {
|
|
|
|
|
|
|
|
return fmt.Errorf("saving prefs: %w", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err := os.RemoveAll(b.chonkPathLocked()); err != nil {
|
|
|
|
|
|
|
|
return fmt.Errorf("deleting TKA state: %w", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
b.tka = nil
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NetworkLockSign signs the given node-key and submits it to the control plane.
|
|
|
|
// NetworkLockSign signs the given node-key and submits it to the control plane.
|
|
|
|
// rotationPublic, if specified, must be an ed25519 public key.
|
|
|
|
// rotationPublic, if specified, must be an ed25519 public key.
|
|
|
|
func (b *LocalBackend) NetworkLockSign(nodeKey key.NodePublic, rotationPublic []byte) error {
|
|
|
|
func (b *LocalBackend) NetworkLockSign(nodeKey key.NodePublic, rotationPublic []byte) error {
|
|
|
|