tstest/integration/testcontrol: expire individual node keys
This adds testcontrol support for expiring individual node keys, in order to enable test scenarios involving to key-expiry and extension. Updates #19326 Signed-off-by: Gesa Stupperich <gesa@tailscale.com>
This commit is contained in:
committed by
Gesa Stupperich
parent
5be05f2c0d
commit
ec8ab870a4
@@ -910,7 +910,8 @@ func (s *Server) serveRegister(w http.ResponseWriter, r *http.Request, mkey key.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this is a followup request, wait until interactive followup URL visit complete.
|
// If this is a followup request, wait until interactive followup URL visit complete.
|
||||||
if req.Followup != "" {
|
isFollowup := req.Followup != ""
|
||||||
|
if isFollowup {
|
||||||
followupURL, err := url.Parse(req.Followup)
|
followupURL, err := url.Parse(req.Followup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -926,18 +927,22 @@ func (s *Server) serveRegister(w http.ResponseWriter, r *http.Request, mkey key.
|
|||||||
// some follow-ups? For now all are successes.
|
// some follow-ups? For now all are successes.
|
||||||
}
|
}
|
||||||
|
|
||||||
// The in-memory list of nodes, users, and logins is keyed by
|
// On a key rotation (OldNodeKey set and known to s.nodes), stage
|
||||||
// the node key. If the node key changes, update all the data stores
|
// the new key as a candidate entry but keep the old key's entry
|
||||||
// to use the new node key.
|
// alive so an in-flight map poll can still receive updates while
|
||||||
|
// the user completes the auth URL.
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
if _, oldNodeKeyOk := s.nodes[req.OldNodeKey]; oldNodeKeyOk {
|
if _, oldNodeKeyOk := s.nodes[req.OldNodeKey]; oldNodeKeyOk {
|
||||||
if _, newNodeKeyOk := s.nodes[req.NodeKey]; !newNodeKeyOk {
|
if _, newNodeKeyOk := s.nodes[req.NodeKey]; !newNodeKeyOk {
|
||||||
s.nodes[req.OldNodeKey].Key = req.NodeKey
|
cloned := s.nodes[req.OldNodeKey].Clone()
|
||||||
s.nodes[req.NodeKey] = s.nodes[req.OldNodeKey]
|
cloned.Key = req.NodeKey
|
||||||
|
s.nodes[req.NodeKey] = cloned
|
||||||
s.users[req.NodeKey] = s.users[req.OldNodeKey]
|
s.users[req.NodeKey] = s.users[req.OldNodeKey]
|
||||||
s.logins[req.NodeKey] = s.logins[req.OldNodeKey]
|
s.logins[req.NodeKey] = s.logins[req.OldNodeKey]
|
||||||
|
}
|
||||||
|
if isFollowup {
|
||||||
|
// The user has completed the auth URL, the new key
|
||||||
|
// is now authoritative. Retire the old key's entry.
|
||||||
delete(s.nodes, req.OldNodeKey)
|
delete(s.nodes, req.OldNodeKey)
|
||||||
delete(s.users, req.OldNodeKey)
|
delete(s.users, req.OldNodeKey)
|
||||||
delete(s.logins, req.OldNodeKey)
|
delete(s.logins, req.OldNodeKey)
|
||||||
@@ -997,11 +1002,19 @@ func (s *Server) serveRegister(w http.ResponseWriter, r *http.Request, mkey key.
|
|||||||
}
|
}
|
||||||
s.nodes[nk] = node
|
s.nodes[nk] = node
|
||||||
}
|
}
|
||||||
|
// Consider a node key expired if allExpired is set or if the nodeKey has
|
||||||
|
// an expiry time in the past. This allows tests to set per-node KeyExpiry
|
||||||
|
// via UpdateNode to simulate an admin-triggered or time-based expiry.
|
||||||
|
nodeKeyExpired := s.allExpired
|
||||||
|
if !nodeKeyExpired && req.OldNodeKey.IsZero() {
|
||||||
|
if n, ok := s.nodes[nk]; ok && !n.KeyExpiry.IsZero() && n.KeyExpiry.Before(time.Now()) {
|
||||||
|
nodeKeyExpired = true
|
||||||
|
}
|
||||||
|
}
|
||||||
requireAuth := s.RequireAuth
|
requireAuth := s.RequireAuth
|
||||||
if requireAuth && s.nodeKeyAuthed.Contains(nk) {
|
if requireAuth && s.nodeKeyAuthed.Contains(nk) && !nodeKeyExpired {
|
||||||
requireAuth = false
|
requireAuth = false
|
||||||
}
|
}
|
||||||
allExpired := s.allExpired
|
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
|
||||||
authURL := ""
|
authURL := ""
|
||||||
@@ -1014,7 +1027,7 @@ func (s *Server) serveRegister(w http.ResponseWriter, r *http.Request, mkey key.
|
|||||||
res, err := s.encode(false, tailcfg.RegisterResponse{
|
res, err := s.encode(false, tailcfg.RegisterResponse{
|
||||||
User: *user,
|
User: *user,
|
||||||
Login: *login,
|
Login: *login,
|
||||||
NodeKeyExpired: allExpired,
|
NodeKeyExpired: nodeKeyExpired,
|
||||||
MachineAuthorized: machineAuthorized,
|
MachineAuthorized: machineAuthorized,
|
||||||
AuthURL: authURL,
|
AuthURL: authURL,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user