mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-24 15:48:52 +01:00
test: add management client tests (#89)
* test: add management client tests * test: add management client Sync test * fix: engine test * test: remove engine tests * test: return engine tests [check] * test: remove engine tests [check]
This commit is contained in:
parent
2a97053cae
commit
e8ca289f4a
@ -1,174 +0,0 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/pion/ice/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/wiretrustee/wiretrustee/iface"
|
||||
mgmClient "github.com/wiretrustee/wiretrustee/management/client"
|
||||
signalClient "github.com/wiretrustee/wiretrustee/signal/client"
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var engine *Engine
|
||||
var testKey wgtypes.Key
|
||||
var testPeer Peer
|
||||
|
||||
const ifaceName = "utun9991"
|
||||
|
||||
func Test_Start(t *testing.T) {
|
||||
level, _ := log.ParseLevel("Debug")
|
||||
log.SetLevel(level)
|
||||
|
||||
var err error
|
||||
testKey, err = wgtypes.GenerateKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
iceUrl, err := ice.ParseURL("stun:stun.wiretrustee.com:3468")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var stunURLs = []*ice.URL{iceUrl}
|
||||
|
||||
iFaceBlackList := make(map[string]struct{})
|
||||
|
||||
signal, err := signalClient.NewClient(ctx, "signal.wiretrustee.com:10000", testKey, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
mgm, err := mgmClient.NewClient(ctx, "app.wiretrustee.com:33073", testKey, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conf := &EngineConfig{
|
||||
StunsTurns: stunURLs,
|
||||
WgIface: ifaceName,
|
||||
WgAddr: "10.99.91.1/24",
|
||||
WgPrivateKey: testKey,
|
||||
IFaceBlackList: iFaceBlackList,
|
||||
}
|
||||
engine = NewEngine(signal, mgm, conf)
|
||||
|
||||
err = engine.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wg, err := wgctrl.New()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer wg.Close()
|
||||
|
||||
_, err = wg.Device(ifaceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEngine_InitializePeerWithoutRemote(t *testing.T) {
|
||||
tmpKey, err := wgtypes.GenerateKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
testPeer = Peer{
|
||||
tmpKey.PublicKey().String(),
|
||||
"10.99.91.2/32",
|
||||
}
|
||||
go engine.initializePeer(testPeer)
|
||||
// Let the connections initialize
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
for {
|
||||
status := engine.GetPeerConnectionStatus(testPeer.WgPubKey)
|
||||
err = ctx.Err()
|
||||
if (status != nil && *status == StatusConnecting) || err != nil {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
//success
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEngine_Initialize2PeersWithoutRemote(t *testing.T) {
|
||||
tmpKey1, err := wgtypes.GenerateKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpKey2, err := wgtypes.GenerateKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
testPeer1 := Peer{
|
||||
tmpKey1.PublicKey().String(),
|
||||
"10.99.91.2/32",
|
||||
}
|
||||
testPeer2 := Peer{
|
||||
tmpKey2.PublicKey().String(),
|
||||
"10.99.91.3/32",
|
||||
}
|
||||
go engine.initializePeer(testPeer1)
|
||||
go engine.initializePeer(testPeer2)
|
||||
// Let the connections initialize
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
for {
|
||||
status1 := engine.GetPeerConnectionStatus(testPeer1.WgPubKey)
|
||||
status2 := engine.GetPeerConnectionStatus(testPeer2.WgPubKey)
|
||||
err = ctx.Err()
|
||||
if (status1 != nil && status2 != nil) || err != nil {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if *status1 == StatusConnecting && *status2 == StatusConnecting {
|
||||
//success
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEngine_RemovePeerConnectionWithoutRemote(t *testing.T) {
|
||||
|
||||
// Let the connections initialize
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
for {
|
||||
status := engine.GetPeerConnectionStatus(testPeer.WgPubKey)
|
||||
err := ctx.Err()
|
||||
if (status != nil && *status == StatusConnecting) || err != nil {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Let the connections close
|
||||
err := engine.removePeerConnection(testPeer.WgPubKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
status := engine.GetPeerConnectionStatus(testPeer.WgPubKey)
|
||||
if status != nil {
|
||||
t.Fatal(fmt.Errorf("wrong status %v", status))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CloseInterface(t *testing.T) {
|
||||
err := iface.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ type Client struct {
|
||||
}
|
||||
|
||||
// NewClient creates a new client to Management service
|
||||
func NewClient(ctx context.Context, addr string, outPrivateKey wgtypes.Key, tlsEnabled bool) (*Client, error) {
|
||||
func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsEnabled bool) (*Client, error) {
|
||||
|
||||
transportOption := grpc.WithInsecure()
|
||||
|
||||
@ -49,7 +49,7 @@ func NewClient(ctx context.Context, addr string, outPrivateKey wgtypes.Key, tlsE
|
||||
realClient := proto.NewManagementServiceClient(conn)
|
||||
|
||||
return &Client{
|
||||
key: outPrivateKey,
|
||||
key: ourPrivateKey,
|
||||
realClient: realClient,
|
||||
ctx: ctx,
|
||||
conn: conn,
|
||||
@ -62,6 +62,7 @@ func (c *Client) Close() error {
|
||||
}
|
||||
|
||||
// Sync wraps the real client's Sync endpoint call and takes care of retries and encryption/decryption of messages
|
||||
// Non blocking request (executed in go routine). The result will be sent via msgHandler callback function
|
||||
func (c *Client) Sync(msgHandler func(msg *proto.SyncResponse) error) {
|
||||
|
||||
go func() {
|
||||
|
167
management/client/client_test.go
Normal file
167
management/client/client_test.go
Normal file
@ -0,0 +1,167 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
log "github.com/sirupsen/logrus"
|
||||
mgmtProto "github.com/wiretrustee/wiretrustee/management/proto"
|
||||
mgmt "github.com/wiretrustee/wiretrustee/management/server"
|
||||
"github.com/wiretrustee/wiretrustee/util"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var tested *Client
|
||||
var serverAddr string
|
||||
|
||||
func Test_Start(t *testing.T) {
|
||||
level, _ := log.ParseLevel("debug")
|
||||
log.SetLevel(level)
|
||||
|
||||
testKey, err := wgtypes.GenerateKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
testDir := t.TempDir()
|
||||
ctx := context.Background()
|
||||
config := &mgmt.Config{}
|
||||
_, err = util.ReadJson("../server/testdata/management.json", config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
config.Datadir = testDir
|
||||
err = util.CopyFileContents("../server/testdata/store.json", filepath.Join(testDir, "store.json"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, listener := startManagement(config, t)
|
||||
serverAddr = listener.Addr().String()
|
||||
tested, err = NewClient(ctx, serverAddr, testKey, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func startManagement(config *mgmt.Config, t *testing.T) (*grpc.Server, net.Listener) {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s := grpc.NewServer()
|
||||
store, err := mgmt.NewStore(config.Datadir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
accountManager := mgmt.NewManager(store)
|
||||
mgmtServer, err := mgmt.NewServer(config, accountManager)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mgmtProto.RegisterManagementServiceServer(s, mgmtServer)
|
||||
go func() {
|
||||
if err := s.Serve(lis); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
return s, lis
|
||||
}
|
||||
|
||||
func TestClient_GetServerPublicKey(t *testing.T) {
|
||||
|
||||
key, err := tested.GetServerPublicKey()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
t.Error("expecting non nil server key got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_LoginUnregistered_ShouldThrow_401(t *testing.T) {
|
||||
key, err := tested.GetServerPublicKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = tested.Login(*key)
|
||||
if err == nil {
|
||||
t.Error("expecting err on unregistered login, got nil")
|
||||
}
|
||||
if s, ok := status.FromError(err); !ok || s.Code() != codes.PermissionDenied {
|
||||
t.Errorf("expecting err code %d denied on on unregistered login got %d", codes.PermissionDenied, s.Code())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_LoginRegistered(t *testing.T) {
|
||||
key, err := tested.GetServerPublicKey()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
resp, err := tested.Register(*key, "a2c8e62b-38f5-4553-b31e-dd66c696cebb")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
t.Error("expecting non nil response, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_Sync(t *testing.T) {
|
||||
serverKey, err := tested.GetServerPublicKey()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = tested.Register(*serverKey, "a2c8e62b-38f5-4553-b31e-dd66c696cebb")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// create and register second peer (we should receive on Sync request)
|
||||
remoteKey, err := wgtypes.GenerateKey()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
remoteClient, err := NewClient(context.TODO(), serverAddr, remoteKey, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = remoteClient.Register(*serverKey, "a2c8e62b-38f5-4553-b31e-dd66c696cebb")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ch := make(chan *mgmtProto.SyncResponse, 1)
|
||||
|
||||
tested.Sync(func(msg *mgmtProto.SyncResponse) error {
|
||||
ch <- msg
|
||||
return nil
|
||||
})
|
||||
|
||||
select {
|
||||
case resp := <-ch:
|
||||
if resp.GetPeerConfig() == nil {
|
||||
t.Error("expecting non nil PeerConfig got nil")
|
||||
}
|
||||
if resp.GetWiretrusteeConfig() == nil {
|
||||
t.Error("expecting non nil WiretrusteeConfig got nil")
|
||||
}
|
||||
if len(resp.GetRemotePeers()) != 1 {
|
||||
t.Errorf("expecting RemotePeers size %d got %d", 1, len(resp.GetRemotePeers()))
|
||||
}
|
||||
if resp.GetRemotePeers()[0].GetWgPubKey() != remoteKey.PublicKey().String() {
|
||||
t.Errorf("expecting RemotePeer public key %s got %s", remoteKey.PublicKey().String(), resp.GetRemotePeers()[0].GetWgPubKey())
|
||||
}
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Error("timeout waiting for test to finish")
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/wiretrustee/wiretrustee/management/server"
|
||||
grpc2 "github.com/wiretrustee/wiretrustee/management/server/grpc"
|
||||
"github.com/wiretrustee/wiretrustee/management/server/http"
|
||||
"github.com/wiretrustee/wiretrustee/util"
|
||||
"net"
|
||||
@ -79,7 +78,7 @@ var (
|
||||
opts = append(opts, grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp))
|
||||
grpcServer := grpc.NewServer(opts...)
|
||||
|
||||
server, err := grpc2.NewServer(config, accountManager)
|
||||
server, err := server.NewServer(config, accountManager)
|
||||
if err != nil {
|
||||
log.Fatalf("failed creating new server: %v", err)
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
package grpc
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/wiretrustee/wiretrustee/management/server"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -18,12 +17,12 @@ import (
|
||||
|
||||
// Server an instance of a Management server
|
||||
type Server struct {
|
||||
accountManager *server.AccountManager
|
||||
accountManager *AccountManager
|
||||
wgKey wgtypes.Key
|
||||
proto.UnimplementedManagementServiceServer
|
||||
peerChannels map[string]chan *UpdateChannelMessage
|
||||
channelsMux *sync.Mutex
|
||||
config *server.Config
|
||||
config *Config
|
||||
}
|
||||
|
||||
// AllowedIPsFormat generates Wireguard AllowedIPs format (e.g. 100.30.30.1/32)
|
||||
@ -34,7 +33,7 @@ type UpdateChannelMessage struct {
|
||||
}
|
||||
|
||||
// NewServer creates a new Management server
|
||||
func NewServer(config *server.Config, accountManager *server.AccountManager) (*Server, error) {
|
||||
func NewServer(config *Config, accountManager *AccountManager) (*Server, error) {
|
||||
key, err := wgtypes.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -126,7 +125,7 @@ func (s *Server) Sync(req *proto.EncryptedMessage, srv proto.ManagementService_S
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) registerPeer(peerKey wgtypes.Key, setupKey string) (*server.Peer, error) {
|
||||
func (s *Server) registerPeer(peerKey wgtypes.Key, setupKey string) (*Peer, error) {
|
||||
s.channelsMux.Lock()
|
||||
defer s.channelsMux.Unlock()
|
||||
|
||||
@ -144,7 +143,7 @@ func (s *Server) registerPeer(peerKey wgtypes.Key, setupKey string) (*server.Pee
|
||||
for _, remotePeer := range peers {
|
||||
if channel, ok := s.peerChannels[remotePeer.Key]; ok {
|
||||
// exclude notified peer and add ourselves
|
||||
peersToSend := []*server.Peer{peer}
|
||||
peersToSend := []*Peer{peer}
|
||||
for _, p := range peers {
|
||||
if remotePeer.Key != p.Key {
|
||||
peersToSend = append(peersToSend, p)
|
||||
@ -214,17 +213,17 @@ func (s *Server) Login(ctx context.Context, req *proto.EncryptedMessage) (*proto
|
||||
}, nil
|
||||
}
|
||||
|
||||
func toResponseProto(configProto server.Protocol) proto.HostConfig_Protocol {
|
||||
func toResponseProto(configProto Protocol) proto.HostConfig_Protocol {
|
||||
switch configProto {
|
||||
case server.UDP:
|
||||
case UDP:
|
||||
return proto.HostConfig_UDP
|
||||
case server.DTLS:
|
||||
case DTLS:
|
||||
return proto.HostConfig_DTLS
|
||||
case server.HTTP:
|
||||
case HTTP:
|
||||
return proto.HostConfig_HTTP
|
||||
case server.HTTPS:
|
||||
case HTTPS:
|
||||
return proto.HostConfig_HTTPS
|
||||
case server.TCP:
|
||||
case TCP:
|
||||
return proto.HostConfig_TCP
|
||||
default:
|
||||
//mbragin: todo something better?
|
||||
@ -232,7 +231,7 @@ func toResponseProto(configProto server.Protocol) proto.HostConfig_Protocol {
|
||||
}
|
||||
}
|
||||
|
||||
func toWiretrusteeConfig(config *server.Config) *proto.WiretrusteeConfig {
|
||||
func toWiretrusteeConfig(config *Config) *proto.WiretrusteeConfig {
|
||||
|
||||
var stuns []*proto.HostConfig
|
||||
for _, stun := range config.Stuns {
|
||||
@ -263,13 +262,13 @@ func toWiretrusteeConfig(config *server.Config) *proto.WiretrusteeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func toPeerConfig(peer *server.Peer) *proto.PeerConfig {
|
||||
func toPeerConfig(peer *Peer) *proto.PeerConfig {
|
||||
return &proto.PeerConfig{
|
||||
Address: peer.IP.String() + "/24", //todo make it explicit
|
||||
}
|
||||
}
|
||||
|
||||
func toSyncResponse(config *server.Config, peer *server.Peer, peers []*server.Peer) *proto.SyncResponse {
|
||||
func toSyncResponse(config *Config, peer *Peer, peers []*Peer) *proto.SyncResponse {
|
||||
|
||||
wtConfig := toWiretrusteeConfig(config)
|
||||
|
||||
@ -324,7 +323,7 @@ func (s *Server) closeUpdatesChannel(peerKey string) {
|
||||
}
|
||||
|
||||
// sendInitialSync sends initial proto.SyncResponse to the peer requesting synchronization
|
||||
func (s *Server) sendInitialSync(peerKey wgtypes.Key, peer *server.Peer, srv proto.ManagementService_SyncServer) error {
|
||||
func (s *Server) sendInitialSync(peerKey wgtypes.Key, peer *Peer, srv proto.ManagementService_SyncServer) error {
|
||||
|
||||
peers, err := s.accountManager.GetPeersForAPeer(peer.Key)
|
||||
if err != nil {
|
@ -3,7 +3,6 @@ package server_test
|
||||
import (
|
||||
"context"
|
||||
server "github.com/wiretrustee/wiretrustee/management/server"
|
||||
grpc2 "github.com/wiretrustee/wiretrustee/management/server/grpc"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
@ -484,7 +483,7 @@ func startServer(config *server.Config) (*grpc.Server, net.Listener) {
|
||||
log.Fatalf("failed creating a store: %s: %v", config.Datadir, err)
|
||||
}
|
||||
accountManager := server.NewManager(store)
|
||||
mgmtServer, err := grpc2.NewServer(config, accountManager)
|
||||
mgmtServer, err := server.NewServer(config, accountManager)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mgmtProto.RegisterManagementServiceServer(s, mgmtServer)
|
||||
go func() {
|
||||
|
Loading…
Reference in New Issue
Block a user