mirror of
https://github.com/juanfont/headscale.git
synced 2025-01-24 17:53:13 -05:00
Merge pull request #306 from kradalby/apiwork
Introduce API keys and enable remote control API
This commit is contained in:
commit
73497382b7
@ -7,6 +7,9 @@
|
|||||||
**Features**:
|
**Features**:
|
||||||
|
|
||||||
- Add IPv6 support to the prefix assigned to namespaces
|
- Add IPv6 support to the prefix assigned to namespaces
|
||||||
|
- Add API Key support
|
||||||
|
- Enable remote control of `headscale` via CLI [docs](docs/remote-cli.md)
|
||||||
|
- Enable HTTP API (beta, subject to change)
|
||||||
|
|
||||||
**Changes**:
|
**Changes**:
|
||||||
|
|
||||||
|
164
api_key.go
Normal file
164
api_key.go
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
package headscale
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
apiPrefixLength = 7
|
||||||
|
apiKeyLength = 32
|
||||||
|
apiKeyParts = 2
|
||||||
|
|
||||||
|
errAPIKeyFailedToParse = Error("Failed to parse ApiKey")
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIKey describes the datamodel for API keys used to remotely authenticate with
|
||||||
|
// headscale.
|
||||||
|
type APIKey struct {
|
||||||
|
ID uint64 `gorm:"primary_key"`
|
||||||
|
Prefix string `gorm:"uniqueIndex"`
|
||||||
|
Hash []byte
|
||||||
|
|
||||||
|
CreatedAt *time.Time
|
||||||
|
Expiration *time.Time
|
||||||
|
LastSeen *time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAPIKey creates a new ApiKey in a namespace, and returns it.
|
||||||
|
func (h *Headscale) CreateAPIKey(
|
||||||
|
expiration *time.Time,
|
||||||
|
) (string, *APIKey, error) {
|
||||||
|
prefix, err := GenerateRandomStringURLSafe(apiPrefixLength)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
toBeHashed, err := GenerateRandomStringURLSafe(apiKeyLength)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key to return to user, this will only be visible _once_
|
||||||
|
keyStr := prefix + "." + toBeHashed
|
||||||
|
|
||||||
|
hash, err := bcrypt.GenerateFromPassword([]byte(toBeHashed), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
key := APIKey{
|
||||||
|
Prefix: prefix,
|
||||||
|
Hash: hash,
|
||||||
|
Expiration: expiration,
|
||||||
|
}
|
||||||
|
h.db.Save(&key)
|
||||||
|
|
||||||
|
return keyStr, &key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAPIKeys returns the list of ApiKeys for a namespace.
|
||||||
|
func (h *Headscale) ListAPIKeys() ([]APIKey, error) {
|
||||||
|
keys := []APIKey{}
|
||||||
|
if err := h.db.Find(&keys).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAPIKey returns a ApiKey for a given key.
|
||||||
|
func (h *Headscale) GetAPIKey(prefix string) (*APIKey, error) {
|
||||||
|
key := APIKey{}
|
||||||
|
if result := h.db.First(&key, "prefix = ?", prefix); result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return &key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAPIKeyByID returns a ApiKey for a given id.
|
||||||
|
func (h *Headscale) GetAPIKeyByID(id uint64) (*APIKey, error) {
|
||||||
|
key := APIKey{}
|
||||||
|
if result := h.db.Find(&APIKey{ID: id}).First(&key); result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return &key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DestroyAPIKey destroys a ApiKey. Returns error if the ApiKey
|
||||||
|
// does not exist.
|
||||||
|
func (h *Headscale) DestroyAPIKey(key APIKey) error {
|
||||||
|
if result := h.db.Unscoped().Delete(key); result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpireAPIKey marks a ApiKey as expired.
|
||||||
|
func (h *Headscale) ExpireAPIKey(key *APIKey) error {
|
||||||
|
if err := h.db.Model(&key).Update("Expiration", time.Now()).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Headscale) ValidateAPIKey(keyStr string) (bool, error) {
|
||||||
|
prefix, hash, err := splitAPIKey(keyStr)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to validate api key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := h.GetAPIKey(prefix)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to validate api key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if key.Expiration.Before(time.Now()) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bcrypt.CompareHashAndPassword(key.Hash, []byte(hash)); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitAPIKey(key string) (string, string, error) {
|
||||||
|
parts := strings.Split(key, ".")
|
||||||
|
if len(parts) != apiKeyParts {
|
||||||
|
return "", "", errAPIKeyFailedToParse
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts[0], parts[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (key *APIKey) toProto() *v1.ApiKey {
|
||||||
|
protoKey := v1.ApiKey{
|
||||||
|
Id: key.ID,
|
||||||
|
Prefix: key.Prefix,
|
||||||
|
}
|
||||||
|
|
||||||
|
if key.Expiration != nil {
|
||||||
|
protoKey.Expiration = timestamppb.New(*key.Expiration)
|
||||||
|
}
|
||||||
|
|
||||||
|
if key.CreatedAt != nil {
|
||||||
|
protoKey.CreatedAt = timestamppb.New(*key.CreatedAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
if key.LastSeen != nil {
|
||||||
|
protoKey.LastSeen = timestamppb.New(*key.LastSeen)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &protoKey
|
||||||
|
}
|
89
api_key_test.go
Normal file
89
api_key_test.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package headscale
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gopkg.in/check.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (*Suite) TestCreateAPIKey(c *check.C) {
|
||||||
|
apiKeyStr, apiKey, err := app.CreateAPIKey(nil)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(apiKey, check.NotNil)
|
||||||
|
|
||||||
|
// Did we get a valid key?
|
||||||
|
c.Assert(apiKey.Prefix, check.NotNil)
|
||||||
|
c.Assert(apiKey.Hash, check.NotNil)
|
||||||
|
c.Assert(apiKeyStr, check.Not(check.Equals), "")
|
||||||
|
|
||||||
|
_, err = app.ListAPIKeys()
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
|
keys, err := app.ListAPIKeys()
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(len(keys), check.Equals, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Suite) TestAPIKeyDoesNotExist(c *check.C) {
|
||||||
|
key, err := app.GetAPIKey("does-not-exist")
|
||||||
|
c.Assert(err, check.NotNil)
|
||||||
|
c.Assert(key, check.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Suite) TestValidateAPIKeyOk(c *check.C) {
|
||||||
|
nowPlus2 := time.Now().Add(2 * time.Hour)
|
||||||
|
apiKeyStr, apiKey, err := app.CreateAPIKey(&nowPlus2)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(apiKey, check.NotNil)
|
||||||
|
|
||||||
|
valid, err := app.ValidateAPIKey(apiKeyStr)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(valid, check.Equals, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Suite) TestValidateAPIKeyNotOk(c *check.C) {
|
||||||
|
nowMinus2 := time.Now().Add(time.Duration(-2) * time.Hour)
|
||||||
|
apiKeyStr, apiKey, err := app.CreateAPIKey(&nowMinus2)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(apiKey, check.NotNil)
|
||||||
|
|
||||||
|
valid, err := app.ValidateAPIKey(apiKeyStr)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(valid, check.Equals, false)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
apiKeyStrNow, apiKey, err := app.CreateAPIKey(&now)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(apiKey, check.NotNil)
|
||||||
|
|
||||||
|
validNow, err := app.ValidateAPIKey(apiKeyStrNow)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(validNow, check.Equals, false)
|
||||||
|
|
||||||
|
validSilly, err := app.ValidateAPIKey("nota.validkey")
|
||||||
|
c.Assert(err, check.NotNil)
|
||||||
|
c.Assert(validSilly, check.Equals, false)
|
||||||
|
|
||||||
|
validWithErr, err := app.ValidateAPIKey("produceerrorkey")
|
||||||
|
c.Assert(err, check.NotNil)
|
||||||
|
c.Assert(validWithErr, check.Equals, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Suite) TestExpireAPIKey(c *check.C) {
|
||||||
|
nowPlus2 := time.Now().Add(2 * time.Hour)
|
||||||
|
apiKeyStr, apiKey, err := app.CreateAPIKey(&nowPlus2)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(apiKey, check.NotNil)
|
||||||
|
|
||||||
|
valid, err := app.ValidateAPIKey(apiKeyStr)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(valid, check.Equals, true)
|
||||||
|
|
||||||
|
err = app.ExpireAPIKey(apiKey)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(apiKey.Expiration, check.NotNil)
|
||||||
|
|
||||||
|
notValid, err := app.ValidateAPIKey(apiKeyStr)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(notValid, check.Equals, false)
|
||||||
|
}
|
309
app.go
309
app.go
@ -27,7 +27,6 @@ import (
|
|||||||
zerolog "github.com/philip-bui/grpc-zerolog"
|
zerolog "github.com/philip-bui/grpc-zerolog"
|
||||||
zl "github.com/rs/zerolog"
|
zl "github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/soheilhy/cmux"
|
|
||||||
ginprometheus "github.com/zsais/go-gin-prometheus"
|
ginprometheus "github.com/zsais/go-gin-prometheus"
|
||||||
"golang.org/x/crypto/acme"
|
"golang.org/x/crypto/acme"
|
||||||
"golang.org/x/crypto/acme/autocert"
|
"golang.org/x/crypto/acme/autocert"
|
||||||
@ -36,6 +35,7 @@ import (
|
|||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
"google.golang.org/grpc/reflection"
|
"google.golang.org/grpc/reflection"
|
||||||
@ -68,6 +68,8 @@ const (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
ServerURL string
|
ServerURL string
|
||||||
Addr string
|
Addr string
|
||||||
|
GRPCAddr string
|
||||||
|
GRPCAllowInsecure bool
|
||||||
EphemeralNodeInactivityTimeout time.Duration
|
EphemeralNodeInactivityTimeout time.Duration
|
||||||
IPPrefixes []netaddr.IPPrefix
|
IPPrefixes []netaddr.IPPrefix
|
||||||
PrivateKeyPath string
|
PrivateKeyPath string
|
||||||
@ -121,8 +123,8 @@ type DERPConfig struct {
|
|||||||
type CLIConfig struct {
|
type CLIConfig struct {
|
||||||
Address string
|
Address string
|
||||||
APIKey string
|
APIKey string
|
||||||
Insecure bool
|
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
|
Insecure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Headscale represents the base app of the service.
|
// Headscale represents the base app of the service.
|
||||||
@ -325,26 +327,26 @@ func (h *Headscale) grpcAuthenticationInterceptor(ctx context.Context,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(kradalby): Implement API key backend:
|
valid, err := h.ValidateAPIKey(strings.TrimPrefix(token, AuthPrefix))
|
||||||
// - Table in the DB
|
if err != nil {
|
||||||
// - Key name
|
log.Error().
|
||||||
// - Encrypted
|
Caller().
|
||||||
// - Expiry
|
Err(err).
|
||||||
//
|
Str("client_address", client.Addr.String()).
|
||||||
// Currently all other than localhost traffic is unauthorized, this is intentional to allow
|
Msg("failed to validate token")
|
||||||
// us to make use of gRPC for our CLI, but not having to implement any of the remote capabilities
|
|
||||||
// and API key auth
|
|
||||||
return ctx, status.Error(
|
|
||||||
codes.Unauthenticated,
|
|
||||||
"Authentication is not implemented yet",
|
|
||||||
)
|
|
||||||
|
|
||||||
// if strings.TrimPrefix(token, AUTH_PREFIX) != a.Token {
|
return ctx, status.Error(codes.Internal, "failed to validate token")
|
||||||
// log.Error().Caller().Str("client_address", p.Addr.String()).Msg("invalid token")
|
}
|
||||||
// return ctx, status.Error(codes.Unauthenticated, "invalid token")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return handler(ctx, req)
|
if !valid {
|
||||||
|
log.Info().
|
||||||
|
Str("client_address", client.Addr.String()).
|
||||||
|
Msg("invalid token")
|
||||||
|
|
||||||
|
return ctx, status.Error(codes.Unauthenticated, "invalid token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Headscale) httpAuthenticationMiddleware(ctx *gin.Context) {
|
func (h *Headscale) httpAuthenticationMiddleware(ctx *gin.Context) {
|
||||||
@ -367,19 +369,30 @@ func (h *Headscale) httpAuthenticationMiddleware(ctx *gin.Context) {
|
|||||||
|
|
||||||
ctx.AbortWithStatus(http.StatusUnauthorized)
|
ctx.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
|
||||||
// TODO(kradalby): Implement API key backend
|
valid, err := h.ValidateAPIKey(strings.TrimPrefix(authHeader, AuthPrefix))
|
||||||
// Currently all traffic is unauthorized, this is intentional to allow
|
if err != nil {
|
||||||
// us to make use of gRPC for our CLI, but not having to implement any of the remote capabilities
|
log.Error().
|
||||||
// and API key auth
|
Caller().
|
||||||
//
|
Err(err).
|
||||||
// if strings.TrimPrefix(authHeader, AUTH_PREFIX) != a.Token {
|
Str("client_address", ctx.ClientIP()).
|
||||||
// log.Error().Caller().Str("client_address", c.ClientIP()).Msg("invalid token")
|
Msg("failed to validate token")
|
||||||
// c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error", "unauthorized"})
|
|
||||||
|
|
||||||
// return
|
ctx.AbortWithStatus(http.StatusInternalServerError)
|
||||||
// }
|
|
||||||
|
|
||||||
// c.Next()
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !valid {
|
||||||
|
log.Info().
|
||||||
|
Str("client_address", ctx.ClientIP()).
|
||||||
|
Msg("invalid token")
|
||||||
|
|
||||||
|
ctx.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureUnixSocketIsAbsent will check if the given path for headscales unix socket is clear
|
// ensureUnixSocketIsAbsent will check if the given path for headscales unix socket is clear
|
||||||
@ -393,15 +406,71 @@ func (h *Headscale) ensureUnixSocketIsAbsent() error {
|
|||||||
return os.Remove(h.cfg.UnixSocket)
|
return os.Remove(h.cfg.UnixSocket)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine {
|
||||||
|
router := gin.Default()
|
||||||
|
|
||||||
|
prometheus := ginprometheus.NewPrometheus("gin")
|
||||||
|
prometheus.Use(router)
|
||||||
|
|
||||||
|
router.GET(
|
||||||
|
"/health",
|
||||||
|
func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"healthy": "ok"}) },
|
||||||
|
)
|
||||||
|
router.GET("/key", h.KeyHandler)
|
||||||
|
router.GET("/register", h.RegisterWebAPI)
|
||||||
|
router.POST("/machine/:id/map", h.PollNetMapHandler)
|
||||||
|
router.POST("/machine/:id", h.RegistrationHandler)
|
||||||
|
router.GET("/oidc/register/:mkey", h.RegisterOIDC)
|
||||||
|
router.GET("/oidc/callback", h.OIDCCallback)
|
||||||
|
router.GET("/apple", h.AppleMobileConfig)
|
||||||
|
router.GET("/apple/:platform", h.ApplePlatformConfig)
|
||||||
|
router.GET("/swagger", SwaggerUI)
|
||||||
|
router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1)
|
||||||
|
|
||||||
|
api := router.Group("/api")
|
||||||
|
api.Use(h.httpAuthenticationMiddleware)
|
||||||
|
{
|
||||||
|
api.Any("/v1/*any", gin.WrapF(grpcMux.ServeHTTP))
|
||||||
|
}
|
||||||
|
|
||||||
|
router.NoRoute(stdoutHandler)
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
||||||
|
|
||||||
// Serve launches a GIN server with the Headscale API.
|
// Serve launches a GIN server with the Headscale API.
|
||||||
func (h *Headscale) Serve() error {
|
func (h *Headscale) Serve() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
// Fetch an initial DERP Map before we start serving
|
||||||
|
h.DERPMap = GetDERPMap(h.cfg.DERP)
|
||||||
|
|
||||||
|
if h.cfg.DERP.AutoUpdate {
|
||||||
|
derpMapCancelChannel := make(chan struct{})
|
||||||
|
defer func() { derpMapCancelChannel <- struct{}{} }()
|
||||||
|
go h.scheduledDERPMapUpdateWorker(derpMapCancelChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
go h.expireEphemeralNodes(updateInterval)
|
||||||
|
|
||||||
|
if zl.GlobalLevel() == zl.TraceLevel {
|
||||||
|
zerolog.RespLog = true
|
||||||
|
} else {
|
||||||
|
zerolog.RespLog = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare group for running listeners
|
||||||
|
errorGroup := new(errgroup.Group)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Set up LOCAL listeners
|
||||||
|
//
|
||||||
|
|
||||||
err = h.ensureUnixSocketIsAbsent()
|
err = h.ensureUnixSocketIsAbsent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to remove old socket file: %w", err)
|
return fmt.Errorf("unable to remove old socket file: %w", err)
|
||||||
@ -430,32 +499,13 @@ func (h *Headscale) Serve() error {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}(sigc)
|
}(sigc)
|
||||||
|
|
||||||
networkListener, err := net.Listen("tcp", h.cfg.Addr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to bind to TCP address: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the cmux object that will multiplex 2 protocols on the same port.
|
|
||||||
// The two following listeners will be served on the same port below gracefully.
|
|
||||||
networkMutex := cmux.New(networkListener)
|
|
||||||
// Match gRPC requests here
|
|
||||||
grpcListener := networkMutex.MatchWithWriters(
|
|
||||||
cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"),
|
|
||||||
cmux.HTTP2MatchHeaderFieldSendSettings(
|
|
||||||
"content-type",
|
|
||||||
"application/grpc+proto",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
// Otherwise match regular http requests.
|
|
||||||
httpListener := networkMutex.Match(cmux.Any())
|
|
||||||
|
|
||||||
grpcGatewayMux := runtime.NewServeMux()
|
grpcGatewayMux := runtime.NewServeMux()
|
||||||
|
|
||||||
// Make the grpc-gateway connect to grpc over socket
|
// Make the grpc-gateway connect to grpc over socket
|
||||||
grpcGatewayConn, err := grpc.Dial(
|
grpcGatewayConn, err := grpc.Dial(
|
||||||
h.cfg.UnixSocket,
|
h.cfg.UnixSocket,
|
||||||
[]grpc.DialOption{
|
[]grpc.DialOption{
|
||||||
grpc.WithInsecure(),
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
grpc.WithContextDialer(GrpcSocketDialer),
|
grpc.WithContextDialer(GrpcSocketDialer),
|
||||||
}...,
|
}...,
|
||||||
)
|
)
|
||||||
@ -470,44 +520,80 @@ func (h *Headscale) Serve() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
router := gin.Default()
|
// Start the local gRPC server without TLS and without authentication
|
||||||
|
grpcSocket := grpc.NewServer(zerolog.UnaryInterceptor())
|
||||||
|
|
||||||
prometheus := ginprometheus.NewPrometheus("gin")
|
v1.RegisterHeadscaleServiceServer(grpcSocket, newHeadscaleV1APIServer(h))
|
||||||
prometheus.Use(router)
|
reflection.Register(grpcSocket)
|
||||||
|
|
||||||
router.GET(
|
errorGroup.Go(func() error { return grpcSocket.Serve(socketListener) })
|
||||||
"/health",
|
|
||||||
func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"healthy": "ok"}) },
|
//
|
||||||
|
//
|
||||||
|
// Set up REMOTE listeners
|
||||||
|
//
|
||||||
|
|
||||||
|
tlsConfig, err := h.getTLSSettings()
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Failed to set up TLS configuration")
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// gRPC setup
|
||||||
|
//
|
||||||
|
|
||||||
|
// We are sadly not able to run gRPC and HTTPS (2.0) on the same
|
||||||
|
// port because the connection mux does not support matching them
|
||||||
|
// since they are so similar. There is multiple issues open and we
|
||||||
|
// can revisit this if changes:
|
||||||
|
// https://github.com/soheilhy/cmux/issues/68
|
||||||
|
// https://github.com/soheilhy/cmux/issues/91
|
||||||
|
|
||||||
|
if tlsConfig != nil || h.cfg.GRPCAllowInsecure {
|
||||||
|
log.Info().Msgf("Enabling remote gRPC at %s", h.cfg.GRPCAddr)
|
||||||
|
|
||||||
|
grpcOptions := []grpc.ServerOption{
|
||||||
|
grpc.UnaryInterceptor(
|
||||||
|
grpc_middleware.ChainUnaryServer(
|
||||||
|
h.grpcAuthenticationInterceptor,
|
||||||
|
zerolog.NewUnaryServerInterceptor(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
if tlsConfig != nil {
|
||||||
|
grpcOptions = append(grpcOptions,
|
||||||
|
grpc.Creds(credentials.NewTLS(tlsConfig)),
|
||||||
)
|
)
|
||||||
router.GET("/key", h.KeyHandler)
|
} else {
|
||||||
router.GET("/register", h.RegisterWebAPI)
|
log.Warn().Msg("gRPC is running without security")
|
||||||
router.POST("/machine/:id/map", h.PollNetMapHandler)
|
|
||||||
router.POST("/machine/:id", h.RegistrationHandler)
|
|
||||||
router.GET("/oidc/register/:mkey", h.RegisterOIDC)
|
|
||||||
router.GET("/oidc/callback", h.OIDCCallback)
|
|
||||||
router.GET("/apple", h.AppleMobileConfig)
|
|
||||||
router.GET("/apple/:platform", h.ApplePlatformConfig)
|
|
||||||
router.GET("/swagger", SwaggerUI)
|
|
||||||
router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1)
|
|
||||||
|
|
||||||
api := router.Group("/api")
|
|
||||||
api.Use(h.httpAuthenticationMiddleware)
|
|
||||||
{
|
|
||||||
api.Any("/v1/*any", gin.WrapF(grpcGatewayMux.ServeHTTP))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
router.NoRoute(stdoutHandler)
|
grpcServer := grpc.NewServer(grpcOptions...)
|
||||||
|
|
||||||
// Fetch an initial DERP Map before we start serving
|
v1.RegisterHeadscaleServiceServer(grpcServer, newHeadscaleV1APIServer(h))
|
||||||
h.DERPMap = GetDERPMap(h.cfg.DERP)
|
reflection.Register(grpcServer)
|
||||||
|
|
||||||
if h.cfg.DERP.AutoUpdate {
|
grpcListener, err := net.Listen("tcp", h.cfg.GRPCAddr)
|
||||||
derpMapCancelChannel := make(chan struct{})
|
if err != nil {
|
||||||
defer func() { derpMapCancelChannel <- struct{}{} }()
|
return fmt.Errorf("failed to bind to TCP address: %w", err)
|
||||||
go h.scheduledDERPMapUpdateWorker(derpMapCancelChannel)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go h.expireEphemeralNodes(updateInterval)
|
errorGroup.Go(func() error { return grpcServer.Serve(grpcListener) })
|
||||||
|
|
||||||
|
log.Info().
|
||||||
|
Msgf("listening and serving gRPC on: %s", h.cfg.GRPCAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// HTTP setup
|
||||||
|
//
|
||||||
|
|
||||||
|
router := h.createRouter(grpcGatewayMux)
|
||||||
|
|
||||||
httpServer := &http.Server{
|
httpServer := &http.Server{
|
||||||
Addr: h.cfg.Addr,
|
Addr: h.cfg.Addr,
|
||||||
@ -520,65 +606,21 @@ func (h *Headscale) Serve() error {
|
|||||||
WriteTimeout: 0,
|
WriteTimeout: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
if zl.GlobalLevel() == zl.TraceLevel {
|
var httpListener net.Listener
|
||||||
zerolog.RespLog = true
|
|
||||||
} else {
|
|
||||||
zerolog.RespLog = false
|
|
||||||
}
|
|
||||||
|
|
||||||
grpcOptions := []grpc.ServerOption{
|
|
||||||
grpc.UnaryInterceptor(
|
|
||||||
grpc_middleware.ChainUnaryServer(
|
|
||||||
h.grpcAuthenticationInterceptor,
|
|
||||||
zerolog.NewUnaryServerInterceptor(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConfig, err := h.getTLSSettings()
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("Failed to set up TLS configuration")
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
httpServer.TLSConfig = tlsConfig
|
httpServer.TLSConfig = tlsConfig
|
||||||
|
httpListener, err = tls.Listen("tcp", h.cfg.Addr, tlsConfig)
|
||||||
grpcOptions = append(grpcOptions, grpc.Creds(credentials.NewTLS(tlsConfig)))
|
|
||||||
}
|
|
||||||
|
|
||||||
grpcServer := grpc.NewServer(grpcOptions...)
|
|
||||||
|
|
||||||
// Start the local gRPC server without TLS and without authentication
|
|
||||||
grpcSocket := grpc.NewServer(zerolog.UnaryInterceptor())
|
|
||||||
|
|
||||||
v1.RegisterHeadscaleServiceServer(grpcServer, newHeadscaleV1APIServer(h))
|
|
||||||
v1.RegisterHeadscaleServiceServer(grpcSocket, newHeadscaleV1APIServer(h))
|
|
||||||
reflection.Register(grpcServer)
|
|
||||||
reflection.Register(grpcSocket)
|
|
||||||
|
|
||||||
errorGroup := new(errgroup.Group)
|
|
||||||
|
|
||||||
errorGroup.Go(func() error { return grpcSocket.Serve(socketListener) })
|
|
||||||
|
|
||||||
// TODO(kradalby): Verify if we need the same TLS setup for gRPC as HTTP
|
|
||||||
errorGroup.Go(func() error { return grpcServer.Serve(grpcListener) })
|
|
||||||
|
|
||||||
if tlsConfig != nil {
|
|
||||||
errorGroup.Go(func() error {
|
|
||||||
tlsl := tls.NewListener(httpListener, tlsConfig)
|
|
||||||
|
|
||||||
return httpServer.Serve(tlsl)
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
errorGroup.Go(func() error { return httpServer.Serve(httpListener) })
|
httpListener, err = net.Listen("tcp", h.cfg.Addr)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to bind to TCP address: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
errorGroup.Go(func() error { return networkMutex.Serve() })
|
errorGroup.Go(func() error { return httpServer.Serve(httpListener) })
|
||||||
|
|
||||||
log.Info().
|
log.Info().
|
||||||
Msgf("listening and serving (multiplexed HTTP and gRPC) on: %s", h.cfg.Addr)
|
Msgf("listening and serving HTTP on: %s", h.cfg.Addr)
|
||||||
|
|
||||||
return errorGroup.Wait()
|
return errorGroup.Wait()
|
||||||
}
|
}
|
||||||
@ -614,6 +656,7 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
|
|||||||
// service, which can be configured to run on any other port.
|
// service, which can be configured to run on any other port.
|
||||||
go func() {
|
go func() {
|
||||||
log.Fatal().
|
log.Fatal().
|
||||||
|
Caller().
|
||||||
Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, certManager.HTTPHandler(http.HandlerFunc(h.redirect)))).
|
Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, certManager.HTTPHandler(http.HandlerFunc(h.redirect)))).
|
||||||
Msg("failed to set up a HTTP server")
|
Msg("failed to set up a HTTP server")
|
||||||
}()
|
}()
|
||||||
|
183
cmd/headscale/cli/api_key.go
Normal file
183
cmd/headscale/cli/api_key.go
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/juanfont/headscale"
|
||||||
|
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||||
|
"github.com/pterm/pterm"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 90 days.
|
||||||
|
DefaultAPIKeyExpiry = 90 * 24 * time.Hour
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(apiKeysCmd)
|
||||||
|
apiKeysCmd.AddCommand(listAPIKeys)
|
||||||
|
|
||||||
|
createAPIKeyCmd.Flags().
|
||||||
|
DurationP("expiration", "e", DefaultAPIKeyExpiry, "Human-readable expiration of the key (30m, 24h, 365d...)")
|
||||||
|
|
||||||
|
apiKeysCmd.AddCommand(createAPIKeyCmd)
|
||||||
|
|
||||||
|
expireAPIKeyCmd.Flags().StringP("prefix", "p", "", "ApiKey prefix")
|
||||||
|
err := expireAPIKeyCmd.MarkFlagRequired("prefix")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("")
|
||||||
|
}
|
||||||
|
apiKeysCmd.AddCommand(expireAPIKeyCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiKeysCmd = &cobra.Command{
|
||||||
|
Use: "apikeys",
|
||||||
|
Short: "Handle the Api keys in Headscale",
|
||||||
|
}
|
||||||
|
|
||||||
|
var listAPIKeys = &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Short: "List the Api keys for headscale",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
output, _ := cmd.Flags().GetString("output")
|
||||||
|
|
||||||
|
ctx, client, conn, cancel := getHeadscaleCLIClient()
|
||||||
|
defer cancel()
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
request := &v1.ListApiKeysRequest{}
|
||||||
|
|
||||||
|
response, err := client.ListApiKeys(ctx, request)
|
||||||
|
if err != nil {
|
||||||
|
ErrorOutput(
|
||||||
|
err,
|
||||||
|
fmt.Sprintf("Error getting the list of keys: %s", err),
|
||||||
|
output,
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if output != "" {
|
||||||
|
SuccessOutput(response.ApiKeys, "", output)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tableData := pterm.TableData{
|
||||||
|
{"ID", "Prefix", "Expiration", "Created"},
|
||||||
|
}
|
||||||
|
for _, key := range response.ApiKeys {
|
||||||
|
expiration := "-"
|
||||||
|
|
||||||
|
if key.GetExpiration() != nil {
|
||||||
|
expiration = ColourTime(key.Expiration.AsTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
tableData = append(tableData, []string{
|
||||||
|
strconv.FormatUint(key.GetId(), headscale.Base10),
|
||||||
|
key.GetPrefix(),
|
||||||
|
expiration,
|
||||||
|
key.GetCreatedAt().AsTime().Format(HeadscaleDateTimeFormat),
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
err = pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
|
||||||
|
if err != nil {
|
||||||
|
ErrorOutput(
|
||||||
|
err,
|
||||||
|
fmt.Sprintf("Failed to render pterm table: %s", err),
|
||||||
|
output,
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var createAPIKeyCmd = &cobra.Command{
|
||||||
|
Use: "create",
|
||||||
|
Short: "Creates a new Api key",
|
||||||
|
Long: `
|
||||||
|
Creates a new Api key, the Api key is only visible on creation
|
||||||
|
and cannot be retrieved again.
|
||||||
|
If you loose a key, create a new one and revoke (expire) the old one.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
output, _ := cmd.Flags().GetString("output")
|
||||||
|
|
||||||
|
log.Trace().
|
||||||
|
Msg("Preparing to create ApiKey")
|
||||||
|
|
||||||
|
request := &v1.CreateApiKeyRequest{}
|
||||||
|
|
||||||
|
duration, _ := cmd.Flags().GetDuration("expiration")
|
||||||
|
expiration := time.Now().UTC().Add(duration)
|
||||||
|
|
||||||
|
log.Trace().Dur("expiration", duration).Msg("expiration has been set")
|
||||||
|
|
||||||
|
request.Expiration = timestamppb.New(expiration)
|
||||||
|
|
||||||
|
ctx, client, conn, cancel := getHeadscaleCLIClient()
|
||||||
|
defer cancel()
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
response, err := client.CreateApiKey(ctx, request)
|
||||||
|
if err != nil {
|
||||||
|
ErrorOutput(
|
||||||
|
err,
|
||||||
|
fmt.Sprintf("Cannot create Api Key: %s\n", err),
|
||||||
|
output,
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
SuccessOutput(response.ApiKey, response.ApiKey, output)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var expireAPIKeyCmd = &cobra.Command{
|
||||||
|
Use: "expire",
|
||||||
|
Short: "Expire an ApiKey",
|
||||||
|
Aliases: []string{"revoke"},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
output, _ := cmd.Flags().GetString("output")
|
||||||
|
|
||||||
|
prefix, err := cmd.Flags().GetString("prefix")
|
||||||
|
if err != nil {
|
||||||
|
ErrorOutput(
|
||||||
|
err,
|
||||||
|
fmt.Sprintf("Error getting prefix from CLI flag: %s", err),
|
||||||
|
output,
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, client, conn, cancel := getHeadscaleCLIClient()
|
||||||
|
defer cancel()
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
request := &v1.ExpireApiKeyRequest{
|
||||||
|
Prefix: prefix,
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := client.ExpireApiKey(ctx, request)
|
||||||
|
if err != nil {
|
||||||
|
ErrorOutput(
|
||||||
|
err,
|
||||||
|
fmt.Sprintf("Cannot expire Api Key: %s\n", err),
|
||||||
|
output,
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
SuccessOutput(response, "Key expired", output)
|
||||||
|
},
|
||||||
|
}
|
@ -83,7 +83,7 @@ var listPreAuthKeys = &cobra.Command{
|
|||||||
for _, key := range response.PreAuthKeys {
|
for _, key := range response.PreAuthKeys {
|
||||||
expiration := "-"
|
expiration := "-"
|
||||||
if key.GetExpiration() != nil {
|
if key.GetExpiration() != nil {
|
||||||
expiration = key.Expiration.AsTime().Format("2006-01-02 15:04:05")
|
expiration = ColourTime(key.Expiration.AsTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
var reusable string
|
var reusable string
|
||||||
|
19
cmd/headscale/cli/pterm_style.go
Normal file
19
cmd/headscale/cli/pterm_style.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pterm/pterm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ColourTime(date time.Time) string {
|
||||||
|
dateStr := date.Format("2006-01-02 15:04:05")
|
||||||
|
|
||||||
|
if date.After(time.Now()) {
|
||||||
|
dateStr = pterm.LightGreen(dateStr)
|
||||||
|
} else {
|
||||||
|
dateStr = pterm.LightRed(dateStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dateStr
|
||||||
|
}
|
@ -2,6 +2,7 @@ package cli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -19,6 +20,8 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/credentials"
|
||||||
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
@ -27,6 +30,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
PermissionFallback = 0o700
|
PermissionFallback = 0o700
|
||||||
|
HeadscaleDateTimeFormat = "2006-01-02 15:04:05"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadConfig(path string) error {
|
func LoadConfig(path string) error {
|
||||||
@ -54,8 +58,11 @@ func LoadConfig(path string) error {
|
|||||||
viper.SetDefault("unix_socket", "/var/run/headscale.sock")
|
viper.SetDefault("unix_socket", "/var/run/headscale.sock")
|
||||||
viper.SetDefault("unix_socket_permission", "0o770")
|
viper.SetDefault("unix_socket_permission", "0o770")
|
||||||
|
|
||||||
viper.SetDefault("cli.insecure", false)
|
viper.SetDefault("grpc_listen_addr", ":50443")
|
||||||
|
viper.SetDefault("grpc_allow_insecure", false)
|
||||||
|
|
||||||
viper.SetDefault("cli.timeout", "5s")
|
viper.SetDefault("cli.timeout", "5s")
|
||||||
|
viper.SetDefault("cli.insecure", false)
|
||||||
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
return fmt.Errorf("fatal error reading config file: %w", err)
|
return fmt.Errorf("fatal error reading config file: %w", err)
|
||||||
@ -270,12 +277,16 @@ func getHeadscaleConfig() headscale.Config {
|
|||||||
|
|
||||||
if len(prefixes) < 1 {
|
if len(prefixes) < 1 {
|
||||||
prefixes = append(prefixes, netaddr.MustParseIPPrefix("100.64.0.0/10"))
|
prefixes = append(prefixes, netaddr.MustParseIPPrefix("100.64.0.0/10"))
|
||||||
log.Warn().Msgf("'ip_prefixes' not configured, falling back to default: %v", prefixes)
|
log.Warn().
|
||||||
|
Msgf("'ip_prefixes' not configured, falling back to default: %v", prefixes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return headscale.Config{
|
return headscale.Config{
|
||||||
ServerURL: viper.GetString("server_url"),
|
ServerURL: viper.GetString("server_url"),
|
||||||
Addr: viper.GetString("listen_addr"),
|
Addr: viper.GetString("listen_addr"),
|
||||||
|
GRPCAddr: viper.GetString("grpc_listen_addr"),
|
||||||
|
GRPCAllowInsecure: viper.GetBool("grpc_allow_insecure"),
|
||||||
|
|
||||||
IPPrefixes: prefixes,
|
IPPrefixes: prefixes,
|
||||||
PrivateKeyPath: absPath(viper.GetString("private_key_path")),
|
PrivateKeyPath: absPath(viper.GetString("private_key_path")),
|
||||||
BaseDomain: baseDomain,
|
BaseDomain: baseDomain,
|
||||||
@ -321,8 +332,8 @@ func getHeadscaleConfig() headscale.Config {
|
|||||||
CLI: headscale.CLIConfig{
|
CLI: headscale.CLIConfig{
|
||||||
Address: viper.GetString("cli.address"),
|
Address: viper.GetString("cli.address"),
|
||||||
APIKey: viper.GetString("cli.api_key"),
|
APIKey: viper.GetString("cli.api_key"),
|
||||||
Insecure: viper.GetBool("cli.insecure"),
|
|
||||||
Timeout: viper.GetDuration("cli.timeout"),
|
Timeout: viper.GetDuration("cli.timeout"),
|
||||||
|
Insecure: viper.GetBool("cli.insecure"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,14 +404,14 @@ func getHeadscaleCLIClient() (context.Context, v1.HeadscaleServiceClient, *grpc.
|
|||||||
|
|
||||||
grpcOptions = append(
|
grpcOptions = append(
|
||||||
grpcOptions,
|
grpcOptions,
|
||||||
grpc.WithInsecure(),
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
grpc.WithContextDialer(headscale.GrpcSocketDialer),
|
grpc.WithContextDialer(headscale.GrpcSocketDialer),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// If we are not connecting to a local server, require an API key for authentication
|
// If we are not connecting to a local server, require an API key for authentication
|
||||||
apiKey := cfg.CLI.APIKey
|
apiKey := cfg.CLI.APIKey
|
||||||
if apiKey == "" {
|
if apiKey == "" {
|
||||||
log.Fatal().Msgf("HEADSCALE_CLI_API_KEY environment variable needs to be set.")
|
log.Fatal().Caller().Msgf("HEADSCALE_CLI_API_KEY environment variable needs to be set.")
|
||||||
}
|
}
|
||||||
grpcOptions = append(grpcOptions,
|
grpcOptions = append(grpcOptions,
|
||||||
grpc.WithPerRPCCredentials(tokenAuth{
|
grpc.WithPerRPCCredentials(tokenAuth{
|
||||||
@ -409,14 +420,27 @@ func getHeadscaleCLIClient() (context.Context, v1.HeadscaleServiceClient, *grpc.
|
|||||||
)
|
)
|
||||||
|
|
||||||
if cfg.CLI.Insecure {
|
if cfg.CLI.Insecure {
|
||||||
grpcOptions = append(grpcOptions, grpc.WithInsecure())
|
tlsConfig := &tls.Config{
|
||||||
|
// turn of gosec as we are intentionally setting
|
||||||
|
// insecure.
|
||||||
|
//nolint:gosec
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
grpcOptions = append(grpcOptions,
|
||||||
|
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
grpcOptions = append(grpcOptions,
|
||||||
|
grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace().Caller().Str("address", address).Msg("Connecting via gRPC")
|
log.Trace().Caller().Str("address", address).Msg("Connecting via gRPC")
|
||||||
conn, err := grpc.DialContext(ctx, address, grpcOptions...)
|
conn, err := grpc.DialContext(ctx, address, grpcOptions...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msgf("Could not connect: %v", err)
|
log.Fatal().Caller().Err(err).Msgf("Could not connect: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := v1.NewHeadscaleServiceClient(conn)
|
client := v1.NewHeadscaleServiceClient(conn)
|
||||||
@ -425,21 +449,21 @@ func getHeadscaleCLIClient() (context.Context, v1.HeadscaleServiceClient, *grpc.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SuccessOutput(result interface{}, override string, outputFormat string) {
|
func SuccessOutput(result interface{}, override string, outputFormat string) {
|
||||||
var j []byte
|
var jsonBytes []byte
|
||||||
var err error
|
var err error
|
||||||
switch outputFormat {
|
switch outputFormat {
|
||||||
case "json":
|
case "json":
|
||||||
j, err = json.MarshalIndent(result, "", "\t")
|
jsonBytes, err = json.MarshalIndent(result, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err)
|
log.Fatal().Err(err)
|
||||||
}
|
}
|
||||||
case "json-line":
|
case "json-line":
|
||||||
j, err = json.Marshal(result)
|
jsonBytes, err = json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err)
|
log.Fatal().Err(err)
|
||||||
}
|
}
|
||||||
case "yaml":
|
case "yaml":
|
||||||
j, err = yaml.Marshal(result)
|
jsonBytes, err = yaml.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err)
|
log.Fatal().Err(err)
|
||||||
}
|
}
|
||||||
@ -451,7 +475,7 @@ func SuccessOutput(result interface{}, override string, outputFormat string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nolint
|
//nolint
|
||||||
fmt.Println(string(j))
|
fmt.Println(string(jsonBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrorOutput(errResult error, override string, outputFormat string) {
|
func ErrorOutput(errResult error, override string, outputFormat string) {
|
||||||
|
@ -44,7 +44,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err := cli.LoadConfig(""); err != nil {
|
if err := cli.LoadConfig(""); err != nil {
|
||||||
log.Fatal().Err(err)
|
log.Fatal().Caller().Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
machineOutput := cli.HasMachineOutputFlag()
|
machineOutput := cli.HasMachineOutputFlag()
|
||||||
|
@ -61,7 +61,11 @@ func (*Suite) TestConfigLoading(c *check.C) {
|
|||||||
c.Assert(viper.GetString("tls_letsencrypt_listen"), check.Equals, ":http")
|
c.Assert(viper.GetString("tls_letsencrypt_listen"), check.Equals, ":http")
|
||||||
c.Assert(viper.GetString("tls_letsencrypt_challenge_type"), check.Equals, "HTTP-01")
|
c.Assert(viper.GetString("tls_letsencrypt_challenge_type"), check.Equals, "HTTP-01")
|
||||||
c.Assert(viper.GetStringSlice("dns_config.nameservers")[0], check.Equals, "1.1.1.1")
|
c.Assert(viper.GetStringSlice("dns_config.nameservers")[0], check.Equals, "1.1.1.1")
|
||||||
c.Assert(cli.GetFileMode("unix_socket_permission"), check.Equals, fs.FileMode(0o770))
|
c.Assert(
|
||||||
|
cli.GetFileMode("unix_socket_permission"),
|
||||||
|
check.Equals,
|
||||||
|
fs.FileMode(0o770),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Suite) TestDNSConfigLoading(c *check.C) {
|
func (*Suite) TestDNSConfigLoading(c *check.C) {
|
||||||
|
@ -16,6 +16,19 @@ server_url: http://127.0.0.1:8080
|
|||||||
#
|
#
|
||||||
listen_addr: 0.0.0.0:8080
|
listen_addr: 0.0.0.0:8080
|
||||||
|
|
||||||
|
# Address to listen for gRPC.
|
||||||
|
# gRPC is used for controlling a headscale server
|
||||||
|
# remotely with the CLI
|
||||||
|
# Note: Remote access _only_ works if you have
|
||||||
|
# valid certificates.
|
||||||
|
grpc_listen_addr: 0.0.0.0:50443
|
||||||
|
|
||||||
|
# Allow the gRPC admin interface to run in INSECURE
|
||||||
|
# mode. This is not recommended as the traffic will
|
||||||
|
# be unencrypted. Only enable if you know what you
|
||||||
|
# are doing.
|
||||||
|
grpc_allow_insecure: false
|
||||||
|
|
||||||
# Private key used encrypt the traffic between headscale
|
# Private key used encrypt the traffic between headscale
|
||||||
# and Tailscale clients.
|
# and Tailscale clients.
|
||||||
# The private key file which will be
|
# The private key file which will be
|
||||||
|
5
db.go
5
db.go
@ -58,6 +58,11 @@ func (h *Headscale) initDB() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = db.AutoMigrate(&APIKey{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
err = h.setValue("db_version", dbVersion)
|
err = h.setValue("db_version", dbVersion)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
11
dns.go
11
dns.go
@ -51,7 +51,12 @@ func generateMagicDNSRootDomains(ipPrefixes []netaddr.IPPrefix) []dnsname.FQDN {
|
|||||||
generateDNSRoot = generateIPv6DNSRootDomain
|
generateDNSRoot = generateIPv6DNSRootDomain
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unsupported IP version with address length %d", ipPrefix.IP().BitLen()))
|
panic(
|
||||||
|
fmt.Sprintf(
|
||||||
|
"unsupported IP version with address length %d",
|
||||||
|
ipPrefix.IP().BitLen(),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fqdns = append(fqdns, generateDNSRoot(ipPrefix)...)
|
fqdns = append(fqdns, generateDNSRoot(ipPrefix)...)
|
||||||
@ -115,7 +120,9 @@ func generateIPv6DNSRootDomain(ipPrefix netaddr.IPPrefix) []dnsname.FQDN {
|
|||||||
// function is called only once over the lifetime of a server process.
|
// function is called only once over the lifetime of a server process.
|
||||||
prefixConstantParts := []string{}
|
prefixConstantParts := []string{}
|
||||||
for i := 0; i < maskBits/nibbleLen; i++ {
|
for i := 0; i < maskBits/nibbleLen; i++ {
|
||||||
prefixConstantParts = append([]string{string(nibbleStr[i])}, prefixConstantParts...)
|
prefixConstantParts = append(
|
||||||
|
[]string{string(nibbleStr[i])},
|
||||||
|
prefixConstantParts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
makeDomain := func(variablePrefix ...string) (dnsname.FQDN, error) {
|
makeDomain := func(variablePrefix ...string) (dnsname.FQDN, error) {
|
||||||
|
@ -81,7 +81,11 @@ func (s *Suite) TestMagicDNSRootDomainsIPv6Single(c *check.C) {
|
|||||||
domains := generateMagicDNSRootDomains(prefixes)
|
domains := generateMagicDNSRootDomains(prefixes)
|
||||||
|
|
||||||
c.Assert(len(domains), check.Equals, 1)
|
c.Assert(len(domains), check.Equals, 1)
|
||||||
c.Assert(domains[0].WithTrailingDot(), check.Equals, "0.e.1.a.c.5.1.1.a.7.d.f.ip6.arpa.")
|
c.Assert(
|
||||||
|
domains[0].WithTrailingDot(),
|
||||||
|
check.Equals,
|
||||||
|
"0.e.1.a.c.5.1.1.a.7.d.f.ip6.arpa.",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestMagicDNSRootDomainsIPv6SingleMultiple(c *check.C) {
|
func (s *Suite) TestMagicDNSRootDomainsIPv6SingleMultiple(c *check.C) {
|
||||||
|
@ -10,6 +10,7 @@ please ask on [Discord](https://discord.gg/XcQxk2VHjx) instead of opening an Iss
|
|||||||
### How-to
|
### How-to
|
||||||
|
|
||||||
- [Running headscale on Linux](running-headscale-linux.md)
|
- [Running headscale on Linux](running-headscale-linux.md)
|
||||||
|
- [Control headscale remotly](remote-cli.md)
|
||||||
- [Using a Windows client with headscale](windows-client.md)
|
- [Using a Windows client with headscale](windows-client.md)
|
||||||
|
|
||||||
### References
|
### References
|
||||||
|
100
docs/remote-cli.md
Normal file
100
docs/remote-cli.md
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
# Controlling `headscale` with remote CLI
|
||||||
|
|
||||||
|
## Prerequisit
|
||||||
|
|
||||||
|
- A workstation to run `headscale` (could be Linux, macOS, other supported platforms)
|
||||||
|
- A `headscale` server (version `0.13.0` or newer)
|
||||||
|
- Access to create API keys (local access to the `headscale` server)
|
||||||
|
- `headscale` _must_ be served over TLS/HTTPS
|
||||||
|
- Remote access does _not_ support unencrypted traffic.
|
||||||
|
- Port `50443` must be open in the firewall (or port overriden by `grpc_listen_addr` option)
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
This documentation has the goal of showing a user how-to set control a `headscale` instance
|
||||||
|
from a remote machine with the `headscale` command line binary.
|
||||||
|
|
||||||
|
## Create an API key
|
||||||
|
|
||||||
|
We need to create an API key to authenticate our remote `headscale` when using it from our workstation.
|
||||||
|
|
||||||
|
To create a API key, log into your `headscale` server and generate a key:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
headscale apikeys create --expiration 90d
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the output of the command and save it for later. Please not that you can not retrieve a key again,
|
||||||
|
if the key is lost, expire the old one, and create a new key.
|
||||||
|
|
||||||
|
To list the keys currently assosicated with the server:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
headscale apikeys list
|
||||||
|
```
|
||||||
|
|
||||||
|
and to expire a key:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
headscale apikeys expire --prefix "<PREFIX>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Download and configure `headscale`
|
||||||
|
|
||||||
|
1. Download the latest [`headscale` binary from GitHub's release page](https://github.com/juanfont/headscale/releases):
|
||||||
|
|
||||||
|
2. Put the binary somewhere in your `PATH`, e.g. `/usr/local/bin/headcale`
|
||||||
|
|
||||||
|
3. Make `headscale` executable:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
chmod +x /usr/local/bin/headscale
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Configure the CLI through Environment Variables
|
||||||
|
|
||||||
|
```shell
|
||||||
|
export HEADSCALE_CLI_ADDRESS="<HEADSCALE ADDRESS>:<PORT>"
|
||||||
|
export HEADSCALE_CLI_API_KEY="<API KEY FROM PREVIOUS STAGE>"
|
||||||
|
```
|
||||||
|
|
||||||
|
for example:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
export HEADSCALE_CLI_ADDRESS="headscale.example.com:50443"
|
||||||
|
export HEADSCALE_CLI_API_KEY="abcde12345"
|
||||||
|
```
|
||||||
|
|
||||||
|
This will tell the `headscale` binary to connect to a remote instance, instead of looking
|
||||||
|
for a local instance (which is what it does on the server).
|
||||||
|
|
||||||
|
The API key is needed to make sure that your are allowed to access the server. The key is _not_
|
||||||
|
needed when running directly on the server, as the connection is local.
|
||||||
|
|
||||||
|
5. Test the connection
|
||||||
|
|
||||||
|
Let us run the headscale command to verify that we can connect by listing our nodes:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
headscale nodes list
|
||||||
|
```
|
||||||
|
|
||||||
|
You should now be able to see a list of your nodes from your workstation, and you can
|
||||||
|
now control the `headscale` server from your workstation.
|
||||||
|
|
||||||
|
## Behind a proxy
|
||||||
|
|
||||||
|
It is possible to run the gRPC remote endpoint behind a reverse proxy, like Nginx, and have it run on the _same_ port as `headscale`.
|
||||||
|
|
||||||
|
While this is _not a supported_ feature, an example on how this can be set up on
|
||||||
|
[NixOS is shown here](https://github.com/kradalby/dotfiles/blob/4489cdbb19cddfbfae82cd70448a38fde5a76711/machines/headscale.oracldn/headscale.nix#L61-L91).
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
Checklist:
|
||||||
|
|
||||||
|
- Make sure you have the _same_ `headscale` version on your server and workstation
|
||||||
|
- Make sure you use version `0.13.0` or newer.
|
||||||
|
- Verify that your TLS certificate is valid and trusted
|
||||||
|
- If you do not have access to a trusted certificate (e.g. from Let's Encrypt), add your self signed certificate to the trust store of your OS or
|
||||||
|
- Set `HEADSCALE_CLI_INSECURE` to 0 in your environement
|
559
gen/go/headscale/v1/apikey.pb.go
Normal file
559
gen/go/headscale/v1/apikey.pb.go
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.27.1
|
||||||
|
// protoc (unknown)
|
||||||
|
// source: headscale/v1/apikey.proto
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type ApiKey struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
|
Prefix string `protobuf:"bytes,2,opt,name=prefix,proto3" json:"prefix,omitempty"`
|
||||||
|
Expiration *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=expiration,proto3" json:"expiration,omitempty"`
|
||||||
|
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
|
||||||
|
LastSeen *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ApiKey) Reset() {
|
||||||
|
*x = ApiKey{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ApiKey) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ApiKey) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ApiKey) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[0]
|
||||||
|
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 ApiKey.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ApiKey) Descriptor() ([]byte, []int) {
|
||||||
|
return file_headscale_v1_apikey_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ApiKey) GetId() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Id
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ApiKey) GetPrefix() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Prefix
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ApiKey) GetExpiration() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.Expiration
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ApiKey) GetCreatedAt() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.CreatedAt
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ApiKey) GetLastSeen() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.LastSeen
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateApiKeyRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Expiration *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=expiration,proto3" json:"expiration,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CreateApiKeyRequest) Reset() {
|
||||||
|
*x = CreateApiKeyRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CreateApiKeyRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CreateApiKeyRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *CreateApiKeyRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[1]
|
||||||
|
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 CreateApiKeyRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*CreateApiKeyRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_headscale_v1_apikey_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CreateApiKeyRequest) GetExpiration() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.Expiration
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateApiKeyResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
ApiKey string `protobuf:"bytes,1,opt,name=api_key,json=apiKey,proto3" json:"api_key,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CreateApiKeyResponse) Reset() {
|
||||||
|
*x = CreateApiKeyResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CreateApiKeyResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CreateApiKeyResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *CreateApiKeyResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[2]
|
||||||
|
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 CreateApiKeyResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*CreateApiKeyResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_headscale_v1_apikey_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CreateApiKeyResponse) GetApiKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ApiKey
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExpireApiKeyRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ExpireApiKeyRequest) Reset() {
|
||||||
|
*x = ExpireApiKeyRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ExpireApiKeyRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ExpireApiKeyRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ExpireApiKeyRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[3]
|
||||||
|
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 ExpireApiKeyRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ExpireApiKeyRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_headscale_v1_apikey_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ExpireApiKeyRequest) GetPrefix() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Prefix
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExpireApiKeyResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ExpireApiKeyResponse) Reset() {
|
||||||
|
*x = ExpireApiKeyResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ExpireApiKeyResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ExpireApiKeyResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ExpireApiKeyResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[4]
|
||||||
|
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 ExpireApiKeyResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ExpireApiKeyResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_headscale_v1_apikey_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListApiKeysRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListApiKeysRequest) Reset() {
|
||||||
|
*x = ListApiKeysRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListApiKeysRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListApiKeysRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListApiKeysRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[5]
|
||||||
|
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 ListApiKeysRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListApiKeysRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_headscale_v1_apikey_proto_rawDescGZIP(), []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListApiKeysResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
ApiKeys []*ApiKey `protobuf:"bytes,1,rep,name=api_keys,json=apiKeys,proto3" json:"api_keys,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListApiKeysResponse) Reset() {
|
||||||
|
*x = ListApiKeysResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[6]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListApiKeysResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListApiKeysResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListApiKeysResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_headscale_v1_apikey_proto_msgTypes[6]
|
||||||
|
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 ListApiKeysResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListApiKeysResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_headscale_v1_apikey_proto_rawDescGZIP(), []int{6}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListApiKeysResponse) GetApiKeys() []*ApiKey {
|
||||||
|
if x != nil {
|
||||||
|
return x.ApiKeys
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_headscale_v1_apikey_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_headscale_v1_apikey_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x19, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61,
|
||||||
|
0x70, 0x69, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x68, 0x65, 0x61,
|
||||||
|
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||||
|
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73,
|
||||||
|
0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe0, 0x01, 0x0a, 0x06, 0x41,
|
||||||
|
0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18,
|
||||||
|
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x3a, 0x0a,
|
||||||
|
0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
|
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65,
|
||||||
|
0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65,
|
||||||
|
0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
|
||||||
|
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||||
|
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74,
|
||||||
|
0x65, 0x64, 0x41, 0x74, 0x12, 0x37, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65,
|
||||||
|
0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||||
|
0x61, 0x6d, 0x70, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x22, 0x51, 0x0a,
|
||||||
|
0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71,
|
||||||
|
0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69,
|
||||||
|
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||||
|
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
|
||||||
|
0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x22, 0x2f, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79,
|
||||||
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x70, 0x69, 0x5f,
|
||||||
|
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x70, 0x69, 0x4b, 0x65,
|
||||||
|
0x79, 0x22, 0x2d, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65,
|
||||||
|
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66,
|
||||||
|
0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
|
||||||
|
0x22, 0x16, 0x0a, 0x14, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79,
|
||||||
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74,
|
||||||
|
0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x46,
|
||||||
|
0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73,
|
||||||
|
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x6b, 0x65, 0x79,
|
||||||
|
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
|
||||||
|
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x07, 0x61,
|
||||||
|
0x70, 0x69, 0x4b, 0x65, 0x79, 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_apikey_proto_rawDescOnce sync.Once
|
||||||
|
file_headscale_v1_apikey_proto_rawDescData = file_headscale_v1_apikey_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_headscale_v1_apikey_proto_rawDescGZIP() []byte {
|
||||||
|
file_headscale_v1_apikey_proto_rawDescOnce.Do(func() {
|
||||||
|
file_headscale_v1_apikey_proto_rawDescData = protoimpl.X.CompressGZIP(file_headscale_v1_apikey_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_headscale_v1_apikey_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_headscale_v1_apikey_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||||
|
var file_headscale_v1_apikey_proto_goTypes = []interface{}{
|
||||||
|
(*ApiKey)(nil), // 0: headscale.v1.ApiKey
|
||||||
|
(*CreateApiKeyRequest)(nil), // 1: headscale.v1.CreateApiKeyRequest
|
||||||
|
(*CreateApiKeyResponse)(nil), // 2: headscale.v1.CreateApiKeyResponse
|
||||||
|
(*ExpireApiKeyRequest)(nil), // 3: headscale.v1.ExpireApiKeyRequest
|
||||||
|
(*ExpireApiKeyResponse)(nil), // 4: headscale.v1.ExpireApiKeyResponse
|
||||||
|
(*ListApiKeysRequest)(nil), // 5: headscale.v1.ListApiKeysRequest
|
||||||
|
(*ListApiKeysResponse)(nil), // 6: headscale.v1.ListApiKeysResponse
|
||||||
|
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
|
||||||
|
}
|
||||||
|
var file_headscale_v1_apikey_proto_depIdxs = []int32{
|
||||||
|
7, // 0: headscale.v1.ApiKey.expiration:type_name -> google.protobuf.Timestamp
|
||||||
|
7, // 1: headscale.v1.ApiKey.created_at:type_name -> google.protobuf.Timestamp
|
||||||
|
7, // 2: headscale.v1.ApiKey.last_seen:type_name -> google.protobuf.Timestamp
|
||||||
|
7, // 3: headscale.v1.CreateApiKeyRequest.expiration:type_name -> google.protobuf.Timestamp
|
||||||
|
0, // 4: headscale.v1.ListApiKeysResponse.api_keys:type_name -> headscale.v1.ApiKey
|
||||||
|
5, // [5:5] is the sub-list for method output_type
|
||||||
|
5, // [5:5] is the sub-list for method input_type
|
||||||
|
5, // [5:5] is the sub-list for extension type_name
|
||||||
|
5, // [5:5] is the sub-list for extension extendee
|
||||||
|
0, // [0:5] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_headscale_v1_apikey_proto_init() }
|
||||||
|
func file_headscale_v1_apikey_proto_init() {
|
||||||
|
if File_headscale_v1_apikey_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_headscale_v1_apikey_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ApiKey); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_headscale_v1_apikey_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*CreateApiKeyRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_headscale_v1_apikey_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*CreateApiKeyResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_headscale_v1_apikey_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ExpireApiKeyRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_headscale_v1_apikey_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ExpireApiKeyResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_headscale_v1_apikey_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListApiKeysRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_headscale_v1_apikey_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListApiKeysResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_headscale_v1_apikey_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 7,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_headscale_v1_apikey_proto_goTypes,
|
||||||
|
DependencyIndexes: file_headscale_v1_apikey_proto_depIdxs,
|
||||||
|
MessageInfos: file_headscale_v1_apikey_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_headscale_v1_apikey_proto = out.File
|
||||||
|
file_headscale_v1_apikey_proto_rawDesc = nil
|
||||||
|
file_headscale_v1_apikey_proto_goTypes = nil
|
||||||
|
file_headscale_v1_apikey_proto_depIdxs = nil
|
||||||
|
}
|
@ -1,17 +1,18 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.17.3
|
// protoc (unknown)
|
||||||
// source: headscale/v1/device.proto
|
// source: headscale/v1/device.proto
|
||||||
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.17.3
|
// protoc (unknown)
|
||||||
// source: headscale/v1/headscale.proto
|
// source: headscale/v1/headscale.proto
|
||||||
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -34,162 +35,185 @@ 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, 0xf4,
|
0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19,
|
||||||
0x12, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76,
|
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69,
|
||||||
0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
|
0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xcb, 0x15, 0x0a, 0x10, 0x48, 0x65,
|
||||||
0x61, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
|
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x77,
|
||||||
0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52,
|
0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
|
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
|
||||||
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93,
|
0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
|
||||||
0x02, 0x1a, 0x12, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65,
|
0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73,
|
||||||
0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x7c, 0x0a, 0x0f,
|
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f,
|
||||||
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
|
0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||||
0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43,
|
0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x7c, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65,
|
0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
|
|
||||||
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73,
|
|
||||||
0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3,
|
|
||||||
0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61,
|
|
||||||
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x96, 0x01, 0x0a, 0x0f, 0x52,
|
|
||||||
0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x24,
|
|
||||||
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
|
|
||||||
0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71,
|
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
|
|
||||||
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
|
|
||||||
0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4,
|
|
||||||
0x93, 0x02, 0x30, 0x22, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d,
|
|
||||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x7b, 0x6f, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
|
|
||||||
0x7d, 0x2f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x7b, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61,
|
|
||||||
0x6d, 0x65, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61,
|
|
||||||
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
|
|
||||||
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d,
|
|
||||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e,
|
|
||||||
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c,
|
|
||||||
0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70,
|
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, 0x61,
|
|
||||||
0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f,
|
|
||||||
0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x76, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61,
|
|
||||||
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
|
|
||||||
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65,
|
|
||||||
0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e,
|
|
||||||
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
|
|
||||||
0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
|
||||||
0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x61, 0x70,
|
|
||||||
0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x80,
|
|
||||||
0x01, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68,
|
|
||||||
0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
|
|
||||||
0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68,
|
|
||||||
0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, 0x61,
|
|
||||||
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||||
0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x61, 0x70, 0x69,
|
0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
|
||||||
0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x3a, 0x01,
|
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52,
|
||||||
0x2a, 0x12, 0x87, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22,
|
||||||
0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
|
0x11, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||||
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41,
|
0x63, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x96, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65,
|
||||||
0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e,
|
0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64,
|
||||||
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70,
|
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e,
|
||||||
0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73,
|
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x19, 0x2f,
|
0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52,
|
||||||
0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65,
|
0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65,
|
||||||
0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x7a, 0x0a, 0x0f, 0x4c,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e,
|
||||||
0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x24,
|
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
|
||||||
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
|
0x65, 0x2f, 0x7b, 0x6f, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x72, 0x65, 0x6e,
|
||||||
0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71,
|
0x61, 0x6d, 0x65, 0x2f, 0x7b, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x80,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
|
0x01, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||||
0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b,
|
0x63, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
|
||||||
0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4,
|
0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
|
||||||
0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65,
|
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
|
||||||
0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x12, 0x89, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x62, 0x75,
|
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61,
|
||||||
0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x27,
|
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65,
|
0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31,
|
||||||
0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
|
0x7d, 0x12, 0x76, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||||
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61,
|
0x63, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
|
||||||
0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||||
0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f,
|
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
|
||||||
0x76, 0x31, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65,
|
||||||
0x3a, 0x01, 0x2a, 0x12, 0x75, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
|
0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19,
|
||||||
0x65, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
|
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f,
|
||||||
0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x10, 0x43, 0x72,
|
||||||
0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
|
0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25,
|
||||||
0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70,
|
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72,
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61,
|
0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65,
|
||||||
0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
|
||||||
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x52,
|
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75,
|
||||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x24,
|
0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82,
|
||||||
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
|
0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70,
|
||||||
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71,
|
0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x3a, 0x01, 0x2a, 0x12, 0x87, 0x01, 0x0a,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
|
0x10, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65,
|
||||||
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68,
|
0x79, 0x12, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
|
||||||
0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4,
|
0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65,
|
||||||
0x93, 0x02, 0x1a, 0x22, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63,
|
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
|
||||||
0x68, 0x69, 0x6e, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x7e, 0x0a,
|
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72,
|
||||||
0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x22,
|
0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65,
|
0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76,
|
||||||
0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70,
|
||||||
0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
|
0x69, 0x72, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x7a, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72,
|
||||||
0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52,
|
0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x2a,
|
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65,
|
||||||
0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01,
|
0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
|
||||||
0x0a, 0x0d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
|
0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65,
|
||||||
0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12,
|
||||||
0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75,
|
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
|
0x65, 0x79, 0x12, 0x89, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61,
|
||||||
0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x27, 0x2e, 0x68, 0x65, 0x61, 0x64,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25,
|
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72,
|
||||||
0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
|
0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x65,
|
0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
|
||||||
0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x6e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63,
|
0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63,
|
||||||
0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
|
0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3,
|
||||||
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0xe4, 0x93, 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65,
|
||||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
|
0x62, 0x75, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x75,
|
||||||
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68,
|
0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x1f, 0x2e, 0x68,
|
||||||
0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3,
|
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d,
|
||||||
0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61,
|
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e,
|
||||||
0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d,
|
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
|
||||||
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
|
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
|
0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31,
|
||||||
0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64,
|
0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
|
||||||
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61,
|
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||||
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82,
|
0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64,
|
||||||
0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d,
|
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
||||||
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f,
|
0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
0x69, 0x64, 0x7d, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73,
|
0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52,
|
||||||
0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x95, 0x01, 0x0a, 0x0e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72,
|
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65,
|
||||||
0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x18,
|
||||||
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d,
|
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f,
|
||||||
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e,
|
0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x7e, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65,
|
||||||
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73,
|
0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64,
|
||||||
0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d,
|
||||||
0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x22, 0x30, 0x2f, 0x61, 0x70,
|
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e,
|
||||||
|
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c,
|
||||||
|
0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
|
0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x2a, 0x1c, 0x2f, 0x61, 0x70, 0x69,
|
||||||
|
0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63,
|
||||||
|
0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0d, 0x45, 0x78, 0x70,
|
||||||
|
0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x22, 0x2e, 0x68, 0x65, 0x61,
|
||||||
|
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65,
|
||||||
|
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23,
|
||||||
|
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78,
|
||||||
|
0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
|
0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x22, 0x23, 0x2f, 0x61, 0x70,
|
||||||
0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61,
|
0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61,
|
||||||
0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x75, 0x6e, 0x73, 0x68, 0x61, 0x72,
|
0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65,
|
||||||
0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x8b, 0x01,
|
0x12, 0x6e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73,
|
||||||
0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74,
|
0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
|
||||||
0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
|
0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||||
0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
|
0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52,
|
||||||
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12,
|
||||||
0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b,
|
0x0f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
||||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f,
|
0x12, 0x8d, 0x01, 0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
|
||||||
|
0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
|
||||||
|
0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71,
|
||||||
|
0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
|
||||||
|
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
||||||
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30,
|
||||||
|
0x22, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
|
||||||
|
0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73,
|
||||||
|
0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d,
|
||||||
|
0x12, 0x95, 0x01, 0x0a, 0x0e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68,
|
||||||
|
0x69, 0x6e, 0x65, 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
|
||||||
|
0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
|
||||||
|
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
|
||||||
|
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d,
|
||||||
|
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38,
|
||||||
|
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x22, 0x30, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f,
|
||||||
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
||||||
0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13,
|
0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x75, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x6e, 0x61,
|
||||||
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75,
|
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x8b, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74,
|
||||||
0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
|
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x68,
|
||||||
0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d,
|
||||||
0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e,
|
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61,
|
0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
|
||||||
0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73,
|
0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25,
|
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||||
0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
|
0x25, 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69,
|
||||||
0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72,
|
0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
|
||||||
0x6f, 0x75, 0x74, 0x65, 0x73, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c,
|
||||||
0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61,
|
0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28,
|
||||||
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31,
|
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e,
|
||||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
||||||
|
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
|
||||||
|
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61,
|
||||||
|
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
|
0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x22, 0x23, 0x2f, 0x61, 0x70,
|
||||||
|
0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61,
|
||||||
|
0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73,
|
||||||
|
0x12, 0x70, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79,
|
||||||
|
0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
|
||||||
|
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75,
|
||||||
|
0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
|
||||||
|
0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52,
|
||||||
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x22,
|
||||||
|
0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x3a,
|
||||||
|
0x01, 0x2a, 0x12, 0x77, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b,
|
||||||
|
0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
|
||||||
|
0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65,
|
||||||
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
|
||||||
|
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65,
|
||||||
|
0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||||
|
0x1a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65,
|
||||||
|
0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0b, 0x4c,
|
||||||
|
0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61,
|
||||||
|
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70,
|
||||||
|
0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68,
|
||||||
|
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
|
||||||
|
0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
|
0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31,
|
||||||
|
0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 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{}{
|
||||||
@ -211,24 +235,30 @@ var file_headscale_v1_headscale_proto_goTypes = []interface{}{
|
|||||||
(*UnshareMachineRequest)(nil), // 15: headscale.v1.UnshareMachineRequest
|
(*UnshareMachineRequest)(nil), // 15: headscale.v1.UnshareMachineRequest
|
||||||
(*GetMachineRouteRequest)(nil), // 16: headscale.v1.GetMachineRouteRequest
|
(*GetMachineRouteRequest)(nil), // 16: headscale.v1.GetMachineRouteRequest
|
||||||
(*EnableMachineRoutesRequest)(nil), // 17: headscale.v1.EnableMachineRoutesRequest
|
(*EnableMachineRoutesRequest)(nil), // 17: headscale.v1.EnableMachineRoutesRequest
|
||||||
(*GetNamespaceResponse)(nil), // 18: headscale.v1.GetNamespaceResponse
|
(*CreateApiKeyRequest)(nil), // 18: headscale.v1.CreateApiKeyRequest
|
||||||
(*CreateNamespaceResponse)(nil), // 19: headscale.v1.CreateNamespaceResponse
|
(*ExpireApiKeyRequest)(nil), // 19: headscale.v1.ExpireApiKeyRequest
|
||||||
(*RenameNamespaceResponse)(nil), // 20: headscale.v1.RenameNamespaceResponse
|
(*ListApiKeysRequest)(nil), // 20: headscale.v1.ListApiKeysRequest
|
||||||
(*DeleteNamespaceResponse)(nil), // 21: headscale.v1.DeleteNamespaceResponse
|
(*GetNamespaceResponse)(nil), // 21: headscale.v1.GetNamespaceResponse
|
||||||
(*ListNamespacesResponse)(nil), // 22: headscale.v1.ListNamespacesResponse
|
(*CreateNamespaceResponse)(nil), // 22: headscale.v1.CreateNamespaceResponse
|
||||||
(*CreatePreAuthKeyResponse)(nil), // 23: headscale.v1.CreatePreAuthKeyResponse
|
(*RenameNamespaceResponse)(nil), // 23: headscale.v1.RenameNamespaceResponse
|
||||||
(*ExpirePreAuthKeyResponse)(nil), // 24: headscale.v1.ExpirePreAuthKeyResponse
|
(*DeleteNamespaceResponse)(nil), // 24: headscale.v1.DeleteNamespaceResponse
|
||||||
(*ListPreAuthKeysResponse)(nil), // 25: headscale.v1.ListPreAuthKeysResponse
|
(*ListNamespacesResponse)(nil), // 25: headscale.v1.ListNamespacesResponse
|
||||||
(*DebugCreateMachineResponse)(nil), // 26: headscale.v1.DebugCreateMachineResponse
|
(*CreatePreAuthKeyResponse)(nil), // 26: headscale.v1.CreatePreAuthKeyResponse
|
||||||
(*GetMachineResponse)(nil), // 27: headscale.v1.GetMachineResponse
|
(*ExpirePreAuthKeyResponse)(nil), // 27: headscale.v1.ExpirePreAuthKeyResponse
|
||||||
(*RegisterMachineResponse)(nil), // 28: headscale.v1.RegisterMachineResponse
|
(*ListPreAuthKeysResponse)(nil), // 28: headscale.v1.ListPreAuthKeysResponse
|
||||||
(*DeleteMachineResponse)(nil), // 29: headscale.v1.DeleteMachineResponse
|
(*DebugCreateMachineResponse)(nil), // 29: headscale.v1.DebugCreateMachineResponse
|
||||||
(*ExpireMachineResponse)(nil), // 30: headscale.v1.ExpireMachineResponse
|
(*GetMachineResponse)(nil), // 30: headscale.v1.GetMachineResponse
|
||||||
(*ListMachinesResponse)(nil), // 31: headscale.v1.ListMachinesResponse
|
(*RegisterMachineResponse)(nil), // 31: headscale.v1.RegisterMachineResponse
|
||||||
(*ShareMachineResponse)(nil), // 32: headscale.v1.ShareMachineResponse
|
(*DeleteMachineResponse)(nil), // 32: headscale.v1.DeleteMachineResponse
|
||||||
(*UnshareMachineResponse)(nil), // 33: headscale.v1.UnshareMachineResponse
|
(*ExpireMachineResponse)(nil), // 33: headscale.v1.ExpireMachineResponse
|
||||||
(*GetMachineRouteResponse)(nil), // 34: headscale.v1.GetMachineRouteResponse
|
(*ListMachinesResponse)(nil), // 34: headscale.v1.ListMachinesResponse
|
||||||
(*EnableMachineRoutesResponse)(nil), // 35: headscale.v1.EnableMachineRoutesResponse
|
(*ShareMachineResponse)(nil), // 35: headscale.v1.ShareMachineResponse
|
||||||
|
(*UnshareMachineResponse)(nil), // 36: headscale.v1.UnshareMachineResponse
|
||||||
|
(*GetMachineRouteResponse)(nil), // 37: headscale.v1.GetMachineRouteResponse
|
||||||
|
(*EnableMachineRoutesResponse)(nil), // 38: headscale.v1.EnableMachineRoutesResponse
|
||||||
|
(*CreateApiKeyResponse)(nil), // 39: headscale.v1.CreateApiKeyResponse
|
||||||
|
(*ExpireApiKeyResponse)(nil), // 40: headscale.v1.ExpireApiKeyResponse
|
||||||
|
(*ListApiKeysResponse)(nil), // 41: headscale.v1.ListApiKeysResponse
|
||||||
}
|
}
|
||||||
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
|
||||||
@ -249,26 +279,32 @@ var file_headscale_v1_headscale_proto_depIdxs = []int32{
|
|||||||
15, // 15: headscale.v1.HeadscaleService.UnshareMachine:input_type -> headscale.v1.UnshareMachineRequest
|
15, // 15: headscale.v1.HeadscaleService.UnshareMachine:input_type -> headscale.v1.UnshareMachineRequest
|
||||||
16, // 16: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest
|
16, // 16: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest
|
||||||
17, // 17: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest
|
17, // 17: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest
|
||||||
18, // 18: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse
|
18, // 18: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest
|
||||||
19, // 19: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse
|
19, // 19: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest
|
||||||
20, // 20: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse
|
20, // 20: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest
|
||||||
21, // 21: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse
|
21, // 21: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse
|
||||||
22, // 22: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse
|
22, // 22: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse
|
||||||
23, // 23: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse
|
23, // 23: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse
|
||||||
24, // 24: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse
|
24, // 24: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse
|
||||||
25, // 25: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse
|
25, // 25: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse
|
||||||
26, // 26: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse
|
26, // 26: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse
|
||||||
27, // 27: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse
|
27, // 27: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse
|
||||||
28, // 28: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse
|
28, // 28: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse
|
||||||
29, // 29: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse
|
29, // 29: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse
|
||||||
30, // 30: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse
|
30, // 30: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse
|
||||||
31, // 31: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse
|
31, // 31: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse
|
||||||
32, // 32: headscale.v1.HeadscaleService.ShareMachine:output_type -> headscale.v1.ShareMachineResponse
|
32, // 32: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse
|
||||||
33, // 33: headscale.v1.HeadscaleService.UnshareMachine:output_type -> headscale.v1.UnshareMachineResponse
|
33, // 33: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse
|
||||||
34, // 34: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse
|
34, // 34: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse
|
||||||
35, // 35: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse
|
35, // 35: headscale.v1.HeadscaleService.ShareMachine:output_type -> headscale.v1.ShareMachineResponse
|
||||||
18, // [18:36] is the sub-list for method output_type
|
36, // 36: headscale.v1.HeadscaleService.UnshareMachine:output_type -> headscale.v1.UnshareMachineResponse
|
||||||
0, // [0:18] is the sub-list for method input_type
|
37, // 37: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse
|
||||||
|
38, // 38: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse
|
||||||
|
39, // 39: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse
|
||||||
|
40, // 40: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse
|
||||||
|
41, // 41: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse
|
||||||
|
21, // [21:42] is the sub-list for method output_type
|
||||||
|
0, // [0:21] 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
|
||||||
@ -283,6 +319,7 @@ func file_headscale_v1_headscale_proto_init() {
|
|||||||
file_headscale_v1_preauthkey_proto_init()
|
file_headscale_v1_preauthkey_proto_init()
|
||||||
file_headscale_v1_machine_proto_init()
|
file_headscale_v1_machine_proto_init()
|
||||||
file_headscale_v1_routes_proto_init()
|
file_headscale_v1_routes_proto_init()
|
||||||
|
file_headscale_v1_apikey_proto_init()
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
|
@ -891,6 +891,92 @@ func local_request_HeadscaleService_EnableMachineRoutes_0(ctx context.Context, m
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func request_HeadscaleService_CreateApiKey_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq CreateApiKeyRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||||
|
if berr != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||||
|
}
|
||||||
|
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := client.CreateApiKey(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_HeadscaleService_CreateApiKey_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq CreateApiKeyRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||||
|
if berr != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||||
|
}
|
||||||
|
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := server.CreateApiKey(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_HeadscaleService_ExpireApiKey_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq ExpireApiKeyRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||||
|
if berr != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||||
|
}
|
||||||
|
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := client.ExpireApiKey(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_HeadscaleService_ExpireApiKey_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq ExpireApiKeyRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||||
|
if berr != nil {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||||
|
}
|
||||||
|
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||||
|
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := server.ExpireApiKey(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func request_HeadscaleService_ListApiKeys_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq ListApiKeysRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
msg, err := client.ListApiKeys(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_HeadscaleService_ListApiKeys_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var protoReq ListApiKeysRequest
|
||||||
|
var metadata runtime.ServerMetadata
|
||||||
|
|
||||||
|
msg, err := server.ListApiKeys(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterHeadscaleServiceHandlerServer registers the http handlers for service HeadscaleService to "mux".
|
// RegisterHeadscaleServiceHandlerServer registers the http handlers for service HeadscaleService to "mux".
|
||||||
// UnaryRPC :call HeadscaleServiceServer directly.
|
// UnaryRPC :call HeadscaleServiceServer directly.
|
||||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||||
@ -1311,6 +1397,75 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mux.Handle("POST", pattern_HeadscaleService_CreateApiKey_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/CreateApiKey", runtime.WithHTTPPathPattern("/api/v1/apikey"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_HeadscaleService_CreateApiKey_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_CreateApiKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("POST", pattern_HeadscaleService_ExpireApiKey_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/ExpireApiKey", runtime.WithHTTPPathPattern("/api/v1/apikey/expire"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_HeadscaleService_ExpireApiKey_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_ExpireApiKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_HeadscaleService_ListApiKeys_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/ListApiKeys", runtime.WithHTTPPathPattern("/api/v1/apikey"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_HeadscaleService_ListApiKeys_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_ListApiKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1712,6 +1867,66 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mux.Handle("POST", pattern_HeadscaleService_CreateApiKey_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/CreateApiKey", runtime.WithHTTPPathPattern("/api/v1/apikey"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_HeadscaleService_CreateApiKey_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_CreateApiKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("POST", pattern_HeadscaleService_ExpireApiKey_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/ExpireApiKey", runtime.WithHTTPPathPattern("/api/v1/apikey/expire"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_HeadscaleService_ExpireApiKey_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_ExpireApiKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.Handle("GET", pattern_HeadscaleService_ListApiKeys_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/ListApiKeys", runtime.WithHTTPPathPattern("/api/v1/apikey"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_HeadscaleService_ListApiKeys_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_ListApiKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1751,6 +1966,12 @@ var (
|
|||||||
pattern_HeadscaleService_GetMachineRoute_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", "routes"}, ""))
|
pattern_HeadscaleService_GetMachineRoute_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", "routes"}, ""))
|
||||||
|
|
||||||
pattern_HeadscaleService_EnableMachineRoutes_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", "routes"}, ""))
|
pattern_HeadscaleService_EnableMachineRoutes_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", "routes"}, ""))
|
||||||
|
|
||||||
|
pattern_HeadscaleService_CreateApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "apikey"}, ""))
|
||||||
|
|
||||||
|
pattern_HeadscaleService_ExpireApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "apikey", "expire"}, ""))
|
||||||
|
|
||||||
|
pattern_HeadscaleService_ListApiKeys_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "apikey"}, ""))
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -1789,4 +2010,10 @@ var (
|
|||||||
forward_HeadscaleService_GetMachineRoute_0 = runtime.ForwardResponseMessage
|
forward_HeadscaleService_GetMachineRoute_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
forward_HeadscaleService_EnableMachineRoutes_0 = runtime.ForwardResponseMessage
|
forward_HeadscaleService_EnableMachineRoutes_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_HeadscaleService_CreateApiKey_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_HeadscaleService_ExpireApiKey_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
|
forward_HeadscaleService_ListApiKeys_0 = runtime.ForwardResponseMessage
|
||||||
)
|
)
|
||||||
|
@ -4,6 +4,7 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
|
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
codes "google.golang.org/grpc/codes"
|
codes "google.golang.org/grpc/codes"
|
||||||
status "google.golang.org/grpc/status"
|
status "google.golang.org/grpc/status"
|
||||||
@ -40,6 +41,10 @@ type HeadscaleServiceClient interface {
|
|||||||
// --- Route start ---
|
// --- Route start ---
|
||||||
GetMachineRoute(ctx context.Context, in *GetMachineRouteRequest, opts ...grpc.CallOption) (*GetMachineRouteResponse, error)
|
GetMachineRoute(ctx context.Context, in *GetMachineRouteRequest, opts ...grpc.CallOption) (*GetMachineRouteResponse, error)
|
||||||
EnableMachineRoutes(ctx context.Context, in *EnableMachineRoutesRequest, opts ...grpc.CallOption) (*EnableMachineRoutesResponse, error)
|
EnableMachineRoutes(ctx context.Context, in *EnableMachineRoutesRequest, opts ...grpc.CallOption) (*EnableMachineRoutesResponse, error)
|
||||||
|
// --- ApiKeys start ---
|
||||||
|
CreateApiKey(ctx context.Context, in *CreateApiKeyRequest, opts ...grpc.CallOption) (*CreateApiKeyResponse, error)
|
||||||
|
ExpireApiKey(ctx context.Context, in *ExpireApiKeyRequest, opts ...grpc.CallOption) (*ExpireApiKeyResponse, error)
|
||||||
|
ListApiKeys(ctx context.Context, in *ListApiKeysRequest, opts ...grpc.CallOption) (*ListApiKeysResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type headscaleServiceClient struct {
|
type headscaleServiceClient struct {
|
||||||
@ -212,6 +217,33 @@ func (c *headscaleServiceClient) EnableMachineRoutes(ctx context.Context, in *En
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *headscaleServiceClient) CreateApiKey(ctx context.Context, in *CreateApiKeyRequest, opts ...grpc.CallOption) (*CreateApiKeyResponse, error) {
|
||||||
|
out := new(CreateApiKeyResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/CreateApiKey", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *headscaleServiceClient) ExpireApiKey(ctx context.Context, in *ExpireApiKeyRequest, opts ...grpc.CallOption) (*ExpireApiKeyResponse, error) {
|
||||||
|
out := new(ExpireApiKeyResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ExpireApiKey", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *headscaleServiceClient) ListApiKeys(ctx context.Context, in *ListApiKeysRequest, opts ...grpc.CallOption) (*ListApiKeysResponse, error) {
|
||||||
|
out := new(ListApiKeysResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListApiKeys", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// HeadscaleServiceServer is the server API for HeadscaleService service.
|
// HeadscaleServiceServer is the server API for HeadscaleService service.
|
||||||
// All implementations must embed UnimplementedHeadscaleServiceServer
|
// All implementations must embed UnimplementedHeadscaleServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility
|
||||||
@ -238,6 +270,10 @@ type HeadscaleServiceServer interface {
|
|||||||
// --- Route start ---
|
// --- Route start ---
|
||||||
GetMachineRoute(context.Context, *GetMachineRouteRequest) (*GetMachineRouteResponse, error)
|
GetMachineRoute(context.Context, *GetMachineRouteRequest) (*GetMachineRouteResponse, error)
|
||||||
EnableMachineRoutes(context.Context, *EnableMachineRoutesRequest) (*EnableMachineRoutesResponse, error)
|
EnableMachineRoutes(context.Context, *EnableMachineRoutesRequest) (*EnableMachineRoutesResponse, error)
|
||||||
|
// --- ApiKeys start ---
|
||||||
|
CreateApiKey(context.Context, *CreateApiKeyRequest) (*CreateApiKeyResponse, error)
|
||||||
|
ExpireApiKey(context.Context, *ExpireApiKeyRequest) (*ExpireApiKeyResponse, error)
|
||||||
|
ListApiKeys(context.Context, *ListApiKeysRequest) (*ListApiKeysResponse, error)
|
||||||
mustEmbedUnimplementedHeadscaleServiceServer()
|
mustEmbedUnimplementedHeadscaleServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,6 +335,15 @@ func (UnimplementedHeadscaleServiceServer) GetMachineRoute(context.Context, *Get
|
|||||||
func (UnimplementedHeadscaleServiceServer) EnableMachineRoutes(context.Context, *EnableMachineRoutesRequest) (*EnableMachineRoutesResponse, error) {
|
func (UnimplementedHeadscaleServiceServer) EnableMachineRoutes(context.Context, *EnableMachineRoutesRequest) (*EnableMachineRoutesResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method EnableMachineRoutes not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method EnableMachineRoutes not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedHeadscaleServiceServer) CreateApiKey(context.Context, *CreateApiKeyRequest) (*CreateApiKeyResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method CreateApiKey not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedHeadscaleServiceServer) ExpireApiKey(context.Context, *ExpireApiKeyRequest) (*ExpireApiKeyResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ExpireApiKey not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedHeadscaleServiceServer) ListApiKeys(context.Context, *ListApiKeysRequest) (*ListApiKeysResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListApiKeys not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedHeadscaleServiceServer) mustEmbedUnimplementedHeadscaleServiceServer() {}
|
func (UnimplementedHeadscaleServiceServer) mustEmbedUnimplementedHeadscaleServiceServer() {}
|
||||||
|
|
||||||
// UnsafeHeadscaleServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeHeadscaleServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
@ -636,6 +681,60 @@ func _HeadscaleService_EnableMachineRoutes_Handler(srv interface{}, ctx context.
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _HeadscaleService_CreateApiKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(CreateApiKeyRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(HeadscaleServiceServer).CreateApiKey(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/headscale.v1.HeadscaleService/CreateApiKey",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HeadscaleServiceServer).CreateApiKey(ctx, req.(*CreateApiKeyRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _HeadscaleService_ExpireApiKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ExpireApiKeyRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(HeadscaleServiceServer).ExpireApiKey(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/headscale.v1.HeadscaleService/ExpireApiKey",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HeadscaleServiceServer).ExpireApiKey(ctx, req.(*ExpireApiKeyRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _HeadscaleService_ListApiKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListApiKeysRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(HeadscaleServiceServer).ListApiKeys(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/headscale.v1.HeadscaleService/ListApiKeys",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HeadscaleServiceServer).ListApiKeys(ctx, req.(*ListApiKeysRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// HeadscaleService_ServiceDesc is the grpc.ServiceDesc for HeadscaleService service.
|
// HeadscaleService_ServiceDesc is the grpc.ServiceDesc for HeadscaleService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@ -715,6 +814,18 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "EnableMachineRoutes",
|
MethodName: "EnableMachineRoutes",
|
||||||
Handler: _HeadscaleService_EnableMachineRoutes_Handler,
|
Handler: _HeadscaleService_EnableMachineRoutes_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "CreateApiKey",
|
||||||
|
Handler: _HeadscaleService_CreateApiKey_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ExpireApiKey",
|
||||||
|
Handler: _HeadscaleService_ExpireApiKey_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListApiKeys",
|
||||||
|
Handler: _HeadscaleService_ListApiKeys_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "headscale/v1/headscale.proto",
|
Metadata: "headscale/v1/headscale.proto",
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.17.3
|
// protoc (unknown)
|
||||||
// source: headscale/v1/machine.proto
|
// source: headscale/v1/machine.proto
|
||||||
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.17.3
|
// protoc (unknown)
|
||||||
// source: headscale/v1/namespace.proto
|
// source: headscale/v1/namespace.proto
|
||||||
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.17.3
|
// protoc (unknown)
|
||||||
// source: headscale/v1/preauthkey.proto
|
// source: headscale/v1/preauthkey.proto
|
||||||
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.17.3
|
// protoc (unknown)
|
||||||
// source: headscale/v1/routes.proto
|
// source: headscale/v1/routes.proto
|
||||||
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
43
gen/openapiv2/headscale/v1/apikey.swagger.json
Normal file
43
gen/openapiv2/headscale/v1/apikey.swagger.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"title": "headscale/v1/apikey.proto",
|
||||||
|
"version": "version not set"
|
||||||
|
},
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"paths": {},
|
||||||
|
"definitions": {
|
||||||
|
"protobufAny": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"@type": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": {}
|
||||||
|
},
|
||||||
|
"rpcStatus": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"details": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/protobufAny"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,91 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/api/v1/apikey": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "HeadscaleService_ListApiKeys",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A successful response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1ListApiKeysResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "An unexpected error response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/rpcStatus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"HeadscaleService"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"summary": "--- ApiKeys start ---",
|
||||||
|
"operationId": "HeadscaleService_CreateApiKey",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A successful response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1CreateApiKeyResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "An unexpected error response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/rpcStatus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1CreateApiKeyRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"HeadscaleService"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/apikey/expire": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "HeadscaleService_ExpireApiKey",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A successful response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1ExpireApiKeyResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "An unexpected error response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/rpcStatus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1ExpireApiKeyRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"HeadscaleService"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/v1/debug/machine": {
|
"/api/v1/debug/machine": {
|
||||||
"post": {
|
"post": {
|
||||||
"summary": "--- Machine start ---",
|
"summary": "--- Machine start ---",
|
||||||
@ -596,6 +681,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1ApiKey": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uint64"
|
||||||
|
},
|
||||||
|
"prefix": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"expiration": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"lastSeen": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1CreateApiKeyRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"expiration": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1CreateApiKeyResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"apiKey": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1CreateNamespaceRequest": {
|
"v1CreateNamespaceRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -680,6 +806,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1ExpireApiKeyRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"prefix": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1ExpireApiKeyResponse": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"v1ExpireMachineResponse": {
|
"v1ExpireMachineResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -726,6 +863,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1ListApiKeysResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"apiKeys": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/v1ApiKey"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1ListMachinesResponse": {
|
"v1ListMachinesResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
56
grpcv1.go
56
grpcv1.go
@ -349,6 +349,62 @@ func (api headscaleV1APIServer) EnableMachineRoutes(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api headscaleV1APIServer) CreateApiKey(
|
||||||
|
ctx context.Context,
|
||||||
|
request *v1.CreateApiKeyRequest,
|
||||||
|
) (*v1.CreateApiKeyResponse, error) {
|
||||||
|
var expiration time.Time
|
||||||
|
if request.GetExpiration() != nil {
|
||||||
|
expiration = request.GetExpiration().AsTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
apiKey, _, err := api.h.CreateAPIKey(
|
||||||
|
&expiration,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.CreateApiKeyResponse{ApiKey: apiKey}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api headscaleV1APIServer) ExpireApiKey(
|
||||||
|
ctx context.Context,
|
||||||
|
request *v1.ExpireApiKeyRequest,
|
||||||
|
) (*v1.ExpireApiKeyResponse, error) {
|
||||||
|
var apiKey *APIKey
|
||||||
|
var err error
|
||||||
|
|
||||||
|
apiKey, err = api.h.GetAPIKey(request.Prefix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = api.h.ExpireAPIKey(apiKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.ExpireApiKeyResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api headscaleV1APIServer) ListApiKeys(
|
||||||
|
ctx context.Context,
|
||||||
|
request *v1.ListApiKeysRequest,
|
||||||
|
) (*v1.ListApiKeysResponse, error) {
|
||||||
|
apiKeys, err := api.h.ListAPIKeys()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response := make([]*v1.ApiKey, len(apiKeys))
|
||||||
|
for index, key := range apiKeys {
|
||||||
|
response[index] = key.toProto()
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.ListApiKeysResponse{ApiKeys: response}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// The following service calls are for testing and debugging
|
// The following service calls are for testing and debugging
|
||||||
func (api headscaleV1APIServer) DebugCreateMachine(
|
func (api headscaleV1APIServer) DebugCreateMachine(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
@ -1193,3 +1193,148 @@ func (s *IntegrationCLITestSuite) TestRouteCommand() {
|
|||||||
"route (route-machine) is not available on node",
|
"route (route-machine) is not available on node",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *IntegrationCLITestSuite) TestApiKeyCommand() {
|
||||||
|
count := 5
|
||||||
|
|
||||||
|
keys := make([]string, count)
|
||||||
|
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
apiResult, err := ExecuteCommand(
|
||||||
|
&s.headscale,
|
||||||
|
[]string{
|
||||||
|
"headscale",
|
||||||
|
"apikeys",
|
||||||
|
"create",
|
||||||
|
"--expiration",
|
||||||
|
"24h",
|
||||||
|
"--output",
|
||||||
|
"json",
|
||||||
|
},
|
||||||
|
[]string{},
|
||||||
|
)
|
||||||
|
assert.Nil(s.T(), err)
|
||||||
|
assert.NotEmpty(s.T(), apiResult)
|
||||||
|
|
||||||
|
// var apiKey v1.ApiKey
|
||||||
|
// err = json.Unmarshal([]byte(apiResult), &apiKey)
|
||||||
|
// assert.Nil(s.T(), err)
|
||||||
|
|
||||||
|
keys[i] = apiResult
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Len(s.T(), keys, 5)
|
||||||
|
|
||||||
|
// Test list of keys
|
||||||
|
listResult, err := ExecuteCommand(
|
||||||
|
&s.headscale,
|
||||||
|
[]string{
|
||||||
|
"headscale",
|
||||||
|
"apikeys",
|
||||||
|
"list",
|
||||||
|
"--output",
|
||||||
|
"json",
|
||||||
|
},
|
||||||
|
[]string{},
|
||||||
|
)
|
||||||
|
assert.Nil(s.T(), err)
|
||||||
|
|
||||||
|
var listedApiKeys []v1.ApiKey
|
||||||
|
err = json.Unmarshal([]byte(listResult), &listedApiKeys)
|
||||||
|
assert.Nil(s.T(), err)
|
||||||
|
|
||||||
|
assert.Len(s.T(), listedApiKeys, 5)
|
||||||
|
|
||||||
|
assert.Equal(s.T(), uint64(1), listedApiKeys[0].Id)
|
||||||
|
assert.Equal(s.T(), uint64(2), listedApiKeys[1].Id)
|
||||||
|
assert.Equal(s.T(), uint64(3), listedApiKeys[2].Id)
|
||||||
|
assert.Equal(s.T(), uint64(4), listedApiKeys[3].Id)
|
||||||
|
assert.Equal(s.T(), uint64(5), listedApiKeys[4].Id)
|
||||||
|
|
||||||
|
assert.NotEmpty(s.T(), listedApiKeys[0].Prefix)
|
||||||
|
assert.NotEmpty(s.T(), listedApiKeys[1].Prefix)
|
||||||
|
assert.NotEmpty(s.T(), listedApiKeys[2].Prefix)
|
||||||
|
assert.NotEmpty(s.T(), listedApiKeys[3].Prefix)
|
||||||
|
assert.NotEmpty(s.T(), listedApiKeys[4].Prefix)
|
||||||
|
|
||||||
|
assert.True(s.T(), listedApiKeys[0].Expiration.AsTime().After(time.Now()))
|
||||||
|
assert.True(s.T(), listedApiKeys[1].Expiration.AsTime().After(time.Now()))
|
||||||
|
assert.True(s.T(), listedApiKeys[2].Expiration.AsTime().After(time.Now()))
|
||||||
|
assert.True(s.T(), listedApiKeys[3].Expiration.AsTime().After(time.Now()))
|
||||||
|
assert.True(s.T(), listedApiKeys[4].Expiration.AsTime().After(time.Now()))
|
||||||
|
|
||||||
|
assert.True(
|
||||||
|
s.T(),
|
||||||
|
listedApiKeys[0].Expiration.AsTime().Before(time.Now().Add(time.Hour*26)),
|
||||||
|
)
|
||||||
|
assert.True(
|
||||||
|
s.T(),
|
||||||
|
listedApiKeys[1].Expiration.AsTime().Before(time.Now().Add(time.Hour*26)),
|
||||||
|
)
|
||||||
|
assert.True(
|
||||||
|
s.T(),
|
||||||
|
listedApiKeys[2].Expiration.AsTime().Before(time.Now().Add(time.Hour*26)),
|
||||||
|
)
|
||||||
|
assert.True(
|
||||||
|
s.T(),
|
||||||
|
listedApiKeys[3].Expiration.AsTime().Before(time.Now().Add(time.Hour*26)),
|
||||||
|
)
|
||||||
|
assert.True(
|
||||||
|
s.T(),
|
||||||
|
listedApiKeys[4].Expiration.AsTime().Before(time.Now().Add(time.Hour*26)),
|
||||||
|
)
|
||||||
|
|
||||||
|
expiredPrefixes := make(map[string]bool)
|
||||||
|
|
||||||
|
// Expire three keys
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
_, err := ExecuteCommand(
|
||||||
|
&s.headscale,
|
||||||
|
[]string{
|
||||||
|
"headscale",
|
||||||
|
"apikeys",
|
||||||
|
"expire",
|
||||||
|
"--prefix",
|
||||||
|
listedApiKeys[i].Prefix,
|
||||||
|
},
|
||||||
|
[]string{},
|
||||||
|
)
|
||||||
|
assert.Nil(s.T(), err)
|
||||||
|
|
||||||
|
expiredPrefixes[listedApiKeys[i].Prefix] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test list pre auth keys after expire
|
||||||
|
listAfterExpireResult, err := ExecuteCommand(
|
||||||
|
&s.headscale,
|
||||||
|
[]string{
|
||||||
|
"headscale",
|
||||||
|
"apikeys",
|
||||||
|
"list",
|
||||||
|
"--output",
|
||||||
|
"json",
|
||||||
|
},
|
||||||
|
[]string{},
|
||||||
|
)
|
||||||
|
assert.Nil(s.T(), err)
|
||||||
|
|
||||||
|
var listedAfterExpireApiKeys []v1.ApiKey
|
||||||
|
err = json.Unmarshal([]byte(listAfterExpireResult), &listedAfterExpireApiKeys)
|
||||||
|
assert.Nil(s.T(), err)
|
||||||
|
|
||||||
|
for index := range listedAfterExpireApiKeys {
|
||||||
|
if _, ok := expiredPrefixes[listedAfterExpireApiKeys[index].Prefix]; ok {
|
||||||
|
// Expired
|
||||||
|
assert.True(
|
||||||
|
s.T(),
|
||||||
|
listedAfterExpireApiKeys[index].Expiration.AsTime().Before(time.Now()),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Not expired
|
||||||
|
assert.False(
|
||||||
|
s.T(),
|
||||||
|
listedAfterExpireApiKeys[index].Expiration.AsTime().Before(time.Now()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,16 +8,17 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"inet.af/netaddr"
|
|
||||||
|
|
||||||
"github.com/ory/dockertest/v3"
|
"github.com/ory/dockertest/v3"
|
||||||
"github.com/ory/dockertest/v3/docker"
|
"github.com/ory/dockertest/v3/docker"
|
||||||
|
"inet.af/netaddr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DOCKER_EXECUTE_TIMEOUT = 10 * time.Second
|
const DOCKER_EXECUTE_TIMEOUT = 10 * time.Second
|
||||||
|
|
||||||
var IpPrefix4 = netaddr.MustParseIPPrefix("100.64.0.0/10")
|
var (
|
||||||
var IpPrefix6 = netaddr.MustParseIPPrefix("fd7a:115c:a1e0::/48")
|
IpPrefix4 = netaddr.MustParseIPPrefix("100.64.0.0/10")
|
||||||
|
IpPrefix6 = netaddr.MustParseIPPrefix("fd7a:115c:a1e0::/48")
|
||||||
|
)
|
||||||
|
|
||||||
type ExecuteCommandConfig struct {
|
type ExecuteCommandConfig struct {
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
|
35
proto/headscale/v1/apikey.proto
Normal file
35
proto/headscale/v1/apikey.proto
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package headscale.v1;
|
||||||
|
option go_package = "github.com/juanfont/headscale/gen/go/v1";
|
||||||
|
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
|
message ApiKey {
|
||||||
|
uint64 id = 1;
|
||||||
|
string prefix = 2;
|
||||||
|
google.protobuf.Timestamp expiration = 3;
|
||||||
|
google.protobuf.Timestamp created_at = 4;
|
||||||
|
google.protobuf.Timestamp last_seen = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateApiKeyRequest {
|
||||||
|
google.protobuf.Timestamp expiration = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateApiKeyResponse {
|
||||||
|
string api_key = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExpireApiKeyRequest {
|
||||||
|
string prefix = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExpireApiKeyResponse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListApiKeysRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListApiKeysResponse {
|
||||||
|
repeated ApiKey api_keys = 1;
|
||||||
|
}
|
@ -8,6 +8,7 @@ import "headscale/v1/namespace.proto";
|
|||||||
import "headscale/v1/preauthkey.proto";
|
import "headscale/v1/preauthkey.proto";
|
||||||
import "headscale/v1/machine.proto";
|
import "headscale/v1/machine.proto";
|
||||||
import "headscale/v1/routes.proto";
|
import "headscale/v1/routes.proto";
|
||||||
|
import "headscale/v1/apikey.proto";
|
||||||
// import "headscale/v1/device.proto";
|
// import "headscale/v1/device.proto";
|
||||||
|
|
||||||
service HeadscaleService {
|
service HeadscaleService {
|
||||||
@ -131,6 +132,28 @@ service HeadscaleService {
|
|||||||
}
|
}
|
||||||
// --- Route end ---
|
// --- Route end ---
|
||||||
|
|
||||||
|
// --- ApiKeys start ---
|
||||||
|
rpc CreateApiKey(CreateApiKeyRequest) returns (CreateApiKeyResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/api/v1/apikey"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc ExpireApiKey(ExpireApiKeyRequest) returns (ExpireApiKeyResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/api/v1/apikey/expire"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc ListApiKeys(ListApiKeysRequest) returns (ListApiKeysResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/api/v1/apikey"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// --- ApiKeys end ---
|
||||||
|
|
||||||
// Implement Tailscale API
|
// Implement Tailscale API
|
||||||
// rpc GetDevice(GetDeviceRequest) returns(GetDeviceResponse) {
|
// rpc GetDevice(GetDeviceRequest) returns(GetDeviceResponse) {
|
||||||
// option(google.api.http) = {
|
// option(google.api.http) = {
|
||||||
|
28
utils.go
28
utils.go
@ -7,6 +7,8 @@ package headscale
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@ -278,3 +280,29 @@ func containsIPPrefix(prefixes []netaddr.IPPrefix, prefix netaddr.IPPrefix) bool
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateRandomBytes returns securely generated random bytes.
|
||||||
|
// It will return an error if the system's secure random
|
||||||
|
// number generator fails to function correctly, in which
|
||||||
|
// case the caller should not continue.
|
||||||
|
func GenerateRandomBytes(n int) ([]byte, error) {
|
||||||
|
bytes := make([]byte, n)
|
||||||
|
|
||||||
|
// Note that err == nil only if we read len(b) bytes.
|
||||||
|
if _, err := rand.Read(bytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateRandomStringURLSafe returns a URL-safe, base64 encoded
|
||||||
|
// securely generated random string.
|
||||||
|
// It will return an error if the system's secure random
|
||||||
|
// number generator fails to function correctly, in which
|
||||||
|
// case the caller should not continue.
|
||||||
|
func GenerateRandomStringURLSafe(n int) (string, error) {
|
||||||
|
b, err := GenerateRandomBytes(n)
|
||||||
|
|
||||||
|
return base64.RawURLEncoding.EncodeToString(b), err
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user