Merge branch 'main' into fix-derp-example-config

This commit is contained in:
Juan Font 2021-11-24 18:57:31 +01:00 committed by GitHub
commit 45bc3f7a09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 1306 additions and 538 deletions

View file

@ -25,9 +25,6 @@ linters:
- godox - godox
- ireturn - ireturn
# In progress
- gocritic
# We should strive to enable these: # We should strive to enable these:
- wrapcheck - wrapcheck
- dupl - dupl
@ -51,3 +48,9 @@ linters-settings:
- ip - ip
- ok - ok
- c - c
gocritic:
disabled-checks:
- appendAssign
# TODO(kradalby): Remove this
- ifElseChain

View file

@ -100,7 +100,7 @@ func (s *Suite) TestPortNamespace(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: ip.String(), IPAddress: ip.String(),
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }
@ -142,7 +142,7 @@ func (s *Suite) TestPortGroup(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: ip.String(), IPAddress: ip.String(),
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }

466
api.go
View file

@ -18,7 +18,15 @@ import (
"tailscale.com/types/wgkey" "tailscale.com/types/wgkey"
) )
const reservedResponseHeaderSize = 4 const (
reservedResponseHeaderSize = 4
RegisterMethodAuthKey = "authKey"
RegisterMethodOIDC = "oidc"
RegisterMethodCLI = "cli"
ErrRegisterMethodCLIDoesNotSupportExpire = Error(
"machines registered with CLI does not support expire",
)
)
// KeyHandler provides the Headscale pub key // KeyHandler provides the Headscale pub key
// Listens in /key. // Listens in /key.
@ -111,178 +119,52 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) {
machine = &newMachine machine = &newMachine
} }
if !machine.Registered && req.Auth.AuthKey != "" { if machine.Registered {
h.handleAuthKey(ctx, h.db, machineKey, req, *machine) // 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:
return // - Trying to log out (sending a expiry in the past)
} // - A valid, registered machine, looking for the node map
// - Expired machine wanting to reauthenticate
resp := tailcfg.RegisterResponse{} 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)
// We have the updated key! // https://github.com/tailscale/tailscale/blob/main/tailcfg/tailcfg.go#L648
if machine.NodeKey == wgkey.Key(req.NodeKey).HexString() { if !req.Expiry.IsZero() && req.Expiry.UTC().Before(now) {
// The client sends an Expiry in the past if the client is requesting to expire the key (aka logout) h.handleMachineLogOut(ctx, machineKey, *machine)
// 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 return
} }
ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody)
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() {
if machine.Registered && machine.Expiry.UTC().After(now) { h.handleMachineValidRegistration(ctx, machineKey, *machine)
// 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 return
} }
machineRegistrations.WithLabelValues("update", "web", "success", machine.Namespace.Name). }
Inc()
ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) // 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 return
} }
// The client has registered before, but has expired // The machine has expired
log.Debug(). h.handleMachineExpired(ctx, machineKey, req, *machine)
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)
return return
} }
// The NodeKey we have matches OldNodeKey, which means this is a refresh after a key expiration // If the machine has AuthKey set, handle registration via PreAuthKeys
if machine.NodeKey == wgkey.Key(req.OldNodeKey).HexString() && if req.Auth.AuthKey != "" {
machine.Expiry.UTC().After(now) { h.handleAuthKey(ctx, machineKey, req, *machine)
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)
return return
} }
// The machine registration is new, redirect the client to the registration URL h.handleMachineRegistrationNew(ctx, machineKey, req, *machine)
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)
} }
func (h *Headscale) getMapResponse( func (h *Headscale) getMapResponse(
@ -304,7 +186,7 @@ func (h *Headscale) getMapResponse(
return nil, err return nil, err
} }
peers, err := h.getPeers(machine) peers, err := h.getValidPeers(machine)
if err != nil { if err != nil {
log.Error(). log.Error().
Str("func", "getMapResponse"). Str("func", "getMapResponse").
@ -404,19 +286,211 @@ func (h *Headscale) getMapKeepAliveResponse(
return data, nil return data, nil
} }
func (h *Headscale) handleMachineLogOut(
ctx *gin.Context,
machineKey wgkey.Key,
machine Machine,
) {
resp := tailcfg.RegisterResponse{}
log.Info().
Str("handler", "Registration").
Str("machine", machine.Name).
Msg("Client requested logout")
h.ExpireMachine(&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)
}
func (h *Headscale) handleMachineValidRegistration(
ctx *gin.Context,
machineKey wgkey.Key,
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, &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)
}
func (h *Headscale) handleMachineExpired(
ctx *gin.Context,
machineKey wgkey.Key,
registerRequest 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 registerRequest.Auth.AuthKey != "" {
h.handleAuthKey(ctx, machineKey, registerRequest, machine)
return
}
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").
Err(err).
Msg("Cannot encode message")
machineRegistrations.WithLabelValues("reauth", "web", "error", machine.Namespace.Name).
Inc()
ctx.String(http.StatusInternalServerError, "")
return
}
machineRegistrations.WithLabelValues("reauth", "web", "success", machine.Namespace.Name).
Inc()
ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody)
}
func (h *Headscale) handleMachineRefreshKey(
ctx *gin.Context,
machineKey wgkey.Key,
registerRequest 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(registerRequest.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)
}
func (h *Headscale) handleMachineRegistrationNew(
ctx *gin.Context,
machineKey wgkey.Key,
registerRequest 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, "/"),
machineKey.HexString(),
)
} else {
resp.AuthURL = fmt.Sprintf("%s/register?key=%s",
strings.TrimSuffix(h.cfg.ServerURL, "/"), machineKey.HexString())
}
if !registerRequest.Expiry.IsZero() {
log.Trace().
Caller().
Str("machine", machine.Name).
Time("expiry", registerRequest.Expiry).
Msg("Non-zero expiry time requested, adding to cache")
h.requestedExpiryCache.Set(
machineKey.HexString(),
registerRequest.Expiry,
requestedExpiryCacheExpiration,
)
}
machine.NodeKey = wgkey.Key(registerRequest.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)
}
func (h *Headscale) handleAuthKey( func (h *Headscale) handleAuthKey(
ctx *gin.Context, ctx *gin.Context,
db *gorm.DB, machineKey wgkey.Key,
idKey wgkey.Key, registerRequest tailcfg.RegisterRequest,
reqisterRequest tailcfg.RegisterRequest,
machine Machine, machine Machine,
) { ) {
log.Debug(). log.Debug().
Str("func", "handleAuthKey"). Str("func", "handleAuthKey").
Str("machine", reqisterRequest.Hostinfo.Hostname). Str("machine", registerRequest.Hostinfo.Hostname).
Msgf("Processing auth key for %s", reqisterRequest.Hostinfo.Hostname) Msgf("Processing auth key for %s", registerRequest.Hostinfo.Hostname)
resp := tailcfg.RegisterResponse{} resp := tailcfg.RegisterResponse{}
pak, err := h.checkKeyValidity(reqisterRequest.Auth.AuthKey) pak, err := h.checkKeyValidity(registerRequest.Auth.AuthKey)
if err != nil { if err != nil {
log.Error(). log.Error().
Str("func", "handleAuthKey"). Str("func", "handleAuthKey").
@ -424,7 +498,7 @@ func (h *Headscale) handleAuthKey(
Err(err). Err(err).
Msg("Failed authentication via AuthKey") Msg("Failed authentication via AuthKey")
resp.MachineAuthorized = false resp.MachineAuthorized = false
respBody, err := encode(resp, &idKey, h.privateKey) respBody, err := encode(resp, &machineKey, h.privateKey)
if err != nil { if err != nil {
log.Error(). log.Error().
Str("func", "handleAuthKey"). Str("func", "handleAuthKey").
@ -448,43 +522,53 @@ func (h *Headscale) handleAuthKey(
return return
} }
log.Debug(). if machine.isRegistered() {
Str("func", "handleAuthKey"). log.Trace().
Str("machine", machine.Name). Caller().
Msg("Authentication key was valid, proceeding to acquire an IP address") Str("machine", machine.Name).
ip, err := h.getAvailableIP() Msg("machine already registered, reauthenticating")
if err != nil {
log.Error(). h.RefreshMachine(&machine, registerRequest.Expiry)
} else {
log.Debug().
Str("func", "handleAuthKey"). Str("func", "handleAuthKey").
Str("machine", machine.Name). Str("machine", machine.Name).
Msg("Failed to find an available IP") Msg("Authentication key was valid, proceeding to acquire an IP address")
machineRegistrations.WithLabelValues("new", "authkey", "error", machine.Namespace.Name). ip, err := h.getAvailableIP()
Inc() 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 = &registerRequest.Expiry
machine.AuthKeyID = uint(pak.ID)
machine.IPAddress = ip.String()
machine.NamespaceID = pak.NamespaceID
machine.NodeKey = wgkey.Key(registerRequest.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 = "authKey"
db.Save(&machine)
pak.Used = true pak.Used = true
db.Save(&pak) h.db.Save(&pak)
resp.MachineAuthorized = true resp.MachineAuthorized = true
resp.User = *pak.Namespace.toUser() resp.User = *pak.Namespace.toUser()
respBody, err := encode(resp, &idKey, h.privateKey) respBody, err := encode(resp, &machineKey, h.privateKey)
if err != nil { if err != nil {
log.Error(). log.Error().
Str("func", "handleAuthKey"). Str("func", "handleAuthKey").
@ -503,6 +587,6 @@ func (h *Headscale) handleAuthKey(
log.Info(). log.Info().
Str("func", "handleAuthKey"). Str("func", "handleAuthKey").
Str("machine", machine.Name). Str("machine", machine.Name).
Str("ip", ip.String()). Str("ip", machine.IPAddress).
Msg("Successfully authenticated via AuthKey") Msg("Successfully authenticated via AuthKey")
} }

26
app.go
View file

@ -53,6 +53,9 @@ const (
updateInterval = 5000 updateInterval = 5000
HTTPReadTimeout = 30 * time.Second HTTPReadTimeout = 30 * time.Second
requestedExpiryCacheExpiration = time.Minute * 5
requestedExpiryCacheCleanupInterval = time.Minute * 10
errUnsupportedDatabase = Error("unsupported DB") errUnsupportedDatabase = Error("unsupported DB")
errUnsupportedLetsEncryptChallengeType = Error( errUnsupportedLetsEncryptChallengeType = Error(
"unknown value for Lets Encrypt challenge type", "unknown value for Lets Encrypt challenge type",
@ -96,9 +99,6 @@ type Config struct {
OIDC OIDCConfig OIDC OIDCConfig
CLI CLIConfig CLI CLIConfig
MaxMachineRegistrationDuration time.Duration
DefaultMachineRegistrationDuration time.Duration
} }
type OIDCConfig struct { type OIDCConfig struct {
@ -142,6 +142,8 @@ type Headscale struct {
oidcProvider *oidc.Provider oidcProvider *oidc.Provider
oauth2Config *oauth2.Config oauth2Config *oauth2.Config
oidcStateCache *cache.Cache oidcStateCache *cache.Cache
requestedExpiryCache *cache.Cache
} }
// NewHeadscale returns the Headscale app. // NewHeadscale returns the Headscale app.
@ -174,13 +176,19 @@ func NewHeadscale(cfg Config) (*Headscale, error) {
return nil, errUnsupportedDatabase return nil, errUnsupportedDatabase
} }
requestedExpiryCache := cache.New(
requestedExpiryCacheExpiration,
requestedExpiryCacheCleanupInterval,
)
app := Headscale{ app := Headscale{
cfg: cfg, cfg: cfg,
dbType: cfg.DBtype, dbType: cfg.DBtype,
dbString: dbString, dbString: dbString,
privateKey: privKey, privateKey: privKey,
publicKey: &pubKey, publicKey: &pubKey,
aclRules: tailcfg.FilterAllowAll, // default allowall aclRules: tailcfg.FilterAllowAll, // default allowall
requestedExpiryCache: requestedExpiryCache,
} }
err = app.initDB() err = app.initDB()

View file

@ -5,6 +5,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/patrickmn/go-cache"
"gopkg.in/check.v1" "gopkg.in/check.v1"
"inet.af/netaddr" "inet.af/netaddr"
) )
@ -47,6 +48,10 @@ func (s *Suite) ResetDB(c *check.C) {
cfg: cfg, cfg: cfg,
dbType: "sqlite3", dbType: "sqlite3",
dbString: tmpDir + "/headscale_test.db", dbString: tmpDir + "/headscale_test.db",
requestedExpiryCache: cache.New(
requestedExpiryCacheExpiration,
requestedExpiryCacheCleanupInterval,
),
} }
err = app.initDB() err = app.initDB()
if err != nil { if err != nil {

View file

@ -13,15 +13,14 @@ func (s *Suite) TestRegisterMachine(c *check.C) {
now := time.Now().UTC() now := time.Now().UTC()
machine := Machine{ machine := Machine{
ID: 0, ID: 0,
MachineKey: "8ce002a935f8c394e55e78fbbb410576575ff8ec5cfa2e627e4b807f1be15b0e", MachineKey: "8ce002a935f8c394e55e78fbbb410576575ff8ec5cfa2e627e4b807f1be15b0e",
NodeKey: "bar", NodeKey: "bar",
DiscoKey: "faa", DiscoKey: "faa",
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
IPAddress: "10.0.0.1", IPAddress: "10.0.0.1",
Expiry: &now, Expiry: &now,
RequestedExpiry: &now,
} }
app.db.Save(&machine) app.db.Save(&machine)

View file

@ -33,7 +33,14 @@ func init() {
} }
nodeCmd.AddCommand(registerNodeCmd) nodeCmd.AddCommand(registerNodeCmd)
deleteNodeCmd.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().Uint64P("identifier", "i", 0, "Node identifier (ID)")
err = deleteNodeCmd.MarkFlagRequired("identifier") err = deleteNodeCmd.MarkFlagRequired("identifier")
if err != nil { if err != nil {
log.Fatalf(err.Error()) log.Fatalf(err.Error())
@ -45,7 +52,7 @@ func init() {
if err != nil { if err != nil {
log.Fatalf(err.Error()) 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") err = shareMachineCmd.MarkFlagRequired("identifier")
if err != nil { if err != nil {
log.Fatalf(err.Error()) log.Fatalf(err.Error())
@ -57,7 +64,7 @@ func init() {
if err != nil { if err != nil {
log.Fatalf(err.Error()) 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") err = unshareMachineCmd.MarkFlagRequired("identifier")
if err != nil { if err != nil {
log.Fatalf(err.Error()) log.Fatalf(err.Error())
@ -177,13 +184,58 @@ 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")
identifier, err := cmd.Flags().GetUint64("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: 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{ var deleteNodeCmd = &cobra.Command{
Use: "delete", Use: "delete",
Short: "Delete a node", Short: "Delete a node",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output") output, _ := cmd.Flags().GetString("output")
identifier, err := cmd.Flags().GetInt("identifier") identifier, err := cmd.Flags().GetUint64("identifier")
if err != nil { if err != nil {
ErrorOutput( ErrorOutput(
err, err,
@ -199,7 +251,7 @@ var deleteNodeCmd = &cobra.Command{
defer conn.Close() defer conn.Close()
getRequest := &v1.GetMachineRequest{ getRequest := &v1.GetMachineRequest{
MachineId: uint64(identifier), MachineId: identifier,
} }
getResponse, err := client.GetMachine(ctx, getRequest) getResponse, err := client.GetMachine(ctx, getRequest)
@ -217,7 +269,7 @@ var deleteNodeCmd = &cobra.Command{
} }
deleteRequest := &v1.DeleteMachineRequest{ deleteRequest := &v1.DeleteMachineRequest{
MachineId: uint64(identifier), MachineId: identifier,
} }
confirm := false confirm := false
@ -280,7 +332,7 @@ func sharingWorker(
defer cancel() defer cancel()
defer conn.Close() defer conn.Close()
identifier, err := cmd.Flags().GetInt("identifier") identifier, err := cmd.Flags().GetUint64("identifier")
if err != nil { if err != nil {
ErrorOutput(err, fmt.Sprintf("Error converting ID to integer: %s", err), output) ErrorOutput(err, fmt.Sprintf("Error converting ID to integer: %s", err), output)
@ -288,7 +340,7 @@ func sharingWorker(
} }
machineRequest := &v1.GetMachineRequest{ machineRequest := &v1.GetMachineRequest{
MachineId: uint64(identifier), MachineId: identifier,
} }
machineResponse, err := client.GetMachine(ctx, machineRequest) machineResponse, err := client.GetMachine(ctx, machineRequest)
@ -412,6 +464,7 @@ func nodesToPtables(
"Ephemeral", "Ephemeral",
"Last seen", "Last seen",
"Online", "Online",
"Expired",
}, },
} }
@ -420,12 +473,19 @@ func nodesToPtables(
if machine.PreAuthKey != nil && machine.PreAuthKey.Ephemeral { if machine.PreAuthKey != nil && machine.PreAuthKey.Ephemeral {
ephemeral = true ephemeral = true
} }
var lastSeen time.Time var lastSeen time.Time
var lastSeenTime string var lastSeenTime string
if machine.LastSeen != nil { if machine.LastSeen != nil {
lastSeen = machine.LastSeen.AsTime() lastSeen = machine.LastSeen.AsTime()
lastSeenTime = lastSeen.Format("2006-01-02 15:04:05") 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) nKey, err := wgkey.ParseHex(machine.NodeKey)
if err != nil { if err != nil {
return nil, err return nil, err
@ -436,9 +496,16 @@ func nodesToPtables(
if lastSeen.After( if lastSeen.After(
time.Now().Add(-5 * time.Minute), time.Now().Add(-5 * time.Minute),
) { // TODO: Find a better way to reliably show if online ) { // TODO: Find a better way to reliably show if online
online = pterm.LightGreen("true") online = pterm.LightGreen("online")
} else { } else {
online = pterm.LightRed("false") online = pterm.LightRed("offline")
}
var expired string
if expiry.IsZero() || expiry.After(time.Now()) {
expired = pterm.LightGreen("no")
} else {
expired = pterm.LightRed("yes")
} }
var namespace string var namespace string
@ -459,6 +526,7 @@ func nodesToPtables(
strconv.FormatBool(ephemeral), strconv.FormatBool(ephemeral),
lastSeenTime, lastSeenTime,
online, online,
expired,
}, },
) )
} }

View file

@ -218,30 +218,6 @@ func absPath(path string) string {
} }
func getHeadscaleConfig() headscale.Config { 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() dnsConfig, baseDomain := GetDNSConfig()
derpConfig := GetDERPConfig() derpConfig := GetDERPConfig()
@ -295,9 +271,6 @@ func getHeadscaleConfig() headscale.Config {
Insecure: viper.GetBool("cli.insecure"), Insecure: viper.GetBool("cli.insecure"),
Timeout: viper.GetDuration("cli.timeout"), Timeout: viper.GetDuration("cli.timeout"),
}, },
MaxMachineRegistrationDuration: maxMachineRegistrationDuration,
DefaultMachineRegistrationDuration: defaultMachineRegistrationDuration,
} }
} }

View file

@ -123,7 +123,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
NamespaceID: namespaceShared1.ID, NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1, Namespace: *namespaceShared1,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.1", IPAddress: "100.64.0.1",
AuthKeyID: uint(preAuthKeyInShared1.ID), AuthKeyID: uint(preAuthKeyInShared1.ID),
} }
@ -141,7 +141,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
NamespaceID: namespaceShared2.ID, NamespaceID: namespaceShared2.ID,
Namespace: *namespaceShared2, Namespace: *namespaceShared2,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.2", IPAddress: "100.64.0.2",
AuthKeyID: uint(preAuthKeyInShared2.ID), AuthKeyID: uint(preAuthKeyInShared2.ID),
} }
@ -159,7 +159,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
NamespaceID: namespaceShared3.ID, NamespaceID: namespaceShared3.ID,
Namespace: *namespaceShared3, Namespace: *namespaceShared3,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.3", IPAddress: "100.64.0.3",
AuthKeyID: uint(preAuthKeyInShared3.ID), AuthKeyID: uint(preAuthKeyInShared3.ID),
} }
@ -177,7 +177,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
NamespaceID: namespaceShared1.ID, NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1, Namespace: *namespaceShared1,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.4", IPAddress: "100.64.0.4",
AuthKeyID: uint(PreAuthKey2InShared1.ID), AuthKeyID: uint(PreAuthKey2InShared1.ID),
} }
@ -272,7 +272,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
NamespaceID: namespaceShared1.ID, NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1, Namespace: *namespaceShared1,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.1", IPAddress: "100.64.0.1",
AuthKeyID: uint(preAuthKeyInShared1.ID), AuthKeyID: uint(preAuthKeyInShared1.ID),
} }
@ -290,7 +290,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
NamespaceID: namespaceShared2.ID, NamespaceID: namespaceShared2.ID,
Namespace: *namespaceShared2, Namespace: *namespaceShared2,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.2", IPAddress: "100.64.0.2",
AuthKeyID: uint(preAuthKeyInShared2.ID), AuthKeyID: uint(preAuthKeyInShared2.ID),
} }
@ -308,7 +308,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
NamespaceID: namespaceShared3.ID, NamespaceID: namespaceShared3.ID,
Namespace: *namespaceShared3, Namespace: *namespaceShared3,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.3", IPAddress: "100.64.0.3",
AuthKeyID: uint(preAuthKeyInShared3.ID), AuthKeyID: uint(preAuthKeyInShared3.ID),
} }
@ -326,7 +326,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
NamespaceID: namespaceShared1.ID, NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1, Namespace: *namespaceShared1,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.4", IPAddress: "100.64.0.4",
AuthKeyID: uint(preAuthKey2InShared1.ID), AuthKeyID: uint(preAuthKey2InShared1.ID),
} }

View file

@ -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, 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, 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, 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, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xf4,
0x11, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 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, 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, 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, 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, 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, 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, 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, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01,
0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45,
0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75,
0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25,
0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x8d, 0x01, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x65,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x6e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63,
0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e, 0x2f, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68,
0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x68, 0x61, 0x72, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61,
0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x95, 0x01, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d,
0x0a, 0x0e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82,
0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d,
0x93, 0x02, 0x32, 0x22, 0x30, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f,
0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73,
0x7d, 0x2f, 0x75, 0x6e, 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,
0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x8b, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e,
0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73,
0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x22, 0x30, 0x2f, 0x61, 0x70,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x75, 0x6e, 0x73, 0x68, 0x61, 0x72,
0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x8b, 0x01,
0x74, 0x65, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x65, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65,
0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b,
0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f,
0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13,
0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x42, 0x29, 0x5a, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75,
0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 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{}{ 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 (*GetMachineRequest)(nil), // 9: headscale.v1.GetMachineRequest
(*RegisterMachineRequest)(nil), // 10: headscale.v1.RegisterMachineRequest (*RegisterMachineRequest)(nil), // 10: headscale.v1.RegisterMachineRequest
(*DeleteMachineRequest)(nil), // 11: headscale.v1.DeleteMachineRequest (*DeleteMachineRequest)(nil), // 11: headscale.v1.DeleteMachineRequest
(*ListMachinesRequest)(nil), // 12: headscale.v1.ListMachinesRequest (*ExpireMachineRequest)(nil), // 12: headscale.v1.ExpireMachineRequest
(*ShareMachineRequest)(nil), // 13: headscale.v1.ShareMachineRequest (*ListMachinesRequest)(nil), // 13: headscale.v1.ListMachinesRequest
(*UnshareMachineRequest)(nil), // 14: headscale.v1.UnshareMachineRequest (*ShareMachineRequest)(nil), // 14: headscale.v1.ShareMachineRequest
(*GetMachineRouteRequest)(nil), // 15: headscale.v1.GetMachineRouteRequest (*UnshareMachineRequest)(nil), // 15: headscale.v1.UnshareMachineRequest
(*EnableMachineRoutesRequest)(nil), // 16: headscale.v1.EnableMachineRoutesRequest (*GetMachineRouteRequest)(nil), // 16: headscale.v1.GetMachineRouteRequest
(*GetNamespaceResponse)(nil), // 17: headscale.v1.GetNamespaceResponse (*EnableMachineRoutesRequest)(nil), // 17: headscale.v1.EnableMachineRoutesRequest
(*CreateNamespaceResponse)(nil), // 18: headscale.v1.CreateNamespaceResponse (*GetNamespaceResponse)(nil), // 18: headscale.v1.GetNamespaceResponse
(*RenameNamespaceResponse)(nil), // 19: headscale.v1.RenameNamespaceResponse (*CreateNamespaceResponse)(nil), // 19: headscale.v1.CreateNamespaceResponse
(*DeleteNamespaceResponse)(nil), // 20: headscale.v1.DeleteNamespaceResponse (*RenameNamespaceResponse)(nil), // 20: headscale.v1.RenameNamespaceResponse
(*ListNamespacesResponse)(nil), // 21: headscale.v1.ListNamespacesResponse (*DeleteNamespaceResponse)(nil), // 21: headscale.v1.DeleteNamespaceResponse
(*CreatePreAuthKeyResponse)(nil), // 22: headscale.v1.CreatePreAuthKeyResponse (*ListNamespacesResponse)(nil), // 22: headscale.v1.ListNamespacesResponse
(*ExpirePreAuthKeyResponse)(nil), // 23: headscale.v1.ExpirePreAuthKeyResponse (*CreatePreAuthKeyResponse)(nil), // 23: headscale.v1.CreatePreAuthKeyResponse
(*ListPreAuthKeysResponse)(nil), // 24: headscale.v1.ListPreAuthKeysResponse (*ExpirePreAuthKeyResponse)(nil), // 24: headscale.v1.ExpirePreAuthKeyResponse
(*DebugCreateMachineResponse)(nil), // 25: headscale.v1.DebugCreateMachineResponse (*ListPreAuthKeysResponse)(nil), // 25: headscale.v1.ListPreAuthKeysResponse
(*GetMachineResponse)(nil), // 26: headscale.v1.GetMachineResponse (*DebugCreateMachineResponse)(nil), // 26: headscale.v1.DebugCreateMachineResponse
(*RegisterMachineResponse)(nil), // 27: headscale.v1.RegisterMachineResponse (*GetMachineResponse)(nil), // 27: headscale.v1.GetMachineResponse
(*DeleteMachineResponse)(nil), // 28: headscale.v1.DeleteMachineResponse (*RegisterMachineResponse)(nil), // 28: headscale.v1.RegisterMachineResponse
(*ListMachinesResponse)(nil), // 29: headscale.v1.ListMachinesResponse (*DeleteMachineResponse)(nil), // 29: headscale.v1.DeleteMachineResponse
(*ShareMachineResponse)(nil), // 30: headscale.v1.ShareMachineResponse (*ExpireMachineResponse)(nil), // 30: headscale.v1.ExpireMachineResponse
(*UnshareMachineResponse)(nil), // 31: headscale.v1.UnshareMachineResponse (*ListMachinesResponse)(nil), // 31: headscale.v1.ListMachinesResponse
(*GetMachineRouteResponse)(nil), // 32: headscale.v1.GetMachineRouteResponse (*ShareMachineResponse)(nil), // 32: headscale.v1.ShareMachineResponse
(*EnableMachineRoutesResponse)(nil), // 33: headscale.v1.EnableMachineRoutesResponse (*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{ var file_headscale_v1_headscale_proto_depIdxs = []int32{
0, // 0: headscale.v1.HeadscaleService.GetNamespace:input_type -> headscale.v1.GetNamespaceRequest 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 9, // 9: headscale.v1.HeadscaleService.GetMachine:input_type -> headscale.v1.GetMachineRequest
10, // 10: headscale.v1.HeadscaleService.RegisterMachine:input_type -> headscale.v1.RegisterMachineRequest 10, // 10: headscale.v1.HeadscaleService.RegisterMachine:input_type -> headscale.v1.RegisterMachineRequest
11, // 11: headscale.v1.HeadscaleService.DeleteMachine:input_type -> headscale.v1.DeleteMachineRequest 11, // 11: headscale.v1.HeadscaleService.DeleteMachine:input_type -> headscale.v1.DeleteMachineRequest
12, // 12: headscale.v1.HeadscaleService.ListMachines:input_type -> headscale.v1.ListMachinesRequest 12, // 12: headscale.v1.HeadscaleService.ExpireMachine:input_type -> headscale.v1.ExpireMachineRequest
13, // 13: headscale.v1.HeadscaleService.ShareMachine:input_type -> headscale.v1.ShareMachineRequest 13, // 13: headscale.v1.HeadscaleService.ListMachines:input_type -> headscale.v1.ListMachinesRequest
14, // 14: headscale.v1.HeadscaleService.UnshareMachine:input_type -> headscale.v1.UnshareMachineRequest 14, // 14: headscale.v1.HeadscaleService.ShareMachine:input_type -> headscale.v1.ShareMachineRequest
15, // 15: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest 15, // 15: headscale.v1.HeadscaleService.UnshareMachine:input_type -> headscale.v1.UnshareMachineRequest
16, // 16: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest 16, // 16: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest
17, // 17: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse 17, // 17: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest
18, // 18: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse 18, // 18: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse
19, // 19: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse 19, // 19: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse
20, // 20: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse 20, // 20: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse
21, // 21: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse 21, // 21: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse
22, // 22: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse 22, // 22: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse
23, // 23: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse 23, // 23: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse
24, // 24: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse 24, // 24: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse
25, // 25: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse 25, // 25: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse
26, // 26: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse 26, // 26: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse
27, // 27: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse 27, // 27: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse
28, // 28: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse 28, // 28: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse
29, // 29: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse 29, // 29: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse
30, // 30: headscale.v1.HeadscaleService.ShareMachine:output_type -> headscale.v1.ShareMachineResponse 30, // 30: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse
31, // 31: headscale.v1.HeadscaleService.UnshareMachine:output_type -> headscale.v1.UnshareMachineResponse 31, // 31: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse
32, // 32: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse 32, // 32: headscale.v1.HeadscaleService.ShareMachine:output_type -> headscale.v1.ShareMachineResponse
33, // 33: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse 33, // 33: headscale.v1.HeadscaleService.UnshareMachine:output_type -> headscale.v1.UnshareMachineResponse
17, // [17:34] is the sub-list for method output_type 34, // 34: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse
0, // [0:17] is the sub-list for method input_type 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 type_name
0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name 0, // [0:0] is the sub-list for field type_name

View file

@ -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 ( var (
filter_HeadscaleService_ListMachines_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} 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) { mux.Handle("GET", pattern_HeadscaleService_ListMachines_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() 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) { mux.Handle("GET", pattern_HeadscaleService_ListMachines_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() 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_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_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"}, "")) 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_DeleteMachine_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_ExpireMachine_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_ListMachines_0 = runtime.ForwardResponseMessage forward_HeadscaleService_ListMachines_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_ShareMachine_0 = runtime.ForwardResponseMessage forward_HeadscaleService_ShareMachine_0 = runtime.ForwardResponseMessage

View file

@ -33,6 +33,7 @@ type HeadscaleServiceClient interface {
GetMachine(ctx context.Context, in *GetMachineRequest, opts ...grpc.CallOption) (*GetMachineResponse, error) GetMachine(ctx context.Context, in *GetMachineRequest, opts ...grpc.CallOption) (*GetMachineResponse, error)
RegisterMachine(ctx context.Context, in *RegisterMachineRequest, opts ...grpc.CallOption) (*RegisterMachineResponse, error) RegisterMachine(ctx context.Context, in *RegisterMachineRequest, opts ...grpc.CallOption) (*RegisterMachineResponse, error)
DeleteMachine(ctx context.Context, in *DeleteMachineRequest, opts ...grpc.CallOption) (*DeleteMachineResponse, 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) ListMachines(ctx context.Context, in *ListMachinesRequest, opts ...grpc.CallOption) (*ListMachinesResponse, error)
ShareMachine(ctx context.Context, in *ShareMachineRequest, opts ...grpc.CallOption) (*ShareMachineResponse, error) ShareMachine(ctx context.Context, in *ShareMachineRequest, opts ...grpc.CallOption) (*ShareMachineResponse, error)
UnshareMachine(ctx context.Context, in *UnshareMachineRequest, opts ...grpc.CallOption) (*UnshareMachineResponse, 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 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) { func (c *headscaleServiceClient) ListMachines(ctx context.Context, in *ListMachinesRequest, opts ...grpc.CallOption) (*ListMachinesResponse, error) {
out := new(ListMachinesResponse) out := new(ListMachinesResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListMachines", in, out, opts...) 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) GetMachine(context.Context, *GetMachineRequest) (*GetMachineResponse, error)
RegisterMachine(context.Context, *RegisterMachineRequest) (*RegisterMachineResponse, error) RegisterMachine(context.Context, *RegisterMachineRequest) (*RegisterMachineResponse, error)
DeleteMachine(context.Context, *DeleteMachineRequest) (*DeleteMachineResponse, error) DeleteMachine(context.Context, *DeleteMachineRequest) (*DeleteMachineResponse, error)
ExpireMachine(context.Context, *ExpireMachineRequest) (*ExpireMachineResponse, error)
ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error)
ShareMachine(context.Context, *ShareMachineRequest) (*ShareMachineResponse, error) ShareMachine(context.Context, *ShareMachineRequest) (*ShareMachineResponse, error)
UnshareMachine(context.Context, *UnshareMachineRequest) (*UnshareMachineResponse, 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) { func (UnimplementedHeadscaleServiceServer) DeleteMachine(context.Context, *DeleteMachineRequest) (*DeleteMachineResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteMachine not implemented") 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) { func (UnimplementedHeadscaleServiceServer) ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListMachines not implemented") 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) 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) { func _HeadscaleService_ListMachines_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListMachinesRequest) in := new(ListMachinesRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@ -659,6 +691,10 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{
MethodName: "DeleteMachine", MethodName: "DeleteMachine",
Handler: _HeadscaleService_DeleteMachine_Handler, Handler: _HeadscaleService_DeleteMachine_Handler,
}, },
{
MethodName: "ExpireMachine",
Handler: _HeadscaleService_ExpireMachine_Handler,
},
{ {
MethodName: "ListMachines", MethodName: "ListMachines",
Handler: _HeadscaleService_ListMachines_Handler, Handler: _HeadscaleService_ListMachines_Handler,

View file

@ -505,6 +505,100 @@ func (*DeleteMachineResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_machine_proto_rawDescGZIP(), []int{6} 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 { type ListMachinesRequest struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -516,7 +610,7 @@ type ListMachinesRequest struct {
func (x *ListMachinesRequest) Reset() { func (x *ListMachinesRequest) Reset() {
*x = ListMachinesRequest{} *x = ListMachinesRequest{}
if protoimpl.UnsafeEnabled { 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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -529,7 +623,7 @@ func (x *ListMachinesRequest) String() string {
func (*ListMachinesRequest) ProtoMessage() {} func (*ListMachinesRequest) ProtoMessage() {}
func (x *ListMachinesRequest) ProtoReflect() protoreflect.Message { 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 { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -542,7 +636,7 @@ func (x *ListMachinesRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListMachinesRequest.ProtoReflect.Descriptor instead. // Deprecated: Use ListMachinesRequest.ProtoReflect.Descriptor instead.
func (*ListMachinesRequest) Descriptor() ([]byte, []int) { 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 { func (x *ListMachinesRequest) GetNamespace() string {
@ -563,7 +657,7 @@ type ListMachinesResponse struct {
func (x *ListMachinesResponse) Reset() { func (x *ListMachinesResponse) Reset() {
*x = ListMachinesResponse{} *x = ListMachinesResponse{}
if protoimpl.UnsafeEnabled { 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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -576,7 +670,7 @@ func (x *ListMachinesResponse) String() string {
func (*ListMachinesResponse) ProtoMessage() {} func (*ListMachinesResponse) ProtoMessage() {}
func (x *ListMachinesResponse) ProtoReflect() protoreflect.Message { 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 { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -589,7 +683,7 @@ func (x *ListMachinesResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListMachinesResponse.ProtoReflect.Descriptor instead. // Deprecated: Use ListMachinesResponse.ProtoReflect.Descriptor instead.
func (*ListMachinesResponse) Descriptor() ([]byte, []int) { 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 { func (x *ListMachinesResponse) GetMachines() []*Machine {
@ -611,7 +705,7 @@ type ShareMachineRequest struct {
func (x *ShareMachineRequest) Reset() { func (x *ShareMachineRequest) Reset() {
*x = ShareMachineRequest{} *x = ShareMachineRequest{}
if protoimpl.UnsafeEnabled { 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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -624,7 +718,7 @@ func (x *ShareMachineRequest) String() string {
func (*ShareMachineRequest) ProtoMessage() {} func (*ShareMachineRequest) ProtoMessage() {}
func (x *ShareMachineRequest) ProtoReflect() protoreflect.Message { 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 { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -637,7 +731,7 @@ func (x *ShareMachineRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ShareMachineRequest.ProtoReflect.Descriptor instead. // Deprecated: Use ShareMachineRequest.ProtoReflect.Descriptor instead.
func (*ShareMachineRequest) Descriptor() ([]byte, []int) { 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 { func (x *ShareMachineRequest) GetMachineId() uint64 {
@ -665,7 +759,7 @@ type ShareMachineResponse struct {
func (x *ShareMachineResponse) Reset() { func (x *ShareMachineResponse) Reset() {
*x = ShareMachineResponse{} *x = ShareMachineResponse{}
if protoimpl.UnsafeEnabled { 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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -678,7 +772,7 @@ func (x *ShareMachineResponse) String() string {
func (*ShareMachineResponse) ProtoMessage() {} func (*ShareMachineResponse) ProtoMessage() {}
func (x *ShareMachineResponse) ProtoReflect() protoreflect.Message { 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 { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -691,7 +785,7 @@ func (x *ShareMachineResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ShareMachineResponse.ProtoReflect.Descriptor instead. // Deprecated: Use ShareMachineResponse.ProtoReflect.Descriptor instead.
func (*ShareMachineResponse) Descriptor() ([]byte, []int) { 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 { func (x *ShareMachineResponse) GetMachine() *Machine {
@ -713,7 +807,7 @@ type UnshareMachineRequest struct {
func (x *UnshareMachineRequest) Reset() { func (x *UnshareMachineRequest) Reset() {
*x = UnshareMachineRequest{} *x = UnshareMachineRequest{}
if protoimpl.UnsafeEnabled { 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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -726,7 +820,7 @@ func (x *UnshareMachineRequest) String() string {
func (*UnshareMachineRequest) ProtoMessage() {} func (*UnshareMachineRequest) ProtoMessage() {}
func (x *UnshareMachineRequest) ProtoReflect() protoreflect.Message { 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 { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -739,7 +833,7 @@ func (x *UnshareMachineRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use UnshareMachineRequest.ProtoReflect.Descriptor instead. // Deprecated: Use UnshareMachineRequest.ProtoReflect.Descriptor instead.
func (*UnshareMachineRequest) Descriptor() ([]byte, []int) { 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 { func (x *UnshareMachineRequest) GetMachineId() uint64 {
@ -767,7 +861,7 @@ type UnshareMachineResponse struct {
func (x *UnshareMachineResponse) Reset() { func (x *UnshareMachineResponse) Reset() {
*x = UnshareMachineResponse{} *x = UnshareMachineResponse{}
if protoimpl.UnsafeEnabled { 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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -780,7 +874,7 @@ func (x *UnshareMachineResponse) String() string {
func (*UnshareMachineResponse) ProtoMessage() {} func (*UnshareMachineResponse) ProtoMessage() {}
func (x *UnshareMachineResponse) ProtoReflect() protoreflect.Message { 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 { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -793,7 +887,7 @@ func (x *UnshareMachineResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use UnshareMachineResponse.ProtoReflect.Descriptor instead. // Deprecated: Use UnshareMachineResponse.ProtoReflect.Descriptor instead.
func (*UnshareMachineResponse) Descriptor() ([]byte, []int) { 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 { func (x *UnshareMachineResponse) GetMachine() *Machine {
@ -817,7 +911,7 @@ type DebugCreateMachineRequest struct {
func (x *DebugCreateMachineRequest) Reset() { func (x *DebugCreateMachineRequest) Reset() {
*x = DebugCreateMachineRequest{} *x = DebugCreateMachineRequest{}
if protoimpl.UnsafeEnabled { 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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -830,7 +924,7 @@ func (x *DebugCreateMachineRequest) String() string {
func (*DebugCreateMachineRequest) ProtoMessage() {} func (*DebugCreateMachineRequest) ProtoMessage() {}
func (x *DebugCreateMachineRequest) ProtoReflect() protoreflect.Message { 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 { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -843,7 +937,7 @@ func (x *DebugCreateMachineRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DebugCreateMachineRequest.ProtoReflect.Descriptor instead. // Deprecated: Use DebugCreateMachineRequest.ProtoReflect.Descriptor instead.
func (*DebugCreateMachineRequest) Descriptor() ([]byte, []int) { 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 { func (x *DebugCreateMachineRequest) GetNamespace() string {
@ -885,7 +979,7 @@ type DebugCreateMachineResponse struct {
func (x *DebugCreateMachineResponse) Reset() { func (x *DebugCreateMachineResponse) Reset() {
*x = DebugCreateMachineResponse{} *x = DebugCreateMachineResponse{}
if protoimpl.UnsafeEnabled { 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 := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -898,7 +992,7 @@ func (x *DebugCreateMachineResponse) String() string {
func (*DebugCreateMachineResponse) ProtoMessage() {} func (*DebugCreateMachineResponse) ProtoMessage() {}
func (x *DebugCreateMachineResponse) ProtoReflect() protoreflect.Message { 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 { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -911,7 +1005,7 @@ func (x *DebugCreateMachineResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DebugCreateMachineResponse.ProtoReflect.Descriptor instead. // Deprecated: Use DebugCreateMachineResponse.ProtoReflect.Descriptor instead.
func (*DebugCreateMachineResponse) Descriptor() ([]byte, []int) { 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 { 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, 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, 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, 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, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d,
0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x14, 0x4c, 0x69, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x15,
0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73,
0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d,
0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x52, 0x0a, 0x13, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x33, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x14, 0x4c,
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x47, 0x0a, 0x14, 0x53, 0x68, 0x61, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18,
0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x6d, 0x61,
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x52, 0x0a, 0x13, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d,
0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a,
0x6e, 0x65, 0x22, 0x54, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x47, 0x0a, 0x14, 0x53, 0x68,
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, 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, 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, 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, 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, 0x69, 0x6e, 0x65, 0x22, 0x54, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61,
0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a,
0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x16, 0x55, 0x6e, 0x73,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x4d, 0x0a, 0x1a, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01,
0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x77, 0x0a, 0x19, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2a, 0x82, 0x01, 0x0a, 0x0e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01,
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
0x0a, 0x1b, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x1c, 0x0a, 0x18, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18,
0x4f, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x4d, 0x0a,
0x13, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x1a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
0x5f, 0x43, 0x4c, 0x49, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d,
0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x03, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68,
0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68,
0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2a, 0x82, 0x01, 0x0a,
0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12,
0x74, 0x6f, 0x33, 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 ( 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_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{}{ var file_headscale_v1_machine_proto_goTypes = []interface{}{
(RegisterMethod)(0), // 0: headscale.v1.RegisterMethod (RegisterMethod)(0), // 0: headscale.v1.RegisterMethod
(*Machine)(nil), // 1: headscale.v1.Machine (*Machine)(nil), // 1: headscale.v1.Machine
@ -1072,37 +1174,40 @@ var file_headscale_v1_machine_proto_goTypes = []interface{}{
(*GetMachineResponse)(nil), // 5: headscale.v1.GetMachineResponse (*GetMachineResponse)(nil), // 5: headscale.v1.GetMachineResponse
(*DeleteMachineRequest)(nil), // 6: headscale.v1.DeleteMachineRequest (*DeleteMachineRequest)(nil), // 6: headscale.v1.DeleteMachineRequest
(*DeleteMachineResponse)(nil), // 7: headscale.v1.DeleteMachineResponse (*DeleteMachineResponse)(nil), // 7: headscale.v1.DeleteMachineResponse
(*ListMachinesRequest)(nil), // 8: headscale.v1.ListMachinesRequest (*ExpireMachineRequest)(nil), // 8: headscale.v1.ExpireMachineRequest
(*ListMachinesResponse)(nil), // 9: headscale.v1.ListMachinesResponse (*ExpireMachineResponse)(nil), // 9: headscale.v1.ExpireMachineResponse
(*ShareMachineRequest)(nil), // 10: headscale.v1.ShareMachineRequest (*ListMachinesRequest)(nil), // 10: headscale.v1.ListMachinesRequest
(*ShareMachineResponse)(nil), // 11: headscale.v1.ShareMachineResponse (*ListMachinesResponse)(nil), // 11: headscale.v1.ListMachinesResponse
(*UnshareMachineRequest)(nil), // 12: headscale.v1.UnshareMachineRequest (*ShareMachineRequest)(nil), // 12: headscale.v1.ShareMachineRequest
(*UnshareMachineResponse)(nil), // 13: headscale.v1.UnshareMachineResponse (*ShareMachineResponse)(nil), // 13: headscale.v1.ShareMachineResponse
(*DebugCreateMachineRequest)(nil), // 14: headscale.v1.DebugCreateMachineRequest (*UnshareMachineRequest)(nil), // 14: headscale.v1.UnshareMachineRequest
(*DebugCreateMachineResponse)(nil), // 15: headscale.v1.DebugCreateMachineResponse (*UnshareMachineResponse)(nil), // 15: headscale.v1.UnshareMachineResponse
(*Namespace)(nil), // 16: headscale.v1.Namespace (*DebugCreateMachineRequest)(nil), // 16: headscale.v1.DebugCreateMachineRequest
(*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp (*DebugCreateMachineResponse)(nil), // 17: headscale.v1.DebugCreateMachineResponse
(*PreAuthKey)(nil), // 18: headscale.v1.PreAuthKey (*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{ 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 0, // 1: headscale.v1.Machine.register_method:type_name -> headscale.v1.RegisterMethod
17, // 2: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp 19, // 2: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp
17, // 3: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp 19, // 3: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp
17, // 4: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp 19, // 4: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp
18, // 5: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey 20, // 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, // 6: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp
1, // 7: headscale.v1.RegisterMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 7: headscale.v1.RegisterMachineResponse.machine:type_name -> headscale.v1.Machine
1, // 8: headscale.v1.GetMachineResponse.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, // 9: headscale.v1.ExpireMachineResponse.machine:type_name -> headscale.v1.Machine
1, // 10: headscale.v1.ShareMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 10: headscale.v1.ListMachinesResponse.machines:type_name -> headscale.v1.Machine
1, // 11: headscale.v1.UnshareMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 11: headscale.v1.ShareMachineResponse.machine:type_name -> headscale.v1.Machine
1, // 12: headscale.v1.DebugCreateMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 12: headscale.v1.UnshareMachineResponse.machine:type_name -> headscale.v1.Machine
13, // [13:13] is the sub-list for method output_type 1, // 13: headscale.v1.DebugCreateMachineResponse.machine:type_name -> headscale.v1.Machine
13, // [13:13] is the sub-list for method input_type 14, // [14:14] is the sub-list for method output_type
13, // [13:13] is the sub-list for extension type_name 14, // [14:14] is the sub-list for method input_type
13, // [13:13] is the sub-list for extension extendee 14, // [14:14] is the sub-list for extension type_name
0, // [0:13] is the sub-list for field 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() } 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{} { 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: case 0:
return &v.state return &v.state
case 1: 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{} { 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: case 0:
return &v.state return &v.state
case 1: 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{} { 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: case 0:
return &v.state return &v.state
case 1: 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{} { 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: case 0:
return &v.state return &v.state
case 1: 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{} { 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: case 0:
return &v.state return &v.state
case 1: 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{} { 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: case 0:
return &v.state return &v.state
case 1: 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{} { 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: case 0:
return &v.state return &v.state
case 1: 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{} { 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 { switch v := v.(*DebugCreateMachineResponse); i {
case 0: case 0:
return &v.state return &v.state
@ -1300,7 +1429,7 @@ func file_headscale_v1_machine_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_headscale_v1_machine_proto_rawDesc, RawDescriptor: file_headscale_v1_machine_proto_rawDesc,
NumEnums: 1, NumEnums: 1,
NumMessages: 15, NumMessages: 17,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View file

@ -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": { "/api/v1/machine/{machineId}/routes": {
"get": { "get": {
"summary": "--- Route start ---", "summary": "--- Route start ---",
@ -649,6 +680,14 @@
} }
} }
}, },
"v1ExpireMachineResponse": {
"type": "object",
"properties": {
"machine": {
"$ref": "#/definitions/v1Machine"
}
}
},
"v1ExpirePreAuthKeyRequest": { "v1ExpirePreAuthKeyRequest": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -201,6 +201,27 @@ func (api headscaleV1APIServer) DeleteMachine(
return &v1.DeleteMachineResponse{}, nil 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( func (api headscaleV1APIServer) ListMachines(
ctx context.Context, ctx context.Context,
request *v1.ListMachinesRequest, request *v1.ListMachinesRequest,

View file

@ -897,6 +897,133 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
assert.Len(s.T(), listOnlyMachineNamespaceAfterUnshare, 4) 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() { func (s *IntegrationCLITestSuite) TestRouteCommand() {
namespace, err := s.createNamespace("routes-namespace") namespace, err := s.createNamespace("routes-namespace")
assert.Nil(s.T(), err) assert.Nil(s.T(), err)

View file

@ -45,7 +45,6 @@ type Machine struct {
LastSeen *time.Time LastSeen *time.Time
LastSuccessfulUpdate *time.Time LastSuccessfulUpdate *time.Time
Expiry *time.Time Expiry *time.Time
RequestedExpiry *time.Time
HostInfo datatypes.JSON HostInfo datatypes.JSON
Endpoints datatypes.JSON Endpoints datatypes.JSON
@ -62,44 +61,20 @@ type (
) )
// For the time being this method is rather naive. // For the time being this method is rather naive.
func (machine Machine) isAlreadyRegistered() bool { func (machine Machine) isRegistered() bool {
return machine.Registered return machine.Registered
} }
// isExpired returns whether the machine registration has expired. // isExpired returns whether the machine registration has expired.
func (machine Machine) isExpired() bool { func (machine Machine) isExpired() bool {
return time.Now().UTC().After(*machine.Expiry) // 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 the Machine is expired, updateMachineExpiry updates the Machine Expiry time to the maximum allowed duration, if machine.Expiry.IsZero() {
// or the default duration if no Expiry time was requested by the client. The expiry time here does not (yet) cause return false
// 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)
} }
return time.Now().UTC().After(*machine.Expiry)
} }
func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) {
@ -232,6 +207,23 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) {
return peers, nil 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) { func (h *Headscale) ListMachines() ([]Machine, error) {
machines := []Machine{} machines := []Machine{}
if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Find(&machines).Error; err != nil { if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Find(&machines).Error; err != nil {
@ -287,6 +279,28 @@ func (h *Headscale) UpdateMachine(machine *Machine) error {
return nil 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.setLastStateChangeToNow(machine.Namespace.Name)
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.setLastStateChangeToNow(machine.Namespace.Name)
h.db.Save(machine)
}
// DeleteMachine softs deletes a Machine from the database. // DeleteMachine softs deletes a Machine from the database.
func (h *Headscale) DeleteMachine(machine *Machine) error { func (h *Headscale) DeleteMachine(machine *Machine) error {
err := h.RemoveSharedMachineFromAllNamespaces(machine) err := h.RemoveSharedMachineFromAllNamespaces(machine)
@ -624,12 +638,37 @@ func (h *Headscale) RegisterMachine(
return nil, errMachineNotFound 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(). log.Trace().
Caller(). Caller().
Str("machine", machine.Name). Str("machine", machine.Name).
Msg("Attempting to register machine") Msg("Attempting to register machine")
if machine.isAlreadyRegistered() { if machine.isRegistered() {
err := errMachineAlreadyRegistered err := errMachineAlreadyRegistered
log.Error(). log.Error().
Caller(). Caller().
@ -660,7 +699,8 @@ func (h *Headscale) RegisterMachine(
machine.IPAddress = ip.String() machine.IPAddress = ip.String()
machine.NamespaceID = namespace.ID machine.NamespaceID = namespace.ID
machine.Registered = true machine.Registered = true
machine.RegisterMethod = "cli" machine.RegisterMethod = RegisterMethodCLI
machine.Expiry = &requestedTime
h.db.Save(&machine) h.db.Save(&machine)
log.Trace(). log.Trace().

View file

@ -3,6 +3,7 @@ package headscale
import ( import (
"encoding/json" "encoding/json"
"strconv" "strconv"
"time"
"gopkg.in/check.v1" "gopkg.in/check.v1"
) )
@ -25,7 +26,7 @@ func (s *Suite) TestGetMachine(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }
app.db.Save(machine) app.db.Save(machine)
@ -55,7 +56,7 @@ func (s *Suite) TestGetMachineByID(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }
app.db.Save(&machine) app.db.Save(&machine)
@ -78,7 +79,7 @@ func (s *Suite) TestDeleteMachine(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(1), AuthKeyID: uint(1),
} }
app.db.Save(&machine) app.db.Save(&machine)
@ -113,7 +114,7 @@ func (s *Suite) TestHardDeleteMachine(c *check.C) {
Name: "testmachine3", Name: "testmachine3",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(1), AuthKeyID: uint(1),
} }
app.db.Save(&machine) app.db.Save(&machine)
@ -144,7 +145,7 @@ func (s *Suite) TestGetDirectPeers(c *check.C) {
Name: "testmachine" + strconv.Itoa(index), Name: "testmachine" + strconv.Itoa(index),
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }
app.db.Save(&machine) app.db.Save(&machine)
@ -164,3 +165,37 @@ func (s *Suite) TestGetDirectPeers(c *check.C) {
c.Assert(peersOfMachine0[5].Name, check.Equals, "testmachine7") c.Assert(peersOfMachine0[5].Name, check.Equals, "testmachine7")
c.Assert(peersOfMachine0[8].Name, check.Equals, "testmachine10") 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)
}

View file

@ -53,7 +53,7 @@ func (s *Suite) TestDestroyNamespaceErrors(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }
app.db.Save(&machine) app.db.Save(&machine)
@ -145,7 +145,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
NamespaceID: namespaceShared1.ID, NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1, Namespace: *namespaceShared1,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.1", IPAddress: "100.64.0.1",
AuthKeyID: uint(preAuthKeyShared1.ID), AuthKeyID: uint(preAuthKeyShared1.ID),
} }
@ -163,7 +163,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
NamespaceID: namespaceShared2.ID, NamespaceID: namespaceShared2.ID,
Namespace: *namespaceShared2, Namespace: *namespaceShared2,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.2", IPAddress: "100.64.0.2",
AuthKeyID: uint(preAuthKeyShared2.ID), AuthKeyID: uint(preAuthKeyShared2.ID),
} }
@ -181,7 +181,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
NamespaceID: namespaceShared3.ID, NamespaceID: namespaceShared3.ID,
Namespace: *namespaceShared3, Namespace: *namespaceShared3,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.3", IPAddress: "100.64.0.3",
AuthKeyID: uint(preAuthKeyShared3.ID), AuthKeyID: uint(preAuthKeyShared3.ID),
} }
@ -199,7 +199,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
NamespaceID: namespaceShared1.ID, NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1, Namespace: *namespaceShared1,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.4", IPAddress: "100.64.0.4",
AuthKeyID: uint(preAuthKey2Shared1.ID), AuthKeyID: uint(preAuthKey2Shared1.ID),
} }

113
oidc.go
View file

@ -4,6 +4,7 @@ import (
"context" "context"
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"net/http" "net/http"
"regexp" "regexp"
@ -15,6 +16,7 @@ import (
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"golang.org/x/oauth2" "golang.org/x/oauth2"
"gorm.io/gorm"
) )
const ( const (
@ -37,7 +39,10 @@ func (h *Headscale) initOIDC() error {
h.oidcProvider, err = oidc.NewProvider(context.Background(), h.cfg.OIDC.Issuer) h.oidcProvider, err = oidc.NewProvider(context.Background(), h.cfg.OIDC.Issuer)
if err != nil { 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 return err
} }
@ -69,16 +74,23 @@ func (h *Headscale) initOIDC() error {
// Puts machine key in cache so the callback can retrieve it using the oidc state param // Puts machine key in cache so the callback can retrieve it using the oidc state param
// Listens in /oidc/register/:mKey. // Listens in /oidc/register/:mKey.
func (h *Headscale) RegisterOIDC(ctx *gin.Context) { func (h *Headscale) RegisterOIDC(ctx *gin.Context) {
mKeyStr := ctx.Param("mkey") machineKeyStr := ctx.Param("mkey")
if mKeyStr == "" { if machineKeyStr == "" {
ctx.String(http.StatusBadRequest, "Wrong params") ctx.String(http.StatusBadRequest, "Wrong params")
return return
} }
log.Trace().
Caller().
Str("machine_key", machineKeyStr).
Msg("Received oidc register call")
randomBlob := make([]byte, randomByteSize) randomBlob := make([]byte, randomByteSize)
if _, err := rand.Read(randomBlob); err != nil { 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") ctx.String(http.StatusInternalServerError, "could not read 16 bytes from rand")
return return
@ -87,7 +99,7 @@ func (h *Headscale) RegisterOIDC(ctx *gin.Context) {
stateStr := hex.EncodeToString(randomBlob)[:32] stateStr := hex.EncodeToString(randomBlob)[:32]
// place the machine key into the state cache, so it can be retrieved later // 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) authURL := h.oauth2Config.AuthCodeURL(stateStr)
log.Debug().Msgf("Redirecting to %s for authentication", authURL) log.Debug().Msgf("Redirecting to %s for authentication", authURL)
@ -117,7 +129,11 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
return 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) rawIDToken, rawIDTokenOK := oauth2Token.Extra("id_token").(string)
if !rawIDTokenOK { if !rawIDTokenOK {
@ -130,7 +146,11 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
idToken, err := verifier.Verify(context.Background(), rawIDToken) idToken, err := verifier.Verify(context.Background(), rawIDToken)
if err != nil { 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 return
} }
@ -138,34 +158,38 @@ 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) // 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)) // userInfo, err := oidcProvider.UserInfo(context.Background(), oauth2.StaticTokenSource(oauth2Token))
// if err != nil { // 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 // return
// } // }
// Extract custom claims // Extract custom claims
var claims IDTokenClaims var claims IDTokenClaims
if err = idToken.Claims(&claims); err != nil { if err = idToken.Claims(&claims); err != nil {
log.Error().
Err(err).
Caller().
Msg("Failed to decode id token claims")
ctx.String( ctx.String(
http.StatusBadRequest, http.StatusBadRequest,
fmt.Sprintf("Failed to decode id token claims: %s", err), "Failed to decode id token claims",
) )
return return
} }
// retrieve machinekey from state cache // retrieve machinekey from state cache
mKeyIf, mKeyFound := h.oidcStateCache.Get(state) machineKeyIf, machineKeyFound := h.oidcStateCache.Get(state)
if !mKeyFound { if !machineKeyFound {
log.Error(). log.Error().
Msg("requested machine state key expired before authorisation completed") Msg("requested machine state key expired before authorisation completed")
ctx.String(http.StatusBadRequest, "state has expired") ctx.String(http.StatusBadRequest, "state has expired")
return return
} }
mKeyStr, mKeyOK := mKeyIf.(string) machineKey, machineKeyOK := machineKeyIf.(string)
if !mKeyOK { if !machineKeyOK {
log.Error().Msg("could not get machine key from cache") log.Error().Msg("could not get machine key from cache")
ctx.String( ctx.String(
http.StatusInternalServerError, http.StatusInternalServerError,
@ -175,8 +199,16 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
return 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 // retrieve machine information
machine, err := h.GetMachineByMachineKey(mKeyStr) machine, err := h.GetMachineByMachineKey(machineKey)
if err != nil { if err != nil {
log.Error().Msg("machine key not found in database") log.Error().Msg("machine key not found in database")
ctx.String( ctx.String(
@ -187,6 +219,29 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
return 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(`
<html>
<body>
<h1>headscale</h1>
<p>
Reuthenticated as %s, you can now close this window.
</p>
</body>
</html>
`, claims.Email)))
return
}
now := time.Now().UTC() now := time.Now().UTC()
if namespaceName, ok := h.getNamespaceFromEmail(claims.Email); ok { if namespaceName, ok := h.getNamespaceFromEmail(claims.Email); ok {
@ -195,12 +250,14 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
log.Debug().Msg("Registering new machine after successful callback") log.Debug().Msg("Registering new machine after successful callback")
namespace, err := h.GetNamespace(namespaceName) namespace, err := h.GetNamespace(namespaceName)
if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) {
namespace, err = h.CreateNamespace(namespaceName) namespace, err = h.CreateNamespace(namespaceName)
if err != nil { if err != nil {
log.Error(). log.Error().
Msgf("could not create new namespace '%s'", claims.Email) Err(err).
Caller().
Msgf("could not create new namespace '%s'", namespaceName)
ctx.String( ctx.String(
http.StatusInternalServerError, http.StatusInternalServerError,
"could not create new namespace", "could not create new namespace",
@ -208,10 +265,26 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
return 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() ip, err := h.getAvailableIP()
if err != nil { if err != nil {
log.Error().
Caller().
Err(err).
Msg("could not get an IP from the pool")
ctx.String( ctx.String(
http.StatusInternalServerError, http.StatusInternalServerError,
"could not get an IP from the pool", "could not get an IP from the pool",
@ -223,13 +296,12 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
machine.IPAddress = ip.String() machine.IPAddress = ip.String()
machine.NamespaceID = namespace.ID machine.NamespaceID = namespace.ID
machine.Registered = true machine.Registered = true
machine.RegisterMethod = "oidc" machine.RegisterMethod = RegisterMethodOIDC
machine.LastSuccessfulUpdate = &now machine.LastSuccessfulUpdate = &now
machine.Expiry = &requestedTime
h.db.Save(&machine) h.db.Save(&machine)
} }
h.updateMachineExpiry(machine)
ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(fmt.Sprintf(` ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(fmt.Sprintf(`
<html> <html>
<body> <body>
@ -241,9 +313,12 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
</html> </html>
`, claims.Email))) `, claims.Email)))
return
} }
log.Error(). log.Error().
Caller().
Str("email", claims.Email). Str("email", claims.Email).
Str("username", claims.Username). Str("username", claims.Username).
Str("machine", machine.Name). Str("machine", machine.Name).

View file

@ -81,7 +81,7 @@ func (*Suite) TestAlreadyUsedKey(c *check.C) {
Name: "testest", Name: "testest",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }
app.db.Save(&machine) app.db.Save(&machine)
@ -106,7 +106,7 @@ func (*Suite) TestReusableBeingUsedKey(c *check.C) {
Name: "testest", Name: "testest",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }
app.db.Save(&machine) app.db.Save(&machine)
@ -144,7 +144,7 @@ func (*Suite) TestEphemeralKey(c *check.C) {
Name: "testest", Name: "testest",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
LastSeen: &now, LastSeen: &now,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }

View file

@ -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) { rpc ListMachines(ListMachinesRequest) returns (ListMachinesResponse) {
option (google.api.http) = { option (google.api.http) = {
get: "/api/v1/machine" get: "/api/v1/machine"

View file

@ -64,6 +64,14 @@ message DeleteMachineRequest {
message DeleteMachineResponse { message DeleteMachineResponse {
} }
message ExpireMachineRequest {
uint64 machine_id = 1;
}
message ExpireMachineResponse {
Machine machine = 1;
}
message ListMachinesRequest { message ListMachinesRequest {
string namespace = 1; string namespace = 1;
} }

View file

@ -36,7 +36,7 @@ func (s *Suite) TestGetRoutes(c *check.C) {
Name: "test_get_route_machine", Name: "test_get_route_machine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
HostInfo: datatypes.JSON(hostinfo), HostInfo: datatypes.JSON(hostinfo),
} }
@ -90,7 +90,7 @@ func (s *Suite) TestGetEnableRoutes(c *check.C) {
Name: "test_enable_route_machine", Name: "test_enable_route_machine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
HostInfo: datatypes.JSON(hostinfo), HostInfo: datatypes.JSON(hostinfo),
} }

View file

@ -25,7 +25,7 @@ func CreateNodeNamespace(
Name: node, Name: node,
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: ip, IPAddress: ip,
AuthKeyID: uint(pak1.ID), AuthKeyID: uint(pak1.ID),
} }
@ -213,7 +213,7 @@ func (s *Suite) TestComplexSharingAcrossNamespaces(c *check.C) {
Name: "test_get_shared_nodes_4", Name: "test_get_shared_nodes_4",
NamespaceID: namespace1.ID, NamespaceID: namespace1.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.4", IPAddress: "100.64.0.4",
AuthKeyID: uint(pak4.ID), AuthKeyID: uint(pak4.ID),
} }
@ -293,7 +293,7 @@ func (s *Suite) TestDeleteSharedMachine(c *check.C) {
Name: "test_get_shared_nodes_4", Name: "test_get_shared_nodes_4",
NamespaceID: namespace1.ID, NamespaceID: namespace1.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
IPAddress: "100.64.0.4", IPAddress: "100.64.0.4",
AuthKeyID: uint(pak4n1.ID), AuthKeyID: uint(pak4n1.ID),
} }

View file

@ -36,7 +36,7 @@ func (s *Suite) TestGetUsedIps(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
IPAddress: ip.String(), IPAddress: ip.String(),
} }
@ -78,7 +78,7 @@ func (s *Suite) TestGetMultiIp(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
IPAddress: ip.String(), IPAddress: ip.String(),
} }
@ -151,7 +151,7 @@ func (s *Suite) TestGetAvailableIpMachineWithoutIP(c *check.C) {
Name: "testmachine", Name: "testmachine",
NamespaceID: namespace.ID, NamespaceID: namespace.ID,
Registered: true, Registered: true,
RegisterMethod: "authKey", RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID), AuthKeyID: uint(pak.ID),
} }
app.db.Save(&machine) app.db.Save(&machine)