mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-07 16:54:16 +01:00
Split client app into cmd and daemon service (#239)
This commit is contained in:
parent
3e46f38166
commit
ef47385e38
37
client/cmd/down.go
Normal file
37
client/cmd/down.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var downCmd = &cobra.Command{
|
||||||
|
Use: "down",
|
||||||
|
Short: "down wiretrustee connections",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
SetFlagsFromEnvVars()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
conn, err := DialClientGRPCServer(ctx, daemonAddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to connect to service CLI interface %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
daemonClient := proto.NewDaemonServiceClient(conn)
|
||||||
|
|
||||||
|
if _, err := daemonClient.Down(ctx, &proto.DownRequest{}); err != nil {
|
||||||
|
log.Errorf("call service down method: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
@ -1,175 +1,66 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v4"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/wiretrustee/wiretrustee/client/internal"
|
"github.com/wiretrustee/wiretrustee/client/internal"
|
||||||
"github.com/wiretrustee/wiretrustee/client/system"
|
"github.com/wiretrustee/wiretrustee/client/proto"
|
||||||
mgm "github.com/wiretrustee/wiretrustee/management/client"
|
|
||||||
mgmProto "github.com/wiretrustee/wiretrustee/management/proto"
|
|
||||||
"github.com/wiretrustee/wiretrustee/util"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var loginCmd = &cobra.Command{
|
||||||
loginCmd = &cobra.Command{
|
|
||||||
Use: "login",
|
Use: "login",
|
||||||
Short: "login to the Wiretrustee Management Service (first run)",
|
Short: "login to the Wiretrustee Management Service (first run)",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
SetFlagsFromEnvVars()
|
SetFlagsFromEnvVars()
|
||||||
|
ctx := internal.CtxInitState(context.Background())
|
||||||
|
|
||||||
var backOff = &backoff.ExponentialBackOff{
|
// workaround to run without service
|
||||||
InitialInterval: time.Second,
|
if logFile == "console" {
|
||||||
RandomizationFactor: backoff.DefaultRandomizationFactor,
|
|
||||||
Multiplier: backoff.DefaultMultiplier,
|
|
||||||
MaxInterval: 2 * time.Second,
|
|
||||||
MaxElapsedTime: time.Second * 10,
|
|
||||||
Stop: backoff.Stop,
|
|
||||||
Clock: backoff.SystemClock,
|
|
||||||
}
|
|
||||||
|
|
||||||
loginOp := func() error {
|
|
||||||
|
|
||||||
err := util.InitLog(logLevel, logFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed initializing log %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
config, err := internal.GetConfig(managementURL, configPath, preSharedKey)
|
config, err := internal.GetConfig(managementURL, configPath, preSharedKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed getting config %s %v", configPath, err)
|
log.Errorf("get config file: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = WithBackOff(func() error {
|
||||||
//validate our peer's Wireguard PRIVATE key
|
return internal.Login(ctx, config, setupKey)
|
||||||
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
mgmTlsEnabled := false
|
|
||||||
if config.ManagementURL.Scheme == "https" {
|
|
||||||
mgmTlsEnabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("connecting to Management Service %s", config.ManagementURL.String())
|
|
||||||
mgmClient, err := mgm.NewClient(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed connecting to Management Service %s %v", config.ManagementURL.String(), err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Debugf("connected to management Service %s", config.ManagementURL.String())
|
|
||||||
|
|
||||||
serverKey, err := mgmClient.GetServerPublicKey()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed while getting Management Service public key: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = loginPeer(*serverKey, mgmClient, setupKey)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed logging-in peer on Management Service : %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mgmClient.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed closing Management Service client: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := backoff.RetryNotify(loginOp, backOff, func(err error, duration time.Duration) {
|
|
||||||
log.Warnf("retrying Login to the Management service in %v due to error %v", duration, err)
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("exiting login retry loop due to unrecoverable error: %v", err)
|
log.Errorf("backoff cycle failed: %v", err)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if setupKey == "" {
|
||||||
|
log.Error("setup key can't be empty")
|
||||||
|
return fmt.Errorf("empty setup key")
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := DialClientGRPCServer(ctx, daemonAddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to connect to service CLI interface %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
request := proto.LoginRequest{
|
||||||
|
SetupKey: setupKey,
|
||||||
|
PresharedKey: preSharedKey,
|
||||||
|
ManagementUrl: managementURL,
|
||||||
|
}
|
||||||
|
client := proto.NewDaemonServiceClient(conn)
|
||||||
|
err = WithBackOff(func() error {
|
||||||
|
if _, err := client.Login(ctx, &request); err != nil {
|
||||||
|
log.Errorf("try login: %v", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("backoff cycle failed: %v", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// loginPeer attempts to login to Management Service. If peer wasn't registered, tries the registration flow.
|
|
||||||
func loginPeer(serverPublicKey wgtypes.Key, client *mgm.GrpcClient, setupKey string) (*mgmProto.LoginResponse, error) {
|
|
||||||
|
|
||||||
loginResp, err := client.Login(serverPublicKey)
|
|
||||||
if err != nil {
|
|
||||||
if s, ok := status.FromError(err); ok && s.Code() == codes.PermissionDenied {
|
|
||||||
log.Debugf("peer registration required")
|
|
||||||
return registerPeer(serverPublicKey, client, setupKey)
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("peer has successfully logged-in to Management Service")
|
|
||||||
|
|
||||||
return loginResp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// registerPeer checks whether setupKey was provided via cmd line and if not then it prompts user to enter a key.
|
|
||||||
// Otherwise tries to register with the provided setupKey via command line.
|
|
||||||
func registerPeer(serverPublicKey wgtypes.Key, client *mgm.GrpcClient, setupKey string) (*mgmProto.LoginResponse, error) {
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if setupKey == "" {
|
|
||||||
setupKey, err = promptPeerSetupKey()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed getting setup key from user: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
validSetupKey, err := uuid.Parse(setupKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("sending peer registration request to Management Service")
|
|
||||||
info := system.GetInfo()
|
|
||||||
loginResp, err := client.Register(serverPublicKey, validSetupKey.String(), info)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed registering peer %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("peer has been successfully registered on Management Service")
|
|
||||||
|
|
||||||
return loginResp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// promptPeerSetupKey prompts user to enter Setup Key
|
|
||||||
func promptPeerSetupKey() (string, error) {
|
|
||||||
fmt.Print("Enter setup key: ")
|
|
||||||
|
|
||||||
s := bufio.NewScanner(os.Stdin)
|
|
||||||
for s.Scan() {
|
|
||||||
input := s.Text()
|
|
||||||
if input != "" {
|
|
||||||
return input, nil
|
|
||||||
}
|
|
||||||
fmt.Println("Specified key is empty, try again:")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", s.Err()
|
|
||||||
}
|
|
||||||
|
@ -2,13 +2,14 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/wiretrustee/wiretrustee/client/internal"
|
"github.com/wiretrustee/wiretrustee/client/internal"
|
||||||
"github.com/wiretrustee/wiretrustee/iface"
|
"github.com/wiretrustee/wiretrustee/iface"
|
||||||
mgmt "github.com/wiretrustee/wiretrustee/management/server"
|
mgmt "github.com/wiretrustee/wiretrustee/management/server"
|
||||||
"github.com/wiretrustee/wiretrustee/util"
|
"github.com/wiretrustee/wiretrustee/util"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var mgmAddr string
|
var mgmAddr string
|
||||||
@ -25,12 +26,11 @@ func TestLogin_Start(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
_, listener := startManagement(config, t)
|
_, listener := startManagement(t, config)
|
||||||
mgmAddr = listener.Addr().String()
|
mgmAddr = listener.Addr().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogin(t *testing.T) {
|
func TestLogin(t *testing.T) {
|
||||||
|
|
||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
confPath := tempDir + "/config.json"
|
confPath := tempDir + "/config.json"
|
||||||
mgmtURL := fmt.Sprintf("http://%s", mgmAddr)
|
mgmtURL := fmt.Sprintf("http://%s", mgmAddr)
|
||||||
@ -38,6 +38,8 @@ func TestLogin(t *testing.T) {
|
|||||||
"login",
|
"login",
|
||||||
"--config",
|
"--config",
|
||||||
confPath,
|
confPath,
|
||||||
|
"--log-file",
|
||||||
|
"console",
|
||||||
"--setup-key",
|
"--setup-key",
|
||||||
strings.ToUpper("a2c8e62b-38f5-4553-b31e-dd66c696cebb"),
|
strings.ToUpper("a2c8e62b-38f5-4553-b31e-dd66c696cebb"),
|
||||||
"--management-url",
|
"--management-url",
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
"github.com/wiretrustee/wiretrustee/client/internal"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/cenkalti/backoff/v4"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -19,6 +26,7 @@ var (
|
|||||||
logLevel string
|
logLevel string
|
||||||
defaultLogFile string
|
defaultLogFile string
|
||||||
logFile string
|
logFile string
|
||||||
|
daemonAddr string
|
||||||
managementURL string
|
managementURL string
|
||||||
setupKey string
|
setupKey string
|
||||||
preSharedKey string
|
preSharedKey string
|
||||||
@ -37,8 +45,8 @@ var (
|
|||||||
func Execute() error {
|
func Execute() error {
|
||||||
return rootCmd.Execute()
|
return rootCmd.Execute()
|
||||||
}
|
}
|
||||||
func init() {
|
|
||||||
|
|
||||||
|
func init() {
|
||||||
stopCh = make(chan int)
|
stopCh = make(chan int)
|
||||||
cleanupCh = make(chan struct{})
|
cleanupCh = make(chan struct{})
|
||||||
|
|
||||||
@ -49,6 +57,11 @@ func init() {
|
|||||||
defaultLogFile = os.Getenv("PROGRAMDATA") + "\\Wiretrustee\\" + "client.log"
|
defaultLogFile = os.Getenv("PROGRAMDATA") + "\\Wiretrustee\\" + "client.log"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultDaemonAddr := "unix:///var/run/wiretrustee.sock"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
defaultDaemonAddr = "tcp://127.0.0.1:41731"
|
||||||
|
}
|
||||||
|
rootCmd.PersistentFlags().StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]")
|
||||||
rootCmd.PersistentFlags().StringVar(&managementURL, "management-url", "", fmt.Sprintf("Management Service URL [http|https]://[host]:[port] (default \"%s\")", internal.ManagementURLDefault().String()))
|
rootCmd.PersistentFlags().StringVar(&managementURL, "management-url", "", fmt.Sprintf("Management Service URL [http|https]://[host]:[port] (default \"%s\")", internal.ManagementURLDefault().String()))
|
||||||
rootCmd.PersistentFlags().StringVar(&configPath, "config", defaultConfigPath, "Wiretrustee config file location")
|
rootCmd.PersistentFlags().StringVar(&configPath, "config", defaultConfigPath, "Wiretrustee config file location")
|
||||||
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "sets Wiretrustee log level")
|
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "sets Wiretrustee log level")
|
||||||
@ -57,6 +70,8 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().StringVar(&preSharedKey, "preshared-key", "", "Sets Wireguard PreSharedKey property. If set, then only peers that have the same key can communicate.")
|
rootCmd.PersistentFlags().StringVar(&preSharedKey, "preshared-key", "", "Sets Wireguard PreSharedKey property. If set, then only peers that have the same key can communicate.")
|
||||||
rootCmd.AddCommand(serviceCmd)
|
rootCmd.AddCommand(serviceCmd)
|
||||||
rootCmd.AddCommand(upCmd)
|
rootCmd.AddCommand(upCmd)
|
||||||
|
rootCmd.AddCommand(downCmd)
|
||||||
|
rootCmd.AddCommand(statusCmd)
|
||||||
rootCmd.AddCommand(loginCmd)
|
rootCmd.AddCommand(loginCmd)
|
||||||
rootCmd.AddCommand(versionCmd)
|
rootCmd.AddCommand(versionCmd)
|
||||||
serviceCmd.AddCommand(runCmd, startCmd, stopCmd, restartCmd) // service control commands are subcommands of service
|
serviceCmd.AddCommand(runCmd, startCmd, stopCmd, restartCmd) // service control commands are subcommands of service
|
||||||
@ -79,7 +94,6 @@ func SetupCloseHandler() {
|
|||||||
func SetFlagsFromEnvVars() {
|
func SetFlagsFromEnvVars() {
|
||||||
flags := rootCmd.PersistentFlags()
|
flags := rootCmd.PersistentFlags()
|
||||||
flags.VisitAll(func(f *pflag.Flag) {
|
flags.VisitAll(func(f *pflag.Flag) {
|
||||||
|
|
||||||
envVar := FlagNameToEnvVar(f.Name)
|
envVar := FlagNameToEnvVar(f.Name)
|
||||||
|
|
||||||
if value, present := os.LookupEnv(envVar); present {
|
if value, present := os.LookupEnv(envVar); present {
|
||||||
@ -99,3 +113,34 @@ func FlagNameToEnvVar(f string) string {
|
|||||||
upper := strings.ToUpper(parsed)
|
upper := strings.ToUpper(parsed)
|
||||||
return prefix + upper
|
return prefix + upper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DialClientGRPCServer returns client connection to the dameno server.
|
||||||
|
func DialClientGRPCServer(ctx context.Context, addr string) (*grpc.ClientConn, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, time.Second*3)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
return grpc.DialContext(
|
||||||
|
ctx,
|
||||||
|
strings.TrimPrefix(addr, "tcp://"),
|
||||||
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBackOff execute function in backoff cycle.
|
||||||
|
func WithBackOff(bf func() error) error {
|
||||||
|
return backoff.RetryNotify(bf, CLIBackOffSettings, func(err error, duration time.Duration) {
|
||||||
|
log.Warnf("retrying Login to the Management service in %v due to error %v", duration, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CLIBackOffSettings is default backoff settings for CLI commands.
|
||||||
|
var CLIBackOffSettings = &backoff.ExponentialBackOff{
|
||||||
|
InitialInterval: time.Second,
|
||||||
|
RandomizationFactor: backoff.DefaultRandomizationFactor,
|
||||||
|
Multiplier: backoff.DefaultMultiplier,
|
||||||
|
MaxInterval: 10 * time.Second,
|
||||||
|
MaxElapsedTime: 30 * time.Second,
|
||||||
|
Stop: backoff.Stop,
|
||||||
|
Clock: backoff.SystemClock,
|
||||||
|
}
|
||||||
|
@ -1,14 +1,30 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/kardianos/service"
|
"github.com/kardianos/service"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
type program struct {
|
type program struct {
|
||||||
|
ctx context.Context
|
||||||
cmd *cobra.Command
|
cmd *cobra.Command
|
||||||
args []string
|
args []string
|
||||||
|
serv *grpc.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProgram(cmd *cobra.Command, args []string) *program {
|
||||||
|
ctx := internal.CtxInitState(cmd.Context())
|
||||||
|
return &program{
|
||||||
|
ctx: ctx,
|
||||||
|
cmd: cmd,
|
||||||
|
args: args,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSVCConfig() *service.Config {
|
func newSVCConfig() *service.Config {
|
||||||
@ -28,9 +44,8 @@ func newSVC(prg *program, conf *service.Config) (service.Service, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var serviceCmd = &cobra.Command{
|
||||||
serviceCmd = &cobra.Command{
|
|
||||||
Use: "service",
|
Use: "service",
|
||||||
Short: "manages wiretrustee service",
|
Short: "manages wiretrustee service",
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
@ -1,23 +1,60 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/kardianos/service"
|
"github.com/kardianos/service"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/proto"
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/server"
|
||||||
"github.com/wiretrustee/wiretrustee/util"
|
"github.com/wiretrustee/wiretrustee/util"
|
||||||
"time"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *program) Start(service.Service) error {
|
func (p *program) Start(svc service.Service) error {
|
||||||
|
|
||||||
// Start should not block. Do the actual work async.
|
// Start should not block. Do the actual work async.
|
||||||
log.Info("starting service") //nolint
|
log.Info("starting service") //nolint
|
||||||
go func() {
|
go func() {
|
||||||
err := runClient()
|
// in any case, even if configuration does not exists we run daemon to serve CLI gRPC API.
|
||||||
if err != nil {
|
p.serv = grpc.NewServer()
|
||||||
log.Errorf("stopped Wiretrustee client app due to error: %v", err)
|
|
||||||
|
split := strings.Split(daemonAddr, "://")
|
||||||
|
switch split[0] {
|
||||||
|
case "unix":
|
||||||
|
// cleanup failed close
|
||||||
|
stat, err := os.Stat(split[1])
|
||||||
|
if err == nil && !stat.IsDir() {
|
||||||
|
if err := os.Remove(split[1]); err != nil {
|
||||||
|
log.Debugf("remove socket file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "tcp":
|
||||||
|
default:
|
||||||
|
log.Errorf("unsupported daemon address protocol: %v", split[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listen, err := net.Listen(split[0], split[1])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to listen daemon interface: %v", err)
|
||||||
|
}
|
||||||
|
defer listen.Close()
|
||||||
|
|
||||||
|
serverInstance := server.New(p.ctx, managementURL, configPath, stopCh, cleanupCh)
|
||||||
|
if err := serverInstance.Start(); err != nil {
|
||||||
|
log.Fatalf("failed start daemon: %v", err)
|
||||||
|
}
|
||||||
|
proto.RegisterDaemonServiceServer(p.serv, serverInstance)
|
||||||
|
|
||||||
|
log.Printf("started daemon server: %v", split[1])
|
||||||
|
if err := p.serv.Serve(listen); err != nil {
|
||||||
|
log.Errorf("failed to serve daemon requests: %v", err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -27,6 +64,11 @@ func (p *program) Stop(service.Service) error {
|
|||||||
stopCh <- 1
|
stopCh <- 1
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// stop CLI daemon service
|
||||||
|
if p.serv != nil {
|
||||||
|
p.serv.GracefulStop()
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-cleanupCh:
|
case <-cleanupCh:
|
||||||
case <-time.After(time.Second * 10):
|
case <-time.After(time.Second * 10):
|
||||||
@ -36,8 +78,7 @@ func (p *program) Stop(service.Service) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var runCmd = &cobra.Command{
|
||||||
runCmd = &cobra.Command{
|
|
||||||
Use: "run",
|
Use: "run",
|
||||||
Short: "runs wiretrustee as service",
|
Short: "runs wiretrustee as service",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -51,12 +92,7 @@ var (
|
|||||||
|
|
||||||
SetupCloseHandler()
|
SetupCloseHandler()
|
||||||
|
|
||||||
prg := &program{
|
s, err := newSVC(newProgram(cmd, args), newSVCConfig())
|
||||||
cmd: cmd,
|
|
||||||
args: args,
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := newSVC(prg, newSVCConfig())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrln(err)
|
cmd.PrintErrln(err)
|
||||||
return
|
return
|
||||||
@ -69,10 +105,8 @@ var (
|
|||||||
cmd.Printf("Wiretrustee service is running")
|
cmd.Printf("Wiretrustee service is running")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var startCmd = &cobra.Command{
|
||||||
startCmd = &cobra.Command{
|
|
||||||
Use: "start",
|
Use: "start",
|
||||||
Short: "starts wiretrustee service",
|
Short: "starts wiretrustee service",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -83,7 +117,7 @@ var (
|
|||||||
log.Errorf("failed initializing log %v", err)
|
log.Errorf("failed initializing log %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s, err := newSVC(&program{}, newSVCConfig())
|
s, err := newSVC(newProgram(cmd, args), newSVCConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrln(err)
|
cmd.PrintErrln(err)
|
||||||
return err
|
return err
|
||||||
@ -97,10 +131,8 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var stopCmd = &cobra.Command{
|
||||||
stopCmd = &cobra.Command{
|
|
||||||
Use: "stop",
|
Use: "stop",
|
||||||
Short: "stops wiretrustee service",
|
Short: "stops wiretrustee service",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -110,7 +142,7 @@ var (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed initializing log %v", err)
|
log.Errorf("failed initializing log %v", err)
|
||||||
}
|
}
|
||||||
s, err := newSVC(&program{}, newSVCConfig())
|
s, err := newSVC(newProgram(cmd, args), newSVCConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrln(err)
|
cmd.PrintErrln(err)
|
||||||
return
|
return
|
||||||
@ -123,10 +155,8 @@ var (
|
|||||||
cmd.Println("Wiretrustee service has been stopped")
|
cmd.Println("Wiretrustee service has been stopped")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var restartCmd = &cobra.Command{
|
||||||
restartCmd = &cobra.Command{
|
|
||||||
Use: "restart",
|
Use: "restart",
|
||||||
Short: "restarts wiretrustee service",
|
Short: "restarts wiretrustee service",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -136,7 +166,7 @@ var (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed initializing log %v", err)
|
log.Errorf("failed initializing log %v", err)
|
||||||
}
|
}
|
||||||
s, err := newSVC(&program{}, newSVCConfig())
|
s, err := newSVC(newProgram(cmd, args), newSVCConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrln(err)
|
cmd.PrintErrln(err)
|
||||||
return
|
return
|
||||||
@ -149,4 +179,3 @@ var (
|
|||||||
cmd.Println("Wiretrustee service has been restarted")
|
cmd.Println("Wiretrustee service has been restarted")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var installCmd = &cobra.Command{
|
||||||
installCmd = &cobra.Command{
|
|
||||||
Use: "install",
|
Use: "install",
|
||||||
Short: "installs wiretrustee service",
|
Short: "installs wiretrustee service",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -28,7 +28,7 @@ var (
|
|||||||
svcConfig.Dependencies = []string{"After=network.target syslog.target"}
|
svcConfig.Dependencies = []string{"After=network.target syslog.target"}
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := newSVC(&program{}, svcConfig)
|
s, err := newSVC(newProgram(cmd, args), svcConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrln(err)
|
cmd.PrintErrln(err)
|
||||||
return err
|
return err
|
||||||
@ -43,16 +43,14 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var uninstallCmd = &cobra.Command{
|
||||||
uninstallCmd = &cobra.Command{
|
|
||||||
Use: "uninstall",
|
Use: "uninstall",
|
||||||
Short: "uninstalls wiretrustee service from system",
|
Short: "uninstalls wiretrustee service from system",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
SetFlagsFromEnvVars()
|
SetFlagsFromEnvVars()
|
||||||
|
|
||||||
s, err := newSVC(&program{}, newSVCConfig())
|
s, err := newSVC(newProgram(cmd, args), newSVCConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrln(err)
|
cmd.PrintErrln(err)
|
||||||
return
|
return
|
||||||
@ -66,4 +64,4 @@ var (
|
|||||||
cmd.Println("Wiretrustee has been uninstalled")
|
cmd.Println("Wiretrustee has been uninstalled")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
37
client/cmd/status.go
Normal file
37
client/cmd/status.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/internal"
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var statusCmd = &cobra.Command{
|
||||||
|
Use: "status",
|
||||||
|
Short: "status of the Wiretrustee Service",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
SetFlagsFromEnvVars()
|
||||||
|
ctx := internal.CtxInitState(context.Background())
|
||||||
|
|
||||||
|
conn, err := DialClientGRPCServer(ctx, daemonAddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to connect to service CLI interface %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
resp, err := proto.NewDaemonServiceClient(conn).Status(cmd.Context(), &proto.StatusRequest{})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("status failed: %v", status.Convert(err).Message())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("status: %v", resp.Status)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
@ -1,13 +1,18 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
clientProto "github.com/wiretrustee/wiretrustee/client/proto"
|
||||||
|
client "github.com/wiretrustee/wiretrustee/client/server"
|
||||||
mgmtProto "github.com/wiretrustee/wiretrustee/management/proto"
|
mgmtProto "github.com/wiretrustee/wiretrustee/management/proto"
|
||||||
mgmt "github.com/wiretrustee/wiretrustee/management/server"
|
mgmt "github.com/wiretrustee/wiretrustee/management/server"
|
||||||
sigProto "github.com/wiretrustee/wiretrustee/signal/proto"
|
sigProto "github.com/wiretrustee/wiretrustee/signal/proto"
|
||||||
sig "github.com/wiretrustee/wiretrustee/signal/server"
|
sig "github.com/wiretrustee/wiretrustee/signal/server"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func startSignal(t *testing.T) (*grpc.Server, net.Listener) {
|
func startSignal(t *testing.T) (*grpc.Server, net.Listener) {
|
||||||
@ -26,7 +31,7 @@ func startSignal(t *testing.T) (*grpc.Server, net.Listener) {
|
|||||||
return s, lis
|
return s, lis
|
||||||
}
|
}
|
||||||
|
|
||||||
func startManagement(config *mgmt.Config, t *testing.T) (*grpc.Server, net.Listener) {
|
func startManagement(t *testing.T, config *mgmt.Config) (*grpc.Server, net.Listener) {
|
||||||
lis, err := net.Listen("tcp", ":0")
|
lis, err := net.Listen("tcp", ":0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -48,9 +53,40 @@ func startManagement(config *mgmt.Config, t *testing.T) (*grpc.Server, net.Liste
|
|||||||
go func() {
|
go func() {
|
||||||
if err := s.Serve(lis); err != nil {
|
if err := s.Serve(lis); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return s, lis
|
return s, lis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startClientDaemon(
|
||||||
|
t *testing.T, ctx context.Context, managementURL, configPath string,
|
||||||
|
stopCh chan int, cleanupCh chan<- struct{},
|
||||||
|
) (*grpc.Server, net.Listener) {
|
||||||
|
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
s := grpc.NewServer()
|
||||||
|
|
||||||
|
server := client.New(
|
||||||
|
ctx,
|
||||||
|
managementURL,
|
||||||
|
configPath,
|
||||||
|
stopCh,
|
||||||
|
cleanupCh,
|
||||||
|
)
|
||||||
|
if err := server.Start(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
clientProto.RegisterDaemonServiceServer(s, server)
|
||||||
|
go func() {
|
||||||
|
if err := s.Serve(lis); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
return s, lis
|
||||||
|
}
|
||||||
|
262
client/cmd/up.go
262
client/cmd/up.go
@ -1,239 +1,77 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"github.com/wiretrustee/wiretrustee/iface"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v4"
|
|
||||||
"github.com/kardianos/service"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/wiretrustee/wiretrustee/client/internal"
|
"github.com/wiretrustee/wiretrustee/client/internal"
|
||||||
mgm "github.com/wiretrustee/wiretrustee/management/client"
|
"github.com/wiretrustee/wiretrustee/client/proto"
|
||||||
mgmProto "github.com/wiretrustee/wiretrustee/management/proto"
|
|
||||||
signal "github.com/wiretrustee/wiretrustee/signal/client"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var upCmd = &cobra.Command{
|
||||||
upCmd = &cobra.Command{
|
|
||||||
Use: "up",
|
Use: "up",
|
||||||
Short: "install, login and start wiretrustee client",
|
Short: "install, login and start wiretrustee client",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
SetFlagsFromEnvVars()
|
SetFlagsFromEnvVars()
|
||||||
|
ctx := internal.CtxInitState(cmd.Context())
|
||||||
|
|
||||||
err := loginCmd.RunE(cmd, args)
|
// workaround to run without service
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if logFile == "console" {
|
if logFile == "console" {
|
||||||
|
config, err := internal.GetConfig(managementURL, configPath, preSharedKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("get config file: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = WithBackOff(func() error {
|
||||||
|
return internal.Login(ctx, config, setupKey)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("backoff cycle failed: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
SetupCloseHandler()
|
SetupCloseHandler()
|
||||||
return runClient()
|
return internal.RunClient(ctx, config, stopCh, cleanupCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := newSVC(&program{}, newSVCConfig())
|
conn, err := DialClientGRPCServer(ctx, daemonAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrln(err)
|
log.Errorf("failed to connect to service CLI interface %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
daemonClient := proto.NewDaemonServiceClient(conn)
|
||||||
|
|
||||||
|
loginRequest := proto.LoginRequest{
|
||||||
|
SetupKey: setupKey,
|
||||||
|
PresharedKey: preSharedKey,
|
||||||
|
}
|
||||||
|
err = WithBackOff(func() error {
|
||||||
|
_, err := daemonClient.Login(ctx, &loginRequest)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("backoff cycle failed: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
srvStatus, err := s.Status()
|
status, err := daemonClient.Status(ctx, &proto.StatusRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == service.ErrNotInstalled {
|
log.Errorf("get status: %v", err)
|
||||||
log.Infof("%s. Installing it now", err.Error())
|
|
||||||
e := installCmd.RunE(cmd, args)
|
|
||||||
if e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Warnf("failed retrieving service status: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if srvStatus == service.StatusRunning {
|
|
||||||
stopCmd.Run(cmd, args)
|
|
||||||
}
|
|
||||||
return startCmd.RunE(cmd, args)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// createEngineConfig converts configuration received from Management Service to EngineConfig
|
|
||||||
func createEngineConfig(key wgtypes.Key, config *internal.Config, peerConfig *mgmProto.PeerConfig) (*internal.EngineConfig, error) {
|
|
||||||
iFaceBlackList := make(map[string]struct{})
|
|
||||||
for i := 0; i < len(config.IFaceBlackList); i += 2 {
|
|
||||||
iFaceBlackList[config.IFaceBlackList[i]] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
engineConf := &internal.EngineConfig{
|
|
||||||
WgIfaceName: config.WgIface,
|
|
||||||
WgAddr: peerConfig.Address,
|
|
||||||
IFaceBlackList: iFaceBlackList,
|
|
||||||
WgPrivateKey: key,
|
|
||||||
WgPort: iface.DefaultWgPort,
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.PreSharedKey != "" {
|
|
||||||
preSharedKey, err := wgtypes.ParseKey(config.PreSharedKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
engineConf.PreSharedKey = &preSharedKey
|
|
||||||
}
|
|
||||||
|
|
||||||
return engineConf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// connectToSignal creates Signal Service client and established a connection
|
|
||||||
func connectToSignal(ctx context.Context, wtConfig *mgmProto.WiretrusteeConfig, ourPrivateKey wgtypes.Key) (*signal.GrpcClient, error) {
|
|
||||||
var sigTLSEnabled bool
|
|
||||||
if wtConfig.Signal.Protocol == mgmProto.HostConfig_HTTPS {
|
|
||||||
sigTLSEnabled = true
|
|
||||||
} else {
|
|
||||||
sigTLSEnabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
signalClient, err := signal.NewClient(ctx, wtConfig.Signal.Uri, ourPrivateKey, sigTLSEnabled)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("error while connecting to the Signal Exchange Service %s: %s", wtConfig.Signal.Uri, err)
|
|
||||||
return nil, status.Errorf(codes.FailedPrecondition, "failed connecting to Signal Service : %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return signalClient, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// connectToManagement creates Management Services client, establishes a connection, logs-in and gets a global Wiretrustee config (signal, turn, stun hosts, etc)
|
|
||||||
func connectToManagement(ctx context.Context, managementAddr string, ourPrivateKey wgtypes.Key, tlsEnabled bool) (*mgm.GrpcClient, *mgmProto.LoginResponse, error) {
|
|
||||||
log.Debugf("connecting to management server %s", managementAddr)
|
|
||||||
client, err := mgm.NewClient(ctx, managementAddr, ourPrivateKey, tlsEnabled)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, status.Errorf(codes.FailedPrecondition, "failed connecting to Management Service : %s", err)
|
|
||||||
}
|
|
||||||
log.Debugf("connected to management server %s", managementAddr)
|
|
||||||
|
|
||||||
serverPublicKey, err := client.GetServerPublicKey()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, status.Errorf(codes.FailedPrecondition, "failed while getting Management Service public key: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
loginResp, err := client.Login(*serverPublicKey)
|
|
||||||
if err != nil {
|
|
||||||
if s, ok := status.FromError(err); ok && s.Code() == codes.PermissionDenied {
|
|
||||||
log.Error("peer registration required. Please run wiretrustee login command first")
|
|
||||||
return nil, nil, err
|
|
||||||
} else {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("peer logged in to Management Service %s", managementAddr)
|
|
||||||
|
|
||||||
return client, loginResp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func runClient() error {
|
|
||||||
var backOff = &backoff.ExponentialBackOff{
|
|
||||||
InitialInterval: time.Second,
|
|
||||||
RandomizationFactor: backoff.DefaultRandomizationFactor,
|
|
||||||
Multiplier: backoff.DefaultMultiplier,
|
|
||||||
MaxInterval: 10 * time.Second,
|
|
||||||
MaxElapsedTime: 24 * 3 * time.Hour, //stop the client after 3 days trying (must be a huge problem, e.g permission denied)
|
|
||||||
Stop: backoff.Stop,
|
|
||||||
Clock: backoff.SystemClock,
|
|
||||||
}
|
|
||||||
|
|
||||||
operation := func() error {
|
|
||||||
|
|
||||||
config, err := internal.ReadConfig(managementURL, configPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed reading config %s %v", configPath, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//validate our peer's Wireguard PRIVATE key
|
if status.Status != string(internal.StatusIdle) {
|
||||||
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
|
log.Warnf("already connected")
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
mgmTlsEnabled := false
|
|
||||||
if config.ManagementURL.Scheme == "https" {
|
|
||||||
mgmTlsEnabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// connect (just a connection, no stream yet) and login to Management Service to get an initial global Wiretrustee config
|
|
||||||
mgmClient, loginResp, err := connectToManagement(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// with the global Wiretrustee config in hand connect (just a connection, no stream yet) Signal
|
|
||||||
signalClient, err := connectToSignal(ctx, loginResp.GetWiretrusteeConfig(), myPrivateKey)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
peerConfig := loginResp.GetPeerConfig()
|
|
||||||
|
|
||||||
engineConfig, err := createEngineConfig(myPrivateKey, config, peerConfig)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
engine := internal.NewEngine(signalClient, mgmClient, engineConfig, cancel, ctx)
|
|
||||||
err = engine.Start()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("error while starting Wiretrustee Connection Engine: %s", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Print("Wiretrustee engine started, my IP is: ", peerConfig.Address)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-stopCh:
|
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
|
|
||||||
backOff.Reset()
|
|
||||||
|
|
||||||
err = mgmClient.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed closing Management Service client %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = signalClient.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed closing Signal Service client %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = engine.Stop()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed stopping engine %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
cleanupCh <- struct{}{}
|
|
||||||
}()
|
|
||||||
|
|
||||||
log.Info("stopped Wiretrustee client")
|
|
||||||
|
|
||||||
return ctx.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
err := backoff.Retry(operation, backOff)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("exiting client retry loop due to unrecoverable error: %s", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := daemonClient.Up(ctx, &proto.UpRequest{}); err != nil {
|
||||||
|
log.Errorf("call service up method: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
98
client/cmd/up_daemon_test.go
Normal file
98
client/cmd/up_daemon_test.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/internal"
|
||||||
|
mgmt "github.com/wiretrustee/wiretrustee/management/server"
|
||||||
|
"github.com/wiretrustee/wiretrustee/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUpDaemon_Start(t *testing.T) {
|
||||||
|
config := &mgmt.Config{}
|
||||||
|
_, err := util.ReadJson("../testdata/management.json", config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
testDir := t.TempDir()
|
||||||
|
config.Datadir = testDir
|
||||||
|
err = util.CopyFileContents("../testdata/store.json", filepath.Join(testDir, "store.json"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, signalLis := startSignal(t)
|
||||||
|
signalAddr = signalLis.Addr().String()
|
||||||
|
config.Signal.URI = signalAddr
|
||||||
|
|
||||||
|
_, mgmLis := startManagement(t, config)
|
||||||
|
mgmAddr = mgmLis.Addr().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpDaemon(t *testing.T) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
confPath := tempDir + "/config.json"
|
||||||
|
|
||||||
|
stopCh = make(chan int, 1)
|
||||||
|
cleanupCh = make(chan struct{}, 1)
|
||||||
|
|
||||||
|
ctx := internal.CtxInitState(context.Background())
|
||||||
|
state := internal.CtxGetState(ctx)
|
||||||
|
|
||||||
|
_, cliLis := startClientDaemon(t, ctx, "http://"+mgmAddr, confPath, stopCh, cleanupCh)
|
||||||
|
|
||||||
|
cliAddr = cliLis.Addr().String()
|
||||||
|
|
||||||
|
daemonAddr = "tcp://" + cliAddr
|
||||||
|
rootCmd.SetArgs([]string{
|
||||||
|
"login",
|
||||||
|
"--daemon-addr", "tcp://" + cliAddr,
|
||||||
|
"--setup-key", "A2C8E62B-38F5-4553-B31E-DD66C696CEBB",
|
||||||
|
"--log-file", "",
|
||||||
|
})
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
t.Errorf("expected no error while running up command, got %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
if status, err := state.Status(); err != nil && status != internal.StatusIdle {
|
||||||
|
t.Errorf("wrong status after login: %s, %v", internal.StatusIdle, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.SetArgs([]string{
|
||||||
|
"up",
|
||||||
|
"--daemon-addr", "tcp://" + cliAddr,
|
||||||
|
"--log-file", "",
|
||||||
|
})
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
t.Errorf("expected no error while running up command, got %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
if status, err := state.Status(); err != nil && status != internal.StatusConnected {
|
||||||
|
t.Errorf("wrong status after connect: %s, %v", status, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.SetArgs([]string{
|
||||||
|
"status",
|
||||||
|
"--daemon-addr", "tcp://" + cliAddr,
|
||||||
|
})
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
t.Errorf("expected no error while running up command, got %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
|
||||||
|
rootCmd.SetErr(nil)
|
||||||
|
rootCmd.SetArgs([]string{"down", "--daemon-addr", "tcp://" + cliAddr})
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
t.Errorf("expected no error while running up command, got %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// we can't check status here, because context already canceled
|
||||||
|
}
|
@ -1,16 +1,20 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/wiretrustee/wiretrustee/iface"
|
|
||||||
mgmt "github.com/wiretrustee/wiretrustee/management/server"
|
|
||||||
"github.com/wiretrustee/wiretrustee/util"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/wiretrustee/wiretrustee/iface"
|
||||||
|
mgmt "github.com/wiretrustee/wiretrustee/management/server"
|
||||||
|
"github.com/wiretrustee/wiretrustee/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var signalAddr string
|
var (
|
||||||
|
signalAddr string
|
||||||
|
cliAddr string
|
||||||
|
)
|
||||||
|
|
||||||
func TestUp_Start(t *testing.T) {
|
func TestUp_Start(t *testing.T) {
|
||||||
config := &mgmt.Config{}
|
config := &mgmt.Config{}
|
||||||
@ -29,15 +33,11 @@ func TestUp_Start(t *testing.T) {
|
|||||||
signalAddr = signalLis.Addr().String()
|
signalAddr = signalLis.Addr().String()
|
||||||
config.Signal.URI = signalAddr
|
config.Signal.URI = signalAddr
|
||||||
|
|
||||||
_, mgmLis := startManagement(config, t)
|
_, mgmLis := startManagement(t, config)
|
||||||
mgmAddr = mgmLis.Addr().String()
|
mgmAddr = mgmLis.Addr().String()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUp(t *testing.T) {
|
func TestUp(t *testing.T) {
|
||||||
|
|
||||||
//defer iface.Close("wt0")
|
|
||||||
|
|
||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
confPath := tempDir + "/config.json"
|
confPath := tempDir + "/config.json"
|
||||||
mgmtURL, err := url.Parse("http://" + mgmAddr)
|
mgmtURL, err := url.Parse("http://" + mgmAddr)
|
||||||
@ -58,12 +58,13 @@ func TestUp(t *testing.T) {
|
|||||||
"--log-file",
|
"--log-file",
|
||||||
"console",
|
"console",
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err = rootCmd.Execute()
|
if err := rootCmd.Execute(); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Errorf("expected no error while running up command, got %v", err)
|
t.Errorf("expected no error while running up command, got %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
|
||||||
timeout := 15 * time.Second
|
timeout := 15 * time.Second
|
||||||
timeoutChannel := time.After(timeout)
|
timeoutChannel := time.After(timeout)
|
||||||
|
210
client/internal/connect.go
Normal file
210
client/internal/connect.go
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/wiretrustee/wiretrustee/iface"
|
||||||
|
mgm "github.com/wiretrustee/wiretrustee/management/client"
|
||||||
|
mgmProto "github.com/wiretrustee/wiretrustee/management/proto"
|
||||||
|
signal "github.com/wiretrustee/wiretrustee/signal/client"
|
||||||
|
|
||||||
|
"github.com/cenkalti/backoff/v4"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RunClient with main logic.
|
||||||
|
func RunClient(
|
||||||
|
ctx context.Context, config *Config, stopCh <-chan int, cleanupCh chan<- struct{},
|
||||||
|
) error {
|
||||||
|
backOff := &backoff.ExponentialBackOff{
|
||||||
|
InitialInterval: time.Second,
|
||||||
|
RandomizationFactor: backoff.DefaultRandomizationFactor,
|
||||||
|
Multiplier: backoff.DefaultMultiplier,
|
||||||
|
MaxInterval: 10 * time.Second,
|
||||||
|
MaxElapsedTime: 24 * 3 * time.Hour, // stop the client after 3 days trying (must be a huge problem, e.g permission denied)
|
||||||
|
Stop: backoff.Stop,
|
||||||
|
Clock: backoff.SystemClock,
|
||||||
|
}
|
||||||
|
|
||||||
|
state := CtxGetState(ctx)
|
||||||
|
defer state.Set(StatusIdle)
|
||||||
|
|
||||||
|
wrapErr := state.Wrap
|
||||||
|
operation := func() error {
|
||||||
|
// if context cancelled we not start new backoff cycle
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
state.Set(StatusConnecting)
|
||||||
|
// validate our peer's Wireguard PRIVATE key
|
||||||
|
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
|
||||||
|
return wrapErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mgmTlsEnabled bool
|
||||||
|
if config.ManagementURL.Scheme == "https" {
|
||||||
|
mgmTlsEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect (just a connection, no stream yet) and login to Management Service to get an initial global Wiretrustee config
|
||||||
|
mgmClient, loginResp, err := connectToManagement(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn(err)
|
||||||
|
return wrapErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// with the global Wiretrustee config in hand connect (just a connection, no stream yet) Signal
|
||||||
|
signalClient, err := connectToSignal(ctx, loginResp.GetWiretrusteeConfig(), myPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return wrapErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peerConfig := loginResp.GetPeerConfig()
|
||||||
|
|
||||||
|
engineConfig, err := createEngineConfig(myPrivateKey, config, peerConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return wrapErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
engine := NewEngine(ctx, cancel, signalClient, mgmClient, engineConfig)
|
||||||
|
err = engine.Start()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("error while starting Wiretrustee Connection Engine: %s", err)
|
||||||
|
return wrapErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("Wiretrustee engine started, my IP is: ", peerConfig.Address)
|
||||||
|
state.Set(StatusConnected)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-stopCh:
|
||||||
|
case <-ctx.Done():
|
||||||
|
}
|
||||||
|
|
||||||
|
backOff.Reset()
|
||||||
|
|
||||||
|
err = mgmClient.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed closing Management Service client %v", err)
|
||||||
|
return wrapErr(err)
|
||||||
|
}
|
||||||
|
err = signalClient.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed closing Signal Service client %v", err)
|
||||||
|
return wrapErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = engine.Stop()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed stopping engine %v", err)
|
||||||
|
return wrapErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
cleanupCh <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
log.Info("stopped Wiretrustee client")
|
||||||
|
|
||||||
|
if _, err := state.Status(); err == ErrResetConnection {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := backoff.Retry(operation, backOff)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("exiting client retry loop due to unrecoverable error: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createEngineConfig converts configuration received from Management Service to EngineConfig
|
||||||
|
func createEngineConfig(key wgtypes.Key, config *Config, peerConfig *mgmProto.PeerConfig) (*EngineConfig, error) {
|
||||||
|
iFaceBlackList := make(map[string]struct{})
|
||||||
|
for i := 0; i < len(config.IFaceBlackList); i += 2 {
|
||||||
|
iFaceBlackList[config.IFaceBlackList[i]] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
engineConf := &EngineConfig{
|
||||||
|
WgIfaceName: config.WgIface,
|
||||||
|
WgAddr: peerConfig.Address,
|
||||||
|
IFaceBlackList: iFaceBlackList,
|
||||||
|
WgPrivateKey: key,
|
||||||
|
WgPort: iface.DefaultWgPort,
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.PreSharedKey != "" {
|
||||||
|
preSharedKey, err := wgtypes.ParseKey(config.PreSharedKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
engineConf.PreSharedKey = &preSharedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return engineConf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// connectToSignal creates Signal Service client and established a connection
|
||||||
|
func connectToSignal(ctx context.Context, wtConfig *mgmProto.WiretrusteeConfig, ourPrivateKey wgtypes.Key) (*signal.GrpcClient, error) {
|
||||||
|
var sigTLSEnabled bool
|
||||||
|
if wtConfig.Signal.Protocol == mgmProto.HostConfig_HTTPS {
|
||||||
|
sigTLSEnabled = true
|
||||||
|
} else {
|
||||||
|
sigTLSEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
signalClient, err := signal.NewClient(ctx, wtConfig.Signal.Uri, ourPrivateKey, sigTLSEnabled)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("error while connecting to the Signal Exchange Service %s: %s", wtConfig.Signal.Uri, err)
|
||||||
|
return nil, status.Errorf(codes.FailedPrecondition, "failed connecting to Signal Service : %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return signalClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// connectToManagement creates Management Services client, establishes a connection, logs-in and gets a global Wiretrustee config (signal, turn, stun hosts, etc)
|
||||||
|
func connectToManagement(ctx context.Context, managementAddr string, ourPrivateKey wgtypes.Key, tlsEnabled bool) (*mgm.GrpcClient, *mgmProto.LoginResponse, error) {
|
||||||
|
log.Debugf("connecting to management server %s", managementAddr)
|
||||||
|
client, err := mgm.NewClient(ctx, managementAddr, ourPrivateKey, tlsEnabled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, status.Errorf(codes.FailedPrecondition, "failed connecting to Management Service : %s", err)
|
||||||
|
}
|
||||||
|
log.Debugf("connected to management server %s", managementAddr)
|
||||||
|
|
||||||
|
serverPublicKey, err := client.GetServerPublicKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, status.Errorf(codes.FailedPrecondition, "failed while getting Management Service public key: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
loginResp, err := client.Login(*serverPublicKey)
|
||||||
|
if err != nil {
|
||||||
|
if s, ok := status.FromError(err); ok && s.Code() == codes.PermissionDenied {
|
||||||
|
log.Error("peer registration required. Please run wiretrustee login command first")
|
||||||
|
return nil, nil, err
|
||||||
|
} else {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("peer logged in to Management Service %s", managementAddr)
|
||||||
|
|
||||||
|
return client, loginResp, nil
|
||||||
|
}
|
||||||
|
|
@ -31,6 +31,8 @@ const (
|
|||||||
PeerConnectionTimeoutMin = 30000 // ms
|
PeerConnectionTimeoutMin = 30000 // ms
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrResetConnection = fmt.Errorf("reset connection")
|
||||||
|
|
||||||
// EngineConfig is a config for the Engine
|
// EngineConfig is a config for the Engine
|
||||||
type EngineConfig struct {
|
type EngineConfig struct {
|
||||||
WgPort int
|
WgPort int
|
||||||
@ -95,10 +97,12 @@ type Peer struct {
|
|||||||
|
|
||||||
// NewEngine creates a new Connection Engine
|
// NewEngine creates a new Connection Engine
|
||||||
func NewEngine(
|
func NewEngine(
|
||||||
|
ctx context.Context, cancel context.CancelFunc,
|
||||||
signalClient signal.Client, mgmClient mgm.Client, config *EngineConfig,
|
signalClient signal.Client, mgmClient mgm.Client, config *EngineConfig,
|
||||||
cancel context.CancelFunc, ctx context.Context,
|
|
||||||
) *Engine {
|
) *Engine {
|
||||||
return &Engine{
|
return &Engine{
|
||||||
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
signal: signalClient,
|
signal: signalClient,
|
||||||
mgmClient: mgmClient,
|
mgmClient: mgmClient,
|
||||||
peerConns: map[string]*peer.Conn{},
|
peerConns: map[string]*peer.Conn{},
|
||||||
@ -106,8 +110,6 @@ func NewEngine(
|
|||||||
config: config,
|
config: config,
|
||||||
STUNs: []*ice.URL{},
|
STUNs: []*ice.URL{},
|
||||||
TURNs: []*ice.URL{},
|
TURNs: []*ice.URL{},
|
||||||
cancel: cancel,
|
|
||||||
ctx: ctx,
|
|
||||||
networkSerial: 0,
|
networkSerial: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,6 +382,7 @@ func (e *Engine) receiveManagementEvents() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// happens if management is unavailable for a long time.
|
// happens if management is unavailable for a long time.
|
||||||
// We want to cancel the operation of the whole client
|
// We want to cancel the operation of the whole client
|
||||||
|
_ = CtxGetState(e.ctx).Wrap(ErrResetConnection)
|
||||||
e.cancel()
|
e.cancel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -615,6 +618,7 @@ func (e *Engine) receiveSignalEvents() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// happens if signal is unavailable for a long time.
|
// happens if signal is unavailable for a long time.
|
||||||
// We want to cancel the operation of the whole client
|
// We want to cancel the operation of the whole client
|
||||||
|
_ = CtxGetState(e.ctx).Wrap(ErrResetConnection)
|
||||||
e.cancel()
|
e.cancel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestEngine_UpdateNetworkMap(t *testing.T) {
|
func TestEngine_UpdateNetworkMap(t *testing.T) {
|
||||||
|
|
||||||
// test setup
|
// test setup
|
||||||
key, err := wgtypes.GeneratePrivateKey()
|
key, err := wgtypes.GeneratePrivateKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -51,12 +50,12 @@ func TestEngine_UpdateNetworkMap(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
engine := NewEngine(&signal.MockClient{}, &mgmt.MockClient{}, &EngineConfig{
|
engine := NewEngine(ctx, cancel, &signal.MockClient{}, &mgmt.MockClient{}, &EngineConfig{
|
||||||
WgIfaceName: "utun100",
|
WgIfaceName: "utun100",
|
||||||
WgAddr: "100.64.0.1/24",
|
WgAddr: "100.64.0.1/24",
|
||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, cancel, ctx)
|
})
|
||||||
|
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
@ -157,7 +156,6 @@ func TestEngine_UpdateNetworkMap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range []testCase{case1, case2, case3, case4, case5} {
|
for _, c := range []testCase{case1, case2, case3, case4, case5} {
|
||||||
|
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
err = engine.updateNetworkMap(c.networkMap)
|
err = engine.updateNetworkMap(c.networkMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -179,13 +177,10 @@ func TestEngine_UpdateNetworkMap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEngine_Sync(t *testing.T) {
|
func TestEngine_Sync(t *testing.T) {
|
||||||
|
|
||||||
key, err := wgtypes.GeneratePrivateKey()
|
key, err := wgtypes.GeneratePrivateKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -199,7 +194,6 @@ func TestEngine_Sync(t *testing.T) {
|
|||||||
updates := make(chan *mgmtProto.SyncResponse)
|
updates := make(chan *mgmtProto.SyncResponse)
|
||||||
defer close(updates)
|
defer close(updates)
|
||||||
syncFunc := func(msgHandler func(msg *mgmtProto.SyncResponse) error) error {
|
syncFunc := func(msgHandler func(msg *mgmtProto.SyncResponse) error) error {
|
||||||
|
|
||||||
for msg := range updates {
|
for msg := range updates {
|
||||||
err := msgHandler(msg)
|
err := msgHandler(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -209,12 +203,12 @@ func TestEngine_Sync(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
engine := NewEngine(&signal.MockClient{}, &mgmt.MockClient{SyncFunc: syncFunc}, &EngineConfig{
|
engine := NewEngine(ctx, cancel, &signal.MockClient{}, &mgmt.MockClient{SyncFunc: syncFunc}, &EngineConfig{
|
||||||
WgIfaceName: "utun100",
|
WgIfaceName: "utun100",
|
||||||
WgAddr: "100.64.0.1/24",
|
WgAddr: "100.64.0.1/24",
|
||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, cancel, ctx)
|
})
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
err := engine.Stop()
|
err := engine.Stop()
|
||||||
@ -264,11 +258,9 @@ func TestEngine_Sync(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEngine_MultiplePeers(t *testing.T) {
|
func TestEngine_MultiplePeers(t *testing.T) {
|
||||||
|
|
||||||
// log.SetLevel(log.DebugLevel)
|
// log.SetLevel(log.DebugLevel)
|
||||||
|
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
@ -285,8 +277,9 @@ func TestEngine_MultiplePeers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(CtxInitState(context.Background()))
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
sport := 10010
|
sport := 10010
|
||||||
sigServer, err := startSignal(sport)
|
sigServer, err := startSignal(sport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -366,7 +359,6 @@ func TestEngine_MultiplePeers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createEngine(ctx context.Context, cancel context.CancelFunc, setupKey string, i int, mport int, sport int) (*Engine, error) {
|
func createEngine(ctx context.Context, cancel context.CancelFunc, setupKey string, i int, mport int, sport int) (*Engine, error) {
|
||||||
|
|
||||||
key, err := wgtypes.GeneratePrivateKey()
|
key, err := wgtypes.GeneratePrivateKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -406,7 +398,7 @@ func createEngine(ctx context.Context, cancel context.CancelFunc, setupKey strin
|
|||||||
WgPort: wgPort,
|
WgPort: wgPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewEngine(signalClient, mgmtClient, conf, cancel, ctx), nil
|
return NewEngine(ctx, cancel, signalClient, mgmtClient, conf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startSignal(port int) (*grpc.Server, error) {
|
func startSignal(port int) (*grpc.Server, error) {
|
||||||
@ -429,7 +421,6 @@ func startSignal(port int) (*grpc.Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startManagement(port int, dataDir string) (*grpc.Server, error) {
|
func startManagement(port int, dataDir string) (*grpc.Server, error) {
|
||||||
|
|
||||||
config := &server.Config{
|
config := &server.Config{
|
||||||
Stuns: []*server.Host{},
|
Stuns: []*server.Host{},
|
||||||
TURNConfig: &server.TURNConfig{},
|
TURNConfig: &server.TURNConfig{},
|
||||||
|
118
client/internal/login.go
Normal file
118
client/internal/login.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/cenkalti/backoff/v4"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/system"
|
||||||
|
mgm "github.com/wiretrustee/wiretrustee/management/client"
|
||||||
|
mgmProto "github.com/wiretrustee/wiretrustee/management/proto"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Login(ctx context.Context, config *Config, setupKey string) error {
|
||||||
|
backOff := &backoff.ExponentialBackOff{
|
||||||
|
InitialInterval: time.Second,
|
||||||
|
RandomizationFactor: backoff.DefaultRandomizationFactor,
|
||||||
|
Multiplier: backoff.DefaultMultiplier,
|
||||||
|
MaxInterval: 2 * time.Second,
|
||||||
|
MaxElapsedTime: time.Second * 10,
|
||||||
|
Stop: backoff.Stop,
|
||||||
|
Clock: backoff.SystemClock,
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate our peer's Wireguard PRIVATE key
|
||||||
|
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var mgmTlsEnabled bool
|
||||||
|
if config.ManagementURL.Scheme == "https" {
|
||||||
|
mgmTlsEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
loginOp := func() error {
|
||||||
|
log.Debugf("connecting to Management Service %s", config.ManagementURL.String())
|
||||||
|
mgmClient, err := mgm.NewClient(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed connecting to Management Service %s %v", config.ManagementURL.String(), err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugf("connected to management Service %s", config.ManagementURL.String())
|
||||||
|
|
||||||
|
serverKey, err := mgmClient.GetServerPublicKey()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed while getting Management Service public key: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = loginPeer(*serverKey, mgmClient, setupKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed logging-in peer on Management Service : %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mgmClient.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed closing Management Service client: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = backoff.RetryNotify(loginOp, backOff, func(err error, duration time.Duration) {
|
||||||
|
log.Warnf("retrying Login to the Management service in %v due to error %v", duration, err)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("exiting login retry loop due to unrecoverable error: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// loginPeer attempts to login to Management Service. If peer wasn't registered, tries the registration flow.
|
||||||
|
func loginPeer(serverPublicKey wgtypes.Key, client *mgm.GrpcClient, setupKey string) (*mgmProto.LoginResponse, error) {
|
||||||
|
loginResp, err := client.Login(serverPublicKey)
|
||||||
|
if err != nil {
|
||||||
|
if s, ok := status.FromError(err); ok && s.Code() == codes.PermissionDenied {
|
||||||
|
log.Debugf("peer registration required")
|
||||||
|
return registerPeer(serverPublicKey, client, setupKey)
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("peer has successfully logged-in to Management Service")
|
||||||
|
|
||||||
|
return loginResp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// registerPeer checks whether setupKey was provided via cmd line and if not then it prompts user to enter a key.
|
||||||
|
// Otherwise tries to register with the provided setupKey via command line.
|
||||||
|
func registerPeer(serverPublicKey wgtypes.Key, client *mgm.GrpcClient, setupKey string) (*mgmProto.LoginResponse, error) {
|
||||||
|
validSetupKey, err := uuid.Parse(setupKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("sending peer registration request to Management Service")
|
||||||
|
info := system.GetInfo()
|
||||||
|
loginResp, err := client.Register(serverPublicKey, validSetupKey.String(), info)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed registering peer %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("peer has been successfully registered on Management Service")
|
||||||
|
|
||||||
|
return loginResp, nil
|
||||||
|
}
|
67
client/internal/state.go
Normal file
67
client/internal/state.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StatusType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusIdle StatusType = "Idle"
|
||||||
|
|
||||||
|
StatusConnecting StatusType = "Connecting"
|
||||||
|
StatusConnected StatusType = "Connected"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CtxInitState setup context state into the context tree.
|
||||||
|
//
|
||||||
|
// This function should be used to initialize context before
|
||||||
|
// CtxGetState will be executed.
|
||||||
|
func CtxInitState(ctx context.Context) context.Context {
|
||||||
|
return context.WithValue(ctx, stateCtx, &contextState{
|
||||||
|
status: StatusIdle,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CtxGetState object to get/update state/errors of process.
|
||||||
|
func CtxGetState(ctx context.Context) *contextState {
|
||||||
|
return ctx.Value(stateCtx).(*contextState)
|
||||||
|
}
|
||||||
|
|
||||||
|
type contextState struct {
|
||||||
|
err error
|
||||||
|
status StatusType
|
||||||
|
mutex sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *contextState) Set(update StatusType) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
|
c.status = update
|
||||||
|
c.err = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *contextState) Status() (StatusType, error) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
|
if c.err != nil {
|
||||||
|
return "", c.err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.status, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *contextState) Wrap(err error) error {
|
||||||
|
c.mutex.Lock()
|
||||||
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
|
c.err = err
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type stateKey int
|
||||||
|
|
||||||
|
var stateCtx stateKey
|
566
client/proto/daemon.pb.go
Normal file
566
client/proto/daemon.pb.go
Normal file
@ -0,0 +1,566 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.26.0
|
||||||
|
// protoc v3.17.3
|
||||||
|
// source: daemon.proto
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
_ "google.golang.org/protobuf/types/descriptorpb"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 LoginRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// setupKey wiretrustee setup key.
|
||||||
|
SetupKey string `protobuf:"bytes,1,opt,name=setupKey,proto3" json:"setupKey,omitempty"`
|
||||||
|
// presharedKey for wireguard setup.
|
||||||
|
PresharedKey string `protobuf:"bytes,2,opt,name=presharedKey,proto3" json:"presharedKey,omitempty"`
|
||||||
|
// managementUrl to authenticate.
|
||||||
|
ManagementUrl string `protobuf:"bytes,3,opt,name=managementUrl,proto3" json:"managementUrl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LoginRequest) Reset() {
|
||||||
|
*x = LoginRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_daemon_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LoginRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*LoginRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *LoginRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_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 LoginRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*LoginRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LoginRequest) GetSetupKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.SetupKey
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LoginRequest) GetPresharedKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.PresharedKey
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LoginRequest) GetManagementUrl() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ManagementUrl
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LoginResponse) Reset() {
|
||||||
|
*x = LoginResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_daemon_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LoginResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*LoginResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *LoginResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_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 LoginResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*LoginResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UpRequest) Reset() {
|
||||||
|
*x = UpRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_daemon_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UpRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UpRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UpRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_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 UpRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UpRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UpResponse) Reset() {
|
||||||
|
*x = UpResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_daemon_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UpResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UpResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UpResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_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 UpResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UpResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatusRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *StatusRequest) Reset() {
|
||||||
|
*x = StatusRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_daemon_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *StatusRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*StatusRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *StatusRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_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 StatusRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*StatusRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatusResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// status of the server.
|
||||||
|
Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *StatusResponse) Reset() {
|
||||||
|
*x = StatusResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_daemon_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *StatusResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*StatusResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *StatusResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_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 StatusResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*StatusResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_proto_rawDescGZIP(), []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *StatusResponse) GetStatus() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Status
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type DownRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DownRequest) Reset() {
|
||||||
|
*x = DownRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_daemon_proto_msgTypes[6]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DownRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DownRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *DownRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_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 DownRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*DownRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_proto_rawDescGZIP(), []int{6}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DownResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DownResponse) Reset() {
|
||||||
|
*x = DownResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_daemon_proto_msgTypes[7]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DownResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DownResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *DownResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_proto_msgTypes[7]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use DownResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*DownResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_proto_rawDescGZIP(), []int{7}
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_daemon_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_daemon_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x0c, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06,
|
||||||
|
0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||||
|
0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x74, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x69,
|
||||||
|
0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x75,
|
||||||
|
0x70, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x74, 0x75,
|
||||||
|
0x70, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x73, 0x68, 0x61, 0x72, 0x65,
|
||||||
|
0x64, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x73,
|
||||||
|
0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x61, 0x6e, 0x61,
|
||||||
|
0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
|
0x0d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x72, 0x6c, 0x22, 0x0f,
|
||||||
|
0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
|
0x0b, 0x0a, 0x09, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0c, 0x0a, 0x0a,
|
||||||
|
0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x53, 0x74,
|
||||||
|
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x28, 0x0a, 0x0e, 0x53,
|
||||||
|
0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a,
|
||||||
|
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73,
|
||||||
|
0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x0d, 0x0a, 0x0b, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71,
|
||||||
|
0x75, 0x65, 0x73, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70,
|
||||||
|
0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe6, 0x01, 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53,
|
||||||
|
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12,
|
||||||
|
0x14, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65,
|
||||||
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c,
|
||||||
|
0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2d,
|
||||||
|
0x0a, 0x02, 0x55, 0x70, 0x12, 0x11, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x70,
|
||||||
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e,
|
||||||
|
0x2e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a,
|
||||||
|
0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x15, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e,
|
||||||
|
0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16,
|
||||||
|
0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65,
|
||||||
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x04, 0x44, 0x6f, 0x77, 0x6e,
|
||||||
|
0x12, 0x13, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65,
|
||||||
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44,
|
||||||
|
0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a,
|
||||||
|
0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_daemon_proto_rawDescOnce sync.Once
|
||||||
|
file_daemon_proto_rawDescData = file_daemon_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_daemon_proto_rawDescGZIP() []byte {
|
||||||
|
file_daemon_proto_rawDescOnce.Do(func() {
|
||||||
|
file_daemon_proto_rawDescData = protoimpl.X.CompressGZIP(file_daemon_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_daemon_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||||
|
var file_daemon_proto_goTypes = []interface{}{
|
||||||
|
(*LoginRequest)(nil), // 0: daemon.LoginRequest
|
||||||
|
(*LoginResponse)(nil), // 1: daemon.LoginResponse
|
||||||
|
(*UpRequest)(nil), // 2: daemon.UpRequest
|
||||||
|
(*UpResponse)(nil), // 3: daemon.UpResponse
|
||||||
|
(*StatusRequest)(nil), // 4: daemon.StatusRequest
|
||||||
|
(*StatusResponse)(nil), // 5: daemon.StatusResponse
|
||||||
|
(*DownRequest)(nil), // 6: daemon.DownRequest
|
||||||
|
(*DownResponse)(nil), // 7: daemon.DownResponse
|
||||||
|
}
|
||||||
|
var file_daemon_proto_depIdxs = []int32{
|
||||||
|
0, // 0: daemon.DaemonService.Login:input_type -> daemon.LoginRequest
|
||||||
|
2, // 1: daemon.DaemonService.Up:input_type -> daemon.UpRequest
|
||||||
|
4, // 2: daemon.DaemonService.Status:input_type -> daemon.StatusRequest
|
||||||
|
6, // 3: daemon.DaemonService.Down:input_type -> daemon.DownRequest
|
||||||
|
1, // 4: daemon.DaemonService.Login:output_type -> daemon.LoginResponse
|
||||||
|
3, // 5: daemon.DaemonService.Up:output_type -> daemon.UpResponse
|
||||||
|
5, // 6: daemon.DaemonService.Status:output_type -> daemon.StatusResponse
|
||||||
|
7, // 7: daemon.DaemonService.Down:output_type -> daemon.DownResponse
|
||||||
|
4, // [4:8] is the sub-list for method output_type
|
||||||
|
0, // [0:4] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_daemon_proto_init() }
|
||||||
|
func file_daemon_proto_init() {
|
||||||
|
if File_daemon_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_daemon_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*LoginRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_daemon_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*LoginResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_daemon_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*UpRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_daemon_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*UpResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_daemon_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*StatusRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_daemon_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*StatusResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_daemon_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*DownRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_daemon_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*DownResponse); 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_daemon_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 8,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 1,
|
||||||
|
},
|
||||||
|
GoTypes: file_daemon_proto_goTypes,
|
||||||
|
DependencyIndexes: file_daemon_proto_depIdxs,
|
||||||
|
MessageInfos: file_daemon_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_daemon_proto = out.File
|
||||||
|
file_daemon_proto_rawDesc = nil
|
||||||
|
file_daemon_proto_goTypes = nil
|
||||||
|
file_daemon_proto_depIdxs = nil
|
||||||
|
}
|
49
client/proto/daemon.proto
Normal file
49
client/proto/daemon.proto
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
|
option go_package = "/proto";
|
||||||
|
|
||||||
|
package daemon;
|
||||||
|
|
||||||
|
service DaemonService {
|
||||||
|
// Login uses setup key to prepare configuration for the daemon.
|
||||||
|
rpc Login(LoginRequest) returns (LoginResponse) {}
|
||||||
|
|
||||||
|
// Up starts engine work in the daemon.
|
||||||
|
rpc Up(UpRequest) returns (UpResponse) {}
|
||||||
|
|
||||||
|
// Status of the service.
|
||||||
|
rpc Status(StatusRequest) returns (StatusResponse) {}
|
||||||
|
|
||||||
|
// Down engine work in the daemon.
|
||||||
|
rpc Down(DownRequest) returns (DownResponse) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
message LoginRequest {
|
||||||
|
// setupKey wiretrustee setup key.
|
||||||
|
string setupKey = 1;
|
||||||
|
|
||||||
|
// presharedKey for wireguard setup.
|
||||||
|
string presharedKey = 2;
|
||||||
|
|
||||||
|
// managementUrl to authenticate.
|
||||||
|
string managementUrl = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LoginResponse {}
|
||||||
|
|
||||||
|
message UpRequest {}
|
||||||
|
|
||||||
|
message UpResponse {}
|
||||||
|
|
||||||
|
message StatusRequest{}
|
||||||
|
|
||||||
|
message StatusResponse{
|
||||||
|
// status of the server.
|
||||||
|
string status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DownRequest {}
|
||||||
|
|
||||||
|
message DownResponse {}
|
217
client/proto/daemon_grpc.pb.go
Normal file
217
client/proto/daemon_grpc.pb.go
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
|
// DaemonServiceClient is the client API for DaemonService service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
|
type DaemonServiceClient interface {
|
||||||
|
// Login uses setup key to prepare configuration for the daemon.
|
||||||
|
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
|
||||||
|
// Up starts engine work in the daemon.
|
||||||
|
Up(ctx context.Context, in *UpRequest, opts ...grpc.CallOption) (*UpResponse, error)
|
||||||
|
// Status of the service.
|
||||||
|
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
|
||||||
|
// Down engine work in the daemon.
|
||||||
|
Down(ctx context.Context, in *DownRequest, opts ...grpc.CallOption) (*DownResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type daemonServiceClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDaemonServiceClient(cc grpc.ClientConnInterface) DaemonServiceClient {
|
||||||
|
return &daemonServiceClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
|
||||||
|
out := new(LoginResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Login", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grpc.CallOption) (*UpResponse, error) {
|
||||||
|
out := new(UpResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Up", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
|
||||||
|
out := new(StatusResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Status", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts ...grpc.CallOption) (*DownResponse, error) {
|
||||||
|
out := new(DownResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Down", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DaemonServiceServer is the server API for DaemonService service.
|
||||||
|
// All implementations must embed UnimplementedDaemonServiceServer
|
||||||
|
// for forward compatibility
|
||||||
|
type DaemonServiceServer interface {
|
||||||
|
// Login uses setup key to prepare configuration for the daemon.
|
||||||
|
Login(context.Context, *LoginRequest) (*LoginResponse, error)
|
||||||
|
// Up starts engine work in the daemon.
|
||||||
|
Up(context.Context, *UpRequest) (*UpResponse, error)
|
||||||
|
// Status of the service.
|
||||||
|
Status(context.Context, *StatusRequest) (*StatusResponse, error)
|
||||||
|
// Down engine work in the daemon.
|
||||||
|
Down(context.Context, *DownRequest) (*DownResponse, error)
|
||||||
|
mustEmbedUnimplementedDaemonServiceServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedDaemonServiceServer must be embedded to have forward compatible implementations.
|
||||||
|
type UnimplementedDaemonServiceServer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedDaemonServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedDaemonServiceServer) Up(context.Context, *UpRequest) (*UpResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method Up not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedDaemonServiceServer) Status(context.Context, *StatusRequest) (*StatusResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method Status not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedDaemonServiceServer) Down(context.Context, *DownRequest) (*DownResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method Down not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedDaemonServiceServer) mustEmbedUnimplementedDaemonServiceServer() {}
|
||||||
|
|
||||||
|
// UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
// Use of this interface is not recommended, as added methods to DaemonServiceServer will
|
||||||
|
// result in compilation errors.
|
||||||
|
type UnsafeDaemonServiceServer interface {
|
||||||
|
mustEmbedUnimplementedDaemonServiceServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterDaemonServiceServer(s grpc.ServiceRegistrar, srv DaemonServiceServer) {
|
||||||
|
s.RegisterService(&DaemonService_ServiceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _DaemonService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(LoginRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(DaemonServiceServer).Login(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/daemon.DaemonService/Login",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DaemonServiceServer).Login(ctx, req.(*LoginRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _DaemonService_Up_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(UpRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(DaemonServiceServer).Up(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/daemon.DaemonService/Up",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DaemonServiceServer).Up(ctx, req.(*UpRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _DaemonService_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(StatusRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(DaemonServiceServer).Status(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/daemon.DaemonService/Status",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DaemonServiceServer).Status(ctx, req.(*StatusRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _DaemonService_Down_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(DownRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(DaemonServiceServer).Down(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/daemon.DaemonService/Down",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DaemonServiceServer).Down(ctx, req.(*DownRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DaemonService_ServiceDesc is the grpc.ServiceDesc for DaemonService service.
|
||||||
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
var DaemonService_ServiceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "daemon.DaemonService",
|
||||||
|
HandlerType: (*DaemonServiceServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "Login",
|
||||||
|
Handler: _DaemonService_Login_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Up",
|
||||||
|
Handler: _DaemonService_Up_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Status",
|
||||||
|
Handler: _DaemonService_Status_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Down",
|
||||||
|
Handler: _DaemonService_Down_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "daemon.proto",
|
||||||
|
}
|
4
client/proto/generate.sh
Executable file
4
client/proto/generate.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
||||||
|
protoc -I proto/ proto/daemon.proto --go_out=. --go-grpc_out=.
|
166
client/server/server.go
Normal file
166
client/server/server.go
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/internal"
|
||||||
|
"github.com/wiretrustee/wiretrustee/client/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Server for service control.
|
||||||
|
type Server struct {
|
||||||
|
rootCtx context.Context
|
||||||
|
actCancel context.CancelFunc
|
||||||
|
|
||||||
|
managementURL string
|
||||||
|
configPath string
|
||||||
|
stopCh chan int
|
||||||
|
cleanupCh chan<- struct{}
|
||||||
|
|
||||||
|
mutex sync.Mutex
|
||||||
|
config *internal.Config
|
||||||
|
proto.UnimplementedDaemonServiceServer
|
||||||
|
}
|
||||||
|
|
||||||
|
// New server instance constructor.
|
||||||
|
func New(
|
||||||
|
ctx context.Context, managementURL, configPath string,
|
||||||
|
stopCh chan int, cleanupCh chan<- struct{},
|
||||||
|
) *Server {
|
||||||
|
return &Server{
|
||||||
|
rootCtx: ctx,
|
||||||
|
managementURL: managementURL,
|
||||||
|
configPath: configPath,
|
||||||
|
stopCh: stopCh,
|
||||||
|
cleanupCh: cleanupCh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Start() error {
|
||||||
|
state := internal.CtxGetState(s.rootCtx)
|
||||||
|
|
||||||
|
// if current state contains any error, return it
|
||||||
|
// in all other cases we can continue execution only if status is idle and up command was
|
||||||
|
// not in the progress or already successfully estabilished connection.
|
||||||
|
status, err := state.Status()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if status != internal.StatusIdle {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(s.rootCtx)
|
||||||
|
s.actCancel = cancel
|
||||||
|
|
||||||
|
// if configuration exists, we just start connections.
|
||||||
|
config, err := internal.ReadConfig(s.managementURL, s.configPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("no config file, skip connection stage: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := internal.RunClient(ctx, config, s.stopCh, s.cleanupCh); err != nil {
|
||||||
|
log.Errorf("init connections: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login uses setup key to prepare configuration for the daemon.
|
||||||
|
func (s *Server) Login(_ context.Context, msg *proto.LoginRequest) (*proto.LoginResponse, error) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
|
managementURL := s.managementURL
|
||||||
|
if msg.ManagementUrl != "" {
|
||||||
|
managementURL = msg.ManagementUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
config, err := internal.GetConfig(managementURL, s.configPath, msg.PresharedKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.config = config
|
||||||
|
|
||||||
|
// login operation uses backoff scheme to connect to management API
|
||||||
|
// we don't wait for result and return response immediately.
|
||||||
|
if err := internal.Login(s.rootCtx, s.config, msg.SetupKey); err != nil {
|
||||||
|
log.Errorf("failed login: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.LoginResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Up starts engine work in the daemon.
|
||||||
|
func (s *Server) Up(_ context.Context, msg *proto.UpRequest) (*proto.UpResponse, error) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
|
state := internal.CtxGetState(s.rootCtx)
|
||||||
|
|
||||||
|
// if current state contains any error, return it
|
||||||
|
// in all other cases we can continue execution only if status is idle and up command was
|
||||||
|
// not in the progress or already successfully estabilished connection.
|
||||||
|
status, err := state.Status()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if status != internal.StatusIdle {
|
||||||
|
return nil, fmt.Errorf("up already in progress: current status %s", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// it should be nill here, but .
|
||||||
|
if s.actCancel != nil {
|
||||||
|
s.actCancel()
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithCancel(s.rootCtx)
|
||||||
|
s.actCancel = cancel
|
||||||
|
|
||||||
|
if s.config == nil {
|
||||||
|
return nil, fmt.Errorf("config is not defined, please call login command first")
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := internal.RunClient(ctx, s.config, s.stopCh, s.cleanupCh); err != nil {
|
||||||
|
log.Errorf("run client connection: %v", state.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return &proto.UpResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Down dengine work in the daemon.
|
||||||
|
func (s *Server) Down(ctx context.Context, msg *proto.DownRequest) (*proto.DownResponse, error) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
|
if s.actCancel == nil {
|
||||||
|
return nil, fmt.Errorf("service is not up")
|
||||||
|
}
|
||||||
|
s.actCancel()
|
||||||
|
|
||||||
|
return &proto.DownResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status starts engine work in the daemon.
|
||||||
|
func (s *Server) Status(ctx context.Context, msg *proto.StatusRequest) (*proto.StatusResponse, error) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
|
status, err := internal.CtxGetState(s.rootCtx).Status()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.StatusResponse{Status: string(status)}, nil
|
||||||
|
}
|
@ -29,7 +29,6 @@ type GrpcClient struct {
|
|||||||
|
|
||||||
// NewClient creates a new client to Management service
|
// NewClient creates a new client to Management service
|
||||||
func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsEnabled bool) (*GrpcClient, error) {
|
func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsEnabled bool) (*GrpcClient, error) {
|
||||||
|
|
||||||
transportOption := grpc.WithTransportCredentials(insecure.NewCredentials())
|
transportOption := grpc.WithTransportCredentials(insecure.NewCredentials())
|
||||||
|
|
||||||
if tlsEnabled {
|
if tlsEnabled {
|
||||||
@ -47,7 +46,6 @@ func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsE
|
|||||||
Time: 15 * time.Second,
|
Time: 15 * time.Second,
|
||||||
Timeout: 10 * time.Second,
|
Timeout: 10 * time.Second,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed creating connection to Management Service %v", err)
|
log.Errorf("failed creating connection to Management Service %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -90,11 +88,9 @@ func (c *GrpcClient) ready() bool {
|
|||||||
// Sync wraps the real client's Sync endpoint call and takes care of retries and encryption/decryption of messages
|
// Sync wraps the real client's Sync endpoint call and takes care of retries and encryption/decryption of messages
|
||||||
// Blocking request. The result will be sent via msgHandler callback function
|
// Blocking request. The result will be sent via msgHandler callback function
|
||||||
func (c *GrpcClient) Sync(msgHandler func(msg *proto.SyncResponse) error) error {
|
func (c *GrpcClient) Sync(msgHandler func(msg *proto.SyncResponse) error) error {
|
||||||
|
backOff := defaultBackoff(c.ctx)
|
||||||
var backOff = defaultBackoff(c.ctx)
|
|
||||||
|
|
||||||
operation := func() error {
|
operation := func() error {
|
||||||
|
|
||||||
log.Debugf("management connection state %v", c.conn.GetState())
|
log.Debugf("management connection state %v", c.conn.GetState())
|
||||||
|
|
||||||
if !c.ready() {
|
if !c.ready() {
|
||||||
@ -215,7 +211,6 @@ func (c *GrpcClient) login(serverKey wgtypes.Key, req *proto.LoginRequest) (*pro
|
|||||||
WgPubKey: c.key.PublicKey().String(),
|
WgPubKey: c.key.PublicKey().String(),
|
||||||
Body: loginReq,
|
Body: loginReq,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user