state: disable key expiry for tagged nodes

Nodes registered with tagged PreAuthKeys now have key expiry disabled,
matching Tailscale's behavior. User-owned nodes continue to use the
client-requested expiry.

On re-authentication, tagged nodes preserve their disabled expiry while
user-owned nodes can update their expiry from the client request.

Fixes #2971
This commit is contained in:
Kristoffer Dalby
2026-01-09 10:28:50 +00:00
parent 18e13f6ffa
commit 1d9900273e
2 changed files with 170 additions and 7 deletions

View File

@@ -1142,6 +1142,9 @@ func (s *State) createAndSaveNewNode(params newNodeParams) (types.NodeView, erro
nodeToRegister.User = params.PreAuthKey.User
}
// If PreAuthKey.UserID is nil, the node is "orphaned" (system-created)
// Tagged nodes have key expiry disabled.
nodeToRegister.Expiry = nil
} else {
// USER-OWNED NODE
nodeToRegister.UserID = &params.PreAuthKey.User.ID
@@ -1311,10 +1314,14 @@ func (s *State) HandleNodeFromAuthPath(
node.IsOnline = ptr.To(false)
node.LastSeen = ptr.To(time.Now())
if expiry != nil {
node.Expiry = expiry
} else {
node.Expiry = regEntry.Node.Expiry
// Tagged nodes keep their existing expiry (disabled).
// User-owned nodes update expiry from the provided value or registration entry.
if !node.IsTagged() {
if expiry != nil {
node.Expiry = expiry
} else {
node.Expiry = regEntry.Node.Expiry
}
}
})
@@ -1542,9 +1549,11 @@ func (s *State) HandleNodeFromPreAuthKey(
node.IsOnline = ptr.To(false)
node.LastSeen = ptr.To(time.Now())
// Update expiry, if it is zero, it means that the node will
// not have an expiry anymore. If it is non-zero, we set that.
node.Expiry = &regReq.Expiry
// Tagged nodes keep their existing expiry (disabled).
// User-owned nodes update expiry from the client request.
if !node.IsTagged() {
node.Expiry = &regReq.Expiry
}
})
if !ok {