Add user-agent to cmd and UI when calling daemon

This commit is contained in:
braginini
2022-05-22 18:53:21 +02:00
parent 4a499530ee
commit f4ce8c9c4e
12 changed files with 181 additions and 171 deletions

View File

@@ -3,11 +3,11 @@ package cmd
import (
"context"
"fmt"
"github.com/netbirdio/netbird/client/system"
"time"
"github.com/skratchdot/open-golang/open"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
gstatus "google.golang.org/grpc/status"
"github.com/netbirdio/netbird/util"
@@ -69,9 +69,6 @@ var loginCmd = &cobra.Command{
err = WithBackOff(func() error {
var backOffErr error
md := metadata.New(map[string]string{"caller": "cli"})
ctx = metadata.NewOutgoingContext(ctx, md)
loginResp, backOffErr = client.Login(ctx, &loginRequest)
if s, ok := gstatus.FromError(backOffErr); ok && (s.Code() == codes.InvalidArgument ||
s.Code() == codes.PermissionDenied ||
@@ -108,8 +105,10 @@ var loginCmd = &cobra.Command{
func foregroundLogin(ctx context.Context, cmd *cobra.Command, config *internal.Config, setupKey string) error {
needsLogin := false
info := system.GetInfo()
err := WithBackOff(func() error {
err := internal.Login(ctx, config, "", "")
err := internal.Login(ctx, config, "", "", info)
if s, ok := gstatus.FromError(err); ok && (s.Code() == codes.InvalidArgument || s.Code() == codes.PermissionDenied) {
needsLogin = true
return nil
@@ -130,7 +129,7 @@ func foregroundLogin(ctx context.Context, cmd *cobra.Command, config *internal.C
}
err = WithBackOff(func() error {
err := internal.Login(ctx, config, setupKey, jwtToken)
err := internal.Login(ctx, config, setupKey, jwtToken, info)
if s, ok := gstatus.FromError(err); ok && (s.Code() == codes.InvalidArgument || s.Code() == codes.PermissionDenied) {
return nil
}

View File

@@ -3,6 +3,7 @@ package cmd
import (
"context"
"fmt"
"github.com/netbirdio/netbird/client/system"
"os"
"os/signal"
"runtime"
@@ -124,6 +125,7 @@ func DialClientGRPCServer(ctx context.Context, addr string) (*grpc.ClientConn, e
strings.TrimPrefix(addr, "tcp://"),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
grpc.WithUserAgent(system.NetBirdCmdUserAgent()),
)
}

View File

@@ -194,7 +194,7 @@ func connectToManagement(ctx context.Context, managementAddr string, ourPrivateK
return nil, nil, status.Errorf(codes.FailedPrecondition, "failed while getting Management Service public key: %s", err)
}
loginResp, err := client.Login(*serverPublicKey, system.GetInfo(ctx))
loginResp, err := client.Login(*serverPublicKey, system.GetInfo())
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")

View File

@@ -391,7 +391,7 @@ func createEngine(ctx context.Context, cancel context.CancelFunc, setupKey strin
}
//todo
info := system.GetInfo(ctx)
info := system.GetInfo()
resp, err := mgmtClient.Register(*publicKey, setupKey, "", info)
if err != nil {
return nil, err

View File

@@ -13,7 +13,7 @@ import (
"google.golang.org/grpc/status"
)
func Login(ctx context.Context, config *Config, setupKey string, jwtToken string) error {
func Login(ctx context.Context, config *Config, setupKey string, jwtToken string, sysInfo *system.Info) error {
// validate our peer's Wireguard PRIVATE key
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
if err != nil {
@@ -40,7 +40,7 @@ func Login(ctx context.Context, config *Config, setupKey string, jwtToken string
return err
}
_, err = loginPeer(*serverKey, mgmClient, setupKey, jwtToken, ctx)
_, err = loginPeer(*serverKey, mgmClient, setupKey, jwtToken, sysInfo)
if err != nil {
log.Errorf("failed logging-in peer on Management Service : %v", err)
return err
@@ -56,12 +56,12 @@ func Login(ctx context.Context, config *Config, setupKey string, jwtToken string
}
// 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, jwtToken string, ctx context.Context) (*mgmProto.LoginResponse, error) {
loginResp, err := client.Login(serverPublicKey, system.GetInfo(ctx))
func loginPeer(serverPublicKey wgtypes.Key, client *mgm.GrpcClient, setupKey string, jwtToken string, sysInfo *system.Info) (*mgmProto.LoginResponse, error) {
loginResp, err := client.Login(serverPublicKey, sysInfo)
if err != nil {
if s, ok := status.FromError(err); ok && s.Code() == codes.PermissionDenied {
log.Debugf("peer registration required")
return registerPeer(serverPublicKey, client, setupKey, jwtToken, ctx)
return registerPeer(serverPublicKey, client, setupKey, jwtToken, sysInfo)
} else {
return nil, err
}
@@ -74,15 +74,14 @@ func loginPeer(serverPublicKey wgtypes.Key, client *mgm.GrpcClient, setupKey str
// 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, jwtToken string, ctx context.Context) (*mgmProto.LoginResponse, error) {
func registerPeer(serverPublicKey wgtypes.Key, client *mgm.GrpcClient, setupKey string, jwtToken string, sysInfo *system.Info) (*mgmProto.LoginResponse, error) {
validSetupKey, err := uuid.Parse(setupKey)
if err != nil && jwtToken == "" {
return nil, status.Errorf(codes.InvalidArgument, "invalid setup-key or no sso information provided, err: %v", err)
}
log.Debugf("sending peer registration request to Management Service")
info := system.GetInfo(ctx)
loginResp, err := client.Register(serverPublicKey, validSetupKey.String(), jwtToken, info)
loginResp, err := client.Register(serverPublicKey, validSetupKey.String(), jwtToken, sysInfo)
if err != nil {
log.Errorf("failed registering peer %v,%s", err, validSetupKey.String())
return nil, err

View File

@@ -3,6 +3,8 @@ package server
import (
"context"
"fmt"
"github.com/netbirdio/netbird/client/system"
"google.golang.org/grpc/metadata"
"sync"
"time"
@@ -91,6 +93,18 @@ func (s *Server) Start() error {
return nil
}
func extractUserAgent(ctx context.Context) string {
mD, ok := metadata.FromIncomingContext(ctx)
if ok {
agent, ok := mD["user-agent"]
if ok {
return agent[0]
}
}
return ""
}
// Login uses setup key to prepare configuration for the daemon.
func (s *Server) Login(ctx context.Context, msg *proto.LoginRequest) (*proto.LoginResponse, error) {
s.mutex.Lock()
@@ -145,7 +159,7 @@ func (s *Server) Login(ctx context.Context, msg *proto.LoginRequest) (*proto.Log
return nil, gstatus.Errorf(codes.Unimplemented, "the management server, %s, does not support SSO providers, "+
"please update your server or use Setup Keys to login", config.ManagementURL)
} else {
log.Errorf("getting device authorization flow info failed with error: %v", err)
log.Errorf("getting device authorization flow sysInfo failed with error: %v", err)
return nil, err
}
}
@@ -177,7 +191,13 @@ func (s *Server) Login(ctx context.Context, msg *proto.LoginRequest) (*proto.Log
}, nil
}
if err := internal.Login(ctx, s.config, msg.SetupKey, ""); err != nil {
sysInfo := system.GetInfo()
agent := extractUserAgent(ctx)
if agent != "" {
sysInfo.Caller = agent
}
if err := internal.Login(ctx, s.config, msg.SetupKey, "", sysInfo); err != nil {
if s, ok := gstatus.FromError(err); ok && (s.Code() == codes.InvalidArgument || s.Code() == codes.PermissionDenied) {
log.Warnf("failed login with known status: %v", err)
state.Set(internal.StatusNeedsLogin)
@@ -236,7 +256,12 @@ func (s *Server) WaitSSOLogin(_ context.Context, msg *proto.WaitSSOLoginRequest)
return nil, err
}
if err := internal.Login(ctx, s.config, "", tokenInfo.AccessToken); err != nil {
sysInfo := system.GetInfo()
agent := extractUserAgent(ctx)
if agent != "" {
sysInfo.Caller = agent
}
if err := internal.Login(ctx, s.config, "", tokenInfo.AccessToken, sysInfo); err != nil {
if s, ok := gstatus.FromError(err); ok && (s.Code() == codes.InvalidArgument || s.Code() == codes.PermissionDenied) {
log.Warnf("failed login: %v", err)
state.Set(internal.StatusNeedsLogin)

View File

@@ -23,3 +23,11 @@ type Info struct {
func WiretrusteeVersion() string {
return version
}
func NetBirdDesktopUIUserAgent() string {
return "netbird-desktop-ui/" + WiretrusteeVersion()
}
func NetBirdCmdUserAgent() string {
return "netbird-cmd/" + WiretrusteeVersion()
}

View File

@@ -2,18 +2,15 @@ package system
import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
"time"
"google.golang.org/grpc/metadata"
)
func GetInfo(ctx context.Context) *Info {
func GetInfo() *Info {
info := _getInfo()
for strings.Contains(info, "broken pipe") {
info = _getInfo()
@@ -48,15 +45,7 @@ func GetInfo(ctx context.Context) *Info {
gio := &Info{Kernel: osInfo[0], Core: osInfo[1], Platform: osInfo[2], OS: osName, OSVersion: osVer, GoOS: runtime.GOOS, CPUs: runtime.NumCPU()}
gio.Hostname, _ = os.Hostname()
gio.WiretrusteeVersion = WiretrusteeVersion()
if ctx != nil {
metadata, ok := metadata.FromIncomingContext(ctx)
if ok {
gio.Caller = metadata["caller"][0]
gio.CallerVersion = metadata["callerVersion"][0]
}
}
gio.Caller = NetBirdCmdUserAgent()
return gio
}

View File

@@ -4,6 +4,8 @@ import (
"context"
"flag"
"fmt"
"github.com/cenkalti/backoff/v4"
"github.com/netbirdio/netbird/client/system"
"io/ioutil"
"os"
"os/exec"
@@ -14,10 +16,12 @@ import (
"syscall"
"time"
"github.com/cenkalti/backoff/v4"
_ "embed"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
"github.com/getlantern/systray"
"github.com/netbirdio/netbird/client/internal"
"github.com/netbirdio/netbird/client/proto"
@@ -26,12 +30,6 @@ import (
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
)
const (
@@ -197,8 +195,6 @@ func (s *serviceClient) getSettingsForm() *widget.Form {
return
}
md := metadata.New(map[string]string{"caller": "ui"})
s.ctx = metadata.NewOutgoingContext(s.ctx, md)
_, err = client.Login(s.ctx, &proto.LoginRequest{
ManagementUrl: s.iMngURL.Text,
AdminURL: s.iAdminURL.Text,
@@ -453,6 +449,7 @@ func (s *serviceClient) getSrvClient(timeout time.Duration) (proto.DaemonService
strings.TrimPrefix(s.addr, "tcp://"),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
grpc.WithUserAgent(system.NetBirdDesktopUIUserAgent()),
)
if err != nil {
return nil, fmt.Errorf("dial service: %w", err)