From 83b4389090acaafb0f135a38ea56c9068bdfef79 Mon Sep 17 00:00:00 2001 From: Juan Font Date: Mon, 1 May 2023 14:52:03 +0000 Subject: [PATCH] Refactored app code with Node --- acls.go | 90 +++++++-------- api.go | 6 +- api_common.go | 16 +-- app.go | 54 ++++----- dns.go | 22 ++-- metrics.go | 18 +-- oidc.go | 64 +++++------ preauth_keys.go | 6 +- protocol_common.go | 236 +++++++++++++++++++-------------------- protocol_common_poll.go | 232 +++++++++++++++++++------------------- protocol_common_utils.go | 10 +- protocol_legacy.go | 6 +- protocol_legacy_poll.go | 12 +- protocol_noise.go | 4 +- protocol_noise_poll.go | 12 +- users.go | 32 +++--- utils.go | 12 +- 17 files changed, 416 insertions(+), 416 deletions(-) diff --git a/acls.go b/acls.go index 53bb7023..3370297d 100644 --- a/acls.go +++ b/acls.go @@ -119,7 +119,7 @@ func (h *Headscale) LoadACLPolicy(path string) error { } func (h *Headscale) UpdateACLRules() error { - machines, err := h.ListMachines() + nodes, err := h.ListNodes() if err != nil { return err } @@ -128,7 +128,7 @@ func (h *Headscale) UpdateACLRules() error { return errEmptyPolicy } - rules, err := generateACLRules(machines, *h.aclPolicy, h.cfg.OIDC.StripEmaildomain) + rules, err := generateACLRules(nodes, *h.aclPolicy, h.cfg.OIDC.StripEmaildomain) if err != nil { return err } @@ -225,7 +225,7 @@ func expandACLPeerAddr(srcIP string) []string { } func generateACLRules( - machines []Machine, + nodes []Node, aclPolicy ACLPolicy, stripEmaildomain bool, ) ([]tailcfg.FilterRule, error) { @@ -238,7 +238,7 @@ func generateACLRules( srcIPs := []string{} for innerIndex, src := range acl.Sources { - srcs, err := generateACLPolicySrc(machines, aclPolicy, src, stripEmaildomain) + srcs, err := generateACLPolicySrc(nodes, aclPolicy, src, stripEmaildomain) if err != nil { log.Error(). Msgf("Error parsing ACL %d, Source %d", index, innerIndex) @@ -259,7 +259,7 @@ func generateACLRules( destPorts := []tailcfg.NetPortRange{} for innerIndex, dest := range acl.Destinations { dests, err := generateACLPolicyDest( - machines, + nodes, aclPolicy, dest, needsWildcard, @@ -291,7 +291,7 @@ func (h *Headscale) generateSSHRules() ([]*tailcfg.SSHRule, error) { return nil, errEmptyPolicy } - machines, err := h.ListMachines() + nodes, err := h.ListNodes() if err != nil { return nil, err } @@ -339,7 +339,7 @@ func (h *Headscale) generateSSHRules() ([]*tailcfg.SSHRule, error) { principals := make([]*tailcfg.SSHPrincipal, 0, len(sshACL.Sources)) for innerIndex, rawSrc := range sshACL.Sources { expandedSrcs, err := expandAlias( - machines, + nodes, *h.aclPolicy, rawSrc, h.cfg.OIDC.StripEmaildomain, @@ -390,16 +390,16 @@ func sshCheckAction(duration string) (*tailcfg.SSHAction, error) { } func generateACLPolicySrc( - machines []Machine, + nodes []Node, aclPolicy ACLPolicy, src string, stripEmaildomain bool, ) ([]string, error) { - return expandAlias(machines, aclPolicy, src, stripEmaildomain) + return expandAlias(nodes, aclPolicy, src, stripEmaildomain) } func generateACLPolicyDest( - machines []Machine, + nodes []Node, aclPolicy ACLPolicy, dest string, needsWildcard bool, @@ -449,7 +449,7 @@ func generateACLPolicyDest( } expanded, err := expandAlias( - machines, + nodes, aclPolicy, alias, stripEmaildomain, @@ -535,7 +535,7 @@ func parseProtocol(protocol string) ([]int, bool, error) { // - a cidr // and transform these in IPAddresses. func expandAlias( - machines Machines, + nodes Nodes, aclPolicy ACLPolicy, alias string, stripEmailDomain bool, @@ -555,7 +555,7 @@ func expandAlias( return ips, err } for _, n := range users { - nodes := filterMachinesByUser(machines, n) + nodes := filterNodesByUser(nodes, n) for _, node := range nodes { ips = append(ips, node.IPAddresses.ToStringSlice()...) } @@ -566,9 +566,9 @@ func expandAlias( if strings.HasPrefix(alias, "tag:") { // check for forced tags - for _, machine := range machines { - if contains(machine.ForcedTags, alias) { - ips = append(ips, machine.IPAddresses.ToStringSlice()...) + for _, node := range nodes { + if contains(node.ForcedTags, alias) { + ips = append(ips, node.IPAddresses.ToStringSlice()...) } } @@ -590,13 +590,13 @@ func expandAlias( } } - // filter out machines per tag owner + // filter out nodes per tag owner for _, user := range owners { - machines := filterMachinesByUser(machines, user) - for _, machine := range machines { - hi := machine.GetHostInfo() + nodes := filterNodesByUser(nodes, user) + for _, node := range nodes { + hi := node.GetHostInfo() if contains(hi.RequestTags, alias) { - ips = append(ips, machine.IPAddresses.ToStringSlice()...) + ips = append(ips, node.IPAddresses.ToStringSlice()...) } } } @@ -605,10 +605,10 @@ func expandAlias( } // if alias is a user - nodes := filterMachinesByUser(machines, alias) - nodes = excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias, stripEmailDomain) + filteredNodes := filterNodesByUser(nodes, alias) + filteredNodes = excludeCorrectlyTaggedNodes(aclPolicy, filteredNodes, alias, stripEmailDomain) - for _, n := range nodes { + for _, n := range filteredNodes { ips = append(ips, n.IPAddresses.ToStringSlice()...) } if len(ips) > 0 { @@ -619,17 +619,17 @@ func expandAlias( if h, ok := aclPolicy.Hosts[alias]; ok { log.Trace().Str("host", h.String()).Msg("expandAlias got hosts entry") - return expandAlias(machines, aclPolicy, h.String(), stripEmailDomain) + return expandAlias(filteredNodes, aclPolicy, h.String(), stripEmailDomain) } // if alias is an IP if ip, err := netip.ParseAddr(alias); err == nil { log.Trace().Str("ip", ip.String()).Msg("expandAlias got ip") ips := []string{ip.String()} - matches := machines.FilterByIP(ip) + matches := nodes.FilterByIP(ip) - for _, machine := range matches { - ips = append(ips, machine.IPAddresses.ToStringSlice()...) + for _, node := range matches { + ips = append(ips, node.IPAddresses.ToStringSlice()...) } return lo.Uniq(ips), nil @@ -640,12 +640,12 @@ func expandAlias( val := []string{cidr.String()} // This is suboptimal and quite expensive, but if we only add the cidr, we will miss all the relevant IPv6 // addresses for the hosts that belong to tailscale. This doesnt really affect stuff like subnet routers. - for _, machine := range machines { - for _, ip := range machine.IPAddresses { + for _, node := range nodes { + for _, ip := range node.IPAddresses { // log.Trace(). - // Msgf("checking if machine ip (%s) is part of cidr (%s): %v, is single ip cidr (%v), addr: %s", ip.String(), cidr.String(), cidr.Contains(ip), cidr.IsSingleIP(), cidr.Addr().String()) + // Msgf("checking if node ip (%s) is part of cidr (%s): %v, is single ip cidr (%v), addr: %s", ip.String(), cidr.String(), cidr.Contains(ip), cidr.IsSingleIP(), cidr.Addr().String()) if cidr.Contains(ip) { - val = append(val, machine.IPAddresses.ToStringSlice()...) + val = append(val, node.IPAddresses.ToStringSlice()...) } } } @@ -663,11 +663,11 @@ func expandAlias( // we assume in this function that we only have nodes from 1 user. func excludeCorrectlyTaggedNodes( aclPolicy ACLPolicy, - nodes []Machine, + nodes []Node, user string, stripEmailDomain bool, -) []Machine { - out := []Machine{} +) []Node { + out := []Node{} tags := []string{} for tag := range aclPolicy.TagOwners { owners, _ := expandTagOwners(aclPolicy, user, stripEmailDomain) @@ -676,9 +676,9 @@ func excludeCorrectlyTaggedNodes( tags = append(tags, tag) } } - // for each machine if tag is in tags list, don't append it. - for _, machine := range nodes { - hi := machine.GetHostInfo() + // for each node if tag is in tags list, don't append it. + for _, node := range nodes { + hi := node.GetHostInfo() found := false for _, t := range hi.RequestTags { @@ -688,11 +688,11 @@ func excludeCorrectlyTaggedNodes( break } } - if len(machine.ForcedTags) > 0 { + if len(node.ForcedTags) > 0 { found = true } if !found { - out = append(out, machine) + out = append(out, node) } } @@ -747,11 +747,11 @@ func expandPorts(portsStr string, needsWildcard bool) (*[]tailcfg.PortRange, err return &ports, nil } -func filterMachinesByUser(machines []Machine, user string) []Machine { - out := []Machine{} - for _, machine := range machines { - if machine.User.Name == user { - out = append(out, machine) +func filterNodesByUser(nodes []Node, user string) []Node { + out := []Node{} + for _, node := range nodes { + if node.User.Name == user { + out = append(out, node) } } diff --git a/api.go b/api.go index 308bc281..2833aacd 100644 --- a/api.go +++ b/api.go @@ -20,7 +20,7 @@ const ( RegisterMethodOIDC = "oidc" RegisterMethodCLI = "cli" ErrRegisterMethodCLIDoesNotSupportExpire = Error( - "machines registered with CLI does not support expire", + "node registered with CLI does not support expire", ) ) @@ -74,9 +74,9 @@ var registerWebAPITemplate = template.Must(

headscale

-

Machine registration

+

Node registration

- Run the command below in the headscale server to add this machine to your network: + Run the command below in the headscale server to add this node to your network:

headscale nodes register --user USERNAME --key {{.Key}}
diff --git a/api_common.go b/api_common.go index 7905c29d..6a5737a3 100644 --- a/api_common.go +++ b/api_common.go @@ -9,13 +9,13 @@ import ( func (h *Headscale) generateMapResponse( mapRequest tailcfg.MapRequest, - machine *Machine, + node *Node, ) (*tailcfg.MapResponse, error) { log.Trace(). Str("func", "generateMapResponse"). - Str("machine", mapRequest.Hostinfo.Hostname). + Str("node", mapRequest.Hostinfo.Hostname). Msg("Creating Map response") - node, err := h.toNode(*machine, h.cfg.BaseDomain, h.cfg.DNSConfig) + tailNode, err := h.toNode(*node, h.cfg.BaseDomain, h.cfg.DNSConfig) if err != nil { log.Error(). Caller(). @@ -26,7 +26,7 @@ func (h *Headscale) generateMapResponse( return nil, err } - peers, err := h.getValidPeers(machine) + peers, err := h.getValidPeers(node) if err != nil { log.Error(). Caller(). @@ -37,7 +37,7 @@ func (h *Headscale) generateMapResponse( return nil, err } - profiles := h.getMapResponseUserProfiles(*machine, peers) + profiles := h.getMapResponseUserProfiles(*node, peers) nodePeers, err := h.toNodes(peers, h.cfg.BaseDomain, h.cfg.DNSConfig) if err != nil { @@ -53,7 +53,7 @@ func (h *Headscale) generateMapResponse( dnsConfig := getMapResponseDNSConfig( h.cfg.DNSConfig, h.cfg.BaseDomain, - *machine, + *node, peers, ) @@ -61,7 +61,7 @@ func (h *Headscale) generateMapResponse( resp := tailcfg.MapResponse{ KeepAlive: false, - Node: node, + Node: tailNode, // TODO: Only send if updated DERPMap: h.DERPMap, @@ -105,7 +105,7 @@ func (h *Headscale) generateMapResponse( log.Trace(). Str("func", "generateMapResponse"). - Str("machine", mapRequest.Hostinfo.Hostname). + Str("node", mapRequest.Hostinfo.Hostname). // Interface("payload", resp). Msgf("Generated map response: %s", tailMapResponseToString(resp)) diff --git a/app.go b/app.go index b3066916..319d5353 100644 --- a/app.go +++ b/app.go @@ -211,7 +211,7 @@ func (h *Headscale) redirect(w http.ResponseWriter, req *http.Request) { http.Redirect(w, req, target, http.StatusFound) } -// expireEphemeralNodes deletes ephemeral machine records that have not been +// expireEphemeralNodes deletes ephemeral node records that have not been // seen for longer than h.cfg.EphemeralNodeInactivityTimeout. func (h *Headscale) expireEphemeralNodes(milliSeconds int64) { ticker := time.NewTicker(time.Duration(milliSeconds) * time.Millisecond) @@ -220,12 +220,12 @@ func (h *Headscale) expireEphemeralNodes(milliSeconds int64) { } } -// expireExpiredMachines expires machines that have an explicit expiry set +// expireExpiredNodes expires node that have an explicit expiry set // after that expiry time has passed. -func (h *Headscale) expireExpiredMachines(milliSeconds int64) { +func (h *Headscale) expireExpiredNodes(milliSeconds int64) { ticker := time.NewTicker(time.Duration(milliSeconds) * time.Millisecond) for range ticker.C { - h.expireExpiredMachinesWorker() + h.expireExpiredNodesWorker() } } @@ -248,32 +248,32 @@ func (h *Headscale) expireEphemeralNodesWorker() { } for _, user := range users { - machines, err := h.ListMachinesByUser(user.Name) + nodes, err := h.ListNodesByUser(user.Name) if err != nil { log.Error(). Err(err). Str("user", user.Name). - Msg("Error listing machines in user") + Msg("Error listing nodes in user") return } expiredFound := false - for _, machine := range machines { - if machine.isEphemeral() && machine.LastSeen != nil && + for _, node := range nodes { + if node.isEphemeral() && node.LastSeen != nil && time.Now(). - After(machine.LastSeen.Add(h.cfg.EphemeralNodeInactivityTimeout)) { + After(node.LastSeen.Add(h.cfg.EphemeralNodeInactivityTimeout)) { expiredFound = true log.Info(). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Ephemeral client removed from database") - err = h.db.Unscoped().Delete(machine).Error + err = h.db.Unscoped().Delete(node).Error if err != nil { log.Error(). Err(err). - Str("machine", machine.Hostname). - Msg("🤮 Cannot delete ephemeral machine from the database") + Str("node", node.Hostname). + Msg("Cannot delete ephemeral node from the database") } } } @@ -284,7 +284,7 @@ func (h *Headscale) expireEphemeralNodesWorker() { } } -func (h *Headscale) expireExpiredMachinesWorker() { +func (h *Headscale) expireExpiredNodesWorker() { users, err := h.ListUsers() if err != nil { log.Error().Err(err).Msg("Error listing users") @@ -293,34 +293,34 @@ func (h *Headscale) expireExpiredMachinesWorker() { } for _, user := range users { - machines, err := h.ListMachinesByUser(user.Name) + nodes, err := h.ListNodesByUser(user.Name) if err != nil { log.Error(). Err(err). Str("user", user.Name). - Msg("Error listing machines in user") + Msg("Error listing nodes in user") return } expiredFound := false - for index, machine := range machines { - if machine.isExpired() && - machine.Expiry.After(h.getLastStateChange(user)) { + for index, node := range nodes { + if node.isExpired() && + node.Expiry.After(h.getLastStateChange(user)) { expiredFound = true - err := h.ExpireMachine(&machines[index]) + err := h.ExpireNode(&nodes[index]) if err != nil { log.Error(). Err(err). - Str("machine", machine.Hostname). - Str("name", machine.GivenName). - Msg("🤮 Cannot expire machine") + Str("node", node.Hostname). + Str("name", node.GivenName). + Msg("Cannot expire node") } else { log.Info(). - Str("machine", machine.Hostname). - Str("name", machine.GivenName). - Msg("Machine successfully expired") + Str("node", node.Hostname). + Str("name", node.GivenName). + Msg("Node successfully expired") } } } @@ -552,7 +552,7 @@ func (h *Headscale) Serve() error { } go h.expireEphemeralNodes(updateInterval) - go h.expireExpiredMachines(updateInterval) + go h.expireExpiredNodes(updateInterval) go h.failoverSubnetRoutes(updateInterval) diff --git a/dns.go b/dns.go index da1a95d0..2b571c97 100644 --- a/dns.go +++ b/dns.go @@ -159,22 +159,22 @@ func generateIPv6DNSRootDomain(ipPrefix netip.Prefix) []dnsname.FQDN { } // If any nextdns DoH resolvers are present in the list of resolvers it will -// take metadata from the machine metadata and instruct tailscale to add it +// take metadata from the node metadata and instruct tailscale to add it // to the requests. This makes it possible to identify from which device the // requests come in the NextDNS dashboard. // // This will produce a resolver like: // `https://dns.nextdns.io/?device_name=node-name&device_model=linux&device_ip=100.64.0.1` -func addNextDNSMetadata(resolvers []*dnstype.Resolver, machine Machine) { +func addNextDNSMetadata(resolvers []*dnstype.Resolver, node Node) { for _, resolver := range resolvers { if strings.HasPrefix(resolver.Addr, nextDNSDoHPrefix) { attrs := url.Values{ - "device_name": []string{machine.Hostname}, - "device_model": []string{machine.HostInfo.OS}, + "device_name": []string{node.Hostname}, + "device_model": []string{node.HostInfo.OS}, } - if len(machine.IPAddresses) > 0 { - attrs.Add("device_ip", machine.IPAddresses[0].String()) + if len(node.IPAddresses) > 0 { + attrs.Add("device_ip", node.IPAddresses[0].String()) } resolver.Addr = fmt.Sprintf("%s?%s", resolver.Addr, attrs.Encode()) @@ -185,8 +185,8 @@ func addNextDNSMetadata(resolvers []*dnstype.Resolver, machine Machine) { func getMapResponseDNSConfig( dnsConfigOrig *tailcfg.DNSConfig, baseDomain string, - machine Machine, - peers Machines, + node Node, + peers Nodes, ) *tailcfg.DNSConfig { var dnsConfig *tailcfg.DNSConfig = dnsConfigOrig.Clone() if dnsConfigOrig != nil && dnsConfigOrig.Proxied { // if MagicDNS is enabled @@ -195,13 +195,13 @@ func getMapResponseDNSConfig( dnsConfig.Domains, fmt.Sprintf( "%s.%s", - machine.User.Name, + node.User.Name, baseDomain, ), ) userSet := mapset.NewSet[User]() - userSet.Add(machine.User) + userSet.Add(node.User) for _, p := range peers { userSet.Add(p.User) } @@ -213,7 +213,7 @@ func getMapResponseDNSConfig( dnsConfig = dnsConfigOrig } - addNextDNSMetadata(dnsConfig.Resolvers, machine) + addNextDNSMetadata(dnsConfig.Resolvers, node) return dnsConfig } diff --git a/metrics.go b/metrics.go index f1f86909..94da2b74 100644 --- a/metrics.go +++ b/metrics.go @@ -8,34 +8,34 @@ import ( const prometheusNamespace = "headscale" var ( - // This is a high cardinality metric (user x machines), we might want to make this + // This is a high cardinality metric (user x nodes), we might want to make this // configurable/opt-in in the future. lastStateUpdate = promauto.NewGaugeVec(prometheus.GaugeOpts{ Namespace: prometheusNamespace, Name: "last_update_seconds", - Help: "Time stamp in unix time when a machine or headscale was updated", - }, []string{"user", "machine"}) + Help: "Time stamp in unix time when a node or headscale was updated", + }, []string{"user", "nodes"}) - machineRegistrations = promauto.NewCounterVec(prometheus.CounterOpts{ + nodeRegistrations = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: prometheusNamespace, - Name: "machine_registrations_total", - Help: "The total amount of registered machine attempts", + Name: "node_registrations_total", + Help: "The total amount of registered node attempts", }, []string{"action", "auth", "status", "user"}) updateRequestsFromNode = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: prometheusNamespace, Name: "update_request_from_node_total", Help: "The number of updates requested by a node/update function", - }, []string{"user", "machine", "state"}) + }, []string{"user", "node", "state"}) updateRequestsSentToNode = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: prometheusNamespace, Name: "update_request_sent_to_node_total", Help: "The number of calls/messages issued on a specific nodes update channel", - }, []string{"user", "machine", "status"}) + }, []string{"user", "node", "status"}) // TODO(kradalby): This is very debugging, we might want to remove it. updateRequestsReceivedOnChannel = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: prometheusNamespace, Name: "update_request_received_on_channel_total", Help: "The number of update requests received on an update channel", - }, []string{"user", "machine"}) + }, []string{"user", "node"}) ) diff --git a/oidc.go b/oidc.go index 5aa3ba62..6ed6d84d 100644 --- a/oidc.go +++ b/oidc.go @@ -27,8 +27,8 @@ const ( errOIDCAllowedDomains = Error("authenticated principal does not match any allowed domain") errOIDCAllowedGroups = Error("authenticated principal is not in any allowed group") errOIDCAllowedUsers = Error("authenticated principal does not match any allowed user") - errOIDCInvalidMachineState = Error( - "requested machine state key expired before authorisation completed", + errOIDCInvalidNodeState = Error( + "requested node state key expired before authorisation completed", ) errOIDCNodeKeyMissing = Error("could not get node key from cache") ) @@ -181,9 +181,9 @@ var oidcCallbackTemplate = template.Must( ) // OIDCCallback handles the callback from the OIDC endpoint -// Retrieves the nkey from the state cache and adds the machine to the users email user -// TODO: A confirmation page for new machines should be added to avoid phishing vulnerabilities -// TODO: Add groups information from OIDC tokens into machine HostInfo +// Retrieves the nkey from the state cache and adds the node to the users email user +// TODO: A confirmation page for new nodes should be added to avoid phishing vulnerabilities +// TODO: Add groups information from OIDC tokens into node HostInfo // Listens in /oidc/callback. func (h *Headscale) OIDCCallback( writer http.ResponseWriter, @@ -229,13 +229,13 @@ func (h *Headscale) OIDCCallback( return } - nodeKey, machineExists, err := h.validateMachineForOIDCCallback( + nodeKey, nodeExists, err := h.validateNodeForOIDCCallback( writer, state, claims, idTokenExpiry, ) - if err != nil || machineExists { + if err != nil || nodeExists { return } @@ -244,15 +244,15 @@ func (h *Headscale) OIDCCallback( return } - // register the machine if it's new - log.Debug().Msg("Registering new machine after successful callback") + // register the node if it's new + log.Debug().Msg("Registering new node after successful callback") user, err := h.findOrCreateNewUserForOIDCCallback(writer, userName) if err != nil { return } - if err := h.registerMachineForOIDCCallback(writer, user, nodeKey, idTokenExpiry); err != nil { + if err := h.registerNodeForOIDCCallback(writer, user, nodeKey, idTokenExpiry); err != nil { return } @@ -484,21 +484,21 @@ func validateOIDCAllowedUsers( return nil } -// validateMachine retrieves machine information if it exist +// validateNode retrieves node information if it exist // The error is not important, because if it does not -// exist, then this is a new machine and we will move +// exist, then this is a new node and we will move // on to registration. -func (h *Headscale) validateMachineForOIDCCallback( +func (h *Headscale) validateNodeForOIDCCallback( writer http.ResponseWriter, state string, claims *IDTokenClaims, expiry time.Time, ) (*key.NodePublic, bool, error) { - // retrieve machinekey from state cache + // retrieve nodekey from state cache nodeKeyIf, nodeKeyFound := h.registrationCache.Get(state) if !nodeKeyFound { log.Error(). - Msg("requested machine state key expired before authorisation completed") + Msg("requested node state key expired before authorisation completed") writer.Header().Set("Content-Type", "text/plain; charset=utf-8") writer.WriteHeader(http.StatusBadRequest) _, err := writer.Write([]byte("state has expired")) @@ -516,7 +516,7 @@ func (h *Headscale) validateMachineForOIDCCallback( nodeKeyFromCache, nodeKeyOK := nodeKeyIf.(string) if !nodeKeyOK { log.Error(). - Msg("requested machine state key is not a string") + Msg("requested node state key is not a string") writer.Header().Set("Content-Type", "text/plain; charset=utf-8") writer.WriteHeader(http.StatusBadRequest) _, err := writer.Write([]byte("state is invalid")) @@ -527,7 +527,7 @@ func (h *Headscale) validateMachineForOIDCCallback( Msg("Failed to write response") } - return nil, false, errOIDCInvalidMachineState + return nil, false, errOIDCInvalidNodeState } err := nodeKey.UnmarshalText( @@ -551,36 +551,36 @@ func (h *Headscale) validateMachineForOIDCCallback( return nil, false, err } - // retrieve machine information if it exist + // retrieve node information if it exist // The error is not important, because if it does not - // exist, then this is a new machine and we will move + // exist, then this is a new node and we will move // on to registration. - machine, _ := h.GetMachineByNodeKey(nodeKey) + node, _ := h.GetNodeByNodeKey(nodeKey) - if machine != nil { + if node != nil { log.Trace(). Caller(). - Str("machine", machine.Hostname). - Msg("machine already registered, reauthenticating") + Str("node", node.Hostname). + Msg("node already registered, reauthenticating") - err := h.RefreshMachine(machine, expiry) + err := h.RefreshNode(node, expiry) if err != nil { log.Error(). Caller(). Err(err). - Msg("Failed to refresh machine") + Msg("Failed to refresh node") http.Error( writer, - "Failed to refresh machine", + "Failed to refresh node", http.StatusInternalServerError, ) return nil, true, err } log.Debug(). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("expiresAt", fmt.Sprintf("%v", expiry)). - Msg("successfully refreshed machine") + Msg("successfully refreshed node") var content bytes.Buffer if err := oidcCallbackTemplate.Execute(&content, oidcCallbackTemplateConfig{ @@ -696,13 +696,13 @@ func (h *Headscale) findOrCreateNewUserForOIDCCallback( return user, nil } -func (h *Headscale) registerMachineForOIDCCallback( +func (h *Headscale) registerNodeForOIDCCallback( writer http.ResponseWriter, user *User, nodeKey *key.NodePublic, expiry time.Time, ) error { - if _, err := h.RegisterMachineFromAuthCallback( + if _, err := h.RegisterNodeFromAuthCallback( nodeKey.String(), user.Name, &expiry, @@ -711,10 +711,10 @@ func (h *Headscale) registerMachineForOIDCCallback( log.Error(). Caller(). Err(err). - Msg("could not register machine") + Msg("could not register node") writer.Header().Set("Content-Type", "text/plain; charset=utf-8") writer.WriteHeader(http.StatusInternalServerError) - _, werr := writer.Write([]byte("could not register machine")) + _, werr := writer.Write([]byte("could not register node")) if werr != nil { log.Error(). Caller(). diff --git a/preauth_keys.go b/preauth_keys.go index 3222c71d..17cceb6c 100644 --- a/preauth_keys.go +++ b/preauth_keys.go @@ -193,12 +193,12 @@ func (h *Headscale) checkKeyValidity(k string) (*PreAuthKey, error) { return &pak, nil } - machines := []Machine{} - if err := h.db.Preload("AuthKey").Where(&Machine{AuthKeyID: uint(pak.ID)}).Find(&machines).Error; err != nil { + nodes := []Node{} + if err := h.db.Preload("AuthKey").Where(&Node{AuthKeyID: uint(pak.ID)}).Find(&nodes).Error; err != nil { return nil, err } - if len(machines) != 0 || pak.Used { + if len(nodes) != 0 || pak.Used { return nil, ErrSingleUseAuthKeyHasBeenUsed } diff --git a/protocol_common.go b/protocol_common.go index 2a30046f..97e3774f 100644 --- a/protocol_common.go +++ b/protocol_common.go @@ -102,9 +102,9 @@ func (h *Headscale) handleRegisterCommon( isNoise bool, ) { now := time.Now().UTC() - machine, err := h.GetMachineByAnyKey(machineKey, registerRequest.NodeKey, registerRequest.OldNodeKey) + node, err := h.GetNodeByAnyKey(machineKey, registerRequest.NodeKey, registerRequest.OldNodeKey) if errors.Is(err, gorm.ErrRecordNotFound) { - // If the machine has AuthKey set, handle registration via PreAuthKeys + // If the node has AuthKey set, handle registration via PreAuthKeys if registerRequest.Auth.AuthKey != "" { h.handleAuthKeyCommon(writer, registerRequest, machineKey, isNoise) @@ -115,7 +115,7 @@ func (h *Headscale) handleRegisterCommon( // // TODO(juan): We could use this field to improve our protocol implementation, // and hold the request until the client closes it, or the interactive - // login is completed (i.e., the user registers the machine). + // login is completed (i.e., the user registers the node). // This is not implemented yet, as it is no strictly required. The only side-effect // is that the client will hammer headscale with requests until it gets a // successful RegisterResponse. @@ -123,19 +123,19 @@ func (h *Headscale) handleRegisterCommon( if _, ok := h.registrationCache.Get(NodePublicKeyStripPrefix(registerRequest.NodeKey)); ok { log.Debug(). Caller(). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Str("machine_key", machineKey.ShortString()). Str("node_key", registerRequest.NodeKey.ShortString()). Str("node_key_old", registerRequest.OldNodeKey.ShortString()). Str("follow_up", registerRequest.Followup). Bool("noise", isNoise). - Msg("Machine is waiting for interactive login") + Msg("Node is waiting for interactive login") select { case <-req.Context().Done(): return case <-time.After(registrationHoldoff): - h.handleNewMachineCommon(writer, registerRequest, machineKey, isNoise) + h.handleNewNodeCommon(writer, registerRequest, machineKey, isNoise) return } @@ -144,13 +144,13 @@ func (h *Headscale) handleRegisterCommon( log.Info(). Caller(). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Str("machine_key", machineKey.ShortString()). Str("node_key", registerRequest.NodeKey.ShortString()). Str("node_key_old", registerRequest.OldNodeKey.ShortString()). Str("follow_up", registerRequest.Followup). Bool("noise", isNoise). - Msg("New machine not yet in the database") + Msg("New node not yet in the database") givenName, err := h.GenerateGivenName( machineKey.String(), @@ -166,11 +166,11 @@ func (h *Headscale) handleRegisterCommon( return } - // The machine did not have a key to authenticate, which means + // The node did not have a key to authenticate, which means // that we rely on a method that calls back some how (OpenID or CLI) - // We create the machine and then keep it around until a callback + // We create the node and then keep it around until a callback // happens - newMachine := Machine{ + newNode := Node{ MachineKey: MachinePublicKeyStripPrefix(machineKey), Hostname: registerRequest.Hostinfo.Hostname, GivenName: givenName, @@ -183,42 +183,42 @@ func (h *Headscale) handleRegisterCommon( log.Trace(). Caller(). Bool("noise", isNoise). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Time("expiry", registerRequest.Expiry). Msg("Non-zero expiry time requested") - newMachine.Expiry = ®isterRequest.Expiry + newNode.Expiry = ®isterRequest.Expiry } h.registrationCache.Set( - newMachine.NodeKey, - newMachine, + newNode.NodeKey, + newNode, registerCacheExpiration, ) - h.handleNewMachineCommon(writer, registerRequest, machineKey, isNoise) + h.handleNewNodeCommon(writer, registerRequest, machineKey, isNoise) return } - // The machine is already in the DB. This could mean one of the following: - // - The machine is authenticated and ready to /map + // The node is already in the DB. This could mean one of the following: + // - The node is authenticated and ready to /map // - We are doing a key refresh - // - The machine is logged out (or expired) and pending to be authorized. TODO(juan): We need to keep alive the connection here - if machine != nil { + // - The node is logged out (or expired) and pending to be authorized. TODO(juan): We need to keep alive the connection here + if node != nil { // (juan): For a while we had a bug where we were not storing the MachineKey for the nodes using the TS2021, // due to a misunderstanding of the protocol https://github.com/juanfont/headscale/issues/1054 - // So if we have a not valid MachineKey (but we were able to fetch the machine with the NodeKeys), we update it. + // So if we have a not valid MachineKey (but we were able to fetch the node with the NodeKeys), we update it. var storedMachineKey key.MachinePublic err = storedMachineKey.UnmarshalText( - []byte(MachinePublicKeyEnsurePrefix(machine.MachineKey)), + []byte(MachinePublicKeyEnsurePrefix(node.MachineKey)), ) if err != nil || storedMachineKey.IsZero() { - machine.MachineKey = MachinePublicKeyStripPrefix(machineKey) - if err := h.db.Save(&machine).Error; err != nil { + node.MachineKey = MachinePublicKeyStripPrefix(machineKey) + if err := h.db.Save(&node).Error; err != nil { log.Error(). Caller(). Str("func", "RegistrationHandler"). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Err(err). Msg("Error saving machine key to database") @@ -229,34 +229,34 @@ func (h *Headscale) handleRegisterCommon( // If the NodeKey stored in headscale is the same as the key presented in a registration // request, then we have a node that is either: // - Trying to log out (sending a expiry in the past) - // - A valid, registered machine, looking for /map - // - Expired machine wanting to reauthenticate - if machine.NodeKey == NodePublicKeyStripPrefix(registerRequest.NodeKey) { + // - A valid, registered node, looking for /map + // - Expired node wanting to reauthenticate + if node.NodeKey == NodePublicKeyStripPrefix(registerRequest.NodeKey) { // The client sends an Expiry in the past if the client is requesting to expire the key (aka logout) // https://github.com/tailscale/tailscale/blob/main/tailcfg/tailcfg.go#L648 if !registerRequest.Expiry.IsZero() && registerRequest.Expiry.UTC().Before(now) { - h.handleMachineLogOutCommon(writer, *machine, machineKey, isNoise) + h.handleNodeLogOutCommon(writer, *node, machineKey, isNoise) return } - // If machine is not expired, and it is register, we have a already accepted this machine, + // If node is not expired, and it is register, we have a already accepted this node, // let it proceed with a valid registration - if !machine.isExpired() { - h.handleMachineValidRegistrationCommon(writer, *machine, machineKey, isNoise) + if !node.isExpired() { + h.handleNodeValidRegistrationCommon(writer, *node, machineKey, isNoise) return } } // The NodeKey we have matches OldNodeKey, which means this is a refresh after a key expiration - if machine.NodeKey == NodePublicKeyStripPrefix(registerRequest.OldNodeKey) && - !machine.isExpired() { - h.handleMachineRefreshKeyCommon( + if node.NodeKey == NodePublicKeyStripPrefix(registerRequest.OldNodeKey) && + !node.isExpired() { + h.handleNodeRefreshKeyCommon( writer, registerRequest, - *machine, + *node, machineKey, isNoise, ) @@ -272,20 +272,20 @@ func (h *Headscale) handleRegisterCommon( } } - // The machine has expired or it is logged out - h.handleMachineExpiredOrLoggedOutCommon(writer, registerRequest, *machine, machineKey, isNoise) + // The node has expired or it is logged out + h.handleNodeExpiredOrLoggedOutCommon(writer, registerRequest, *node, machineKey, isNoise) // TODO(juan): RegisterRequest includes an Expiry time, that we could optionally use - machine.Expiry = &time.Time{} + node.Expiry = &time.Time{} // If we are here it means the client needs to be reauthorized, // we need to make sure the NodeKey matches the one in the request // TODO(juan): What happens when using fast user switching between two // headscale-managed tailnets? - machine.NodeKey = NodePublicKeyStripPrefix(registerRequest.NodeKey) + node.NodeKey = NodePublicKeyStripPrefix(registerRequest.NodeKey) h.registrationCache.Set( NodePublicKeyStripPrefix(registerRequest.NodeKey), - *machine, + *node, registerCacheExpiration, ) @@ -306,7 +306,7 @@ func (h *Headscale) handleAuthKeyCommon( ) { log.Debug(). Str("func", "handleAuthKeyCommon"). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Bool("noise", isNoise). Msgf("Processing auth key for %s", registerRequest.Hostinfo.Hostname) resp := tailcfg.RegisterResponse{} @@ -317,7 +317,7 @@ func (h *Headscale) handleAuthKeyCommon( Caller(). Str("func", "handleAuthKeyCommon"). Bool("noise", isNoise). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Err(err). Msg("Failed authentication via AuthKey") resp.MachineAuthorized = false @@ -328,11 +328,11 @@ func (h *Headscale) handleAuthKeyCommon( Caller(). Str("func", "handleAuthKeyCommon"). Bool("noise", isNoise). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Err(err). Msg("Cannot encode message") http.Error(writer, "Internal server error", http.StatusInternalServerError) - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). + nodeRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). Inc() return @@ -353,14 +353,14 @@ func (h *Headscale) handleAuthKeyCommon( Caller(). Str("func", "handleAuthKeyCommon"). Bool("noise", isNoise). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Msg("Failed authentication via AuthKey") if pak != nil { - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). + nodeRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). Inc() } else { - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", "unknown").Inc() + nodeRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", "unknown").Inc() } return @@ -369,33 +369,33 @@ func (h *Headscale) handleAuthKeyCommon( log.Debug(). Str("func", "handleAuthKeyCommon"). Bool("noise", isNoise). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Msg("Authentication key was valid, proceeding to acquire IP addresses") nodeKey := NodePublicKeyStripPrefix(registerRequest.NodeKey) - // retrieve machine information if it exist + // retrieve node information if it exist // The error is not important, because if it does not - // exist, then this is a new machine and we will move + // exist, then this is a new node and we will move // on to registration. - machine, _ := h.GetMachineByAnyKey(machineKey, registerRequest.NodeKey, registerRequest.OldNodeKey) - if machine != nil { + node, _ := h.GetNodeByAnyKey(machineKey, registerRequest.NodeKey, registerRequest.OldNodeKey) + if node != nil { log.Trace(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). - Msg("machine was already registered before, refreshing with new auth key") + Str("node", node.Hostname). + Msg("node was already registered before, refreshing with new auth key") - machine.NodeKey = nodeKey - machine.AuthKeyID = uint(pak.ID) - err := h.RefreshMachine(machine, registerRequest.Expiry) + node.NodeKey = nodeKey + node.AuthKeyID = uint(pak.ID) + err := h.RefreshNode(node, registerRequest.Expiry) if err != nil { log.Error(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Err(err). - Msg("Failed to refresh machine") + Msg("Failed to refresh node") return } @@ -403,16 +403,16 @@ func (h *Headscale) handleAuthKeyCommon( aclTags := pak.toProto().AclTags if len(aclTags) > 0 { // This conditional preserves the existing behaviour, although SaaS would reset the tags on auth-key login - err = h.SetTags(machine, aclTags) + err = h.SetTags(node, aclTags) if err != nil { log.Error(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Strs("aclTags", aclTags). Err(err). - Msg("Failed to set tags after refreshing machine") + Msg("Failed to set tags after refreshing node") return } @@ -432,7 +432,7 @@ func (h *Headscale) handleAuthKeyCommon( return } - machineToRegister := Machine{ + nodeToRegister := Node{ Hostname: registerRequest.Hostinfo.Hostname, GivenName: givenName, UserID: pak.User.ID, @@ -445,16 +445,16 @@ func (h *Headscale) handleAuthKeyCommon( ForcedTags: pak.toProto().AclTags, } - machine, err = h.RegisterMachine( - machineToRegister, + node, err = h.RegisterNode( + nodeToRegister, ) if err != nil { log.Error(). Caller(). Bool("noise", isNoise). Err(err). - Msg("could not register machine") - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). + Msg("could not register node") + nodeRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). Inc() http.Error(writer, "Internal server error", http.StatusInternalServerError) @@ -469,7 +469,7 @@ func (h *Headscale) handleAuthKeyCommon( Bool("noise", isNoise). Err(err). Msg("Failed to use pre-auth key") - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). + nodeRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). Inc() http.Error(writer, "Internal server error", http.StatusInternalServerError) @@ -488,16 +488,16 @@ func (h *Headscale) handleAuthKeyCommon( Caller(). Bool("noise", isNoise). Str("func", "handleAuthKeyCommon"). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Err(err). Msg("Cannot encode message") - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). + nodeRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name). Inc() http.Error(writer, "Internal server error", http.StatusInternalServerError) return } - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "success", pak.User.Name). + nodeRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "success", pak.User.Name). Inc() writer.Header().Set("Content-Type", "application/json; charset=utf-8") writer.WriteHeader(http.StatusOK) @@ -513,14 +513,14 @@ func (h *Headscale) handleAuthKeyCommon( log.Info(). Str("func", "handleAuthKeyCommon"). Bool("noise", isNoise). - Str("machine", registerRequest.Hostinfo.Hostname). - Str("ips", strings.Join(machine.IPAddresses.ToStringSlice(), ", ")). + Str("node", registerRequest.Hostinfo.Hostname). + Str("ips", strings.Join(node.IPAddresses.ToStringSlice(), ", ")). Msg("Successfully authenticated via AuthKey") } -// handleNewMachineCommon exposes for both legacy and Noise the functionality to get a URL -// for authorizing the machine. This url is then showed to the user by the local Tailscale client. -func (h *Headscale) handleNewMachineCommon( +// handleNewNodeCommon exposes for both legacy and Noise the functionality to get a URL +// for authorizing the node. This url is then showed to the user by the local Tailscale client. +func (h *Headscale) handleNewNodeCommon( writer http.ResponseWriter, registerRequest tailcfg.RegisterRequest, machineKey key.MachinePublic, @@ -528,11 +528,11 @@ func (h *Headscale) handleNewMachineCommon( ) { resp := tailcfg.RegisterResponse{} - // The machine registration is new, redirect the client to the registration URL + // The node registration is new, redirect the client to the registration URL log.Debug(). Caller(). Bool("noise", isNoise). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Msg("The node seems to be new, sending auth url") if h.oauth2Config != nil { @@ -574,13 +574,13 @@ func (h *Headscale) handleNewMachineCommon( Caller(). Bool("noise", isNoise). Str("AuthURL", resp.AuthURL). - Str("machine", registerRequest.Hostinfo.Hostname). + Str("node", registerRequest.Hostinfo.Hostname). Msg("Successfully sent auth url") } -func (h *Headscale) handleMachineLogOutCommon( +func (h *Headscale) handleNodeLogOutCommon( writer http.ResponseWriter, - machine Machine, + node Node, machineKey key.MachinePublic, isNoise bool, ) { @@ -588,17 +588,17 @@ func (h *Headscale) handleMachineLogOutCommon( log.Info(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Client requested logout") - err := h.ExpireMachine(&machine) + err := h.ExpireNode(&node) if err != nil { log.Error(). Caller(). Bool("noise", isNoise). - Str("func", "handleMachineLogOutCommon"). + Str("func", "handleNodeLogOutCommon"). Err(err). - Msg("Failed to expire machine") + Msg("Failed to expire node") http.Error(writer, "Internal server error", http.StatusInternalServerError) return @@ -607,7 +607,7 @@ func (h *Headscale) handleMachineLogOutCommon( resp.AuthURL = "" resp.MachineAuthorized = false resp.NodeKeyExpired = true - resp.User = *machine.User.toTailscaleUser() + resp.User = *node.User.toTailscaleUser() respBody, err := h.marshalResponse(resp, machineKey, isNoise) if err != nil { log.Error(). @@ -633,13 +633,13 @@ func (h *Headscale) handleMachineLogOutCommon( return } - if machine.isEphemeral() { - err = h.HardDeleteMachine(&machine) + if node.isEphemeral() { + err = h.HardDeleteNode(&node) if err != nil { log.Error(). Err(err). - Str("machine", machine.Hostname). - Msg("Cannot delete ephemeral machine from the database") + Str("node", node.Hostname). + Msg("Cannot delete ephemeral node from the database") } return @@ -648,29 +648,29 @@ func (h *Headscale) handleMachineLogOutCommon( log.Info(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Successfully logged out") } -func (h *Headscale) handleMachineValidRegistrationCommon( +func (h *Headscale) handleNodeValidRegistrationCommon( writer http.ResponseWriter, - machine Machine, + node Node, machineKey key.MachinePublic, isNoise bool, ) { resp := tailcfg.RegisterResponse{} - // The machine registration is valid, respond with redirect to /map + // The node registration is valid, respond with redirect to /map log.Debug(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Client is registered and we have the current NodeKey. All clear to /map") resp.AuthURL = "" resp.MachineAuthorized = true - resp.User = *machine.User.toTailscaleUser() - resp.Login = *machine.User.toTailscaleLogin() + resp.User = *node.User.toTailscaleUser() + resp.Login = *node.User.toTailscaleLogin() respBody, err := h.marshalResponse(resp, machineKey, isNoise) if err != nil { @@ -679,13 +679,13 @@ func (h *Headscale) handleMachineValidRegistrationCommon( Bool("noise", isNoise). Err(err). Msg("Cannot encode message") - machineRegistrations.WithLabelValues("update", "web", "error", machine.User.Name). + nodeRegistrations.WithLabelValues("update", "web", "error", node.User.Name). Inc() http.Error(writer, "Internal server error", http.StatusInternalServerError) return } - machineRegistrations.WithLabelValues("update", "web", "success", machine.User.Name). + nodeRegistrations.WithLabelValues("update", "web", "success", node.User.Name). Inc() writer.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -702,14 +702,14 @@ func (h *Headscale) handleMachineValidRegistrationCommon( log.Info(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). - Msg("Machine successfully authorized") + Str("node", node.Hostname). + Msg("Node successfully authorized") } -func (h *Headscale) handleMachineRefreshKeyCommon( +func (h *Headscale) handleNodeRefreshKeyCommon( writer http.ResponseWriter, registerRequest tailcfg.RegisterRequest, - machine Machine, + node Node, machineKey key.MachinePublic, isNoise bool, ) { @@ -718,22 +718,22 @@ func (h *Headscale) handleMachineRefreshKeyCommon( log.Info(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("We have the OldNodeKey in the database. This is a key refresh") - machine.NodeKey = NodePublicKeyStripPrefix(registerRequest.NodeKey) + node.NodeKey = NodePublicKeyStripPrefix(registerRequest.NodeKey) - if err := h.db.Save(&machine).Error; err != nil { + if err := h.db.Save(&node).Error; err != nil { log.Error(). Caller(). Err(err). - Msg("Failed to update machine key in the database") + Msg("Failed to update node key in the database") http.Error(writer, "Internal server error", http.StatusInternalServerError) return } resp.AuthURL = "" - resp.User = *machine.User.toTailscaleUser() + resp.User = *node.User.toTailscaleUser() respBody, err := h.marshalResponse(resp, machineKey, isNoise) if err != nil { log.Error(). @@ -762,14 +762,14 @@ func (h *Headscale) handleMachineRefreshKeyCommon( Bool("noise", isNoise). Str("node_key", registerRequest.NodeKey.ShortString()). Str("old_node_key", registerRequest.OldNodeKey.ShortString()). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Node key successfully refreshed") } -func (h *Headscale) handleMachineExpiredOrLoggedOutCommon( +func (h *Headscale) handleNodeExpiredOrLoggedOutCommon( writer http.ResponseWriter, registerRequest tailcfg.RegisterRequest, - machine Machine, + node Node, machineKey key.MachinePublic, isNoise bool, ) { @@ -785,11 +785,11 @@ func (h *Headscale) handleMachineExpiredOrLoggedOutCommon( log.Trace(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("machine_key", machineKey.ShortString()). Str("node_key", registerRequest.NodeKey.ShortString()). Str("node_key_old", registerRequest.OldNodeKey.ShortString()). - Msg("Machine registration has expired or logged out. Sending a auth url to register") + Msg("Node registration has expired or logged out. Sending a auth url to register") if h.oauth2Config != nil { resp.AuthURL = fmt.Sprintf("%s/oidc/register/%s", @@ -808,13 +808,13 @@ func (h *Headscale) handleMachineExpiredOrLoggedOutCommon( Bool("noise", isNoise). Err(err). Msg("Cannot encode message") - machineRegistrations.WithLabelValues("reauth", "web", "error", machine.User.Name). + nodeRegistrations.WithLabelValues("reauth", "web", "error", node.User.Name). Inc() http.Error(writer, "Internal server error", http.StatusInternalServerError) return } - machineRegistrations.WithLabelValues("reauth", "web", "success", machine.User.Name). + nodeRegistrations.WithLabelValues("reauth", "web", "success", node.User.Name). Inc() writer.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -834,6 +834,6 @@ func (h *Headscale) handleMachineExpiredOrLoggedOutCommon( Str("machine_key", machineKey.ShortString()). Str("node_key", registerRequest.NodeKey.ShortString()). Str("node_key_old", registerRequest.OldNodeKey.ShortString()). - Str("machine", machine.Hostname). - Msg("Machine logged out. Sent AuthURL for reauthentication") + Str("node", node.Hostname). + Msg("Node logged out. Sent AuthURL for reauthentication") } diff --git a/protocol_common_poll.go b/protocol_common_poll.go index 09df6309..1406a647 100644 --- a/protocol_common_poll.go +++ b/protocol_common_poll.go @@ -16,29 +16,29 @@ const ( type contextKey string -const machineNameContextKey = contextKey("machineName") +const nodeNameContextKey = contextKey("machineName") // handlePollCommon is the common code for the legacy and Noise protocols to // managed the poll loop. func (h *Headscale) handlePollCommon( writer http.ResponseWriter, ctx context.Context, - machine *Machine, + node *Node, mapRequest tailcfg.MapRequest, isNoise bool, ) { - machine.Hostname = mapRequest.Hostinfo.Hostname - machine.HostInfo = HostInfo(*mapRequest.Hostinfo) - machine.DiscoKey = DiscoPublicKeyStripPrefix(mapRequest.DiscoKey) + node.Hostname = mapRequest.Hostinfo.Hostname + node.HostInfo = HostInfo(*mapRequest.Hostinfo) + node.DiscoKey = DiscoPublicKeyStripPrefix(mapRequest.DiscoKey) now := time.Now().UTC() - err := h.processMachineRoutes(machine) + err := h.processNodeRoutes(node) if err != nil { log.Error(). Caller(). Err(err). - Str("machine", machine.Hostname). - Msg("Error processing machine routes") + Str("node", node.Hostname). + Msg("Error processing node routes") } // update ACLRules with peer informations (to update server tags if necessary) @@ -48,17 +48,17 @@ func (h *Headscale) handlePollCommon( log.Error(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Err(err) } // update routes with peer information - err = h.EnableAutoApprovedRoutes(machine) + err = h.EnableAutoApprovedRoutes(node) if err != nil { log.Error(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Err(err). Msg("Error running auto approved routes") } @@ -73,32 +73,32 @@ func (h *Headscale) handlePollCommon( // The intended use is for clients to discover the DERP map at start-up // before their first real endpoint update. if !mapRequest.ReadOnly { - machine.Endpoints = mapRequest.Endpoints - machine.LastSeen = &now + node.Endpoints = mapRequest.Endpoints + node.LastSeen = &now } - if err := h.db.Updates(machine).Error; err != nil { + if err := h.db.Updates(node).Error; err != nil { if err != nil { log.Error(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("node_key", machine.NodeKey). - Str("machine", machine.Hostname). + Str("node_key", node.NodeKey). + Str("node", node.Hostname). Err(err). - Msg("Failed to persist/update machine in the database") + Msg("Failed to persist/update node in the database") http.Error(writer, "", http.StatusInternalServerError) return } } - mapResp, err := h.getMapResponseData(mapRequest, machine, isNoise) + mapResp, err := h.getMapResponseData(mapRequest, node, isNoise) if err != nil { log.Error(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("node_key", machine.NodeKey). - Str("machine", machine.Hostname). + Str("node_key", node.NodeKey). + Str("node", node.Hostname). Err(err). Msg("Failed to get Map response") http.Error(writer, "", http.StatusInternalServerError) @@ -114,7 +114,7 @@ func (h *Headscale) handlePollCommon( log.Debug(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Bool("readOnly", mapRequest.ReadOnly). Bool("omitPeers", mapRequest.OmitPeers). Bool("stream", mapRequest.Stream). @@ -124,7 +124,7 @@ func (h *Headscale) handlePollCommon( log.Info(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Client is starting up. Probably interested in a DERP map") writer.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -155,14 +155,14 @@ func (h *Headscale) handlePollCommon( log.Trace(). Caller(). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Loading or creating update channel") const chanSize = 8 updateChan := make(chan struct{}, chanSize) pollDataChan := make(chan []byte, chanSize) - defer closeChanWithLog(pollDataChan, machine.Hostname, "pollDataChan") + defer closeChanWithLog(pollDataChan, node.Hostname, "pollDataChan") keepAliveChan := make(chan []byte) @@ -170,7 +170,7 @@ func (h *Headscale) handlePollCommon( log.Info(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Client sent endpoint update and is ok with a response without peer list") writer.Header().Set("Content-Type", "application/json; charset=utf-8") writer.WriteHeader(http.StatusOK) @@ -183,7 +183,7 @@ func (h *Headscale) handlePollCommon( } // It sounds like we should update the nodes when we have received a endpoint update // even tho the comments in the tailscale code dont explicitly say so. - updateRequestsFromNode.WithLabelValues(machine.User.Name, machine.Hostname, "endpoint-update"). + updateRequestsFromNode.WithLabelValues(node.User.Name, node.Hostname, "endpoint-update"). Inc() updateChan <- struct{}{} @@ -192,7 +192,7 @@ func (h *Headscale) handlePollCommon( log.Warn(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Ignoring request, don't know how to handle it") http.Error(writer, "", http.StatusBadRequest) @@ -202,28 +202,28 @@ func (h *Headscale) handlePollCommon( log.Info(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Client is ready to access the tailnet") log.Info(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Sending initial map") pollDataChan <- mapResp log.Info(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Notifying peers") - updateRequestsFromNode.WithLabelValues(machine.User.Name, machine.Hostname, "full-update"). + updateRequestsFromNode.WithLabelValues(node.User.Name, node.Hostname, "full-update"). Inc() updateChan <- struct{}{} h.pollNetMapStream( writer, ctx, - machine, + node, mapRequest, pollDataChan, keepAliveChan, @@ -234,7 +234,7 @@ func (h *Headscale) handlePollCommon( log.Trace(). Str("handler", "PollNetMap"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Finished stream, closing PollNetMap session") } @@ -243,7 +243,7 @@ func (h *Headscale) handlePollCommon( func (h *Headscale) pollNetMapStream( writer http.ResponseWriter, ctxReq context.Context, - machine *Machine, + node *Node, mapRequest tailcfg.MapRequest, pollDataChan chan []byte, keepAliveChan chan []byte, @@ -253,7 +253,7 @@ func (h *Headscale) pollNetMapStream( h.pollNetMapStreamWG.Add(1) defer h.pollNetMapStreamWG.Done() - ctx := context.WithValue(ctxReq, machineNameContextKey, machine.Hostname) + ctx := context.WithValue(ctxReq, nodeNameContextKey, node.Hostname) ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -263,20 +263,20 @@ func (h *Headscale) pollNetMapStream( updateChan, keepAliveChan, mapRequest, - machine, + node, isNoise, ) log.Trace(). Str("handler", "pollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("Waiting for data to stream...") log.Trace(). Str("handler", "pollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msgf("pollData is %#v, keepAliveChan is %#v, updateChan is %#v", pollDataChan, keepAliveChan, updateChan) for { @@ -285,7 +285,7 @@ func (h *Headscale) pollNetMapStream( log.Trace(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "pollData"). Int("bytes", len(data)). Msg("Sending data received via pollData channel") @@ -294,7 +294,7 @@ func (h *Headscale) pollNetMapStream( log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "pollData"). Err(err). Msg("Cannot write data") @@ -308,7 +308,7 @@ func (h *Headscale) pollNetMapStream( Caller(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "pollData"). Msg("Cannot cast writer to http.Flusher") } else { @@ -318,43 +318,43 @@ func (h *Headscale) pollNetMapStream( log.Trace(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "pollData"). Int("bytes", len(data)). Msg("Data from pollData channel written successfully") // TODO(kradalby): Abstract away all the database calls, this can cause race conditions - // when an outdated machine object is kept alive, e.g. db is update from + // when an outdated node object is kept alive, e.g. db is update from // command line, but then overwritten. - err = h.UpdateMachineFromDatabase(machine) + err = h.UpdateNodeFromDatabase(node) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "pollData"). Err(err). - Msg("Cannot update machine from database") + Msg("Cannot update node from database") // client has been removed from database // since the stream opened, terminate connection. return } now := time.Now().UTC() - machine.LastSeen = &now + node.LastSeen = &now - lastStateUpdate.WithLabelValues(machine.User.Name, machine.Hostname). + lastStateUpdate.WithLabelValues(node.User.Name, node.Hostname). Set(float64(now.Unix())) - machine.LastSuccessfulUpdate = &now + node.LastSuccessfulUpdate = &now - err = h.TouchMachine(machine) + err = h.TouchNode(node) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "pollData"). Err(err). - Msg("Cannot update machine LastSuccessfulUpdate") + Msg("Cannot update node LastSuccessfulUpdate") return } @@ -362,15 +362,15 @@ func (h *Headscale) pollNetMapStream( log.Trace(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "pollData"). Int("bytes", len(data)). - Msg("Machine entry in database updated successfully after sending data") + Msg("Node entry in database updated successfully after sending data") case data := <-keepAliveChan: log.Trace(). Str("handler", "PollNetMapStream"). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "keepAlive"). Int("bytes", len(data)). Msg("Sending keep alive message") @@ -379,7 +379,7 @@ func (h *Headscale) pollNetMapStream( log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "keepAlive"). Err(err). Msg("Cannot write keep alive message") @@ -392,7 +392,7 @@ func (h *Headscale) pollNetMapStream( Caller(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "keepAlive"). Msg("Cannot cast writer to http.Flusher") } else { @@ -402,38 +402,38 @@ func (h *Headscale) pollNetMapStream( log.Trace(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "keepAlive"). Int("bytes", len(data)). Msg("Keep alive sent successfully") // TODO(kradalby): Abstract away all the database calls, this can cause race conditions - // when an outdated machine object is kept alive, e.g. db is update from + // when an outdated node object is kept alive, e.g. db is update from // command line, but then overwritten. - err = h.UpdateMachineFromDatabase(machine) + err = h.UpdateNodeFromDatabase(node) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "keepAlive"). Err(err). - Msg("Cannot update machine from database") + Msg("Cannot update node from database") // client has been removed from database // since the stream opened, terminate connection. return } now := time.Now().UTC() - machine.LastSeen = &now - err = h.TouchMachine(machine) + node.LastSeen = &now + err = h.TouchNode(node) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "keepAlive"). Err(err). - Msg("Cannot update machine LastSeen") + Msg("Cannot update node LastSeen") return } @@ -441,39 +441,39 @@ func (h *Headscale) pollNetMapStream( log.Trace(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "keepAlive"). Int("bytes", len(data)). - Msg("Machine updated successfully after sending keep alive") + Msg("Node updated successfully after sending keep alive") case <-updateChan: log.Trace(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "update"). Msg("Received a request for update") - updateRequestsReceivedOnChannel.WithLabelValues(machine.User.Name, machine.Hostname). + updateRequestsReceivedOnChannel.WithLabelValues(node.User.Name, node.Hostname). Inc() - if h.isOutdated(machine) { + if h.isOutdated(node) { var lastUpdate time.Time - if machine.LastSuccessfulUpdate != nil { - lastUpdate = *machine.LastSuccessfulUpdate + if node.LastSuccessfulUpdate != nil { + lastUpdate = *node.LastSuccessfulUpdate } log.Debug(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Time("last_successful_update", lastUpdate). - Time("last_state_change", h.getLastStateChange(machine.User)). - Msgf("There has been updates since the last successful update to %s", machine.Hostname) - data, err := h.getMapResponseData(mapRequest, machine, isNoise) + Time("last_state_change", h.getLastStateChange(node.User)). + Msgf("There has been updates since the last successful update to %s", node.Hostname) + data, err := h.getMapResponseData(mapRequest, node, isNoise) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "update"). Err(err). Msg("Could not get the map update") @@ -485,11 +485,11 @@ func (h *Headscale) pollNetMapStream( log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "update"). Err(err). Msg("Could not write the map response") - updateRequestsSentToNode.WithLabelValues(machine.User.Name, machine.Hostname, "failed"). + updateRequestsSentToNode.WithLabelValues(node.User.Name, node.Hostname, "failed"). Inc() return @@ -501,7 +501,7 @@ func (h *Headscale) pollNetMapStream( Caller(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "update"). Msg("Cannot cast writer to http.Flusher") } else { @@ -511,10 +511,10 @@ func (h *Headscale) pollNetMapStream( log.Trace(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "update"). Msg("Updated Map has been sent") - updateRequestsSentToNode.WithLabelValues(machine.User.Name, machine.Hostname, "success"). + updateRequestsSentToNode.WithLabelValues(node.User.Name, node.Hostname, "success"). Inc() // Keep track of the last successful update, @@ -522,17 +522,17 @@ func (h *Headscale) pollNetMapStream( // is not picked up by a client and we use this // to determine if we should "force" an update. // TODO(kradalby): Abstract away all the database calls, this can cause race conditions - // when an outdated machine object is kept alive, e.g. db is update from + // when an outdated node object is kept alive, e.g. db is update from // command line, but then overwritten. - err = h.UpdateMachineFromDatabase(machine) + err = h.UpdateNodeFromDatabase(node) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "update"). Err(err). - Msg("Cannot update machine from database") + Msg("Cannot update node from database") // client has been removed from database // since the stream opened, terminate connection. @@ -540,69 +540,69 @@ func (h *Headscale) pollNetMapStream( } now := time.Now().UTC() - lastStateUpdate.WithLabelValues(machine.User.Name, machine.Hostname). + lastStateUpdate.WithLabelValues(node.User.Name, node.Hostname). Set(float64(now.Unix())) - machine.LastSuccessfulUpdate = &now + node.LastSuccessfulUpdate = &now - err = h.TouchMachine(machine) + err = h.TouchNode(node) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "update"). Err(err). - Msg("Cannot update machine LastSuccessfulUpdate") + Msg("Cannot update node LastSuccessfulUpdate") return } } else { var lastUpdate time.Time - if machine.LastSuccessfulUpdate != nil { - lastUpdate = *machine.LastSuccessfulUpdate + if node.LastSuccessfulUpdate != nil { + lastUpdate = *node.LastSuccessfulUpdate } log.Trace(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Time("last_successful_update", lastUpdate). - Time("last_state_change", h.getLastStateChange(machine.User)). - Msgf("%s is up to date", machine.Hostname) + Time("last_state_change", h.getLastStateChange(node.User)). + Msgf("%s is up to date", node.Hostname) } case <-ctx.Done(): log.Info(). Str("handler", "PollNetMapStream"). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("The client has closed the connection") // TODO: Abstract away all the database calls, this can cause race conditions - // when an outdated machine object is kept alive, e.g. db is update from + // when an outdated node object is kept alive, e.g. db is update from // command line, but then overwritten. - err := h.UpdateMachineFromDatabase(machine) + err := h.UpdateNodeFromDatabase(node) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "Done"). Err(err). - Msg("Cannot update machine from database") + Msg("Cannot update node from database") // client has been removed from database // since the stream opened, terminate connection. return } now := time.Now().UTC() - machine.LastSeen = &now - err = h.TouchMachine(machine) + node.LastSeen = &now + err = h.TouchNode(node) if err != nil { log.Error(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Str("channel", "Done"). Err(err). - Msg("Cannot update machine LastSeen") + Msg("Cannot update node LastSeen") } // The connection has been closed, so we can stop polling. @@ -612,7 +612,7 @@ func (h *Headscale) pollNetMapStream( log.Info(). Str("handler", "PollNetMapStream"). Bool("noise", isNoise). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Msg("The long-poll handler is shutting down") return @@ -625,7 +625,7 @@ func (h *Headscale) scheduledPollWorker( updateChan chan struct{}, keepAliveChan chan []byte, mapRequest tailcfg.MapRequest, - machine *Machine, + node *Node, isNoise bool, ) { keepAliveTicker := time.NewTicker(keepAliveInterval) @@ -633,12 +633,12 @@ func (h *Headscale) scheduledPollWorker( defer closeChanWithLog( updateChan, - fmt.Sprint(ctx.Value(machineNameContextKey)), + fmt.Sprint(ctx.Value(nodeNameContextKey)), "updateChan", ) defer closeChanWithLog( keepAliveChan, - fmt.Sprint(ctx.Value(machineNameContextKey)), + fmt.Sprint(ctx.Value(nodeNameContextKey)), "keepAliveChan", ) @@ -648,7 +648,7 @@ func (h *Headscale) scheduledPollWorker( return case <-keepAliveTicker.C: - data, err := h.getMapKeepAliveResponseData(mapRequest, machine, isNoise) + data, err := h.getMapKeepAliveResponseData(mapRequest, node, isNoise) if err != nil { log.Error(). Str("func", "keepAlive"). @@ -661,7 +661,7 @@ func (h *Headscale) scheduledPollWorker( log.Debug(). Str("func", "keepAlive"). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Bool("noise", isNoise). Msg("Sending keepalive") select { @@ -673,10 +673,10 @@ func (h *Headscale) scheduledPollWorker( case <-updateCheckerTicker.C: log.Debug(). Str("func", "scheduledPollWorker"). - Str("machine", machine.Hostname). + Str("node", node.Hostname). Bool("noise", isNoise). Msg("Sending update request") - updateRequestsFromNode.WithLabelValues(machine.User.Name, machine.Hostname, "scheduled-update"). + updateRequestsFromNode.WithLabelValues(node.User.Name, node.Hostname, "scheduled-update"). Inc() select { case updateChan <- struct{}{}: @@ -687,10 +687,10 @@ func (h *Headscale) scheduledPollWorker( } } -func closeChanWithLog[C chan []byte | chan struct{}](channel C, machine, name string) { +func closeChanWithLog[C chan []byte | chan struct{}](channel C, node, name string) { log.Trace(). Str("handler", "PollNetMap"). - Str("machine", machine). + Str("node", node). Str("channel", "Done"). Msg(fmt.Sprintf("Closing %s channel", name)) diff --git a/protocol_common_utils.go b/protocol_common_utils.go index 96c236d0..a5fdeff7 100644 --- a/protocol_common_utils.go +++ b/protocol_common_utils.go @@ -14,10 +14,10 @@ import ( func (h *Headscale) getMapResponseData( mapRequest tailcfg.MapRequest, - machine *Machine, + node *Node, isNoise bool, ) ([]byte, error) { - mapResponse, err := h.generateMapResponse(mapRequest, machine) + mapResponse, err := h.generateMapResponse(mapRequest, node) if err != nil { return nil, err } @@ -27,7 +27,7 @@ func (h *Headscale) getMapResponseData( } var machineKey key.MachinePublic - err = machineKey.UnmarshalText([]byte(MachinePublicKeyEnsurePrefix(machine.MachineKey))) + err = machineKey.UnmarshalText([]byte(MachinePublicKeyEnsurePrefix(node.MachineKey))) if err != nil { log.Error(). Caller(). @@ -42,7 +42,7 @@ func (h *Headscale) getMapResponseData( func (h *Headscale) getMapKeepAliveResponseData( mapRequest tailcfg.MapRequest, - machine *Machine, + node *Node, isNoise bool, ) ([]byte, error) { keepAliveResponse := tailcfg.MapResponse{ @@ -54,7 +54,7 @@ func (h *Headscale) getMapKeepAliveResponseData( } var machineKey key.MachinePublic - err := machineKey.UnmarshalText([]byte(MachinePublicKeyEnsurePrefix(machine.MachineKey))) + err := machineKey.UnmarshalText([]byte(MachinePublicKeyEnsurePrefix(node.MachineKey))) if err != nil { log.Error(). Caller(). diff --git a/protocol_legacy.go b/protocol_legacy.go index 99f68e5e..37809abd 100644 --- a/protocol_legacy.go +++ b/protocol_legacy.go @@ -12,7 +12,7 @@ import ( "tailscale.com/types/key" ) -// RegistrationHandler handles the actual registration process of a machine +// RegistrationHandler handles the actual registration process of a node // Endpoint /machine/:mkey. func (h *Headscale) RegistrationHandler( writer http.ResponseWriter, @@ -38,7 +38,7 @@ func (h *Headscale) RegistrationHandler( Caller(). Err(err). Msg("Cannot parse machine key") - machineRegistrations.WithLabelValues("unknown", "web", "error", "unknown").Inc() + nodeRegistrations.WithLabelValues("unknown", "web", "error", "unknown").Inc() http.Error(writer, "Cannot parse machine key", http.StatusBadRequest) return @@ -50,7 +50,7 @@ func (h *Headscale) RegistrationHandler( Caller(). Err(err). Msg("Cannot decode message") - machineRegistrations.WithLabelValues("unknown", "web", "error", "unknown").Inc() + nodeRegistrations.WithLabelValues("unknown", "web", "error", "unknown").Inc() http.Error(writer, "Cannot decode message", http.StatusBadRequest) return diff --git a/protocol_legacy_poll.go b/protocol_legacy_poll.go index a8d9343a..d250f057 100644 --- a/protocol_legacy_poll.go +++ b/protocol_legacy_poll.go @@ -67,12 +67,12 @@ func (h *Headscale) PollNetMapHandler( return } - machine, err := h.GetMachineByMachineKey(machineKey) + node, err := h.GetNodeByMachineKey(machineKey) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { log.Warn(). Str("handler", "PollNetMap"). - Msgf("Ignoring request, cannot find machine with key %s", machineKey.String()) + Msgf("Ignoring request, cannot find node with mkey %s", machineKey.String()) http.Error(writer, "", http.StatusUnauthorized) @@ -80,7 +80,7 @@ func (h *Headscale) PollNetMapHandler( } log.Error(). Str("handler", "PollNetMap"). - Msgf("Failed to fetch machine from the database with Machine key: %s", machineKey.String()) + Msgf("Failed to fetch node from the database with Machine key: %s", machineKey.String()) http.Error(writer, "", http.StatusInternalServerError) return @@ -89,8 +89,8 @@ func (h *Headscale) PollNetMapHandler( log.Trace(). Str("handler", "PollNetMap"). Str("id", machineKeyStr). - Str("machine", machine.Hostname). - Msg("A machine is entering polling via the legacy protocol") + Str("machine", node.Hostname). + Msg("A node is entering polling via the legacy protocol") - h.handlePollCommon(writer, req.Context(), machine, mapRequest, false) + h.handlePollCommon(writer, req.Context(), node, mapRequest, false) } diff --git a/protocol_noise.go b/protocol_noise.go index 1d1b9c8a..3b22e12e 100644 --- a/protocol_noise.go +++ b/protocol_noise.go @@ -9,7 +9,7 @@ import ( "tailscale.com/tailcfg" ) -// // NoiseRegistrationHandler handles the actual registration process of a machine. +// NoiseRegistrationHandler handles the actual registration process of a node. func (t *ts2021App) NoiseRegistrationHandler( writer http.ResponseWriter, req *http.Request, @@ -27,7 +27,7 @@ func (t *ts2021App) NoiseRegistrationHandler( Caller(). Err(err). Msg("Cannot parse RegisterRequest") - machineRegistrations.WithLabelValues("unknown", "web", "error", "unknown").Inc() + nodeRegistrations.WithLabelValues("unknown", "web", "error", "unknown").Inc() http.Error(writer, "Internal error", http.StatusInternalServerError) return diff --git a/protocol_noise_poll.go b/protocol_noise_poll.go index 2c298693..85481399 100644 --- a/protocol_noise_poll.go +++ b/protocol_noise_poll.go @@ -41,27 +41,27 @@ func (t *ts2021App) NoisePollNetMapHandler( return } - machine, err := t.headscale.GetMachineByAnyKey(t.conn.Peer(), mapRequest.NodeKey, key.NodePublic{}) + node, err := t.headscale.GetNodeByAnyKey(t.conn.Peer(), mapRequest.NodeKey, key.NodePublic{}) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { log.Warn(). Str("handler", "NoisePollNetMap"). - Msgf("Ignoring request, cannot find machine with key %s", mapRequest.NodeKey.String()) + Msgf("Ignoring request, cannot find node with key %s", mapRequest.NodeKey.String()) http.Error(writer, "Internal error", http.StatusNotFound) return } log.Error(). Str("handler", "NoisePollNetMap"). - Msgf("Failed to fetch machine from the database with node key: %s", mapRequest.NodeKey.String()) + Msgf("Failed to fetch node from the database with node key: %s", mapRequest.NodeKey.String()) http.Error(writer, "Internal error", http.StatusInternalServerError) return } log.Debug(). Str("handler", "NoisePollNetMap"). - Str("machine", machine.Hostname). - Msg("A machine is entering polling via the Noise protocol") + Str("node", node.Hostname). + Msg("A node is entering polling via the Noise protocol") - t.headscale.handlePollCommon(writer, req.Context(), machine, mapRequest, true) + t.headscale.handlePollCommon(writer, req.Context(), node, mapRequest, true) } diff --git a/users.go b/users.go index c32213aa..0d3b9a99 100644 --- a/users.go +++ b/users.go @@ -32,7 +32,7 @@ var invalidCharsInUserRegex = regexp.MustCompile("[^a-z0-9-.]+") // User is the way Headscale implements the concept of users in Tailscale // // At the end of the day, users in Tailscale are some kind of 'bubbles' or users -// that contain our machines. +// that contain our nodes. type User struct { gorm.Model Name string `gorm:"unique"` @@ -63,18 +63,18 @@ func (h *Headscale) CreateUser(name string) (*User, error) { } // DestroyUser destroys a User. Returns error if the User does -// not exist or if there are machines associated with it. +// not exist or if there are nodes associated with it. func (h *Headscale) DestroyUser(name string) error { user, err := h.GetUser(name) if err != nil { return ErrUserNotFound } - machines, err := h.ListMachinesByUser(name) + nodes, err := h.ListNodesByUser(name) if err != nil { return err } - if len(machines) > 0 { + if len(nodes) > 0 { return ErrUserStillHasNodes } @@ -148,8 +148,8 @@ func (h *Headscale) ListUsers() ([]User, error) { return users, nil } -// ListMachinesByUser gets all the nodes in a given user. -func (h *Headscale) ListMachinesByUser(name string) ([]Machine, error) { +// ListNodesByUser gets all the nodes in a given user. +func (h *Headscale) ListNodesByUser(name string) ([]Node, error) { err := CheckForFQDNRules(name) if err != nil { return nil, err @@ -159,16 +159,16 @@ func (h *Headscale) ListMachinesByUser(name string) ([]Machine, error) { return nil, err } - machines := []Machine{} - if err := h.db.Preload("AuthKey").Preload("AuthKey.User").Preload("User").Where(&Machine{UserID: user.ID}).Find(&machines).Error; err != nil { + nodes := []Node{} + if err := h.db.Preload("AuthKey").Preload("AuthKey.User").Preload("User").Where(&Node{UserID: user.ID}).Find(&nodes).Error; err != nil { return nil, err } - return machines, nil + return nodes, nil } -// SetMachineUser assigns a Machine to a user. -func (h *Headscale) SetMachineUser(machine *Machine, username string) error { +// SetNodeUser assigns a Node to a user. +func (h *Headscale) SetNodeUser(node *Node, username string) error { err := CheckForFQDNRules(username) if err != nil { return err @@ -177,8 +177,8 @@ func (h *Headscale) SetMachineUser(machine *Machine, username string) error { if err != nil { return err } - machine.User = *user - if result := h.db.Save(&machine); result.Error != nil { + node.User = *user + if result := h.db.Save(&node); result.Error != nil { return result.Error } @@ -212,11 +212,11 @@ func (n *User) toTailscaleLogin() *tailcfg.Login { } func (h *Headscale) getMapResponseUserProfiles( - machine Machine, - peers Machines, + node Node, + peers Nodes, ) []tailcfg.UserProfile { userMap := make(map[string]User) - userMap[machine.User.Name] = machine.User + userMap[node.User.Name] = node.User for _, peer := range peers { userMap[peer.User.Name] = peer.User // not worth checking if already is there } diff --git a/utils.go b/utils.go index 8bdb2b3f..d4b3ee08 100644 --- a/utils.go +++ b/utils.go @@ -139,8 +139,8 @@ func decode( return nil } -func (h *Headscale) getAvailableIPs() (MachineAddresses, error) { - var ips MachineAddresses +func (h *Headscale) getAvailableIPs() (NodeAddresses, error) { + var ips NodeAddresses var err error ipPrefixes := h.cfg.IPPrefixes for _, ipPrefix := range ipPrefixes { @@ -201,12 +201,12 @@ func (h *Headscale) getUsedIPs() (*netipx.IPSet, error) { // but this was quick to get running and it should be enough // to begin experimenting with a dual stack tailnet. var addressesSlices []string - h.db.Model(&Machine{}).Pluck("ip_addresses", &addressesSlices) + h.db.Model(&Node{}).Pluck("ip_addresses", &addressesSlices) var ips netipx.IPSetBuilder for _, slice := range addressesSlices { - var machineAddresses MachineAddresses - err := machineAddresses.Scan(slice) + var nodeAddresses NodeAddresses + err := nodeAddresses.Scan(slice) if err != nil { return &netipx.IPSet{}, fmt.Errorf( "failed to read ip from database: %w", @@ -214,7 +214,7 @@ func (h *Headscale) getUsedIPs() (*netipx.IPSet, error) { ) } - for _, ip := range machineAddresses { + for _, ip := range nodeAddresses { ips.Add(ip) } }