2022-08-18 18:22:15 +02:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/netbirdio/netbird/route"
|
|
|
|
"github.com/rs/xid"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"net/netip"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
const peer1Key = "BhRPtynAAYRDy08+q4HTMsos8fs4plTP4NOSh7C1ry8="
|
|
|
|
const peer2Key = "/yF0+vCfv+mRR5k0dca0TrGdO/oiNeAI58gToZm5NyI="
|
|
|
|
|
|
|
|
func TestCreateRoute(t *testing.T) {
|
|
|
|
|
|
|
|
type input struct {
|
2022-08-22 14:10:24 +02:00
|
|
|
network string
|
|
|
|
netID string
|
2022-08-18 18:22:15 +02:00
|
|
|
peer string
|
|
|
|
description string
|
|
|
|
masquerade bool
|
|
|
|
metric int
|
|
|
|
enabled bool
|
|
|
|
}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
name string
|
|
|
|
inputArgs input
|
|
|
|
shouldCreate bool
|
|
|
|
errFunc require.ErrorAssertionFunc
|
|
|
|
expectedRoute *route.Route
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Happy Path",
|
|
|
|
inputArgs: input{
|
2022-08-22 14:10:24 +02:00
|
|
|
network: "192.168.0.0/16",
|
|
|
|
netID: "happy",
|
2022-08-18 18:22:15 +02:00
|
|
|
peer: peer1Key,
|
|
|
|
description: "super",
|
|
|
|
masquerade: false,
|
|
|
|
metric: 9999,
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
errFunc: require.NoError,
|
|
|
|
shouldCreate: true,
|
|
|
|
expectedRoute: &route.Route{
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetworkType: route.IPv4Network,
|
|
|
|
NetID: "happy",
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Bad Prefix",
|
|
|
|
inputArgs: input{
|
2022-08-22 14:10:24 +02:00
|
|
|
network: "192.168.0.0/34",
|
|
|
|
netID: "happy",
|
2022-08-18 18:22:15 +02:00
|
|
|
peer: peer1Key,
|
|
|
|
description: "super",
|
|
|
|
masquerade: false,
|
|
|
|
metric: 9999,
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
shouldCreate: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Bad Peer",
|
|
|
|
inputArgs: input{
|
2022-08-22 14:10:24 +02:00
|
|
|
network: "192.168.0.0/16",
|
|
|
|
netID: "happy",
|
2022-08-18 18:22:15 +02:00
|
|
|
peer: "notExistingPeer",
|
|
|
|
description: "super",
|
|
|
|
masquerade: false,
|
|
|
|
metric: 9999,
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
shouldCreate: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Empty Peer",
|
|
|
|
inputArgs: input{
|
2022-08-22 14:10:24 +02:00
|
|
|
network: "192.168.0.0/16",
|
|
|
|
netID: "happy",
|
2022-08-18 18:22:15 +02:00
|
|
|
peer: "",
|
|
|
|
description: "super",
|
|
|
|
masquerade: false,
|
|
|
|
metric: 9999,
|
|
|
|
enabled: false,
|
|
|
|
},
|
|
|
|
errFunc: require.NoError,
|
|
|
|
shouldCreate: true,
|
|
|
|
expectedRoute: &route.Route{
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetworkType: route.IPv4Network,
|
|
|
|
NetID: "happy",
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: "",
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Large Metric",
|
|
|
|
inputArgs: input{
|
2022-08-22 14:10:24 +02:00
|
|
|
network: "192.168.0.0/16",
|
2022-08-18 18:22:15 +02:00
|
|
|
peer: peer1Key,
|
2022-08-22 14:10:24 +02:00
|
|
|
netID: "happy",
|
2022-08-18 18:22:15 +02:00
|
|
|
description: "super",
|
|
|
|
masquerade: false,
|
|
|
|
metric: 99999,
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
shouldCreate: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Small Metric",
|
|
|
|
inputArgs: input{
|
2022-08-22 14:10:24 +02:00
|
|
|
network: "192.168.0.0/16",
|
|
|
|
netID: "happy",
|
2022-08-18 18:22:15 +02:00
|
|
|
peer: peer1Key,
|
|
|
|
description: "super",
|
|
|
|
masquerade: false,
|
|
|
|
metric: 0,
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
shouldCreate: false,
|
|
|
|
},
|
2022-08-22 14:10:24 +02:00
|
|
|
{
|
|
|
|
name: "Large NetID",
|
|
|
|
inputArgs: input{
|
|
|
|
network: "192.168.0.0/16",
|
|
|
|
peer: peer1Key,
|
|
|
|
netID: "12345678901234567890qwertyuiopqwertyuiop1",
|
|
|
|
description: "super",
|
|
|
|
masquerade: false,
|
|
|
|
metric: 9999,
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
shouldCreate: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Small NetID",
|
|
|
|
inputArgs: input{
|
|
|
|
network: "192.168.0.0/16",
|
|
|
|
netID: "",
|
|
|
|
peer: peer1Key,
|
|
|
|
description: "",
|
|
|
|
masquerade: false,
|
|
|
|
metric: 9999,
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
shouldCreate: false,
|
|
|
|
},
|
2022-08-18 18:22:15 +02:00
|
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
|
|
am, err := createRouterManager(t)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to create account manager")
|
|
|
|
}
|
|
|
|
|
|
|
|
account, err := initTestRouteAccount(t, am)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to init testing account")
|
|
|
|
}
|
|
|
|
|
|
|
|
outRoute, err := am.CreateRoute(
|
|
|
|
account.Id,
|
2022-08-22 14:10:24 +02:00
|
|
|
testCase.inputArgs.network,
|
2022-08-18 18:22:15 +02:00
|
|
|
testCase.inputArgs.peer,
|
|
|
|
testCase.inputArgs.description,
|
2022-08-22 14:10:24 +02:00
|
|
|
testCase.inputArgs.netID,
|
2022-08-18 18:22:15 +02:00
|
|
|
testCase.inputArgs.masquerade,
|
|
|
|
testCase.inputArgs.metric,
|
|
|
|
testCase.inputArgs.enabled,
|
|
|
|
)
|
|
|
|
|
|
|
|
testCase.errFunc(t, err)
|
|
|
|
|
|
|
|
if !testCase.shouldCreate {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// assign generated ID
|
|
|
|
testCase.expectedRoute.ID = outRoute.ID
|
|
|
|
|
|
|
|
if !testCase.expectedRoute.IsEqual(outRoute) {
|
|
|
|
t.Errorf("new route didn't match expected route:\nGot %#v\nExpected:%#v\n", outRoute, testCase.expectedRoute)
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSaveRoute(t *testing.T) {
|
|
|
|
|
|
|
|
validPeer := peer2Key
|
|
|
|
invalidPeer := "nonExisting"
|
|
|
|
validPrefix := netip.MustParsePrefix("192.168.0.0/24")
|
|
|
|
invalidPrefix, _ := netip.ParsePrefix("192.168.0.0/34")
|
|
|
|
validMetric := 1000
|
|
|
|
invalidMetric := 99999
|
2022-08-22 14:10:24 +02:00
|
|
|
validNetID := "12345678901234567890qw"
|
|
|
|
invalidNetID := "12345678901234567890qwertyuiopqwertyuiop1"
|
2022-08-18 18:22:15 +02:00
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
name string
|
|
|
|
existingRoute *route.Route
|
|
|
|
newPeer *string
|
|
|
|
newMetric *int
|
|
|
|
newPrefix *netip.Prefix
|
|
|
|
skipCopying bool
|
|
|
|
shouldCreate bool
|
|
|
|
errFunc require.ErrorAssertionFunc
|
|
|
|
expectedRoute *route.Route
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Happy Path",
|
|
|
|
existingRoute: &route.Route{
|
|
|
|
ID: "testingRoute",
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: validNetID,
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
newPeer: &validPeer,
|
|
|
|
newMetric: &validMetric,
|
|
|
|
newPrefix: &validPrefix,
|
|
|
|
errFunc: require.NoError,
|
|
|
|
shouldCreate: true,
|
|
|
|
expectedRoute: &route.Route{
|
|
|
|
ID: "testingRoute",
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: validPrefix,
|
|
|
|
NetID: validNetID,
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: validPeer,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: validMetric,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Bad Prefix",
|
|
|
|
existingRoute: &route.Route{
|
|
|
|
ID: "testingRoute",
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: validNetID,
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
newPrefix: &invalidPrefix,
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Bad Peer",
|
|
|
|
existingRoute: &route.Route{
|
|
|
|
ID: "testingRoute",
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: validNetID,
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
newPeer: &invalidPeer,
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid Metric",
|
|
|
|
existingRoute: &route.Route{
|
|
|
|
ID: "testingRoute",
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: validNetID,
|
|
|
|
NetworkType: route.IPv4Network,
|
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
newMetric: &invalidMetric,
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid NetID",
|
|
|
|
existingRoute: &route.Route{
|
|
|
|
ID: "testingRoute",
|
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: invalidNetID,
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
newMetric: &invalidMetric,
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Nil Route",
|
|
|
|
existingRoute: &route.Route{
|
|
|
|
ID: "testingRoute",
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: validNetID,
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
skipCopying: true,
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
|
|
am, err := createRouterManager(t)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to create account manager")
|
|
|
|
}
|
|
|
|
|
|
|
|
account, err := initTestRouteAccount(t, am)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to init testing account")
|
|
|
|
}
|
|
|
|
|
|
|
|
account.Routes[testCase.existingRoute.ID] = testCase.existingRoute
|
|
|
|
|
|
|
|
err = am.Store.SaveAccount(account)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("account should be saved")
|
|
|
|
}
|
|
|
|
|
|
|
|
var routeToSave *route.Route
|
|
|
|
|
|
|
|
if !testCase.skipCopying {
|
|
|
|
routeToSave = testCase.existingRoute.Copy()
|
|
|
|
if testCase.newPeer != nil {
|
|
|
|
routeToSave.Peer = *testCase.newPeer
|
|
|
|
}
|
|
|
|
|
|
|
|
if testCase.newMetric != nil {
|
|
|
|
routeToSave.Metric = *testCase.newMetric
|
|
|
|
}
|
|
|
|
|
|
|
|
if testCase.newPrefix != nil {
|
2022-08-22 14:10:24 +02:00
|
|
|
routeToSave.Network = *testCase.newPrefix
|
2022-08-18 18:22:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = am.SaveRoute(account.Id, routeToSave)
|
|
|
|
|
|
|
|
testCase.errFunc(t, err)
|
|
|
|
|
|
|
|
if !testCase.shouldCreate {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-11-07 17:52:23 +01:00
|
|
|
account, err = am.Store.GetAccount(account.Id)
|
2022-11-07 12:10:56 +01:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2022-08-18 18:22:15 +02:00
|
|
|
savedRoute, saved := account.Routes[testCase.expectedRoute.ID]
|
|
|
|
require.True(t, saved)
|
|
|
|
|
|
|
|
if !testCase.expectedRoute.IsEqual(savedRoute) {
|
|
|
|
t.Errorf("new route didn't match expected route:\nGot %#v\nExpected:%#v\n", savedRoute, testCase.expectedRoute)
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUpdateRoute(t *testing.T) {
|
|
|
|
routeID := "testingRouteID"
|
|
|
|
|
|
|
|
existingRoute := &route.Route{
|
|
|
|
ID: routeID,
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: "superRoute",
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
name string
|
|
|
|
existingRoute *route.Route
|
|
|
|
operations []RouteUpdateOperation
|
|
|
|
shouldCreate bool
|
|
|
|
errFunc require.ErrorAssertionFunc
|
|
|
|
expectedRoute *route.Route
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Happy Path Single OPS",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRoutePeer,
|
|
|
|
Values: []string{peer2Key},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.NoError,
|
|
|
|
shouldCreate: true,
|
|
|
|
expectedRoute: &route.Route{
|
|
|
|
ID: routeID,
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: "superRoute",
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer2Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Happy Path Multiple OPS",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteDescription,
|
|
|
|
Values: []string{"great"},
|
|
|
|
},
|
|
|
|
RouteUpdateOperation{
|
2022-08-22 14:10:24 +02:00
|
|
|
Type: UpdateRouteNetwork,
|
2022-08-18 18:22:15 +02:00
|
|
|
Values: []string{"192.168.0.0/24"},
|
|
|
|
},
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRoutePeer,
|
|
|
|
Values: []string{peer2Key},
|
|
|
|
},
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteMetric,
|
|
|
|
Values: []string{"3030"},
|
|
|
|
},
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteMasquerade,
|
|
|
|
Values: []string{"true"},
|
|
|
|
},
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteEnabled,
|
|
|
|
Values: []string{"false"},
|
|
|
|
},
|
2022-08-22 14:10:24 +02:00
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteNetworkIdentifier,
|
|
|
|
Values: []string{"megaRoute"},
|
|
|
|
},
|
2022-08-18 18:22:15 +02:00
|
|
|
},
|
|
|
|
errFunc: require.NoError,
|
|
|
|
shouldCreate: true,
|
|
|
|
expectedRoute: &route.Route{
|
|
|
|
ID: routeID,
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/24"),
|
|
|
|
NetID: "megaRoute",
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer2Key,
|
|
|
|
Description: "great",
|
|
|
|
Masquerade: true,
|
|
|
|
Metric: 3030,
|
|
|
|
Enabled: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Empty Values",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRoutePeer,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Multiple Values",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRoutePeer,
|
|
|
|
Values: []string{peer2Key, peer1Key},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Bad Prefix",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
2022-08-22 14:10:24 +02:00
|
|
|
Type: UpdateRouteNetwork,
|
2022-08-18 18:22:15 +02:00
|
|
|
Values: []string{"192.168.0.0/34"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Bad Peer",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRoutePeer,
|
|
|
|
Values: []string{"non existing Peer"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Empty Peer",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRoutePeer,
|
|
|
|
Values: []string{""},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.NoError,
|
|
|
|
shouldCreate: true,
|
|
|
|
expectedRoute: &route.Route{
|
|
|
|
ID: routeID,
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: "superRoute",
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: "",
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
},
|
|
|
|
},
|
2022-08-22 14:10:24 +02:00
|
|
|
{
|
|
|
|
name: "Large Network ID",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteNetworkIdentifier,
|
|
|
|
Values: []string{"12345678901234567890qwertyuiopqwertyuiop1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Empty Network ID",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteNetworkIdentifier,
|
|
|
|
Values: []string{""},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
2022-08-18 18:22:15 +02:00
|
|
|
{
|
|
|
|
name: "Invalid Metric",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteMetric,
|
|
|
|
Values: []string{"999999"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid Boolean",
|
|
|
|
existingRoute: existingRoute,
|
|
|
|
operations: []RouteUpdateOperation{
|
|
|
|
RouteUpdateOperation{
|
|
|
|
Type: UpdateRouteMasquerade,
|
|
|
|
Values: []string{"yes"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
errFunc: require.Error,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
|
|
am, err := createRouterManager(t)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to create account manager")
|
|
|
|
}
|
|
|
|
|
|
|
|
account, err := initTestRouteAccount(t, am)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to init testing account")
|
|
|
|
}
|
|
|
|
|
|
|
|
account.Routes[testCase.existingRoute.ID] = testCase.existingRoute
|
|
|
|
|
|
|
|
err = am.Store.SaveAccount(account)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("account should be saved")
|
|
|
|
}
|
|
|
|
|
|
|
|
updatedRoute, err := am.UpdateRoute(account.Id, testCase.existingRoute.ID, testCase.operations)
|
|
|
|
|
|
|
|
testCase.errFunc(t, err)
|
|
|
|
|
|
|
|
if !testCase.shouldCreate {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
testCase.expectedRoute.ID = updatedRoute.ID
|
|
|
|
|
|
|
|
if !testCase.expectedRoute.IsEqual(updatedRoute) {
|
|
|
|
t.Errorf("new route didn't match expected route:\nGot %#v\nExpected:%#v\n", updatedRoute, testCase.expectedRoute)
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteRoute(t *testing.T) {
|
|
|
|
|
|
|
|
testingRoute := &route.Route{
|
|
|
|
ID: "testingRoute",
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
am, err := createRouterManager(t)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to create account manager")
|
|
|
|
}
|
|
|
|
|
|
|
|
account, err := initTestRouteAccount(t, am)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to init testing account")
|
|
|
|
}
|
|
|
|
|
|
|
|
account.Routes[testingRoute.ID] = testingRoute
|
|
|
|
|
|
|
|
err = am.Store.SaveAccount(account)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to save account")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = am.DeleteRoute(account.Id, testingRoute.ID)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("deleting route failed with error: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
savedAccount, err := am.Store.GetAccount(account.Id)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to retrieve saved account with error: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, found := savedAccount.Routes[testingRoute.ID]
|
|
|
|
if found {
|
|
|
|
t.Error("route shouldn't be found after delete")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetNetworkMap_RouteSync(t *testing.T) {
|
|
|
|
// no routes for peer in different groups
|
|
|
|
// no routes when route is deleted
|
|
|
|
|
|
|
|
baseRoute := &route.Route{
|
|
|
|
ID: "testingRoute",
|
2022-08-22 14:10:24 +02:00
|
|
|
Network: netip.MustParsePrefix("192.168.0.0/16"),
|
|
|
|
NetID: "superNet",
|
|
|
|
NetworkType: route.IPv4Network,
|
2022-08-18 18:22:15 +02:00
|
|
|
Peer: peer1Key,
|
|
|
|
Description: "super",
|
|
|
|
Masquerade: false,
|
|
|
|
Metric: 9999,
|
|
|
|
Enabled: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
am, err := createRouterManager(t)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to create account manager")
|
|
|
|
}
|
|
|
|
|
|
|
|
account, err := initTestRouteAccount(t, am)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to init testing account")
|
|
|
|
}
|
|
|
|
|
|
|
|
newAccountRoutes, err := am.GetNetworkMap(peer1Key)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, newAccountRoutes.Routes, 0, "new accounts should have no routes")
|
|
|
|
|
2022-08-22 14:10:24 +02:00
|
|
|
createdRoute, err := am.CreateRoute(account.Id, baseRoute.Network.String(), baseRoute.Peer,
|
|
|
|
baseRoute.Description, baseRoute.NetID, baseRoute.Masquerade, baseRoute.Metric, false)
|
2022-08-18 18:22:15 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
noDisabledRoutes, err := am.GetNetworkMap(peer1Key)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, noDisabledRoutes.Routes, 0, "no routes for disabled routes")
|
|
|
|
|
|
|
|
enabledRoute := createdRoute.Copy()
|
|
|
|
enabledRoute.Enabled = true
|
|
|
|
|
|
|
|
err = am.SaveRoute(account.Id, enabledRoute)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
peer1Routes, err := am.GetNetworkMap(peer1Key)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, peer1Routes.Routes, 1, "we should receive one route for peer1")
|
|
|
|
require.True(t, enabledRoute.IsEqual(peer1Routes.Routes[0]), "received route should be equal")
|
|
|
|
|
|
|
|
peer2Routes, err := am.GetNetworkMap(peer2Key)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, peer2Routes.Routes, 1, "we should receive one route for peer2")
|
|
|
|
require.True(t, peer1Routes.Routes[0].IsEqual(peer2Routes.Routes[0]), "routes should be the same for peers in the same group")
|
|
|
|
|
|
|
|
newGroup := &Group{
|
|
|
|
ID: xid.New().String(),
|
|
|
|
Name: "peer1 group",
|
|
|
|
Peers: []string{peer1Key},
|
|
|
|
}
|
|
|
|
err = am.SaveGroup(account.Id, newGroup)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-11-05 10:24:50 +01:00
|
|
|
rules, err := am.ListRules(account.Id, "testingUser")
|
2022-08-18 18:22:15 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
defaultRule := rules[0]
|
|
|
|
newRule := defaultRule.Copy()
|
|
|
|
newRule.ID = xid.New().String()
|
|
|
|
newRule.Name = "peer1 only"
|
|
|
|
newRule.Source = []string{newGroup.ID}
|
|
|
|
newRule.Destination = []string{newGroup.ID}
|
|
|
|
|
|
|
|
err = am.SaveRule(account.Id, newRule)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = am.DeleteRule(account.Id, defaultRule.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
peer1GroupRoutes, err := am.GetNetworkMap(peer1Key)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, peer1GroupRoutes.Routes, 1, "we should receive one route for peer1")
|
|
|
|
|
|
|
|
peer2GroupRoutes, err := am.GetNetworkMap(peer2Key)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, peer2GroupRoutes.Routes, 0, "we should not receive routes for peer2")
|
|
|
|
|
|
|
|
err = am.DeleteRoute(account.Id, enabledRoute.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
peer1DeletedRoute, err := am.GetNetworkMap(peer1Key)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, peer1DeletedRoute.Routes, 0, "we should receive one route for peer1")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func createRouterManager(t *testing.T) (*DefaultAccountManager, error) {
|
|
|
|
store, err := createRouterStore(t)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-11-07 15:38:21 +01:00
|
|
|
return BuildManager(store, NewPeersUpdateManager(), nil, "", "")
|
2022-08-18 18:22:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func createRouterStore(t *testing.T) (Store, error) {
|
|
|
|
dataDir := t.TempDir()
|
2022-11-08 10:46:12 +01:00
|
|
|
store, err := NewFileStore(dataDir)
|
2022-08-18 18:22:15 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return store, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func initTestRouteAccount(t *testing.T, am *DefaultAccountManager) (*Account, error) {
|
|
|
|
peer1 := &Peer{
|
|
|
|
Key: peer1Key,
|
|
|
|
Name: "test-host1@netbird.io",
|
|
|
|
Meta: PeerSystemMeta{
|
|
|
|
Hostname: "test-host1@netbird.io",
|
|
|
|
GoOS: "linux",
|
|
|
|
Kernel: "Linux",
|
|
|
|
Core: "21.04",
|
|
|
|
Platform: "x86_64",
|
|
|
|
OS: "Ubuntu",
|
|
|
|
WtVersion: "development",
|
|
|
|
UIVersion: "development",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
peer2 := &Peer{
|
|
|
|
Key: peer2Key,
|
|
|
|
Name: "test-host2@netbird.io",
|
|
|
|
Meta: PeerSystemMeta{
|
|
|
|
Hostname: "test-host2@netbird.io",
|
|
|
|
GoOS: "linux",
|
|
|
|
Kernel: "Linux",
|
|
|
|
Core: "21.04",
|
|
|
|
Platform: "x86_64",
|
|
|
|
OS: "Ubuntu",
|
|
|
|
WtVersion: "development",
|
|
|
|
UIVersion: "development",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
accountID := "testingAcc"
|
|
|
|
userID := "testingUser"
|
|
|
|
domain := "example.com"
|
|
|
|
|
|
|
|
account := newAccountWithId(accountID, userID, domain)
|
|
|
|
err := am.Store.SaveAccount(account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = am.AddPeer("", userID, peer1)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
_, err = am.AddPeer("", userID, peer2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-11-07 17:52:23 +01:00
|
|
|
return am.Store.GetAccount(account.Id)
|
2022-08-18 18:22:15 +02:00
|
|
|
}
|