From 35c3fe96083baaca8a1f25d1b8f42e3bfef4e5e9 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 17 Nov 2021 22:39:41 +0000 Subject: [PATCH 01/38] Move registration workflow into functions --- api.go | 352 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 206 insertions(+), 146 deletions(-) diff --git a/api.go b/api.go index 85c28e3e..367a0031 100644 --- a/api.go +++ b/api.go @@ -112,177 +112,41 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { } if !machine.Registered && req.Auth.AuthKey != "" { - h.handleAuthKey(ctx, h.db, machineKey, req, *machine) + h.handleAuthKey(ctx, machineKey, req, *machine) return } - resp := tailcfg.RegisterResponse{} - // We have the updated key! if machine.NodeKey == wgkey.Key(req.NodeKey).HexString() { // 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 !req.Expiry.IsZero() && req.Expiry.UTC().Before(now) { - log.Info(). - Str("handler", "Registration"). - Str("machine", machine.Name). - Msg("Client requested logout") - - machine.Expiry = &req.Expiry // save the expiry so that the machine is marked as expired - h.db.Save(&machine) - - resp.AuthURL = "" - resp.MachineAuthorized = false - resp.User = *machine.Namespace.toUser() - respBody, err := encode(resp, &machineKey, h.privateKey) - if err != nil { - log.Error(). - Str("handler", "Registration"). - Err(err). - Msg("Cannot encode message") - ctx.String(http.StatusInternalServerError, "") - - return - } - ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + h.handleMachineLogOut(ctx, machineKey, req, *machine) return } if machine.Registered && machine.Expiry.UTC().After(now) { - // The machine registration is valid, respond with redirect to /map - log.Debug(). - Str("handler", "Registration"). - Str("machine", machine.Name). - Msg("Client is registered and we have the current NodeKey. All clear to /map") - - resp.AuthURL = "" - resp.MachineAuthorized = true - resp.User = *machine.Namespace.toUser() - resp.Login = *machine.Namespace.toLogin() - - respBody, err := encode(resp, &machineKey, h.privateKey) - if err != nil { - log.Error(). - Str("handler", "Registration"). - Err(err). - Msg("Cannot encode message") - machineRegistrations.WithLabelValues("update", "web", "error", machine.Namespace.Name). - Inc() - ctx.String(http.StatusInternalServerError, "") - - return - } - machineRegistrations.WithLabelValues("update", "web", "success", machine.Namespace.Name). - Inc() - ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + h.handleMachineValidRegistration(ctx, machineKey, req, *machine) return } - // The client has registered before, but has expired - log.Debug(). - Str("handler", "Registration"). - Str("machine", machine.Name). - Msg("Machine registration has expired. Sending a authurl to register") - - if h.cfg.OIDC.Issuer != "" { - resp.AuthURL = fmt.Sprintf("%s/oidc/register/%s", - strings.TrimSuffix(h.cfg.ServerURL, "/"), machineKey.HexString()) - } else { - resp.AuthURL = fmt.Sprintf("%s/register?key=%s", - strings.TrimSuffix(h.cfg.ServerURL, "/"), machineKey.HexString()) - } - - // When a client connects, it may request a specific expiry time in its - // RegisterRequest (https://github.com/tailscale/tailscale/blob/main/tailcfg/tailcfg.go#L634) - // RequestedExpiry is used to store the clients requested expiry time since the authentication flow is broken - // into two steps (which cant pass arbitrary data between them easily) and needs to be - // retrieved again after the user has authenticated. After the authentication flow - // completes, RequestedExpiry is copied into Expiry. - machine.RequestedExpiry = &req.Expiry - - h.db.Save(&machine) - - respBody, err := encode(resp, &machineKey, h.privateKey) - if err != nil { - log.Error(). - Str("handler", "Registration"). - Err(err). - Msg("Cannot encode message") - machineRegistrations.WithLabelValues("new", "web", "error", machine.Namespace.Name). - Inc() - ctx.String(http.StatusInternalServerError, "") - - return - } - machineRegistrations.WithLabelValues("new", "web", "success", machine.Namespace.Name). - Inc() - ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + h.handleMachineExpired(ctx, machineKey, req, *machine) return } // The NodeKey we have matches OldNodeKey, which means this is a refresh after a key expiration if machine.NodeKey == wgkey.Key(req.OldNodeKey).HexString() && - machine.Expiry.UTC().After(now) { - log.Debug(). - Str("handler", "Registration"). - Str("machine", machine.Name). - Msg("We have the OldNodeKey in the database. This is a key refresh") - machine.NodeKey = wgkey.Key(req.NodeKey).HexString() - h.db.Save(&machine) - - resp.AuthURL = "" - resp.User = *machine.Namespace.toUser() - respBody, err := encode(resp, &machineKey, h.privateKey) - if err != nil { - log.Error(). - Str("handler", "Registration"). - Err(err). - Msg("Cannot encode message") - ctx.String(http.StatusInternalServerError, "Extremely sad!") - - return - } - ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + !machine.isExpired() { + h.handleMachineRefreshKey(ctx, machineKey, req, *machine) return } - // The machine registration is new, redirect the client to the registration URL - log.Debug(). - Str("handler", "Registration"). - Str("machine", machine.Name). - Msg("The node is sending us a new NodeKey, sending auth url") - if h.cfg.OIDC.Issuer != "" { - resp.AuthURL = fmt.Sprintf( - "%s/oidc/register/%s", - strings.TrimSuffix(h.cfg.ServerURL, "/"), - machineKey.HexString(), - ) - } else { - resp.AuthURL = fmt.Sprintf("%s/register?key=%s", - strings.TrimSuffix(h.cfg.ServerURL, "/"), machineKey.HexString()) - } - - // save the requested expiry time for retrieval later in the authentication flow - machine.RequestedExpiry = &req.Expiry - machine.NodeKey = wgkey.Key(req.NodeKey).HexString() // save the NodeKey - h.db.Save(&machine) - - respBody, err := encode(resp, &machineKey, h.privateKey) - if err != nil { - log.Error(). - Str("handler", "Registration"). - Err(err). - Msg("Cannot encode message") - ctx.String(http.StatusInternalServerError, "") - - return - } - ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + h.handleMachineRegistrationNew(ctx, machineKey, req, *machine) } func (h *Headscale) getMapResponse( @@ -404,9 +268,205 @@ func (h *Headscale) getMapKeepAliveResponse( return data, nil } +func (h *Headscale) handleMachineLogOut( + ctx *gin.Context, + idKey wgkey.Key, + reqisterRequest tailcfg.RegisterRequest, + machine Machine, +) { + resp := tailcfg.RegisterResponse{} + + log.Info(). + Str("handler", "Registration"). + Str("machine", machine.Name). + Msg("Client requested logout") + + machine.Expiry = &reqisterRequest.Expiry // save the expiry so that the machine is marked as expired + h.db.Save(&machine) + + resp.AuthURL = "" + resp.MachineAuthorized = false + resp.User = *machine.Namespace.toUser() + respBody, err := encode(resp, &idKey, h.privateKey) + if err != nil { + log.Error(). + Str("handler", "Registration"). + Err(err). + Msg("Cannot encode message") + ctx.String(http.StatusInternalServerError, "") + + return + } + ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + + return +} + +func (h *Headscale) handleMachineValidRegistration( + ctx *gin.Context, + idKey wgkey.Key, + reqisterRequest tailcfg.RegisterRequest, + machine Machine, +) { + resp := tailcfg.RegisterResponse{} + + // The machine registration is valid, respond with redirect to /map + log.Debug(). + Str("handler", "Registration"). + Str("machine", machine.Name). + Msg("Client is registered and we have the current NodeKey. All clear to /map") + + resp.AuthURL = "" + resp.MachineAuthorized = true + resp.User = *machine.Namespace.toUser() + resp.Login = *machine.Namespace.toLogin() + + respBody, err := encode(resp, &idKey, h.privateKey) + if err != nil { + log.Error(). + Str("handler", "Registration"). + Err(err). + Msg("Cannot encode message") + machineRegistrations.WithLabelValues("update", "web", "error", machine.Namespace.Name). + Inc() + ctx.String(http.StatusInternalServerError, "") + + return + } + machineRegistrations.WithLabelValues("update", "web", "success", machine.Namespace.Name). + Inc() + ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + + return +} + +func (h *Headscale) handleMachineExpired( + ctx *gin.Context, + idKey wgkey.Key, + reqisterRequest tailcfg.RegisterRequest, + machine Machine, +) { + resp := tailcfg.RegisterResponse{} + + // The client has registered before, but has expired + log.Debug(). + Str("handler", "Registration"). + Str("machine", machine.Name). + Msg("Machine registration has expired. Sending a authurl to register") + + if h.cfg.OIDC.Issuer != "" { + resp.AuthURL = fmt.Sprintf("%s/oidc/register/%s", + strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) + } else { + resp.AuthURL = fmt.Sprintf("%s/register?key=%s", + strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) + } + + // When a client connects, it may request a specific expiry time in its + // RegisterRequest (https://github.com/tailscale/tailscale/blob/main/tailcfg/tailcfg.go#L634) + // RequestedExpiry is used to store the clients requested expiry time since the authentication flow is broken + // into two steps (which cant pass arbitrary data between them easily) and needs to be + // retrieved again after the user has authenticated. After the authentication flow + // completes, RequestedExpiry is copied into Expiry. + machine.RequestedExpiry = &reqisterRequest.Expiry + + h.db.Save(&machine) + + respBody, err := encode(resp, &idKey, h.privateKey) + if err != nil { + log.Error(). + Str("handler", "Registration"). + Err(err). + Msg("Cannot encode message") + machineRegistrations.WithLabelValues("new", "web", "error", machine.Namespace.Name). + Inc() + ctx.String(http.StatusInternalServerError, "") + + return + } + machineRegistrations.WithLabelValues("new", "web", "success", machine.Namespace.Name). + Inc() + ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + + return +} + +func (h *Headscale) handleMachineRefreshKey( + ctx *gin.Context, + idKey wgkey.Key, + reqisterRequest tailcfg.RegisterRequest, + machine Machine, +) { + resp := tailcfg.RegisterResponse{} + + log.Debug(). + Str("handler", "Registration"). + Str("machine", machine.Name). + Msg("We have the OldNodeKey in the database. This is a key refresh") + machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey).HexString() + h.db.Save(&machine) + + resp.AuthURL = "" + resp.User = *machine.Namespace.toUser() + respBody, err := encode(resp, &idKey, h.privateKey) + if err != nil { + log.Error(). + Str("handler", "Registration"). + Err(err). + Msg("Cannot encode message") + ctx.String(http.StatusInternalServerError, "Extremely sad!") + + return + } + ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) + + return +} + +func (h *Headscale) handleMachineRegistrationNew( + ctx *gin.Context, + idKey wgkey.Key, + reqisterRequest tailcfg.RegisterRequest, + machine Machine, +) { + resp := tailcfg.RegisterResponse{} + + // The machine registration is new, redirect the client to the registration URL + log.Debug(). + Str("handler", "Registration"). + Str("machine", machine.Name). + Msg("The node is sending us a new NodeKey, sending auth url") + if h.cfg.OIDC.Issuer != "" { + resp.AuthURL = fmt.Sprintf( + "%s/oidc/register/%s", + strings.TrimSuffix(h.cfg.ServerURL, "/"), + idKey.HexString(), + ) + } else { + resp.AuthURL = fmt.Sprintf("%s/register?key=%s", + strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) + } + + // save the requested expiry time for retrieval later in the authentication flow + machine.RequestedExpiry = &reqisterRequest.Expiry + machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey).HexString() // save the NodeKey + h.db.Save(&machine) + + respBody, err := encode(resp, &idKey, h.privateKey) + if err != nil { + log.Error(). + Str("handler", "Registration"). + Err(err). + Msg("Cannot encode message") + ctx.String(http.StatusInternalServerError, "") + + return + } + ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) +} + func (h *Headscale) handleAuthKey( ctx *gin.Context, - db *gorm.DB, idKey wgkey.Key, reqisterRequest tailcfg.RegisterRequest, machine Machine, @@ -477,10 +537,10 @@ func (h *Headscale) handleAuthKey( // we update it just in case machine.Registered = true machine.RegisterMethod = "authKey" - db.Save(&machine) + h.db.Save(&machine) pak.Used = true - db.Save(&pak) + h.db.Save(&pak) resp.MachineAuthorized = true resp.User = *pak.Namespace.toUser() From a8a8f01429af9897b87d03235faa31197ee18c40 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 18 Nov 2021 08:49:55 +0000 Subject: [PATCH 02/38] Make "authKey" a constant --- acls_test.go | 4 ++-- api.go | 7 +++++-- dns_test.go | 16 ++++++++-------- machine_test.go | 10 +++++----- namespaces_test.go | 10 +++++----- preauth_keys_test.go | 6 +++--- routes_test.go | 4 ++-- sharing_test.go | 6 +++--- utils_test.go | 6 +++--- 9 files changed, 36 insertions(+), 33 deletions(-) diff --git a/acls_test.go b/acls_test.go index 3e051f5f..629ce1da 100644 --- a/acls_test.go +++ b/acls_test.go @@ -100,7 +100,7 @@ func (s *Suite) TestPortNamespace(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: ip.String(), AuthKeyID: uint(pak.ID), } @@ -142,7 +142,7 @@ func (s *Suite) TestPortGroup(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: ip.String(), AuthKeyID: uint(pak.ID), } diff --git a/api.go b/api.go index 367a0031..45b59d3c 100644 --- a/api.go +++ b/api.go @@ -18,7 +18,10 @@ import ( "tailscale.com/types/wgkey" ) -const reservedResponseHeaderSize = 4 +const ( + reservedResponseHeaderSize = 4 + RegisterMethodAuthKey = "authKey" +) // KeyHandler provides the Headscale pub key // Listens in /key. @@ -536,7 +539,7 @@ func (h *Headscale) handleAuthKey( HexString() // we update it just in case machine.Registered = true - machine.RegisterMethod = "authKey" + machine.RegisterMethod = RegisterMethodAuthKey h.db.Save(&machine) pak.Used = true diff --git a/dns_test.go b/dns_test.go index a2f7a652..92f7476f 100644 --- a/dns_test.go +++ b/dns_test.go @@ -123,7 +123,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.1", AuthKeyID: uint(preAuthKeyInShared1.ID), } @@ -141,7 +141,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { NamespaceID: namespaceShared2.ID, Namespace: *namespaceShared2, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.2", AuthKeyID: uint(preAuthKeyInShared2.ID), } @@ -159,7 +159,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { NamespaceID: namespaceShared3.ID, Namespace: *namespaceShared3, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.3", AuthKeyID: uint(preAuthKeyInShared3.ID), } @@ -177,7 +177,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.4", AuthKeyID: uint(PreAuthKey2InShared1.ID), } @@ -272,7 +272,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.1", AuthKeyID: uint(preAuthKeyInShared1.ID), } @@ -290,7 +290,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { NamespaceID: namespaceShared2.ID, Namespace: *namespaceShared2, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.2", AuthKeyID: uint(preAuthKeyInShared2.ID), } @@ -308,7 +308,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { NamespaceID: namespaceShared3.ID, Namespace: *namespaceShared3, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.3", AuthKeyID: uint(preAuthKeyInShared3.ID), } @@ -326,7 +326,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.4", AuthKeyID: uint(preAuthKey2InShared1.ID), } diff --git a/machine_test.go b/machine_test.go index cf367403..fdbc3cb5 100644 --- a/machine_test.go +++ b/machine_test.go @@ -25,7 +25,7 @@ func (s *Suite) TestGetMachine(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } app.db.Save(machine) @@ -55,7 +55,7 @@ func (s *Suite) TestGetMachineByID(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } app.db.Save(&machine) @@ -78,7 +78,7 @@ func (s *Suite) TestDeleteMachine(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(1), } app.db.Save(&machine) @@ -113,7 +113,7 @@ func (s *Suite) TestHardDeleteMachine(c *check.C) { Name: "testmachine3", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(1), } app.db.Save(&machine) @@ -144,7 +144,7 @@ func (s *Suite) TestGetDirectPeers(c *check.C) { Name: "testmachine" + strconv.Itoa(index), NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } app.db.Save(&machine) diff --git a/namespaces_test.go b/namespaces_test.go index bbae98f9..9793e608 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -53,7 +53,7 @@ func (s *Suite) TestDestroyNamespaceErrors(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } app.db.Save(&machine) @@ -145,7 +145,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.1", AuthKeyID: uint(preAuthKeyShared1.ID), } @@ -163,7 +163,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { NamespaceID: namespaceShared2.ID, Namespace: *namespaceShared2, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.2", AuthKeyID: uint(preAuthKeyShared2.ID), } @@ -181,7 +181,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { NamespaceID: namespaceShared3.ID, Namespace: *namespaceShared3, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.3", AuthKeyID: uint(preAuthKeyShared3.ID), } @@ -199,7 +199,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.4", AuthKeyID: uint(preAuthKey2Shared1.ID), } diff --git a/preauth_keys_test.go b/preauth_keys_test.go index fd0feb03..f8cf276d 100644 --- a/preauth_keys_test.go +++ b/preauth_keys_test.go @@ -81,7 +81,7 @@ func (*Suite) TestAlreadyUsedKey(c *check.C) { Name: "testest", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } app.db.Save(&machine) @@ -106,7 +106,7 @@ func (*Suite) TestReusableBeingUsedKey(c *check.C) { Name: "testest", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } app.db.Save(&machine) @@ -144,7 +144,7 @@ func (*Suite) TestEphemeralKey(c *check.C) { Name: "testest", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, LastSeen: &now, AuthKeyID: uint(pak.ID), } diff --git a/routes_test.go b/routes_test.go index 18cb0ceb..94bda45b 100644 --- a/routes_test.go +++ b/routes_test.go @@ -36,7 +36,7 @@ func (s *Suite) TestGetRoutes(c *check.C) { Name: "test_get_route_machine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostinfo), } @@ -90,7 +90,7 @@ func (s *Suite) TestGetEnableRoutes(c *check.C) { Name: "test_enable_route_machine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostinfo), } diff --git a/sharing_test.go b/sharing_test.go index 7ec1b0ee..fd7634da 100644 --- a/sharing_test.go +++ b/sharing_test.go @@ -25,7 +25,7 @@ func CreateNodeNamespace( Name: node, NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: ip, AuthKeyID: uint(pak1.ID), } @@ -213,7 +213,7 @@ func (s *Suite) TestComplexSharingAcrossNamespaces(c *check.C) { Name: "test_get_shared_nodes_4", NamespaceID: namespace1.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.4", AuthKeyID: uint(pak4.ID), } @@ -293,7 +293,7 @@ func (s *Suite) TestDeleteSharedMachine(c *check.C) { Name: "test_get_shared_nodes_4", NamespaceID: namespace1.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, IPAddress: "100.64.0.4", AuthKeyID: uint(pak4n1.ID), } diff --git a/utils_test.go b/utils_test.go index dcda6130..95722a83 100644 --- a/utils_test.go +++ b/utils_test.go @@ -36,7 +36,7 @@ func (s *Suite) TestGetUsedIps(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), IPAddress: ip.String(), } @@ -78,7 +78,7 @@ func (s *Suite) TestGetMultiIp(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), IPAddress: ip.String(), } @@ -151,7 +151,7 @@ func (s *Suite) TestGetAvailableIpMachineWithoutIP(c *check.C) { Name: "testmachine", NamespaceID: namespace.ID, Registered: true, - RegisterMethod: "authKey", + RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } app.db.Save(&machine) From 50dcb8bb753210dd5bee08e9079f64fa2cfe3e5a Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 18 Nov 2021 08:50:53 +0000 Subject: [PATCH 03/38] Use valid handler for registered authkey machines --- api.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/api.go b/api.go index 45b59d3c..a92b5e6b 100644 --- a/api.go +++ b/api.go @@ -130,8 +130,15 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { return } - if machine.Registered && machine.Expiry.UTC().After(now) { - h.handleMachineValidRegistration(ctx, machineKey, req, *machine) + // We dont care about expiry time if the method is AuthKey, as we dont set that. + if machine.Registered && machine.RegisterMethod == RegisterMethodAuthKey { + h.handleMachineValidRegistration(ctx, machineKey, *machine) + + return + } + + if machine.Registered && !machine.isExpired() { + h.handleMachineValidRegistration(ctx, machineKey, *machine) return } From 981f712660746ac692255929ed62a29f5167321d Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 18 Nov 2021 08:51:21 +0000 Subject: [PATCH 04/38] Remove unused param --- api.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api.go b/api.go index a92b5e6b..2c4f9897 100644 --- a/api.go +++ b/api.go @@ -315,7 +315,6 @@ func (h *Headscale) handleMachineLogOut( func (h *Headscale) handleMachineValidRegistration( ctx *gin.Context, idKey wgkey.Key, - reqisterRequest tailcfg.RegisterRequest, machine Machine, ) { resp := tailcfg.RegisterResponse{} From 58d12553577a98f4371ebfd0f9409a2f03ab9543 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 18 Nov 2021 08:51:33 +0000 Subject: [PATCH 05/38] Remove unneeded returns --- api.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/api.go b/api.go index 2c4f9897..d11971b6 100644 --- a/api.go +++ b/api.go @@ -308,8 +308,6 @@ func (h *Headscale) handleMachineLogOut( return } ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) - - return } func (h *Headscale) handleMachineValidRegistration( @@ -345,8 +343,6 @@ func (h *Headscale) handleMachineValidRegistration( machineRegistrations.WithLabelValues("update", "web", "success", machine.Namespace.Name). Inc() ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) - - return } func (h *Headscale) handleMachineExpired( @@ -396,8 +392,6 @@ func (h *Headscale) handleMachineExpired( machineRegistrations.WithLabelValues("new", "web", "success", machine.Namespace.Name). Inc() ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) - - return } func (h *Headscale) handleMachineRefreshKey( From 106b1e7e8d35ef7deae2dc2c2cbe27e1c60d3e3e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 18 Nov 2021 17:51:54 +0000 Subject: [PATCH 06/38] Create constants for other reg methods --- api.go | 4 ++-- machine.go | 2 +- oidc.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api.go b/api.go index d11971b6..b8169111 100644 --- a/api.go +++ b/api.go @@ -21,6 +21,8 @@ import ( const ( reservedResponseHeaderSize = 4 RegisterMethodAuthKey = "authKey" + RegisterMethodOIDC = "oidc" + RegisterMethodCLI = "cli" ) // KeyHandler provides the Headscale pub key @@ -422,8 +424,6 @@ func (h *Headscale) handleMachineRefreshKey( return } ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) - - return } func (h *Headscale) handleMachineRegistrationNew( diff --git a/machine.go b/machine.go index dcd79700..293b26fa 100644 --- a/machine.go +++ b/machine.go @@ -660,7 +660,7 @@ func (h *Headscale) RegisterMachine( machine.IPAddress = ip.String() machine.NamespaceID = namespace.ID machine.Registered = true - machine.RegisterMethod = "cli" + machine.RegisterMethod = RegisterMethodCLI h.db.Save(&machine) log.Trace(). diff --git a/oidc.go b/oidc.go index 07561e8a..f796c908 100644 --- a/oidc.go +++ b/oidc.go @@ -223,7 +223,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { machine.IPAddress = ip.String() machine.NamespaceID = namespace.ID machine.Registered = true - machine.RegisterMethod = "oidc" + machine.RegisterMethod = RegisterMethodOIDC machine.LastSuccessfulUpdate = &now h.db.Save(&machine) } From 9aac1fb255f25473cc5a2890eebce128dbc97dc3 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 19 Nov 2021 09:02:29 +0000 Subject: [PATCH 07/38] Remove expiry logic, this needs to be redone --- api.go | 16 +++++++--------- app.go | 3 --- cli_test.go | 17 ++++++++--------- machine.go | 39 +++++++-------------------------------- oidc.go | 2 -- 5 files changed, 22 insertions(+), 55 deletions(-) diff --git a/api.go b/api.go index b8169111..ee10e88f 100644 --- a/api.go +++ b/api.go @@ -369,13 +369,9 @@ func (h *Headscale) handleMachineExpired( strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) } - // When a client connects, it may request a specific expiry time in its - // RegisterRequest (https://github.com/tailscale/tailscale/blob/main/tailcfg/tailcfg.go#L634) - // RequestedExpiry is used to store the clients requested expiry time since the authentication flow is broken - // into two steps (which cant pass arbitrary data between them easily) and needs to be - // retrieved again after the user has authenticated. After the authentication flow - // completes, RequestedExpiry is copied into Expiry. - machine.RequestedExpiry = &reqisterRequest.Expiry + if !reqisterRequest.Expiry.IsZero() { + machine.Expiry = &reqisterRequest.Expiry + } h.db.Save(&machine) @@ -450,8 +446,10 @@ func (h *Headscale) handleMachineRegistrationNew( strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) } - // save the requested expiry time for retrieval later in the authentication flow - machine.RequestedExpiry = &reqisterRequest.Expiry + if !reqisterRequest.Expiry.IsZero() { + machine.Expiry = &reqisterRequest.Expiry + } + machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey).HexString() // save the NodeKey h.db.Save(&machine) diff --git a/app.go b/app.go index 08b67fe0..b2b545b4 100644 --- a/app.go +++ b/app.go @@ -96,9 +96,6 @@ type Config struct { OIDC OIDCConfig CLI CLIConfig - - MaxMachineRegistrationDuration time.Duration - DefaultMachineRegistrationDuration time.Duration } type OIDCConfig struct { diff --git a/cli_test.go b/cli_test.go index 44ef9f08..ef7e2993 100644 --- a/cli_test.go +++ b/cli_test.go @@ -13,15 +13,14 @@ func (s *Suite) TestRegisterMachine(c *check.C) { now := time.Now().UTC() machine := Machine{ - ID: 0, - MachineKey: "8ce002a935f8c394e55e78fbbb410576575ff8ec5cfa2e627e4b807f1be15b0e", - NodeKey: "bar", - DiscoKey: "faa", - Name: "testmachine", - NamespaceID: namespace.ID, - IPAddress: "10.0.0.1", - Expiry: &now, - RequestedExpiry: &now, + ID: 0, + MachineKey: "8ce002a935f8c394e55e78fbbb410576575ff8ec5cfa2e627e4b807f1be15b0e", + NodeKey: "bar", + DiscoKey: "faa", + Name: "testmachine", + NamespaceID: namespace.ID, + IPAddress: "10.0.0.1", + Expiry: &now, } app.db.Save(&machine) diff --git a/machine.go b/machine.go index 293b26fa..813da35c 100644 --- a/machine.go +++ b/machine.go @@ -45,7 +45,6 @@ type Machine struct { LastSeen *time.Time LastSuccessfulUpdate *time.Time Expiry *time.Time - RequestedExpiry *time.Time HostInfo datatypes.JSON Endpoints datatypes.JSON @@ -68,38 +67,14 @@ func (machine Machine) isAlreadyRegistered() bool { // isExpired returns whether the machine registration has expired. func (machine Machine) isExpired() bool { - return time.Now().UTC().After(*machine.Expiry) -} - -// If the Machine is expired, updateMachineExpiry updates the Machine Expiry time to the maximum allowed duration, -// or the default duration if no Expiry time was requested by the client. The expiry time here does not (yet) cause -// a client to be disconnected, however they will have to re-auth the machine if they attempt to reconnect after the -// expiry time. -func (h *Headscale) updateMachineExpiry(machine *Machine) { - if machine.isExpired() { - now := time.Now().UTC() - maxExpiry := now.Add( - h.cfg.MaxMachineRegistrationDuration, - ) // calculate the maximum expiry - defaultExpiry := now.Add( - h.cfg.DefaultMachineRegistrationDuration, - ) // calculate the default expiry - - // clamp the expiry time of the machine registration to the maximum allowed, or use the default if none supplied - if maxExpiry.Before(*machine.RequestedExpiry) { - log.Debug(). - Msgf("Clamping registration expiry time to maximum: %v (%v)", maxExpiry, h.cfg.MaxMachineRegistrationDuration) - machine.Expiry = &maxExpiry - } else if machine.RequestedExpiry.IsZero() { - log.Debug().Msgf("Using default machine registration expiry time: %v (%v)", defaultExpiry, h.cfg.DefaultMachineRegistrationDuration) - machine.Expiry = &defaultExpiry - } else { - log.Debug().Msgf("Using requested machine registration expiry time: %v", machine.RequestedExpiry) - machine.Expiry = machine.RequestedExpiry - } - - h.db.Save(&machine) + // If Expiry is not set, the client has not indicated that + // it wants an expiry time, it is therefor considered + // to mean "not expired" + if machine.Expiry.IsZero() { + return false } + + return time.Now().UTC().After(*machine.Expiry) } func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { diff --git a/oidc.go b/oidc.go index f796c908..fb27354b 100644 --- a/oidc.go +++ b/oidc.go @@ -228,8 +228,6 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { h.db.Save(&machine) } - h.updateMachineExpiry(machine) - ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(fmt.Sprintf(` From 6a9dd2029e0985e5cbde1d11bdae16f3625b3ac1 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 19 Nov 2021 09:02:49 +0000 Subject: [PATCH 08/38] Remove expiry logic, this needs to be redone --- cmd/headscale/cli/utils.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 958fb893..98b53619 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -218,30 +218,6 @@ func absPath(path string) string { } func getHeadscaleConfig() headscale.Config { - // maxMachineRegistrationDuration is the maximum time headscale will allow a client to (optionally) request for - // the machine key expiry time. RegisterRequests with Expiry times that are more than - // maxMachineRegistrationDuration in the future will be clamped to (now + maxMachineRegistrationDuration) - maxMachineRegistrationDuration, _ := time.ParseDuration( - "10h", - ) // use 10h here because it is the length of a standard business day plus a small amount of leeway - if viper.GetDuration("max_machine_registration_duration") >= time.Second { - maxMachineRegistrationDuration = viper.GetDuration( - "max_machine_registration_duration", - ) - } - - // defaultMachineRegistrationDuration is the default time assigned to a machine registration if one is not - // specified by the tailscale client. It is the default amount of time a machine registration is valid for - // (ie the amount of time before the user has to re-authenticate when requesting a connection) - defaultMachineRegistrationDuration, _ := time.ParseDuration( - "8h", - ) // use 8h here because it's the length of a standard business day - if viper.GetDuration("default_machine_registration_duration") >= time.Second { - defaultMachineRegistrationDuration = viper.GetDuration( - "default_machine_registration_duration", - ) - } - dnsConfig, baseDomain := GetDNSConfig() derpConfig := GetDERPConfig() @@ -295,9 +271,6 @@ func getHeadscaleConfig() headscale.Config { Insecure: viper.GetBool("cli.insecure"), Timeout: viper.GetDuration("cli.timeout"), }, - - MaxMachineRegistrationDuration: maxMachineRegistrationDuration, - DefaultMachineRegistrationDuration: defaultMachineRegistrationDuration, } } From e91f72fe4c9cf747605cbbd64f89b5016be35c00 Mon Sep 17 00:00:00 2001 From: lion24 Date: Sat, 20 Nov 2021 23:31:49 +0100 Subject: [PATCH 09/38] Running.md: fix missing backslash (\) * This would cause otherwise the command to abort after the first statement of the docker command ;) --- docs/Running.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Running.md b/docs/Running.md index 867c5ed2..ac9d2282 100644 --- a/docs/Running.md +++ b/docs/Running.md @@ -26,7 +26,7 @@ ```shell docker run --name headscale \ - -e POSTGRES_DB=headscale + -e POSTGRES_DB=headscale \ -e POSTGRES_USER=foo \ -e POSTGRES_PASSWORD=bar \ -p 5432:5432 \ From 1c7aff5dd912d89e4c571e93369517928a71db55 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 09:44:38 +0000 Subject: [PATCH 10/38] Add expired column to machine list command --- cmd/headscale/cli/nodes.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cmd/headscale/cli/nodes.go b/cmd/headscale/cli/nodes.go index 218d25bd..878fc7a4 100644 --- a/cmd/headscale/cli/nodes.go +++ b/cmd/headscale/cli/nodes.go @@ -412,6 +412,7 @@ func nodesToPtables( "Ephemeral", "Last seen", "Online", + "Expired", }, } @@ -420,12 +421,19 @@ func nodesToPtables( if machine.PreAuthKey != nil && machine.PreAuthKey.Ephemeral { ephemeral = true } + var lastSeen time.Time var lastSeenTime string if machine.LastSeen != nil { lastSeen = machine.LastSeen.AsTime() lastSeenTime = lastSeen.Format("2006-01-02 15:04:05") } + + var expiry time.Time + if machine.Expiry != nil { + expiry = machine.Expiry.AsTime() + } + nKey, err := wgkey.ParseHex(machine.NodeKey) if err != nil { return nil, err @@ -436,9 +444,21 @@ func nodesToPtables( if lastSeen.After( time.Now().Add(-5 * time.Minute), ) { // TODO: Find a better way to reliably show if online - online = pterm.LightGreen("true") + online = pterm.LightGreen("online") } else { - online = pterm.LightRed("false") + online = pterm.LightRed("offline") + } + + fmt.Printf( + "Machine %s, expiry: %s\n", + machine.Name, + expiry.Format("2006-01-02 15:04:05"), + ) + var expired string + if expiry.IsZero() || expiry.After(time.Now()) { + expired = pterm.LightGreen("no") + } else { + expired = pterm.LightRed("yes") } var namespace string @@ -459,6 +479,7 @@ func nodesToPtables( strconv.FormatBool(ephemeral), lastSeenTime, online, + expired, }, ) } From f85a77edb5110fca8f880793abbb98d1a6169c68 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 09:48:59 +0000 Subject: [PATCH 11/38] Remove println statement --- cmd/headscale/cli/nodes.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cmd/headscale/cli/nodes.go b/cmd/headscale/cli/nodes.go index 878fc7a4..7c2cd6c1 100644 --- a/cmd/headscale/cli/nodes.go +++ b/cmd/headscale/cli/nodes.go @@ -449,11 +449,6 @@ func nodesToPtables( online = pterm.LightRed("offline") } - fmt.Printf( - "Machine %s, expiry: %s\n", - machine.Name, - expiry.Format("2006-01-02 15:04:05"), - ) var expired string if expiry.IsZero() || expiry.After(time.Now()) { expired = pterm.LightGreen("no") From f1c05f80104e4468d46bf684d6bc9d9922821324 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 13:40:04 +0000 Subject: [PATCH 12/38] Add ExpireMachine spec to rpc --- gen/go/headscale/v1/headscale.pb.go | 205 ++++++----- gen/go/headscale/v1/headscale.pb.gw.go | 99 +++++ gen/go/headscale/v1/headscale_grpc.pb.go | 36 ++ gen/go/headscale/v1/machine.pb.go | 345 ++++++++++++------ .../headscale/v1/headscale.swagger.json | 39 ++ proto/headscale/v1/headscale.proto | 6 + proto/headscale/v1/machine.proto | 8 + 7 files changed, 534 insertions(+), 204 deletions(-) diff --git a/gen/go/headscale/v1/headscale.pb.go b/gen/go/headscale/v1/headscale.pb.go index 56911b6b..dd27265d 100644 --- a/gen/go/headscale/v1/headscale.pb.go +++ b/gen/go/headscale/v1/headscale.pb.go @@ -34,8 +34,8 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{ 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, - 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xec, - 0x11, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xf4, + 0x12, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, @@ -133,54 +133,63 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{ 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x2a, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x6e, 0x0a, - 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x21, 0x2e, - 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x8d, 0x01, - 0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x21, - 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, - 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, - 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x95, 0x01, - 0x0a, 0x0e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x32, 0x22, 0x30, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, - 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, - 0x7d, 0x2f, 0x75, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x8b, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, - 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, - 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, - 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x65, - 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x42, 0x29, 0x5a, - 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, - 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, - 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, + 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, + 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, + 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, + 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x6e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, + 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, + 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, + 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, + 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x95, 0x01, 0x0a, 0x0e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, + 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, + 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, + 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x22, 0x30, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x75, 0x6e, 0x73, 0x68, 0x61, 0x72, + 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x8b, 0x01, + 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, + 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, + 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, + 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, + 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, + 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x73, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_headscale_v1_headscale_proto_goTypes = []interface{}{ @@ -196,28 +205,30 @@ var file_headscale_v1_headscale_proto_goTypes = []interface{}{ (*GetMachineRequest)(nil), // 9: headscale.v1.GetMachineRequest (*RegisterMachineRequest)(nil), // 10: headscale.v1.RegisterMachineRequest (*DeleteMachineRequest)(nil), // 11: headscale.v1.DeleteMachineRequest - (*ListMachinesRequest)(nil), // 12: headscale.v1.ListMachinesRequest - (*ShareMachineRequest)(nil), // 13: headscale.v1.ShareMachineRequest - (*UnshareMachineRequest)(nil), // 14: headscale.v1.UnshareMachineRequest - (*GetMachineRouteRequest)(nil), // 15: headscale.v1.GetMachineRouteRequest - (*EnableMachineRoutesRequest)(nil), // 16: headscale.v1.EnableMachineRoutesRequest - (*GetNamespaceResponse)(nil), // 17: headscale.v1.GetNamespaceResponse - (*CreateNamespaceResponse)(nil), // 18: headscale.v1.CreateNamespaceResponse - (*RenameNamespaceResponse)(nil), // 19: headscale.v1.RenameNamespaceResponse - (*DeleteNamespaceResponse)(nil), // 20: headscale.v1.DeleteNamespaceResponse - (*ListNamespacesResponse)(nil), // 21: headscale.v1.ListNamespacesResponse - (*CreatePreAuthKeyResponse)(nil), // 22: headscale.v1.CreatePreAuthKeyResponse - (*ExpirePreAuthKeyResponse)(nil), // 23: headscale.v1.ExpirePreAuthKeyResponse - (*ListPreAuthKeysResponse)(nil), // 24: headscale.v1.ListPreAuthKeysResponse - (*DebugCreateMachineResponse)(nil), // 25: headscale.v1.DebugCreateMachineResponse - (*GetMachineResponse)(nil), // 26: headscale.v1.GetMachineResponse - (*RegisterMachineResponse)(nil), // 27: headscale.v1.RegisterMachineResponse - (*DeleteMachineResponse)(nil), // 28: headscale.v1.DeleteMachineResponse - (*ListMachinesResponse)(nil), // 29: headscale.v1.ListMachinesResponse - (*ShareMachineResponse)(nil), // 30: headscale.v1.ShareMachineResponse - (*UnshareMachineResponse)(nil), // 31: headscale.v1.UnshareMachineResponse - (*GetMachineRouteResponse)(nil), // 32: headscale.v1.GetMachineRouteResponse - (*EnableMachineRoutesResponse)(nil), // 33: headscale.v1.EnableMachineRoutesResponse + (*ExpireMachineRequest)(nil), // 12: headscale.v1.ExpireMachineRequest + (*ListMachinesRequest)(nil), // 13: headscale.v1.ListMachinesRequest + (*ShareMachineRequest)(nil), // 14: headscale.v1.ShareMachineRequest + (*UnshareMachineRequest)(nil), // 15: headscale.v1.UnshareMachineRequest + (*GetMachineRouteRequest)(nil), // 16: headscale.v1.GetMachineRouteRequest + (*EnableMachineRoutesRequest)(nil), // 17: headscale.v1.EnableMachineRoutesRequest + (*GetNamespaceResponse)(nil), // 18: headscale.v1.GetNamespaceResponse + (*CreateNamespaceResponse)(nil), // 19: headscale.v1.CreateNamespaceResponse + (*RenameNamespaceResponse)(nil), // 20: headscale.v1.RenameNamespaceResponse + (*DeleteNamespaceResponse)(nil), // 21: headscale.v1.DeleteNamespaceResponse + (*ListNamespacesResponse)(nil), // 22: headscale.v1.ListNamespacesResponse + (*CreatePreAuthKeyResponse)(nil), // 23: headscale.v1.CreatePreAuthKeyResponse + (*ExpirePreAuthKeyResponse)(nil), // 24: headscale.v1.ExpirePreAuthKeyResponse + (*ListPreAuthKeysResponse)(nil), // 25: headscale.v1.ListPreAuthKeysResponse + (*DebugCreateMachineResponse)(nil), // 26: headscale.v1.DebugCreateMachineResponse + (*GetMachineResponse)(nil), // 27: headscale.v1.GetMachineResponse + (*RegisterMachineResponse)(nil), // 28: headscale.v1.RegisterMachineResponse + (*DeleteMachineResponse)(nil), // 29: headscale.v1.DeleteMachineResponse + (*ExpireMachineResponse)(nil), // 30: headscale.v1.ExpireMachineResponse + (*ListMachinesResponse)(nil), // 31: headscale.v1.ListMachinesResponse + (*ShareMachineResponse)(nil), // 32: headscale.v1.ShareMachineResponse + (*UnshareMachineResponse)(nil), // 33: headscale.v1.UnshareMachineResponse + (*GetMachineRouteResponse)(nil), // 34: headscale.v1.GetMachineRouteResponse + (*EnableMachineRoutesResponse)(nil), // 35: headscale.v1.EnableMachineRoutesResponse } var file_headscale_v1_headscale_proto_depIdxs = []int32{ 0, // 0: headscale.v1.HeadscaleService.GetNamespace:input_type -> headscale.v1.GetNamespaceRequest @@ -232,30 +243,32 @@ var file_headscale_v1_headscale_proto_depIdxs = []int32{ 9, // 9: headscale.v1.HeadscaleService.GetMachine:input_type -> headscale.v1.GetMachineRequest 10, // 10: headscale.v1.HeadscaleService.RegisterMachine:input_type -> headscale.v1.RegisterMachineRequest 11, // 11: headscale.v1.HeadscaleService.DeleteMachine:input_type -> headscale.v1.DeleteMachineRequest - 12, // 12: headscale.v1.HeadscaleService.ListMachines:input_type -> headscale.v1.ListMachinesRequest - 13, // 13: headscale.v1.HeadscaleService.ShareMachine:input_type -> headscale.v1.ShareMachineRequest - 14, // 14: headscale.v1.HeadscaleService.UnshareMachine:input_type -> headscale.v1.UnshareMachineRequest - 15, // 15: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest - 16, // 16: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest - 17, // 17: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse - 18, // 18: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse - 19, // 19: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse - 20, // 20: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse - 21, // 21: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse - 22, // 22: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse - 23, // 23: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse - 24, // 24: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse - 25, // 25: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse - 26, // 26: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse - 27, // 27: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse - 28, // 28: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse - 29, // 29: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse - 30, // 30: headscale.v1.HeadscaleService.ShareMachine:output_type -> headscale.v1.ShareMachineResponse - 31, // 31: headscale.v1.HeadscaleService.UnshareMachine:output_type -> headscale.v1.UnshareMachineResponse - 32, // 32: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse - 33, // 33: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse - 17, // [17:34] is the sub-list for method output_type - 0, // [0:17] is the sub-list for method input_type + 12, // 12: headscale.v1.HeadscaleService.ExpireMachine:input_type -> headscale.v1.ExpireMachineRequest + 13, // 13: headscale.v1.HeadscaleService.ListMachines:input_type -> headscale.v1.ListMachinesRequest + 14, // 14: headscale.v1.HeadscaleService.ShareMachine:input_type -> headscale.v1.ShareMachineRequest + 15, // 15: headscale.v1.HeadscaleService.UnshareMachine:input_type -> headscale.v1.UnshareMachineRequest + 16, // 16: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest + 17, // 17: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest + 18, // 18: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse + 19, // 19: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse + 20, // 20: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse + 21, // 21: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse + 22, // 22: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse + 23, // 23: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse + 24, // 24: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse + 25, // 25: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse + 26, // 26: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse + 27, // 27: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse + 28, // 28: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse + 29, // 29: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse + 30, // 30: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse + 31, // 31: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse + 32, // 32: headscale.v1.HeadscaleService.ShareMachine:output_type -> headscale.v1.ShareMachineResponse + 33, // 33: headscale.v1.HeadscaleService.UnshareMachine:output_type -> headscale.v1.UnshareMachineResponse + 34, // 34: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse + 35, // 35: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse + 18, // [18:36] is the sub-list for method output_type + 0, // [0:18] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/gen/go/headscale/v1/headscale.pb.gw.go b/gen/go/headscale/v1/headscale.pb.gw.go index ba2d492f..41502c8f 100644 --- a/gen/go/headscale/v1/headscale.pb.gw.go +++ b/gen/go/headscale/v1/headscale.pb.gw.go @@ -537,6 +537,58 @@ func local_request_HeadscaleService_DeleteMachine_0(ctx context.Context, marshal } +func request_HeadscaleService_ExpireMachine_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ExpireMachineRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["machine_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") + } + + protoReq.MachineId, err = runtime.Uint64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) + } + + msg, err := client.ExpireMachine(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_HeadscaleService_ExpireMachine_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ExpireMachineRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["machine_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") + } + + protoReq.MachineId, err = runtime.Uint64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) + } + + msg, err := server.ExpireMachine(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_HeadscaleService_ListMachines_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -1121,6 +1173,29 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser }) + mux.Handle("POST", pattern_HeadscaleService_ExpireMachine_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/ExpireMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/expire")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_HeadscaleService_ExpireMachine_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_HeadscaleService_ExpireMachine_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_HeadscaleService_ListMachines_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1517,6 +1592,26 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser }) + mux.Handle("POST", pattern_HeadscaleService_ExpireMachine_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/ExpireMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/expire")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_HeadscaleService_ExpireMachine_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_HeadscaleService_ExpireMachine_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_HeadscaleService_ListMachines_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1645,6 +1740,8 @@ var ( pattern_HeadscaleService_DeleteMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "machine", "machine_id"}, "")) + pattern_HeadscaleService_ExpireMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "machine", "machine_id", "expire"}, "")) + pattern_HeadscaleService_ListMachines_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "machine"}, "")) pattern_HeadscaleService_ShareMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "machine", "machine_id", "share", "namespace"}, "")) @@ -1681,6 +1778,8 @@ var ( forward_HeadscaleService_DeleteMachine_0 = runtime.ForwardResponseMessage + forward_HeadscaleService_ExpireMachine_0 = runtime.ForwardResponseMessage + forward_HeadscaleService_ListMachines_0 = runtime.ForwardResponseMessage forward_HeadscaleService_ShareMachine_0 = runtime.ForwardResponseMessage diff --git a/gen/go/headscale/v1/headscale_grpc.pb.go b/gen/go/headscale/v1/headscale_grpc.pb.go index 06a98b49..ab6cb70c 100644 --- a/gen/go/headscale/v1/headscale_grpc.pb.go +++ b/gen/go/headscale/v1/headscale_grpc.pb.go @@ -33,6 +33,7 @@ type HeadscaleServiceClient interface { GetMachine(ctx context.Context, in *GetMachineRequest, opts ...grpc.CallOption) (*GetMachineResponse, error) RegisterMachine(ctx context.Context, in *RegisterMachineRequest, opts ...grpc.CallOption) (*RegisterMachineResponse, error) DeleteMachine(ctx context.Context, in *DeleteMachineRequest, opts ...grpc.CallOption) (*DeleteMachineResponse, error) + ExpireMachine(ctx context.Context, in *ExpireMachineRequest, opts ...grpc.CallOption) (*ExpireMachineResponse, error) ListMachines(ctx context.Context, in *ListMachinesRequest, opts ...grpc.CallOption) (*ListMachinesResponse, error) ShareMachine(ctx context.Context, in *ShareMachineRequest, opts ...grpc.CallOption) (*ShareMachineResponse, error) UnshareMachine(ctx context.Context, in *UnshareMachineRequest, opts ...grpc.CallOption) (*UnshareMachineResponse, error) @@ -157,6 +158,15 @@ func (c *headscaleServiceClient) DeleteMachine(ctx context.Context, in *DeleteMa return out, nil } +func (c *headscaleServiceClient) ExpireMachine(ctx context.Context, in *ExpireMachineRequest, opts ...grpc.CallOption) (*ExpireMachineResponse, error) { + out := new(ExpireMachineResponse) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ExpireMachine", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *headscaleServiceClient) ListMachines(ctx context.Context, in *ListMachinesRequest, opts ...grpc.CallOption) (*ListMachinesResponse, error) { out := new(ListMachinesResponse) err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListMachines", in, out, opts...) @@ -221,6 +231,7 @@ type HeadscaleServiceServer interface { GetMachine(context.Context, *GetMachineRequest) (*GetMachineResponse, error) RegisterMachine(context.Context, *RegisterMachineRequest) (*RegisterMachineResponse, error) DeleteMachine(context.Context, *DeleteMachineRequest) (*DeleteMachineResponse, error) + ExpireMachine(context.Context, *ExpireMachineRequest) (*ExpireMachineResponse, error) ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) ShareMachine(context.Context, *ShareMachineRequest) (*ShareMachineResponse, error) UnshareMachine(context.Context, *UnshareMachineRequest) (*UnshareMachineResponse, error) @@ -270,6 +281,9 @@ func (UnimplementedHeadscaleServiceServer) RegisterMachine(context.Context, *Reg func (UnimplementedHeadscaleServiceServer) DeleteMachine(context.Context, *DeleteMachineRequest) (*DeleteMachineResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteMachine not implemented") } +func (UnimplementedHeadscaleServiceServer) ExpireMachine(context.Context, *ExpireMachineRequest) (*ExpireMachineResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExpireMachine not implemented") +} func (UnimplementedHeadscaleServiceServer) ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListMachines not implemented") } @@ -514,6 +528,24 @@ func _HeadscaleService_DeleteMachine_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _HeadscaleService_ExpireMachine_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExpireMachineRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HeadscaleServiceServer).ExpireMachine(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/headscale.v1.HeadscaleService/ExpireMachine", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HeadscaleServiceServer).ExpireMachine(ctx, req.(*ExpireMachineRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _HeadscaleService_ListMachines_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListMachinesRequest) if err := dec(in); err != nil { @@ -659,6 +691,10 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeleteMachine", Handler: _HeadscaleService_DeleteMachine_Handler, }, + { + MethodName: "ExpireMachine", + Handler: _HeadscaleService_ExpireMachine_Handler, + }, { MethodName: "ListMachines", Handler: _HeadscaleService_ListMachines_Handler, diff --git a/gen/go/headscale/v1/machine.pb.go b/gen/go/headscale/v1/machine.pb.go index b5ec2cda..deafbe5c 100644 --- a/gen/go/headscale/v1/machine.pb.go +++ b/gen/go/headscale/v1/machine.pb.go @@ -505,6 +505,100 @@ func (*DeleteMachineResponse) Descriptor() ([]byte, []int) { return file_headscale_v1_machine_proto_rawDescGZIP(), []int{6} } +type ExpireMachineRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"` +} + +func (x *ExpireMachineRequest) Reset() { + *x = ExpireMachineRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_headscale_v1_machine_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExpireMachineRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExpireMachineRequest) ProtoMessage() {} + +func (x *ExpireMachineRequest) ProtoReflect() protoreflect.Message { + mi := &file_headscale_v1_machine_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExpireMachineRequest.ProtoReflect.Descriptor instead. +func (*ExpireMachineRequest) Descriptor() ([]byte, []int) { + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{7} +} + +func (x *ExpireMachineRequest) GetMachineId() uint64 { + if x != nil { + return x.MachineId + } + return 0 +} + +type ExpireMachineResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Machine *Machine `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"` +} + +func (x *ExpireMachineResponse) Reset() { + *x = ExpireMachineResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_headscale_v1_machine_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExpireMachineResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExpireMachineResponse) ProtoMessage() {} + +func (x *ExpireMachineResponse) ProtoReflect() protoreflect.Message { + mi := &file_headscale_v1_machine_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExpireMachineResponse.ProtoReflect.Descriptor instead. +func (*ExpireMachineResponse) Descriptor() ([]byte, []int) { + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{8} +} + +func (x *ExpireMachineResponse) GetMachine() *Machine { + if x != nil { + return x.Machine + } + return nil +} + type ListMachinesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -516,7 +610,7 @@ type ListMachinesRequest struct { func (x *ListMachinesRequest) Reset() { *x = ListMachinesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[7] + mi := &file_headscale_v1_machine_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -529,7 +623,7 @@ func (x *ListMachinesRequest) String() string { func (*ListMachinesRequest) ProtoMessage() {} func (x *ListMachinesRequest) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[7] + mi := &file_headscale_v1_machine_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -542,7 +636,7 @@ func (x *ListMachinesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMachinesRequest.ProtoReflect.Descriptor instead. func (*ListMachinesRequest) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{7} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{9} } func (x *ListMachinesRequest) GetNamespace() string { @@ -563,7 +657,7 @@ type ListMachinesResponse struct { func (x *ListMachinesResponse) Reset() { *x = ListMachinesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[8] + mi := &file_headscale_v1_machine_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -576,7 +670,7 @@ func (x *ListMachinesResponse) String() string { func (*ListMachinesResponse) ProtoMessage() {} func (x *ListMachinesResponse) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[8] + mi := &file_headscale_v1_machine_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -589,7 +683,7 @@ func (x *ListMachinesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMachinesResponse.ProtoReflect.Descriptor instead. func (*ListMachinesResponse) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{8} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{10} } func (x *ListMachinesResponse) GetMachines() []*Machine { @@ -611,7 +705,7 @@ type ShareMachineRequest struct { func (x *ShareMachineRequest) Reset() { *x = ShareMachineRequest{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[9] + mi := &file_headscale_v1_machine_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -624,7 +718,7 @@ func (x *ShareMachineRequest) String() string { func (*ShareMachineRequest) ProtoMessage() {} func (x *ShareMachineRequest) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[9] + mi := &file_headscale_v1_machine_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -637,7 +731,7 @@ func (x *ShareMachineRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ShareMachineRequest.ProtoReflect.Descriptor instead. func (*ShareMachineRequest) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{9} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{11} } func (x *ShareMachineRequest) GetMachineId() uint64 { @@ -665,7 +759,7 @@ type ShareMachineResponse struct { func (x *ShareMachineResponse) Reset() { *x = ShareMachineResponse{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[10] + mi := &file_headscale_v1_machine_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -678,7 +772,7 @@ func (x *ShareMachineResponse) String() string { func (*ShareMachineResponse) ProtoMessage() {} func (x *ShareMachineResponse) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[10] + mi := &file_headscale_v1_machine_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -691,7 +785,7 @@ func (x *ShareMachineResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ShareMachineResponse.ProtoReflect.Descriptor instead. func (*ShareMachineResponse) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{10} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{12} } func (x *ShareMachineResponse) GetMachine() *Machine { @@ -713,7 +807,7 @@ type UnshareMachineRequest struct { func (x *UnshareMachineRequest) Reset() { *x = UnshareMachineRequest{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[11] + mi := &file_headscale_v1_machine_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -726,7 +820,7 @@ func (x *UnshareMachineRequest) String() string { func (*UnshareMachineRequest) ProtoMessage() {} func (x *UnshareMachineRequest) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[11] + mi := &file_headscale_v1_machine_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -739,7 +833,7 @@ func (x *UnshareMachineRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnshareMachineRequest.ProtoReflect.Descriptor instead. func (*UnshareMachineRequest) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{11} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{13} } func (x *UnshareMachineRequest) GetMachineId() uint64 { @@ -767,7 +861,7 @@ type UnshareMachineResponse struct { func (x *UnshareMachineResponse) Reset() { *x = UnshareMachineResponse{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[12] + mi := &file_headscale_v1_machine_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -780,7 +874,7 @@ func (x *UnshareMachineResponse) String() string { func (*UnshareMachineResponse) ProtoMessage() {} func (x *UnshareMachineResponse) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[12] + mi := &file_headscale_v1_machine_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -793,7 +887,7 @@ func (x *UnshareMachineResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnshareMachineResponse.ProtoReflect.Descriptor instead. func (*UnshareMachineResponse) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{12} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{14} } func (x *UnshareMachineResponse) GetMachine() *Machine { @@ -817,7 +911,7 @@ type DebugCreateMachineRequest struct { func (x *DebugCreateMachineRequest) Reset() { *x = DebugCreateMachineRequest{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[13] + mi := &file_headscale_v1_machine_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -830,7 +924,7 @@ func (x *DebugCreateMachineRequest) String() string { func (*DebugCreateMachineRequest) ProtoMessage() {} func (x *DebugCreateMachineRequest) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[13] + mi := &file_headscale_v1_machine_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -843,7 +937,7 @@ func (x *DebugCreateMachineRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DebugCreateMachineRequest.ProtoReflect.Descriptor instead. func (*DebugCreateMachineRequest) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{13} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{15} } func (x *DebugCreateMachineRequest) GetNamespace() string { @@ -885,7 +979,7 @@ type DebugCreateMachineResponse struct { func (x *DebugCreateMachineResponse) Reset() { *x = DebugCreateMachineResponse{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[14] + mi := &file_headscale_v1_machine_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -898,7 +992,7 @@ func (x *DebugCreateMachineResponse) String() string { func (*DebugCreateMachineResponse) ProtoMessage() {} func (x *DebugCreateMachineResponse) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[14] + mi := &file_headscale_v1_machine_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -911,7 +1005,7 @@ func (x *DebugCreateMachineResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DebugCreateMachineResponse.ProtoReflect.Descriptor instead. func (*DebugCreateMachineResponse) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{14} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{16} } func (x *DebugCreateMachineResponse) GetMachine() *Machine { @@ -994,59 +1088,67 @@ var file_headscale_v1_machine_proto_rawDesc = []byte{ 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, - 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x14, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x6d, 0x61, 0x63, - 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x52, 0x0a, 0x13, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x47, 0x0a, 0x14, 0x53, 0x68, 0x61, - 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x22, 0x54, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, - 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, - 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x16, 0x55, 0x6e, 0x73, 0x68, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x15, + 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x33, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x14, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x6d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x52, 0x0a, 0x13, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x47, 0x0a, 0x14, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x22, 0x77, 0x0a, 0x19, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x4d, 0x0a, 0x1a, - 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, - 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2a, 0x82, 0x01, 0x0a, 0x0e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, - 0x0a, 0x1b, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, - 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, - 0x4f, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x12, 0x17, 0x0a, - 0x13, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, - 0x5f, 0x43, 0x4c, 0x49, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, - 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x03, - 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, - 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x69, 0x6e, 0x65, 0x22, 0x54, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x16, 0x55, 0x6e, 0x73, + 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, + 0x68, 0x69, 0x6e, 0x65, 0x22, 0x77, 0x0a, 0x19, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x4d, 0x0a, + 0x1a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, + 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, + 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, + 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2a, 0x82, 0x01, 0x0a, + 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, + 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, + 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, + 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x12, 0x17, + 0x0a, 0x13, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, + 0x44, 0x5f, 0x43, 0x4c, 0x49, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x47, 0x49, 0x53, + 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, + 0x03, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1062,7 +1164,7 @@ func file_headscale_v1_machine_proto_rawDescGZIP() []byte { } var file_headscale_v1_machine_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_headscale_v1_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_headscale_v1_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_headscale_v1_machine_proto_goTypes = []interface{}{ (RegisterMethod)(0), // 0: headscale.v1.RegisterMethod (*Machine)(nil), // 1: headscale.v1.Machine @@ -1072,37 +1174,40 @@ var file_headscale_v1_machine_proto_goTypes = []interface{}{ (*GetMachineResponse)(nil), // 5: headscale.v1.GetMachineResponse (*DeleteMachineRequest)(nil), // 6: headscale.v1.DeleteMachineRequest (*DeleteMachineResponse)(nil), // 7: headscale.v1.DeleteMachineResponse - (*ListMachinesRequest)(nil), // 8: headscale.v1.ListMachinesRequest - (*ListMachinesResponse)(nil), // 9: headscale.v1.ListMachinesResponse - (*ShareMachineRequest)(nil), // 10: headscale.v1.ShareMachineRequest - (*ShareMachineResponse)(nil), // 11: headscale.v1.ShareMachineResponse - (*UnshareMachineRequest)(nil), // 12: headscale.v1.UnshareMachineRequest - (*UnshareMachineResponse)(nil), // 13: headscale.v1.UnshareMachineResponse - (*DebugCreateMachineRequest)(nil), // 14: headscale.v1.DebugCreateMachineRequest - (*DebugCreateMachineResponse)(nil), // 15: headscale.v1.DebugCreateMachineResponse - (*Namespace)(nil), // 16: headscale.v1.Namespace - (*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp - (*PreAuthKey)(nil), // 18: headscale.v1.PreAuthKey + (*ExpireMachineRequest)(nil), // 8: headscale.v1.ExpireMachineRequest + (*ExpireMachineResponse)(nil), // 9: headscale.v1.ExpireMachineResponse + (*ListMachinesRequest)(nil), // 10: headscale.v1.ListMachinesRequest + (*ListMachinesResponse)(nil), // 11: headscale.v1.ListMachinesResponse + (*ShareMachineRequest)(nil), // 12: headscale.v1.ShareMachineRequest + (*ShareMachineResponse)(nil), // 13: headscale.v1.ShareMachineResponse + (*UnshareMachineRequest)(nil), // 14: headscale.v1.UnshareMachineRequest + (*UnshareMachineResponse)(nil), // 15: headscale.v1.UnshareMachineResponse + (*DebugCreateMachineRequest)(nil), // 16: headscale.v1.DebugCreateMachineRequest + (*DebugCreateMachineResponse)(nil), // 17: headscale.v1.DebugCreateMachineResponse + (*Namespace)(nil), // 18: headscale.v1.Namespace + (*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp + (*PreAuthKey)(nil), // 20: headscale.v1.PreAuthKey } var file_headscale_v1_machine_proto_depIdxs = []int32{ - 16, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace + 18, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace 0, // 1: headscale.v1.Machine.register_method:type_name -> headscale.v1.RegisterMethod - 17, // 2: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp - 17, // 3: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp - 17, // 4: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp - 18, // 5: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey - 17, // 6: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp + 19, // 2: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp + 19, // 3: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp + 19, // 4: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp + 20, // 5: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey + 19, // 6: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp 1, // 7: headscale.v1.RegisterMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 8: headscale.v1.GetMachineResponse.machine:type_name -> headscale.v1.Machine - 1, // 9: headscale.v1.ListMachinesResponse.machines:type_name -> headscale.v1.Machine - 1, // 10: headscale.v1.ShareMachineResponse.machine:type_name -> headscale.v1.Machine - 1, // 11: headscale.v1.UnshareMachineResponse.machine:type_name -> headscale.v1.Machine - 1, // 12: headscale.v1.DebugCreateMachineResponse.machine:type_name -> headscale.v1.Machine - 13, // [13:13] is the sub-list for method output_type - 13, // [13:13] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 1, // 9: headscale.v1.ExpireMachineResponse.machine:type_name -> headscale.v1.Machine + 1, // 10: headscale.v1.ListMachinesResponse.machines:type_name -> headscale.v1.Machine + 1, // 11: headscale.v1.ShareMachineResponse.machine:type_name -> headscale.v1.Machine + 1, // 12: headscale.v1.UnshareMachineResponse.machine:type_name -> headscale.v1.Machine + 1, // 13: headscale.v1.DebugCreateMachineResponse.machine:type_name -> headscale.v1.Machine + 14, // [14:14] is the sub-list for method output_type + 14, // [14:14] is the sub-list for method input_type + 14, // [14:14] is the sub-list for extension type_name + 14, // [14:14] is the sub-list for extension extendee + 0, // [0:14] is the sub-list for field type_name } func init() { file_headscale_v1_machine_proto_init() } @@ -1198,7 +1303,7 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMachinesRequest); i { + switch v := v.(*ExpireMachineRequest); i { case 0: return &v.state case 1: @@ -1210,7 +1315,7 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMachinesResponse); i { + switch v := v.(*ExpireMachineResponse); i { case 0: return &v.state case 1: @@ -1222,7 +1327,7 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ShareMachineRequest); i { + switch v := v.(*ListMachinesRequest); i { case 0: return &v.state case 1: @@ -1234,7 +1339,7 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ShareMachineResponse); i { + switch v := v.(*ListMachinesResponse); i { case 0: return &v.state case 1: @@ -1246,7 +1351,7 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnshareMachineRequest); i { + switch v := v.(*ShareMachineRequest); i { case 0: return &v.state case 1: @@ -1258,7 +1363,7 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnshareMachineResponse); i { + switch v := v.(*ShareMachineResponse); i { case 0: return &v.state case 1: @@ -1270,7 +1375,7 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DebugCreateMachineRequest); i { + switch v := v.(*UnshareMachineRequest); i { case 0: return &v.state case 1: @@ -1282,6 +1387,30 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UnshareMachineResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_headscale_v1_machine_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DebugCreateMachineRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_headscale_v1_machine_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DebugCreateMachineResponse); i { case 0: return &v.state @@ -1300,7 +1429,7 @@ func file_headscale_v1_machine_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_headscale_v1_machine_proto_rawDesc, NumEnums: 1, - NumMessages: 15, + NumMessages: 17, NumExtensions: 0, NumServices: 0, }, diff --git a/gen/openapiv2/headscale/v1/headscale.swagger.json b/gen/openapiv2/headscale/v1/headscale.swagger.json index f1e95cad..2274e22c 100644 --- a/gen/openapiv2/headscale/v1/headscale.swagger.json +++ b/gen/openapiv2/headscale/v1/headscale.swagger.json @@ -161,6 +161,37 @@ ] } }, + "/api/v1/machine/{machineId}/expire": { + "post": { + "operationId": "HeadscaleService_ExpireMachine", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ExpireMachineResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "machineId", + "in": "path", + "required": true, + "type": "string", + "format": "uint64" + } + ], + "tags": [ + "HeadscaleService" + ] + } + }, "/api/v1/machine/{machineId}/routes": { "get": { "summary": "--- Route start ---", @@ -649,6 +680,14 @@ } } }, + "v1ExpireMachineResponse": { + "type": "object", + "properties": { + "machine": { + "$ref": "#/definitions/v1Machine" + } + } + }, "v1ExpirePreAuthKeyRequest": { "type": "object", "properties": { diff --git a/proto/headscale/v1/headscale.proto b/proto/headscale/v1/headscale.proto index e7a63fc5..f7332a88 100644 --- a/proto/headscale/v1/headscale.proto +++ b/proto/headscale/v1/headscale.proto @@ -92,6 +92,12 @@ service HeadscaleService { }; } + rpc ExpireMachine(ExpireMachineRequest) returns (ExpireMachineResponse) { + option (google.api.http) = { + post: "/api/v1/machine/{machine_id}/expire" + }; + } + rpc ListMachines(ListMachinesRequest) returns (ListMachinesResponse) { option (google.api.http) = { get: "/api/v1/machine" diff --git a/proto/headscale/v1/machine.proto b/proto/headscale/v1/machine.proto index 4e53c4ad..ed99f002 100644 --- a/proto/headscale/v1/machine.proto +++ b/proto/headscale/v1/machine.proto @@ -64,6 +64,14 @@ message DeleteMachineRequest { message DeleteMachineResponse { } +message ExpireMachineRequest { + uint64 machine_id = 1; +} + +message ExpireMachineResponse { + Machine machine = 1; +} + message ListMachinesRequest { string namespace = 1; } From bd1d1b1a3b859f155012710cc2681f23d37707d5 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 13:40:19 +0000 Subject: [PATCH 13/38] Implement ExpireMachine rpc --- grpcv1.go | 21 +++++++++++++++++++++ machine.go | 8 ++++++++ machine_test.go | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/grpcv1.go b/grpcv1.go index 40419c3c..1850ce7a 100644 --- a/grpcv1.go +++ b/grpcv1.go @@ -201,6 +201,27 @@ func (api headscaleV1APIServer) DeleteMachine( return &v1.DeleteMachineResponse{}, nil } +func (api headscaleV1APIServer) ExpireMachine( + ctx context.Context, + request *v1.ExpireMachineRequest, +) (*v1.ExpireMachineResponse, error) { + machine, err := api.h.GetMachineByID(request.GetMachineId()) + if err != nil { + return nil, err + } + + api.h.ExpireMachine( + machine, + ) + + log.Trace(). + Str("machine", machine.Name). + Time("expiry", *machine.Expiry). + Msg("machine expired") + + return &v1.ExpireMachineResponse{Machine: machine.toProto()}, nil +} + func (api headscaleV1APIServer) ListMachines( ctx context.Context, request *v1.ListMachinesRequest, diff --git a/machine.go b/machine.go index 813da35c..e34bff87 100644 --- a/machine.go +++ b/machine.go @@ -262,6 +262,14 @@ func (h *Headscale) UpdateMachine(machine *Machine) error { return nil } +// ExpireMachine takes a Machine struct and sets the expire field to now. +func (h *Headscale) ExpireMachine(machine *Machine) { + now := time.Now() + machine.Expiry = &now + + h.db.Save(machine) +} + // DeleteMachine softs deletes a Machine from the database. func (h *Headscale) DeleteMachine(machine *Machine) error { err := h.RemoveSharedMachineFromAllNamespaces(machine) diff --git a/machine_test.go b/machine_test.go index fdbc3cb5..eb090072 100644 --- a/machine_test.go +++ b/machine_test.go @@ -3,6 +3,7 @@ package headscale import ( "encoding/json" "strconv" + "time" "gopkg.in/check.v1" ) @@ -164,3 +165,37 @@ func (s *Suite) TestGetDirectPeers(c *check.C) { c.Assert(peersOfMachine0[5].Name, check.Equals, "testmachine7") c.Assert(peersOfMachine0[8].Name, check.Equals, "testmachine10") } + +func (s *Suite) TestExpireMachine(c *check.C) { + namespace, err := app.CreateNamespace("test") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("test", "testmachine") + c.Assert(err, check.NotNil) + + machine := &Machine{ + ID: 0, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "testmachine", + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + Expiry: &time.Time{}, + } + app.db.Save(machine) + + machineFromDB, err := app.GetMachine("test", "testmachine") + c.Assert(err, check.IsNil) + + c.Assert(machineFromDB.isExpired(), check.Equals, false) + + app.ExpireMachine(machineFromDB) + + c.Assert(machineFromDB.isExpired(), check.Equals, true) +} From a2b9f3bedea8a3216b8885fc5b7196d0aace957d Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 13:40:44 +0000 Subject: [PATCH 14/38] Add expire (logout) machine command --- cmd/headscale/cli/nodes.go | 51 +++++++++++++++ integration_cli_test.go | 127 +++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/cmd/headscale/cli/nodes.go b/cmd/headscale/cli/nodes.go index 7c2cd6c1..29679f0d 100644 --- a/cmd/headscale/cli/nodes.go +++ b/cmd/headscale/cli/nodes.go @@ -33,6 +33,13 @@ func init() { } nodeCmd.AddCommand(registerNodeCmd) + expireNodeCmd.Flags().IntP("identifier", "i", 0, "Node identifier (ID)") + err = expireNodeCmd.MarkFlagRequired("identifier") + if err != nil { + log.Fatalf(err.Error()) + } + nodeCmd.AddCommand(expireNodeCmd) + deleteNodeCmd.Flags().IntP("identifier", "i", 0, "Node identifier (ID)") err = deleteNodeCmd.MarkFlagRequired("identifier") if err != nil { @@ -177,6 +184,50 @@ var listNodesCmd = &cobra.Command{ }, } +var expireNodeCmd = &cobra.Command{ + Use: "expire", + Short: "Expire (log out) a machine in your network", + Aliases: []string{"logout"}, + Run: func(cmd *cobra.Command, args []string) { + output, _ := cmd.Flags().GetString("output") + + identifier, err := cmd.Flags().GetInt("identifier") + if err != nil { + ErrorOutput( + err, + fmt.Sprintf("Error converting ID to integer: %s", err), + output, + ) + + return + } + + ctx, client, conn, cancel := getHeadscaleCLIClient() + defer cancel() + defer conn.Close() + + request := &v1.ExpireMachineRequest{ + MachineId: uint64(identifier), + } + + response, err := client.ExpireMachine(ctx, request) + if err != nil { + ErrorOutput( + err, + fmt.Sprintf( + "Cannot expire machine: %s\n", + status.Convert(err).Message(), + ), + output, + ) + + return + } + + SuccessOutput(response.Machine, "Machine expired", output) + }, +} + var deleteNodeCmd = &cobra.Command{ Use: "delete", Short: "Delete a node", diff --git a/integration_cli_test.go b/integration_cli_test.go index 898e2cd7..ee940542 100644 --- a/integration_cli_test.go +++ b/integration_cli_test.go @@ -897,6 +897,133 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { assert.Len(s.T(), listOnlyMachineNamespaceAfterUnshare, 4) } +func (s *IntegrationCLITestSuite) TestNodeExpireCommand() { + namespace, err := s.createNamespace("machine-expire-namespace") + assert.Nil(s.T(), err) + + // Randomly generated machine keys + machineKeys := []string{ + "9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe", + "6abd00bb5fdda622db51387088c68e97e71ce58e7056aa54f592b6a8219d524c", + "f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507", + "8bc13285cee598acf76b1824a6f4490f7f2e3751b201e28aeb3b07fe81d5b4a1", + "cf7b0fd05da556fdc3bab365787b506fd82d64a70745db70e00e86c1b1c03084", + } + machines := make([]*v1.Machine, len(machineKeys)) + assert.Nil(s.T(), err) + + for index, machineKey := range machineKeys { + _, err := ExecuteCommand( + &s.headscale, + []string{ + "headscale", + "debug", + "create-node", + "--name", + fmt.Sprintf("machine-%d", index+1), + "--namespace", + namespace.Name, + "--key", + machineKey, + "--output", + "json", + }, + []string{}, + ) + assert.Nil(s.T(), err) + + machineResult, err := ExecuteCommand( + &s.headscale, + []string{ + "headscale", + "nodes", + "--namespace", + namespace.Name, + "register", + "--key", + machineKey, + "--output", + "json", + }, + []string{}, + ) + assert.Nil(s.T(), err) + + var machine v1.Machine + err = json.Unmarshal([]byte(machineResult), &machine) + assert.Nil(s.T(), err) + + machines[index] = &machine + } + + assert.Len(s.T(), machines, len(machineKeys)) + + listAllResult, err := ExecuteCommand( + &s.headscale, + []string{ + "headscale", + "nodes", + "list", + "--output", + "json", + }, + []string{}, + ) + assert.Nil(s.T(), err) + + var listAll []v1.Machine + err = json.Unmarshal([]byte(listAllResult), &listAll) + assert.Nil(s.T(), err) + + assert.Len(s.T(), listAll, 5) + + assert.True(s.T(), listAll[0].Expiry.AsTime().IsZero()) + assert.True(s.T(), listAll[1].Expiry.AsTime().IsZero()) + assert.True(s.T(), listAll[2].Expiry.AsTime().IsZero()) + assert.True(s.T(), listAll[3].Expiry.AsTime().IsZero()) + assert.True(s.T(), listAll[4].Expiry.AsTime().IsZero()) + + for i := 0; i < 3; i++ { + _, err := ExecuteCommand( + &s.headscale, + []string{ + "headscale", + "nodes", + "expire", + "--identifier", + fmt.Sprintf("%d", listAll[i].Id), + }, + []string{}, + ) + assert.Nil(s.T(), err) + } + + listAllAfterExpiryResult, err := ExecuteCommand( + &s.headscale, + []string{ + "headscale", + "nodes", + "list", + "--output", + "json", + }, + []string{}, + ) + assert.Nil(s.T(), err) + + var listAllAfterExpiry []v1.Machine + err = json.Unmarshal([]byte(listAllAfterExpiryResult), &listAllAfterExpiry) + assert.Nil(s.T(), err) + + assert.Len(s.T(), listAllAfterExpiry, 5) + + assert.True(s.T(), listAllAfterExpiry[0].Expiry.AsTime().Before(time.Now())) + assert.True(s.T(), listAllAfterExpiry[1].Expiry.AsTime().Before(time.Now())) + assert.True(s.T(), listAllAfterExpiry[2].Expiry.AsTime().Before(time.Now())) + assert.True(s.T(), listAllAfterExpiry[3].Expiry.AsTime().IsZero()) + assert.True(s.T(), listAllAfterExpiry[4].Expiry.AsTime().IsZero()) +} + func (s *IntegrationCLITestSuite) TestRouteCommand() { namespace, err := s.createNamespace("routes-namespace") assert.Nil(s.T(), err) From 8ccc51ae5750ffa099509c13b6dacbd523f2c55b Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 13:45:19 +0000 Subject: [PATCH 15/38] Remove special case for authkey We no longer have weird expire behaviour, so we dont need this case --- api.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/api.go b/api.go index ee10e88f..61146c6a 100644 --- a/api.go +++ b/api.go @@ -132,13 +132,6 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { return } - // We dont care about expiry time if the method is AuthKey, as we dont set that. - if machine.Registered && machine.RegisterMethod == RegisterMethodAuthKey { - h.handleMachineValidRegistration(ctx, machineKey, *machine) - - return - } - if machine.Registered && !machine.isExpired() { h.handleMachineValidRegistration(ctx, machineKey, *machine) From c4ecc4db91acc64261bab971ab4191eab43eef06 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 13:59:24 +0000 Subject: [PATCH 16/38] Simplify control flow in RegistrationHandler This commits tries to dismantle the complicated "if and or" in the RegistrationHandler by factoring out the "is Registrated" into a root if. This, together with some new comments, should hopefully make it a bit easier to follow what is happening in all the different cases that needs to be handled when a Node contacts the registration endpoint. --- api.go | 73 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/api.go b/api.go index 61146c6a..8e8e6d67 100644 --- a/api.go +++ b/api.go @@ -116,41 +116,51 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { machine = &newMachine } - if !machine.Registered && req.Auth.AuthKey != "" { + if machine.Registered { + // 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 the node map + // - Expired machine wanting to reauthenticate + if machine.NodeKey == wgkey.Key(req.NodeKey).HexString() { + // 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 !req.Expiry.IsZero() && req.Expiry.UTC().Before(now) { + h.handleMachineLogOut(ctx, machineKey, req, *machine) + + return + } + + // If machine is not expired, and is register, we have a already accepted this machine, + // let it proceed with a valid registration + if !machine.isExpired() { + h.handleMachineValidRegistration(ctx, machineKey, *machine) + + return + } + + // The machine has expired + h.handleMachineExpired(ctx, machineKey, req, *machine) + + return + } + + // The NodeKey we have matches OldNodeKey, which means this is a refresh after a key expiration + if machine.NodeKey == wgkey.Key(req.OldNodeKey).HexString() && + !machine.isExpired() { + h.handleMachineRefreshKey(ctx, machineKey, req, *machine) + + return + } + } + + // If the machine has AuthKey set, handle registration via PreAuthKeys + if req.Auth.AuthKey != "" { h.handleAuthKey(ctx, machineKey, req, *machine) return } - // We have the updated key! - if machine.NodeKey == wgkey.Key(req.NodeKey).HexString() { - // 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 !req.Expiry.IsZero() && req.Expiry.UTC().Before(now) { - h.handleMachineLogOut(ctx, machineKey, req, *machine) - - return - } - - if machine.Registered && !machine.isExpired() { - h.handleMachineValidRegistration(ctx, machineKey, *machine) - - return - } - - h.handleMachineExpired(ctx, machineKey, req, *machine) - - return - } - - // The NodeKey we have matches OldNodeKey, which means this is a refresh after a key expiration - if machine.NodeKey == wgkey.Key(req.OldNodeKey).HexString() && - !machine.isExpired() { - h.handleMachineRefreshKey(ctx, machineKey, req, *machine) - - return - } - h.handleMachineRegistrationNew(ctx, machineKey, req, *machine) } @@ -286,8 +296,7 @@ func (h *Headscale) handleMachineLogOut( Str("machine", machine.Name). Msg("Client requested logout") - machine.Expiry = &reqisterRequest.Expiry // save the expiry so that the machine is marked as expired - h.db.Save(&machine) + h.ExpireMachine(&machine) resp.AuthURL = "" resp.MachineAuthorized = false From bda2d9c3b0566c270ba4e7f93185a440c50c1d1d Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 14:00:48 +0000 Subject: [PATCH 17/38] Remove unused param --- api.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api.go b/api.go index 8e8e6d67..bc1dccbb 100644 --- a/api.go +++ b/api.go @@ -126,7 +126,7 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { // 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 !req.Expiry.IsZero() && req.Expiry.UTC().Before(now) { - h.handleMachineLogOut(ctx, machineKey, req, *machine) + h.handleMachineLogOut(ctx, machineKey, *machine) return } @@ -286,7 +286,6 @@ func (h *Headscale) getMapKeepAliveResponse( func (h *Headscale) handleMachineLogOut( ctx *gin.Context, idKey wgkey.Key, - reqisterRequest tailcfg.RegisterRequest, machine Machine, ) { resp := tailcfg.RegisterResponse{} From fd5f42c2e6241adbac3080a851d85b9883e32bfe Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 21:14:13 +0000 Subject: [PATCH 18/38] Move handle expired machine to the end of registration --- api.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api.go b/api.go index bc1dccbb..6901896f 100644 --- a/api.go +++ b/api.go @@ -138,11 +138,6 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { return } - - // The machine has expired - h.handleMachineExpired(ctx, machineKey, req, *machine) - - return } // The NodeKey we have matches OldNodeKey, which means this is a refresh after a key expiration @@ -152,6 +147,11 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { return } + + // The machine has expired + h.handleMachineExpired(ctx, machineKey, req, *machine) + + return } // If the machine has AuthKey set, handle registration via PreAuthKeys From c2393685f1747512f9bf45ac846a4a9716969cd5 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 21:14:40 +0000 Subject: [PATCH 19/38] Remove expiry update in expiry, we dont want to extend it just because they _try_ to connect --- api.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/api.go b/api.go index 6901896f..565db969 100644 --- a/api.go +++ b/api.go @@ -370,12 +370,6 @@ func (h *Headscale) handleMachineExpired( strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) } - if !reqisterRequest.Expiry.IsZero() { - machine.Expiry = &reqisterRequest.Expiry - } - - h.db.Save(&machine) - respBody, err := encode(resp, &idKey, h.privateKey) if err != nil { log.Error(). From 1687e3b03f92d7e063c780882af3884776015f5a Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 21:29:27 +0000 Subject: [PATCH 20/38] Removed unused parameter --- api.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api.go b/api.go index 565db969..c5002bb1 100644 --- a/api.go +++ b/api.go @@ -149,7 +149,7 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { } // The machine has expired - h.handleMachineExpired(ctx, machineKey, req, *machine) + h.handleMachineExpired(ctx, machineKey, *machine) return } @@ -351,7 +351,6 @@ func (h *Headscale) handleMachineValidRegistration( func (h *Headscale) handleMachineExpired( ctx *gin.Context, idKey wgkey.Key, - reqisterRequest tailcfg.RegisterRequest, machine Machine, ) { resp := tailcfg.RegisterResponse{} From b152e53b13f9c93900a1290af473a7eb1fcdc07e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 21:34:03 +0000 Subject: [PATCH 21/38] Use correct type for nodes command --- cmd/headscale/cli/nodes.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/headscale/cli/nodes.go b/cmd/headscale/cli/nodes.go index 29679f0d..4bc0e316 100644 --- a/cmd/headscale/cli/nodes.go +++ b/cmd/headscale/cli/nodes.go @@ -191,7 +191,7 @@ var expireNodeCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") - identifier, err := cmd.Flags().GetInt("identifier") + identifier, err := cmd.Flags().GetUint64("identifier") if err != nil { ErrorOutput( err, @@ -207,7 +207,7 @@ var expireNodeCmd = &cobra.Command{ defer conn.Close() request := &v1.ExpireMachineRequest{ - MachineId: uint64(identifier), + MachineId: identifier, } response, err := client.ExpireMachine(ctx, request) @@ -234,7 +234,7 @@ var deleteNodeCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") - identifier, err := cmd.Flags().GetInt("identifier") + identifier, err := cmd.Flags().GetUint64("identifier") if err != nil { ErrorOutput( err, @@ -250,7 +250,7 @@ var deleteNodeCmd = &cobra.Command{ defer conn.Close() getRequest := &v1.GetMachineRequest{ - MachineId: uint64(identifier), + MachineId: identifier, } getResponse, err := client.GetMachine(ctx, getRequest) @@ -331,7 +331,7 @@ func sharingWorker( defer cancel() defer conn.Close() - identifier, err := cmd.Flags().GetInt("identifier") + identifier, err := cmd.Flags().GetUint64("identifier") if err != nil { ErrorOutput(err, fmt.Sprintf("Error converting ID to integer: %s", err), output) @@ -339,7 +339,7 @@ func sharingWorker( } machineRequest := &v1.GetMachineRequest{ - MachineId: uint64(identifier), + MachineId: identifier, } machineResponse, err := client.GetMachine(ctx, machineRequest) From fac33e46e11475ed7061d286d6e97d67ce1bf53c Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 21:35:36 +0000 Subject: [PATCH 22/38] Add long description for expire --- cmd/headscale/cli/nodes.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/headscale/cli/nodes.go b/cmd/headscale/cli/nodes.go index 4bc0e316..01d37a7d 100644 --- a/cmd/headscale/cli/nodes.go +++ b/cmd/headscale/cli/nodes.go @@ -187,6 +187,7 @@ var listNodesCmd = &cobra.Command{ var expireNodeCmd = &cobra.Command{ Use: "expire", Short: "Expire (log out) a machine in your network", + Long: "Expiring a node will keep the node in the database and force it to reauthenticate.", Aliases: []string{"logout"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") From fcd4d94927fb261ae24762b42efdd941087a97f6 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 21:51:39 +0000 Subject: [PATCH 23/38] Clean up logging and error handling in oidc We should never expose errors via web, it gives attackers a lot of info (Insert OWASP guide). Also handle error that didnt separate not found gorm issue and other errors. --- oidc.go | 62 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/oidc.go b/oidc.go index fb27354b..e569fe10 100644 --- a/oidc.go +++ b/oidc.go @@ -4,6 +4,7 @@ import ( "context" "crypto/rand" "encoding/hex" + "errors" "fmt" "net/http" "regexp" @@ -15,6 +16,7 @@ import ( "github.com/patrickmn/go-cache" "github.com/rs/zerolog/log" "golang.org/x/oauth2" + "gorm.io/gorm" ) const ( @@ -37,7 +39,10 @@ func (h *Headscale) initOIDC() error { h.oidcProvider, err = oidc.NewProvider(context.Background(), h.cfg.OIDC.Issuer) if err != nil { - log.Error().Msgf("Could not retrieve OIDC Config: %s", err.Error()) + log.Error(). + Err(err). + Caller(). + Msgf("Could not retrieve OIDC Config: %s", err.Error()) return err } @@ -69,8 +74,8 @@ func (h *Headscale) initOIDC() error { // Puts machine key in cache so the callback can retrieve it using the oidc state param // Listens in /oidc/register/:mKey. func (h *Headscale) RegisterOIDC(ctx *gin.Context) { - mKeyStr := ctx.Param("mkey") - if mKeyStr == "" { + machineKeyStr := ctx.Param("mkey") + if machineKeyStr == "" { ctx.String(http.StatusBadRequest, "Wrong params") return @@ -78,7 +83,9 @@ func (h *Headscale) RegisterOIDC(ctx *gin.Context) { randomBlob := make([]byte, randomByteSize) if _, err := rand.Read(randomBlob); err != nil { - log.Error().Msg("could not read 16 bytes from rand") + log.Error(). + Caller(). + Msg("could not read 16 bytes from rand") ctx.String(http.StatusInternalServerError, "could not read 16 bytes from rand") return @@ -87,7 +94,7 @@ func (h *Headscale) RegisterOIDC(ctx *gin.Context) { stateStr := hex.EncodeToString(randomBlob)[:32] // place the machine key into the state cache, so it can be retrieved later - h.oidcStateCache.Set(stateStr, mKeyStr, oidcStateCacheExpiration) + h.oidcStateCache.Set(stateStr, machineKeyStr, oidcStateCacheExpiration) authURL := h.oauth2Config.AuthCodeURL(stateStr) log.Debug().Msgf("Redirecting to %s for authentication", authURL) @@ -130,7 +137,11 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { idToken, err := verifier.Verify(context.Background(), rawIDToken) if err != nil { - ctx.String(http.StatusBadRequest, "Failed to verify id token: %s", err.Error()) + log.Error(). + Err(err). + Caller(). + Msg("failed to verify id token") + ctx.String(http.StatusBadRequest, "Failed to verify id token") return } @@ -145,27 +156,31 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { // Extract custom claims var claims IDTokenClaims if err = idToken.Claims(&claims); err != nil { + log.Error(). + Err(err). + Caller(). + Msg("Failed to decode id token claims") ctx.String( http.StatusBadRequest, - fmt.Sprintf("Failed to decode id token claims: %s", err), + fmt.Sprintf("Failed to decode id token claims"), ) return } // retrieve machinekey from state cache - mKeyIf, mKeyFound := h.oidcStateCache.Get(state) + machineKeyIf, machineKeyFound := h.oidcStateCache.Get(state) - if !mKeyFound { + if !machineKeyFound { log.Error(). Msg("requested machine state key expired before authorisation completed") ctx.String(http.StatusBadRequest, "state has expired") return } - mKeyStr, mKeyOK := mKeyIf.(string) + machineKey, machineKeyOK := machineKeyIf.(string) - if !mKeyOK { + if !machineKeyOK { log.Error().Msg("could not get machine key from cache") ctx.String( http.StatusInternalServerError, @@ -176,7 +191,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { } // retrieve machine information - machine, err := h.GetMachineByMachineKey(mKeyStr) + machine, err := h.GetMachineByMachineKey(machineKey) if err != nil { log.Error().Msg("machine key not found in database") ctx.String( @@ -195,12 +210,14 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { log.Debug().Msg("Registering new machine after successful callback") namespace, err := h.GetNamespace(namespaceName) - if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { namespace, err = h.CreateNamespace(namespaceName) if err != nil { log.Error(). - Msgf("could not create new namespace '%s'", claims.Email) + Err(err). + Caller(). + Msgf("could not create new namespace '%s'", namespaceName) ctx.String( http.StatusInternalServerError, "could not create new namespace", @@ -208,10 +225,26 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } + } else if err != nil { + log.Error(). + Caller(). + Err(err). + Str("namespace", namespaceName). + Msg("could not find or create namespace") + ctx.String( + http.StatusInternalServerError, + "could not find or create namespace", + ) + + return } ip, err := h.getAvailableIP() if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("could not get an IP from the pool") ctx.String( http.StatusInternalServerError, "could not get an IP from the pool", @@ -242,6 +275,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { } log.Error(). + Caller(). Str("email", claims.Email). Str("username", claims.Username). Str("machine", machine.Name). From 74044f62f4bd67070ab72e743f2f6486e0203d22 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 21 Nov 2021 21:54:19 +0000 Subject: [PATCH 24/38] Remove anouther potential error leak --- oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oidc.go b/oidc.go index e569fe10..8fafc89a 100644 --- a/oidc.go +++ b/oidc.go @@ -149,7 +149,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { // TODO: we can use userinfo at some point to grab additional information about the user (groups membership, etc) // userInfo, err := oidcProvider.UserInfo(context.Background(), oauth2.StaticTokenSource(oauth2Token)) // if err != nil { - // c.String(http.StatusBadRequest, fmt.Sprintf("Failed to retrieve userinfo: %s", err)) + // c.String(http.StatusBadRequest, fmt.Sprintf("Failed to retrieve userinfo")) // return // } From 5cbd4513a436592f6971a2a4c78b6fe332e067b5 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 22 Nov 2021 17:21:56 +0000 Subject: [PATCH 25/38] Simplify register function if --- machine.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/machine.go b/machine.go index e34bff87..d6903bd7 100644 --- a/machine.go +++ b/machine.go @@ -61,7 +61,7 @@ type ( ) // For the time being this method is rather naive. -func (machine Machine) isAlreadyRegistered() bool { +func (machine Machine) isRegistered() bool { return machine.Registered } @@ -612,7 +612,7 @@ func (h *Headscale) RegisterMachine( Str("machine", machine.Name). Msg("Attempting to register machine") - if machine.isAlreadyRegistered() { + if machine.isRegistered() { err := errMachineAlreadyRegistered log.Error(). Caller(). From e8faff4fe2bbdd36a383032dc4954fdc204768f7 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 22 Nov 2021 17:22:22 +0000 Subject: [PATCH 26/38] Use uint64 straight instead of converting --- cmd/headscale/cli/nodes.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/headscale/cli/nodes.go b/cmd/headscale/cli/nodes.go index 01d37a7d..f5117d95 100644 --- a/cmd/headscale/cli/nodes.go +++ b/cmd/headscale/cli/nodes.go @@ -33,14 +33,14 @@ func init() { } nodeCmd.AddCommand(registerNodeCmd) - expireNodeCmd.Flags().IntP("identifier", "i", 0, "Node identifier (ID)") + expireNodeCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") err = expireNodeCmd.MarkFlagRequired("identifier") if err != nil { log.Fatalf(err.Error()) } nodeCmd.AddCommand(expireNodeCmd) - deleteNodeCmd.Flags().IntP("identifier", "i", 0, "Node identifier (ID)") + deleteNodeCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") err = deleteNodeCmd.MarkFlagRequired("identifier") if err != nil { log.Fatalf(err.Error()) @@ -52,7 +52,7 @@ func init() { if err != nil { log.Fatalf(err.Error()) } - shareMachineCmd.Flags().IntP("identifier", "i", 0, "Node identifier (ID)") + shareMachineCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") err = shareMachineCmd.MarkFlagRequired("identifier") if err != nil { log.Fatalf(err.Error()) @@ -64,7 +64,7 @@ func init() { if err != nil { log.Fatalf(err.Error()) } - unshareMachineCmd.Flags().IntP("identifier", "i", 0, "Node identifier (ID)") + unshareMachineCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") err = unshareMachineCmd.MarkFlagRequired("identifier") if err != nil { log.Fatalf(err.Error()) @@ -269,7 +269,7 @@ var deleteNodeCmd = &cobra.Command{ } deleteRequest := &v1.DeleteMachineRequest{ - MachineId: uint64(identifier), + MachineId: identifier, } confirm := false From 200c10e48c19866379f096b4b322d1270d32a81d Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 22 Nov 2021 17:22:47 +0000 Subject: [PATCH 27/38] Add missing return in oidc.go --- oidc.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/oidc.go b/oidc.go index 8fafc89a..cdd4fc21 100644 --- a/oidc.go +++ b/oidc.go @@ -162,7 +162,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { Msg("Failed to decode id token claims") ctx.String( http.StatusBadRequest, - fmt.Sprintf("Failed to decode id token claims"), + "Failed to decode id token claims", ) return @@ -272,6 +272,8 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { `, claims.Email))) + + return } log.Error(). From e600ead3e9d8d8689013a2cd27c19977087fc74b Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 22 Nov 2021 19:32:11 +0000 Subject: [PATCH 28/38] Make sure nodes can reauthenticate This commit fixes an issue where nodes were not able to reauthenticate. --- api.go | 68 +++++++++++++++++++++++++++++++----------------------- machine.go | 10 ++++++++ oidc.go | 35 +++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 30 deletions(-) diff --git a/api.go b/api.go index c5002bb1..50af5522 100644 --- a/api.go +++ b/api.go @@ -375,13 +375,13 @@ func (h *Headscale) handleMachineExpired( Str("handler", "Registration"). Err(err). Msg("Cannot encode message") - machineRegistrations.WithLabelValues("new", "web", "error", machine.Namespace.Name). + machineRegistrations.WithLabelValues("reauth", "web", "error", machine.Namespace.Name). Inc() ctx.String(http.StatusInternalServerError, "") return } - machineRegistrations.WithLabelValues("new", "web", "success", machine.Namespace.Name). + machineRegistrations.WithLabelValues("reauth", "web", "success", machine.Namespace.Name). Inc() ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) } @@ -503,36 +503,46 @@ func (h *Headscale) handleAuthKey( return } - log.Debug(). - Str("func", "handleAuthKey"). - Str("machine", machine.Name). - Msg("Authentication key was valid, proceeding to acquire an IP address") - ip, err := h.getAvailableIP() - if err != nil { - log.Error(). + if machine.isRegistered() { + log.Trace(). + Caller(). + Str("machine", machine.Name). + Msg("machine already registered, reauthenticating") + + h.RefreshMachine(&machine, reqisterRequest.Expiry) + } else { + log.Debug(). Str("func", "handleAuthKey"). Str("machine", machine.Name). - Msg("Failed to find an available IP") - machineRegistrations.WithLabelValues("new", "authkey", "error", machine.Namespace.Name). - Inc() + Msg("Authentication key was valid, proceeding to acquire an IP address") + ip, err := h.getAvailableIP() + if err != nil { + log.Error(). + Str("func", "handleAuthKey"). + Str("machine", machine.Name). + Msg("Failed to find an available IP") + machineRegistrations.WithLabelValues("new", "authkey", "error", machine.Namespace.Name). + Inc() - return + return + } + log.Info(). + Str("func", "handleAuthKey"). + Str("machine", machine.Name). + Str("ip", ip.String()). + Msgf("Assigning %s to %s", ip, machine.Name) + + machine.Expiry = &reqisterRequest.Expiry + machine.AuthKeyID = uint(pak.ID) + machine.IPAddress = ip.String() + machine.NamespaceID = pak.NamespaceID + machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey). + HexString() + // we update it just in case + machine.Registered = true + machine.RegisterMethod = RegisterMethodAuthKey + h.db.Save(&machine) } - log.Info(). - Str("func", "handleAuthKey"). - Str("machine", machine.Name). - Str("ip", ip.String()). - Msgf("Assigning %s to %s", ip, machine.Name) - - machine.AuthKeyID = uint(pak.ID) - machine.IPAddress = ip.String() - machine.NamespaceID = pak.NamespaceID - machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey). - HexString() - // we update it just in case - machine.Registered = true - machine.RegisterMethod = RegisterMethodAuthKey - h.db.Save(&machine) pak.Used = true h.db.Save(&pak) @@ -558,6 +568,6 @@ func (h *Headscale) handleAuthKey( log.Info(). Str("func", "handleAuthKey"). Str("machine", machine.Name). - Str("ip", ip.String()). + Str("ip", machine.IPAddress). Msg("Successfully authenticated via AuthKey") } diff --git a/machine.go b/machine.go index d6903bd7..dd7124ec 100644 --- a/machine.go +++ b/machine.go @@ -270,6 +270,15 @@ func (h *Headscale) ExpireMachine(machine *Machine) { h.db.Save(machine) } +// RefreshMachine takes a Machine struct and sets the expire field to now. +func (h *Headscale) RefreshMachine(machine *Machine, expiry time.Time) { + now := time.Now() + + machine.LastSuccessfulUpdate = &now + machine.Expiry = &expiry + h.db.Save(machine) +} + // DeleteMachine softs deletes a Machine from the database. func (h *Headscale) DeleteMachine(machine *Machine) error { err := h.RemoveSharedMachineFromAllNamespaces(machine) @@ -644,6 +653,7 @@ func (h *Headscale) RegisterMachine( machine.NamespaceID = namespace.ID machine.Registered = true machine.RegisterMethod = RegisterMethodCLI + machine.Expiry = &requestedTime h.db.Save(&machine) log.Trace(). diff --git a/oidc.go b/oidc.go index cdd4fc21..2f7d6d61 100644 --- a/oidc.go +++ b/oidc.go @@ -81,6 +81,11 @@ func (h *Headscale) RegisterOIDC(ctx *gin.Context) { return } + log.Trace(). + Caller(). + Str("machine_key", machineKeyStr). + Msg("Received oidc register call") + randomBlob := make([]byte, randomByteSize) if _, err := rand.Read(randomBlob); err != nil { log.Error(). @@ -124,7 +129,11 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - log.Debug().Msgf("AccessToken: %v", oauth2Token.AccessToken) + log.Trace(). + Caller(). + Str("code", code). + Str("state", state). + Msg("Got oidc callback") rawIDToken, rawIDTokenOK := oauth2Token.Extra("id_token").(string) if !rawIDTokenOK { @@ -202,6 +211,29 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } + if machine.isRegistered() { + log.Trace(). + Caller(). + Str("machine", machine.Name). + Msg("machine already registered, reauthenticating") + + h.RefreshMachine(machine, requestedTime) + + ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(fmt.Sprintf(` + + +

