mirror of
https://github.com/juanfont/headscale.git
synced 2026-11-01 03:04:07 +09:00
state: roll back node store when re-registration write fails
Re-registration mutated the node store before the database write and did not revert on failure, so a restart could drop the client's current node key. Snapshot the node and restore it if the write fails. Updates #3312
This commit is contained in:
1 parent
9b8949727d
commit
96d2e6ed60
2 files changed
+67
No files matched your search
@@ -2321,6 +2321,12 @@ func (s *State) HandleNodeFromPreAuthKey(
|
||||
return types.NodeView{}, change.Change{}, ErrNodeKeyInUse
|
||||
}
|
||||
|
||||
// Snapshot the pre-update node so the NodeStore can be rolled back if
|
||||
// the database write below fails. The view points at the immutable
|
||||
// pre-update snapshot (UpdateNode swaps in a new one), so this stays
|
||||
// valid after the mutation.
|
||||
priorNode := existingNodeSameUser.AsStruct()
|
||||
|
||||
// Update existing node - NodeStore first, then database
|
||||
updatedNodeView, ok := s.nodeStore.UpdateNode(existingNodeSameUser.ID(), func(node *types.Node) {
|
||||
node.NodeKey = regReq.NodeKey
|
||||
@@ -2401,6 +2407,13 @@ func (s *State) HandleNodeFromPreAuthKey(
|
||||
return nil, nil //nolint:nilnil // intentional: transaction success
|
||||
})
|
||||
if err != nil {
|
||||
// The NodeStore was updated before the database write. Roll it back
|
||||
// so it does not advertise a registration the database rejected
|
||||
// (e.g. a node key that a restart would not reload).
|
||||
if priorNode != nil {
|
||||
s.nodeStore.PutNode(*priorNode)
|
||||
}
|
||||
|
||||
return types.NodeView{}, change.Change{}, fmt.Errorf("writing node to database: %w", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user