headscale

+

+ Reuthenticated as %s, you can now close this window. +

+ + + +`, claims.Email))) + + return + } + now := time.Now().UTC() if namespaceName, ok := h.getNamespaceFromEmail(claims.Email); ok { @@ -258,6 +290,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { machine.Registered = true machine.RegisterMethod = RegisterMethodOIDC machine.LastSuccessfulUpdate = &now + machine.Expiry = &requestedTime h.db.Save(&machine) } From 021c464148c65f836f83b8a0196995587270b917 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 22 Nov 2021 19:32:52 +0000 Subject: [PATCH 29/38] Add cache for requested expiry times This commit adds a sentral cache to keep track of clients whom has requested an expiry time, but were we need to keep hold of it until the second request comes in. --- api.go | 22 +++++++++++++++++----- app.go | 23 +++++++++++++++++------ machine.go | 25 +++++++++++++++++++++++++ oidc.go | 8 ++++++++ 4 files changed, 67 insertions(+), 11 deletions(-) diff --git a/api.go b/api.go index 50af5522..92186ee8 100644 --- a/api.go +++ b/api.go @@ -19,10 +19,13 @@ import ( ) const ( - reservedResponseHeaderSize = 4 - RegisterMethodAuthKey = "authKey" - RegisterMethodOIDC = "oidc" - RegisterMethodCLI = "cli" + reservedResponseHeaderSize = 4 + RegisterMethodAuthKey = "authKey" + RegisterMethodOIDC = "oidc" + RegisterMethodCLI = "cli" + ErrRegisterMethodCLIDoesNotSupportExpire = Error( + "machines registered with CLI does not support expire", + ) ) // KeyHandler provides the Headscale pub key @@ -441,7 +444,16 @@ func (h *Headscale) handleMachineRegistrationNew( } if !reqisterRequest.Expiry.IsZero() { - machine.Expiry = &reqisterRequest.Expiry + log.Trace(). + Caller(). + Str("machine", machine.Name). + Time("expiry", reqisterRequest.Expiry). + Msg("Non-zero expiry time requested, adding to cache") + h.requestedExpiryCache.Set( + idKey.HexString(), + reqisterRequest.Expiry, + requestedExpiryCacheExpiration, + ) } machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey).HexString() // save the NodeKey diff --git a/app.go b/app.go index b2b545b4..0d3332dd 100644 --- a/app.go +++ b/app.go @@ -53,6 +53,9 @@ const ( updateInterval = 5000 HTTPReadTimeout = 30 * time.Second + requestedExpiryCacheExpiration = time.Minute * 5 + requestedExpiryCacheCleanupInterval = time.Minute * 10 + errUnsupportedDatabase = Error("unsupported DB") errUnsupportedLetsEncryptChallengeType = Error( "unknown value for Lets Encrypt challenge type", @@ -139,6 +142,8 @@ type Headscale struct { oidcProvider *oidc.Provider oauth2Config *oauth2.Config oidcStateCache *cache.Cache + + requestedExpiryCache *cache.Cache } // NewHeadscale returns the Headscale app. @@ -171,13 +176,19 @@ func NewHeadscale(cfg Config) (*Headscale, error) { return nil, errUnsupportedDatabase } + requestedExpiryCache := cache.New( + requestedExpiryCacheExpiration, + requestedExpiryCacheCleanupInterval, + ) + app := Headscale{ - cfg: cfg, - dbType: cfg.DBtype, - dbString: dbString, - privateKey: privKey, - publicKey: &pubKey, - aclRules: tailcfg.FilterAllowAll, // default allowall + cfg: cfg, + dbType: cfg.DBtype, + dbString: dbString, + privateKey: privKey, + publicKey: &pubKey, + aclRules: tailcfg.FilterAllowAll, // default allowall + requestedExpiryCache: requestedExpiryCache, } err = app.initDB() diff --git a/machine.go b/machine.go index dd7124ec..06fec743 100644 --- a/machine.go +++ b/machine.go @@ -616,6 +616,31 @@ func (h *Headscale) RegisterMachine( return nil, errMachineNotFound } + // TODO(kradalby): Currently, if it fails to find a requested expiry, non will be set + // This means that if a user is to slow with register a machine, it will possibly not + // have the correct expiry. + requestedTime := time.Time{} + if requestedTimeIf, found := h.requestedExpiryCache.Get(machineKey.HexString()); found { + log.Trace(). + Caller(). + Str("machine", machine.Name). + Msg("Expiry time found in cache, assigning to node") + if reqTime, ok := requestedTimeIf.(time.Time); ok { + requestedTime = reqTime + } + } + + if machine.isRegistered() { + log.Trace(). + Caller(). + Str("machine", machine.Name). + Msg("machine already registered, reauthenticating") + + h.RefreshMachine(&machine, requestedTime) + + return &machine, nil + } + log.Trace(). Caller(). Str("machine", machine.Name). diff --git a/oidc.go b/oidc.go index 2f7d6d61..9b0a3087 100644 --- a/oidc.go +++ b/oidc.go @@ -199,6 +199,14 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } + // TODO(kradalby): Currently, if it fails to find a requested expiry, non will be set + requestedTime := time.Time{} + if requestedTimeIf, found := h.requestedExpiryCache.Get(machineKey); found { + if reqTime, ok := requestedTimeIf.(time.Time); ok { + requestedTime = reqTime + } + } + // retrieve machine information machine, err := h.GetMachineByMachineKey(machineKey) if err != nil { From caf1b1cabce45fa30bee6fee71d9ede3816e1605 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 22 Nov 2021 19:35:24 +0000 Subject: [PATCH 30/38] Fix typo --- api.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/api.go b/api.go index 92186ee8..5a0b9d37 100644 --- a/api.go +++ b/api.go @@ -392,7 +392,7 @@ func (h *Headscale) handleMachineExpired( func (h *Headscale) handleMachineRefreshKey( ctx *gin.Context, idKey wgkey.Key, - reqisterRequest tailcfg.RegisterRequest, + registerRequest tailcfg.RegisterRequest, machine Machine, ) { resp := tailcfg.RegisterResponse{} @@ -401,7 +401,7 @@ func (h *Headscale) handleMachineRefreshKey( Str("handler", "Registration"). Str("machine", machine.Name). Msg("We have the OldNodeKey in the database. This is a key refresh") - machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey).HexString() + machine.NodeKey = wgkey.Key(registerRequest.NodeKey).HexString() h.db.Save(&machine) resp.AuthURL = "" @@ -422,7 +422,7 @@ func (h *Headscale) handleMachineRefreshKey( func (h *Headscale) handleMachineRegistrationNew( ctx *gin.Context, idKey wgkey.Key, - reqisterRequest tailcfg.RegisterRequest, + registerRequest tailcfg.RegisterRequest, machine Machine, ) { resp := tailcfg.RegisterResponse{} @@ -443,20 +443,20 @@ func (h *Headscale) handleMachineRegistrationNew( strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) } - if !reqisterRequest.Expiry.IsZero() { + if !registerRequest.Expiry.IsZero() { log.Trace(). Caller(). Str("machine", machine.Name). - Time("expiry", reqisterRequest.Expiry). + Time("expiry", registerRequest.Expiry). Msg("Non-zero expiry time requested, adding to cache") h.requestedExpiryCache.Set( idKey.HexString(), - reqisterRequest.Expiry, + registerRequest.Expiry, requestedExpiryCacheExpiration, ) } - machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey).HexString() // save the NodeKey + machine.NodeKey = wgkey.Key(registerRequest.NodeKey).HexString() // save the NodeKey h.db.Save(&machine) respBody, err := encode(resp, &idKey, h.privateKey) @@ -475,15 +475,15 @@ func (h *Headscale) handleMachineRegistrationNew( func (h *Headscale) handleAuthKey( ctx *gin.Context, idKey wgkey.Key, - reqisterRequest tailcfg.RegisterRequest, + registerRequest tailcfg.RegisterRequest, machine Machine, ) { log.Debug(). Str("func", "handleAuthKey"). - Str("machine", reqisterRequest.Hostinfo.Hostname). - Msgf("Processing auth key for %s", reqisterRequest.Hostinfo.Hostname) + Str("machine", registerRequest.Hostinfo.Hostname). + Msgf("Processing auth key for %s", registerRequest.Hostinfo.Hostname) resp := tailcfg.RegisterResponse{} - pak, err := h.checkKeyValidity(reqisterRequest.Auth.AuthKey) + pak, err := h.checkKeyValidity(registerRequest.Auth.AuthKey) if err != nil { log.Error(). Str("func", "handleAuthKey"). @@ -521,7 +521,7 @@ func (h *Headscale) handleAuthKey( Str("machine", machine.Name). Msg("machine already registered, reauthenticating") - h.RefreshMachine(&machine, reqisterRequest.Expiry) + h.RefreshMachine(&machine, registerRequest.Expiry) } else { log.Debug(). Str("func", "handleAuthKey"). @@ -544,11 +544,11 @@ func (h *Headscale) handleAuthKey( Str("ip", ip.String()). Msgf("Assigning %s to %s", ip, machine.Name) - machine.Expiry = &reqisterRequest.Expiry + machine.Expiry = ®isterRequest.Expiry machine.AuthKeyID = uint(pak.ID) machine.IPAddress = ip.String() machine.NamespaceID = pak.NamespaceID - machine.NodeKey = wgkey.Key(reqisterRequest.NodeKey). + machine.NodeKey = wgkey.Key(registerRequest.NodeKey). HexString() // we update it just in case machine.Registered = true From 68dc2a70dbe789a7b7de78439dd52d0a6f0a0cab Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 22 Nov 2021 19:51:16 +0000 Subject: [PATCH 31/38] Update neighbours if node is expired or refreshed In addition, only pass the map of registered and not expired nodes to clients. --- api.go | 2 +- machine.go | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/api.go b/api.go index 5a0b9d37..6b75ad45 100644 --- a/api.go +++ b/api.go @@ -186,7 +186,7 @@ func (h *Headscale) getMapResponse( return nil, err } - peers, err := h.getPeers(machine) + peers, err := h.getValidPeers(machine) if err != nil { log.Error(). Str("func", "getMapResponse"). diff --git a/machine.go b/machine.go index 06fec743..306b3a47 100644 --- a/machine.go +++ b/machine.go @@ -207,6 +207,23 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { return peers, nil } +func (h *Headscale) getValidPeers(machine *Machine) (Machines, error) { + validPeers := make(Machines, 0) + + peers, err := h.getPeers(machine) + if err != nil { + return Machines{}, err + } + + for _, peer := range peers { + if peer.isRegistered() && !peer.isExpired() { + validPeers = append(validPeers, peer) + } + } + + return validPeers, nil +} + func (h *Headscale) ListMachines() ([]Machine, error) { machines := []Machine{} if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Find(&machines).Error; err != nil { @@ -267,6 +284,8 @@ func (h *Headscale) ExpireMachine(machine *Machine) { now := time.Now() machine.Expiry = &now + h.setLastStateChangeToNow(machine.Namespace.Name) + h.db.Save(machine) } @@ -276,6 +295,9 @@ func (h *Headscale) RefreshMachine(machine *Machine, expiry time.Time) { machine.LastSuccessfulUpdate = &now machine.Expiry = &expiry + + h.setLastStateChangeToNow(machine.Namespace.Name) + h.db.Save(machine) } From 1f1c45a2c0834be24d85ebdc8bad7bfe6049b200 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 22 Nov 2021 19:59:44 +0000 Subject: [PATCH 32/38] Fix cli_test --- app_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app_test.go b/app_test.go index 947062bf..bff13933 100644 --- a/app_test.go +++ b/app_test.go @@ -5,6 +5,7 @@ import ( "os" "testing" + "github.com/patrickmn/go-cache" "gopkg.in/check.v1" "inet.af/netaddr" ) @@ -47,6 +48,10 @@ func (s *Suite) ResetDB(c *check.C) { cfg: cfg, dbType: "sqlite3", dbString: tmpDir + "/headscale_test.db", + requestedExpiryCache: cache.New( + requestedExpiryCacheExpiration, + requestedExpiryCacheCleanupInterval, + ), } err = app.initDB() if err != nil { From 2eca344f0e8ff0467afa2318029132b3c77fafc5 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 24 Nov 2021 10:13:41 +0000 Subject: [PATCH 33/38] Fix gocritic --- .golangci.yaml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 2defdc88..09b50d78 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -25,9 +25,6 @@ linters: - godox - ireturn - # In progress - - gocritic - # We should strive to enable these: - wrapcheck - dupl @@ -51,3 +48,10 @@ linters-settings: - ip - ok - c + + gocritic: + disabled-checks: + - appendAssign + # TODO(kradalby): Remove this + - ifElseChain + From 9968992be078073c913e19805bac500a2f019a0b Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 24 Nov 2021 10:47:20 +0000 Subject: [PATCH 34/38] Fix prettier --- .golangci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yaml b/.golangci.yaml index 09b50d78..965f5496 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -54,4 +54,3 @@ linters-settings: - appendAssign # TODO(kradalby): Remove this - ifElseChain - From fdd64d98c81c186743b5eec60928292d743d656e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 24 Nov 2021 12:15:32 +0000 Subject: [PATCH 35/38] Add missing iff to handle expired preauthkey machines --- api.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/api.go b/api.go index 6b75ad45..43a9f235 100644 --- a/api.go +++ b/api.go @@ -364,15 +364,21 @@ func (h *Headscale) handleMachineExpired( Str("machine", machine.Name). Msg("Machine registration has expired. Sending a authurl to register") - if h.cfg.OIDC.Issuer != "" { - resp.AuthURL = fmt.Sprintf("%s/oidc/register/%s", - strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) - } else { - resp.AuthURL = fmt.Sprintf("%s/register?key=%s", - strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) + if registerRequest.Auth.AuthKey != "" { + h.handleAuthKey(ctx, machineKey, registerRequest, machine) + + return } - respBody, err := encode(resp, &idKey, h.privateKey) + if h.cfg.OIDC.Issuer != "" { + resp.AuthURL = fmt.Sprintf("%s/oidc/register/%s", + strings.TrimSuffix(h.cfg.ServerURL, "/"), machineKey.HexString()) + } else { + resp.AuthURL = fmt.Sprintf("%s/register?key=%s", + strings.TrimSuffix(h.cfg.ServerURL, "/"), machineKey.HexString()) + } + + respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). Str("handler", "Registration"). From dcbf289470a72adef36ca39e5b5e8e3081459e9c Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 24 Nov 2021 12:15:55 +0000 Subject: [PATCH 36/38] Rename idKey to machineKey to keep consistency --- api.go | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/api.go b/api.go index 43a9f235..96a1d5cb 100644 --- a/api.go +++ b/api.go @@ -288,7 +288,7 @@ func (h *Headscale) getMapKeepAliveResponse( func (h *Headscale) handleMachineLogOut( ctx *gin.Context, - idKey wgkey.Key, + machineKey wgkey.Key, machine Machine, ) { resp := tailcfg.RegisterResponse{} @@ -303,7 +303,7 @@ func (h *Headscale) handleMachineLogOut( resp.AuthURL = "" resp.MachineAuthorized = false resp.User = *machine.Namespace.toUser() - respBody, err := encode(resp, &idKey, h.privateKey) + respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). Str("handler", "Registration"). @@ -318,7 +318,7 @@ func (h *Headscale) handleMachineLogOut( func (h *Headscale) handleMachineValidRegistration( ctx *gin.Context, - idKey wgkey.Key, + machineKey wgkey.Key, machine Machine, ) { resp := tailcfg.RegisterResponse{} @@ -334,7 +334,7 @@ func (h *Headscale) handleMachineValidRegistration( resp.User = *machine.Namespace.toUser() resp.Login = *machine.Namespace.toLogin() - respBody, err := encode(resp, &idKey, h.privateKey) + respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). Str("handler", "Registration"). @@ -353,7 +353,8 @@ func (h *Headscale) handleMachineValidRegistration( func (h *Headscale) handleMachineExpired( ctx *gin.Context, - idKey wgkey.Key, + machineKey wgkey.Key, + registerRequest tailcfg.RegisterRequest, machine Machine, ) { resp := tailcfg.RegisterResponse{} @@ -397,7 +398,7 @@ func (h *Headscale) handleMachineExpired( func (h *Headscale) handleMachineRefreshKey( ctx *gin.Context, - idKey wgkey.Key, + machineKey wgkey.Key, registerRequest tailcfg.RegisterRequest, machine Machine, ) { @@ -412,7 +413,7 @@ func (h *Headscale) handleMachineRefreshKey( resp.AuthURL = "" resp.User = *machine.Namespace.toUser() - respBody, err := encode(resp, &idKey, h.privateKey) + respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). Str("handler", "Registration"). @@ -427,7 +428,7 @@ func (h *Headscale) handleMachineRefreshKey( func (h *Headscale) handleMachineRegistrationNew( ctx *gin.Context, - idKey wgkey.Key, + machineKey wgkey.Key, registerRequest tailcfg.RegisterRequest, machine Machine, ) { @@ -442,11 +443,11 @@ func (h *Headscale) handleMachineRegistrationNew( resp.AuthURL = fmt.Sprintf( "%s/oidc/register/%s", strings.TrimSuffix(h.cfg.ServerURL, "/"), - idKey.HexString(), + machineKey.HexString(), ) } else { resp.AuthURL = fmt.Sprintf("%s/register?key=%s", - strings.TrimSuffix(h.cfg.ServerURL, "/"), idKey.HexString()) + strings.TrimSuffix(h.cfg.ServerURL, "/"), machineKey.HexString()) } if !registerRequest.Expiry.IsZero() { @@ -456,7 +457,7 @@ func (h *Headscale) handleMachineRegistrationNew( Time("expiry", registerRequest.Expiry). Msg("Non-zero expiry time requested, adding to cache") h.requestedExpiryCache.Set( - idKey.HexString(), + machineKey.HexString(), registerRequest.Expiry, requestedExpiryCacheExpiration, ) @@ -465,7 +466,7 @@ func (h *Headscale) handleMachineRegistrationNew( machine.NodeKey = wgkey.Key(registerRequest.NodeKey).HexString() // save the NodeKey h.db.Save(&machine) - respBody, err := encode(resp, &idKey, h.privateKey) + respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). Str("handler", "Registration"). @@ -480,7 +481,7 @@ func (h *Headscale) handleMachineRegistrationNew( func (h *Headscale) handleAuthKey( ctx *gin.Context, - idKey wgkey.Key, + machineKey wgkey.Key, registerRequest tailcfg.RegisterRequest, machine Machine, ) { @@ -497,7 +498,7 @@ func (h *Headscale) handleAuthKey( Err(err). Msg("Failed authentication via AuthKey") resp.MachineAuthorized = false - respBody, err := encode(resp, &idKey, h.privateKey) + respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). Str("func", "handleAuthKey"). @@ -567,7 +568,7 @@ func (h *Headscale) handleAuthKey( resp.MachineAuthorized = true resp.User = *pak.Namespace.toUser() - respBody, err := encode(resp, &idKey, h.privateKey) + respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). Str("func", "handleAuthKey"). From cec1e86b588b28d7c62eb371dc91ca5af7a22e87 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 24 Nov 2021 12:16:56 +0000 Subject: [PATCH 37/38] Add missing request arguemnt --- api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.go b/api.go index 96a1d5cb..1a51fdfe 100644 --- a/api.go +++ b/api.go @@ -152,7 +152,7 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { } // The machine has expired - h.handleMachineExpired(ctx, machineKey, *machine) + h.handleMachineExpired(ctx, machineKey, req, *machine) return } From f2e273b8a2d182adfb427f872245d16e1751aee1 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 24 Nov 2021 15:51:24 +0100 Subject: [PATCH 38/38] fix(derp-example): change regionid in nodes Using a wrong regionid value lead to non working DERP custom server. No checks are performed for this kind of errors making it difficult to find. --- derp-example.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/derp-example.yaml b/derp-example.yaml index a9901bef..0ebe32ed 100644 --- a/derp-example.yaml +++ b/derp-example.yaml @@ -5,8 +5,8 @@ regions: regioncode: custom regionname: My Region nodes: - - name: 1a - regionid: 1 + - name: 900a + regionid: 900 hostname: myderp.mydomain.no ipv4: 123.123.123.123 ipv6: "2604:a880:400:d1::828:b001"