2021-08-20 15:18:29 +02:00
package server
import (
2024-07-03 11:33:02 +02:00
"context"
2023-03-16 15:57:44 +01:00
"crypto/sha256"
2023-03-29 15:21:53 +02:00
b64 "encoding/base64"
2023-08-22 17:56:39 +02:00
"encoding/json"
2022-11-07 17:37:28 +01:00
"fmt"
2024-11-28 14:59:53 +01:00
"io"
2022-05-05 08:58:34 +02:00
"net"
2024-11-28 14:59:53 +01:00
"os"
2022-11-07 17:37:28 +01:00
"reflect"
2024-11-28 14:59:53 +01:00
"strconv"
2022-06-04 22:02:22 +02:00
"sync"
2022-05-05 08:58:34 +02:00
"testing"
2023-01-24 10:17:24 +01:00
"time"
2022-05-05 08:58:34 +02:00
2023-06-27 16:51:05 +02:00
"github.com/golang-jwt/jwt"
2024-12-11 12:58:45 +01:00
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
2024-11-28 14:59:53 +01:00
log "github.com/sirupsen/logrus"
2024-03-27 18:48:48 +01:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
2023-09-04 11:37:39 +02:00
2023-03-08 12:21:44 +01:00
nbdns "github.com/netbirdio/netbird/dns"
2024-03-27 18:48:48 +01:00
"github.com/netbirdio/netbird/management/server/account"
2023-03-08 12:21:44 +01:00
"github.com/netbirdio/netbird/management/server/activity"
2024-03-27 18:48:48 +01:00
"github.com/netbirdio/netbird/management/server/group"
"github.com/netbirdio/netbird/management/server/jwtclaims"
2023-11-28 13:45:26 +01:00
nbpeer "github.com/netbirdio/netbird/management/server/peer"
2024-02-20 09:59:56 +01:00
"github.com/netbirdio/netbird/management/server/posture"
2024-12-11 12:58:45 +01:00
"github.com/netbirdio/netbird/management/server/store"
2024-08-07 10:52:31 +02:00
"github.com/netbirdio/netbird/management/server/telemetry"
2024-12-11 12:58:45 +01:00
"github.com/netbirdio/netbird/management/server/types"
2023-03-08 12:21:44 +01:00
"github.com/netbirdio/netbird/route"
2024-03-27 18:48:48 +01:00
)
2023-03-08 12:21:44 +01:00
2024-03-27 18:48:48 +01:00
type MocIntegratedValidator struct {
2024-11-07 09:50:13 +01:00
ValidatePeerFunc func ( _ context . Context , update * nbpeer . Peer , peer * nbpeer . Peer , userID string , accountID string , dnsDomain string , peersGroup [ ] string , extraSettings * account . ExtraSettings ) ( * nbpeer . Peer , bool , error )
2024-03-27 18:48:48 +01:00
}
2023-03-08 12:21:44 +01:00
2024-07-03 11:33:02 +02:00
func ( a MocIntegratedValidator ) ValidateExtraSettings ( _ context . Context , newExtraSettings * account . ExtraSettings , oldExtraSettings * account . ExtraSettings , peers map [ string ] * nbpeer . Peer , userID string , accountID string ) error {
2024-03-27 18:48:48 +01:00
return nil
}
2024-11-07 09:50:13 +01:00
func ( a MocIntegratedValidator ) ValidatePeer ( _ context . Context , update * nbpeer . Peer , peer * nbpeer . Peer , userID string , accountID string , dnsDomain string , peersGroup [ ] string , extraSettings * account . ExtraSettings ) ( * nbpeer . Peer , bool , error ) {
if a . ValidatePeerFunc != nil {
return a . ValidatePeerFunc ( context . Background ( ) , update , peer , userID , accountID , dnsDomain , peersGroup , extraSettings )
}
return update , false , nil
2024-03-27 18:48:48 +01:00
}
func ( a MocIntegratedValidator ) GetValidatedPeers ( accountID string , groups map [ string ] * group . Group , peers map [ string ] * nbpeer . Peer , extraSettings * account . ExtraSettings ) ( map [ string ] struct { } , error ) {
validatedPeers := make ( map [ string ] struct { } )
for _ , peer := range peers {
validatedPeers [ peer . ID ] = struct { } { }
}
return validatedPeers , nil
}
2024-07-03 11:33:02 +02:00
func ( MocIntegratedValidator ) PreparePeer ( _ context . Context , accountID string , peer * nbpeer . Peer , peersGroup [ ] string , extraSettings * account . ExtraSettings ) * nbpeer . Peer {
2024-03-27 18:48:48 +01:00
return peer
}
2024-07-03 11:33:02 +02:00
func ( MocIntegratedValidator ) IsNotValidPeer ( _ context . Context , accountID string , peer * nbpeer . Peer , peersGroup [ ] string , extraSettings * account . ExtraSettings ) ( bool , bool , error ) {
2024-05-24 13:29:25 +02:00
return false , false , nil
2024-03-27 18:48:48 +01:00
}
2024-07-03 11:33:02 +02:00
func ( MocIntegratedValidator ) PeerDeleted ( _ context . Context , _ , _ string ) error {
2024-03-27 18:48:48 +01:00
return nil
}
func ( MocIntegratedValidator ) SetPeerInvalidationListener ( func ( accountID string ) ) {
}
2024-07-03 11:33:02 +02:00
func ( MocIntegratedValidator ) Stop ( _ context . Context ) {
2024-03-27 18:48:48 +01:00
}
2021-08-20 15:18:29 +02:00
2024-12-11 12:58:45 +01:00
func verifyCanAddPeerToAccount ( t * testing . T , manager AccountManager , account * types . Account , userID string ) {
2023-11-10 16:33:13 +01:00
t . Helper ( )
2023-11-28 13:45:26 +01:00
peer := & nbpeer . Peer {
2022-06-09 13:14:34 +02:00
Key : "BhRPtynAAYRDy08+q4HTMsos8fs4plTP4NOSh7C1ry8=" ,
Name : "test-host@netbird.io" ,
2023-11-28 13:45:26 +01:00
Meta : nbpeer . PeerSystemMeta {
2022-06-09 13:14:34 +02:00
Hostname : "test-host@netbird.io" ,
GoOS : "linux" ,
Kernel : "Linux" ,
Core : "21.04" ,
Platform : "x86_64" ,
OS : "Ubuntu" ,
WtVersion : "development" ,
UIVersion : "development" ,
} ,
}
var setupKey string
for _ , key := range account . SetupKeys {
setupKey = key . Key
}
2024-07-03 11:33:02 +02:00
_ , _ , _ , err := manager . AddPeer ( context . Background ( ) , setupKey , userID , peer )
2022-06-09 13:14:34 +02:00
if err != nil {
t . Error ( "expected to add new peer successfully after creating new account, but failed" , err )
}
}
2024-12-11 12:58:45 +01:00
func verifyNewAccountHasDefaultFields ( t * testing . T , account * types . Account , createdBy string , domain string , expectedUsers [ ] string ) {
2023-11-10 16:33:13 +01:00
t . Helper ( )
2022-06-09 13:14:34 +02:00
if len ( account . Peers ) != 0 {
t . Errorf ( "expected account to have len(Peers) = %v, got %v" , 0 , len ( account . Peers ) )
}
2023-06-27 17:17:24 +02:00
if len ( account . SetupKeys ) != 0 {
2022-06-09 13:14:34 +02:00
t . Errorf ( "expected account to have len(SetupKeys) = %v, got %v" , 2 , len ( account . SetupKeys ) )
}
ipNet := net . IPNet { IP : net . ParseIP ( "100.64.0.0" ) , Mask : net . IPMask { 255 , 192 , 0 , 0 } }
if ! ipNet . Contains ( account . Network . Net . IP ) {
t . Errorf ( "expected account's Network to be a subnet of %v, got %v" , ipNet . String ( ) , account . Network . Net . String ( ) )
}
g , err := account . GetGroupAll ( )
if err != nil {
t . Fatal ( err )
}
if g . Name != "All" {
t . Errorf ( "expecting account to have group ALL added by default" )
}
if len ( account . Users ) != len ( expectedUsers ) {
t . Errorf ( "expecting account to have %d users, got %d" , len ( expectedUsers ) , len ( account . Users ) )
}
if account . Users [ createdBy ] == nil {
t . Errorf ( "expecting account to have createdBy user %s in a user map " , createdBy )
}
for _ , expectedUserID := range expectedUsers {
if account . Users [ expectedUserID ] == nil {
t . Errorf ( "expecting account to have a user %s in a user map" , expectedUserID )
}
}
if account . CreatedBy != createdBy {
t . Errorf ( "expecting newly created account to be created by user %s, got %s" , createdBy , account . CreatedBy )
}
2024-03-02 13:49:40 +01:00
if account . CreatedAt . IsZero ( ) {
t . Errorf ( "expecting newly created account to have a non-zero creation time" )
}
2022-06-09 13:14:34 +02:00
if account . Domain != domain {
t . Errorf ( "expecting newly created account to have domain %s, got %s" , domain , account . Domain )
}
}
2023-03-09 11:24:42 +01:00
func TestAccount_GetPeerNetworkMap ( t * testing . T ) {
peerID1 := "peer-1"
peerID2 := "peer-2"
2023-11-28 13:45:26 +01:00
// peerID3 := "peer-3"
2023-03-09 11:24:42 +01:00
tt := [ ] struct {
name string
2024-12-11 12:58:45 +01:00
accountSettings types . Settings
2023-03-09 11:24:42 +01:00
peerID string
expectedPeers [ ] string
expectedOfflinePeers [ ] string
2023-11-28 13:45:26 +01:00
peers map [ string ] * nbpeer . Peer
2023-03-09 11:24:42 +01:00
} {
{
name : "Should return ALL peers when global peer login expiration disabled" ,
2024-12-11 12:58:45 +01:00
accountSettings : types . Settings { PeerLoginExpirationEnabled : false , PeerLoginExpiration : time . Hour } ,
2023-03-09 11:24:42 +01:00
peerID : peerID1 ,
expectedPeers : [ ] string { peerID2 } ,
expectedOfflinePeers : [ ] string { } ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-03-09 11:24:42 +01:00
"peer-1" : {
ID : peerID1 ,
Key : "peer-1-key" ,
IP : net . IP { 100 , 64 , 0 , 1 } ,
Name : peerID1 ,
DNSLabel : peerID1 ,
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-04-03 15:09:35 +02:00
LastSeen : time . Now ( ) . UTC ( ) ,
2023-03-09 11:24:42 +01:00
Connected : false ,
LoginExpired : true ,
} ,
UserID : userID ,
2023-04-03 15:09:35 +02:00
LastLogin : time . Now ( ) . UTC ( ) . Add ( - time . Hour * 24 * 30 * 30 ) ,
2023-03-09 11:24:42 +01:00
} ,
"peer-2" : {
ID : peerID2 ,
Key : "peer-2-key" ,
IP : net . IP { 100 , 64 , 0 , 1 } ,
Name : peerID2 ,
DNSLabel : peerID2 ,
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-04-03 15:09:35 +02:00
LastSeen : time . Now ( ) . UTC ( ) ,
2023-03-09 11:24:42 +01:00
Connected : false ,
LoginExpired : false ,
} ,
UserID : userID ,
2023-04-03 15:09:35 +02:00
LastLogin : time . Now ( ) . UTC ( ) ,
2023-03-09 11:24:42 +01:00
LoginExpirationEnabled : true ,
} ,
} ,
} ,
{
name : "Should return no peers when global peer login expiration enabled and peers expired" ,
2024-12-11 12:58:45 +01:00
accountSettings : types . Settings { PeerLoginExpirationEnabled : true , PeerLoginExpiration : time . Hour } ,
2023-03-09 11:24:42 +01:00
peerID : peerID1 ,
expectedPeers : [ ] string { } ,
expectedOfflinePeers : [ ] string { peerID2 } ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-03-09 11:24:42 +01:00
"peer-1" : {
ID : peerID1 ,
Key : "peer-1-key" ,
IP : net . IP { 100 , 64 , 0 , 1 } ,
Name : peerID1 ,
DNSLabel : peerID1 ,
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-04-03 15:09:35 +02:00
LastSeen : time . Now ( ) . UTC ( ) ,
2023-03-09 11:24:42 +01:00
Connected : false ,
LoginExpired : true ,
} ,
UserID : userID ,
2023-04-03 15:09:35 +02:00
LastLogin : time . Now ( ) . UTC ( ) . Add ( - time . Hour * 24 * 30 * 30 ) ,
2023-03-09 11:24:42 +01:00
LoginExpirationEnabled : true ,
} ,
"peer-2" : {
ID : peerID2 ,
Key : "peer-2-key" ,
IP : net . IP { 100 , 64 , 0 , 1 } ,
Name : peerID2 ,
DNSLabel : peerID2 ,
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-04-03 15:09:35 +02:00
LastSeen : time . Now ( ) . UTC ( ) ,
2023-03-09 11:24:42 +01:00
Connected : false ,
LoginExpired : true ,
} ,
UserID : userID ,
2023-04-03 15:09:35 +02:00
LastLogin : time . Now ( ) . UTC ( ) . Add ( - time . Hour * 24 * 30 * 30 ) ,
2023-03-09 11:24:42 +01:00
LoginExpirationEnabled : true ,
} ,
} ,
} ,
2023-11-28 13:45:26 +01:00
// {
// name: "Should return only peers that are approved when peer approval is enabled",
// accountSettings: Settings{PeerApprovalEnabled: true},
// peerID: peerID1,
// expectedPeers: []string{peerID3},
// expectedOfflinePeers: []string{},
// peers: map[string]*Peer{
// "peer-1": {
// ID: peerID1,
// Key: "peer-1-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID1,
// DNSLabel: peerID1,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: true,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// "peer-2": {
// ID: peerID2,
// Key: "peer-2-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID2,
// DNSLabel: peerID2,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: false,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// "peer-3": {
// ID: peerID3,
// Key: "peer-3-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID3,
// DNSLabel: peerID3,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: true,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// },
// },
// {
// name: "Should return all peers when peer approval is disabled",
// accountSettings: Settings{PeerApprovalEnabled: false},
// peerID: peerID1,
// expectedPeers: []string{peerID2, peerID3},
// expectedOfflinePeers: []string{},
// peers: map[string]*Peer{
// "peer-1": {
// ID: peerID1,
// Key: "peer-1-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID1,
// DNSLabel: peerID1,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: true,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// "peer-2": {
// ID: peerID2,
// Key: "peer-2-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID2,
// DNSLabel: peerID2,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: false,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// "peer-3": {
// ID: peerID3,
// Key: "peer-3-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID3,
// DNSLabel: peerID3,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: true,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// },
// },
// {
// name: "Should return no peers when peer approval is enabled and the requesting peer is not approved",
// accountSettings: Settings{PeerApprovalEnabled: true},
// peerID: peerID1,
// expectedPeers: []string{},
// expectedOfflinePeers: []string{},
// peers: map[string]*Peer{
// "peer-1": {
// ID: peerID1,
// Key: "peer-1-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID1,
// DNSLabel: peerID1,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: false,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// "peer-2": {
// ID: peerID2,
// Key: "peer-2-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID2,
// DNSLabel: peerID2,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: true,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// "peer-3": {
// ID: peerID3,
// Key: "peer-3-key",
// IP: net.IP{100, 64, 0, 1},
// Name: peerID3,
// DNSLabel: peerID3,
// Status: &PeerStatus{
// LastSeen: time.Now().UTC(),
// Connected: false,
// Approved: true,
// },
// UserID: userID,
// LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
// },
// },
// },
2023-03-09 11:24:42 +01:00
}
netIP := net . IP { 100 , 64 , 0 , 0 }
netMask := net . IPMask { 255 , 255 , 0 , 0 }
2024-12-11 12:58:45 +01:00
network := & types . Network {
2023-10-12 15:42:36 +02:00
Identifier : "network" ,
Net : net . IPNet { IP : netIP , Mask : netMask } ,
Dns : "netbird.selfhosted" ,
Serial : 0 ,
2024-12-11 12:58:45 +01:00
Mu : sync . Mutex { } ,
2023-03-09 11:24:42 +01:00
}
for _ , testCase := range tt {
2024-07-03 11:33:02 +02:00
account := newAccountWithId ( context . Background ( ) , "account-1" , userID , "netbird.io" )
2023-11-28 13:45:26 +01:00
account . UpdateSettings ( & testCase . accountSettings )
2023-03-09 11:24:42 +01:00
account . Network = network
account . Peers = testCase . peers
for _ , peer := range account . Peers {
all , _ := account . GetGroupAll ( )
account . Groups [ all . ID ] . Peers = append ( account . Groups [ all . ID ] . Peers , peer . ID )
}
2022-06-09 13:14:34 +02:00
2024-03-27 18:48:48 +01:00
validatedPeers := map [ string ] struct { } { }
for p := range account . Peers {
validatedPeers [ p ] = struct { } { }
}
2024-08-07 10:52:31 +02:00
customZone := account . GetPeersCustomZone ( context . Background ( ) , "netbird.io" )
networkMap := account . GetPeerNetworkMap ( context . Background ( ) , testCase . peerID , customZone , validatedPeers , nil )
2023-03-09 11:24:42 +01:00
assert . Len ( t , networkMap . Peers , len ( testCase . expectedPeers ) )
assert . Len ( t , networkMap . OfflinePeers , len ( testCase . expectedOfflinePeers ) )
}
}
2022-06-09 13:14:34 +02:00
func TestNewAccount ( t * testing . T ) {
domain := "netbird.io"
userId := "account_creator"
2022-06-20 18:20:43 +02:00
accountID := "account_id"
2024-07-03 11:33:02 +02:00
account := newAccountWithId ( context . Background ( ) , accountID , userId , domain )
2022-06-09 13:14:34 +02:00
verifyNewAccountHasDefaultFields ( t , account , userId , domain , [ ] string { userId } )
}
2021-12-27 13:17:15 +01:00
func TestAccountManager_GetOrCreateAccountByUser ( t * testing . T ) {
2021-08-20 15:44:18 +02:00
manager , err := createManager ( t )
2021-08-20 15:18:29 +02:00
if err != nil {
t . Fatal ( err )
2021-08-20 15:44:18 +02:00
return
2021-08-20 15:18:29 +02:00
}
2024-07-03 11:33:02 +02:00
account , err := manager . GetOrCreateAccountByUser ( context . Background ( ) , userID , "" )
2021-08-20 15:18:29 +02:00
if err != nil {
t . Fatal ( err )
}
2021-12-27 13:17:15 +01:00
if account == nil {
2023-01-02 15:11:32 +01:00
t . Fatalf ( "expected to create an account for a user %s" , userID )
return
2021-08-20 15:18:29 +02:00
}
2024-07-03 11:33:02 +02:00
account , err = manager . Store . GetAccountByUser ( context . Background ( ) , userID )
2021-12-27 13:17:15 +01:00
if err != nil {
2023-01-02 15:11:32 +01:00
t . Errorf ( "expected to get existing account after creation, no account was found for a user %s" , userID )
return
2021-08-20 15:18:29 +02:00
}
2023-01-02 15:11:32 +01:00
if account != nil && account . Users [ userID ] == nil {
2023-11-07 13:37:57 +01:00
t . Fatalf ( "expected to create an account for a user %s but no user was found after creation under the account %s" , userID , account . Id )
2023-01-02 15:11:32 +01:00
return
}
// check the corresponding events that should have been generated
2023-01-24 10:17:24 +01:00
ev := getEvent ( t , account . Id , manager , activity . AccountCreated )
2023-01-02 15:11:32 +01:00
assert . NotNil ( t , ev )
assert . Equal ( t , account . Id , ev . AccountID )
assert . Equal ( t , userID , ev . InitiatorID )
assert . Equal ( t , account . Id , ev . TargetID )
2022-03-01 15:22:18 +01:00
}
2024-09-27 16:10:50 +02:00
func TestDefaultAccountManager_GetAccountIDFromToken ( t * testing . T ) {
2022-03-01 15:22:18 +01:00
type initUserParams jwtclaims . AuthorizationClaims
var (
publicDomain = "public.com"
privateDomain = "private.com"
unknownDomain = "unknown.com"
)
defaultInitAccount := initUserParams {
Domain : publicDomain ,
UserId : "defaultUser" ,
}
initUnknown := defaultInitAccount
2024-12-11 12:58:45 +01:00
initUnknown . DomainCategory = types . UnknownCategory
2022-03-01 15:22:18 +01:00
initUnknown . Domain = unknownDomain
privateInitAccount := defaultInitAccount
privateInitAccount . Domain = privateDomain
2024-12-11 12:58:45 +01:00
privateInitAccount . DomainCategory = types . PrivateCategory
2022-03-01 15:22:18 +01:00
2024-10-12 08:35:51 +02:00
testCases := [ ] struct {
name string
inputClaims jwtclaims . AuthorizationClaims
inputInitUserParams initUserParams
inputUpdateAttrs bool
inputUpdateClaimAccount bool
testingFunc require . ComparisonAssertionFunc
expectedMSG string
2024-12-11 12:58:45 +01:00
expectedUserRole types . UserRole
2024-10-12 08:35:51 +02:00
expectedDomainCategory string
expectedDomain string
expectedPrimaryDomainStatus bool
expectedCreatedBy string
expectedUsers [ ] string
} {
{
name : "New User With Public Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : publicDomain ,
UserId : "pub-domain-user" ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . PublicCategory ,
2024-10-12 08:35:51 +02:00
} ,
inputInitUserParams : defaultInitAccount ,
testingFunc : require . NotEqual ,
expectedMSG : "account IDs shouldn't match" ,
2024-12-11 12:58:45 +01:00
expectedUserRole : types . UserRoleOwner ,
2024-10-12 08:35:51 +02:00
expectedDomainCategory : "" ,
expectedDomain : publicDomain ,
expectedPrimaryDomainStatus : false ,
expectedCreatedBy : "pub-domain-user" ,
expectedUsers : [ ] string { "pub-domain-user" } ,
2022-03-01 15:22:18 +01:00
} ,
2024-10-12 08:35:51 +02:00
{
name : "New User With Unknown Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : unknownDomain ,
UserId : "unknown-domain-user" ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . UnknownCategory ,
2024-10-12 08:35:51 +02:00
} ,
inputInitUserParams : initUnknown ,
testingFunc : require . NotEqual ,
expectedMSG : "account IDs shouldn't match" ,
2024-12-11 12:58:45 +01:00
expectedUserRole : types . UserRoleOwner ,
2024-10-12 08:35:51 +02:00
expectedDomain : unknownDomain ,
expectedDomainCategory : "" ,
expectedPrimaryDomainStatus : false ,
expectedCreatedBy : "unknown-domain-user" ,
expectedUsers : [ ] string { "unknown-domain-user" } ,
2022-03-01 15:22:18 +01:00
} ,
2024-10-12 08:35:51 +02:00
{
name : "New User With Private Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : privateDomain ,
UserId : "pvt-domain-user" ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
} ,
inputInitUserParams : defaultInitAccount ,
testingFunc : require . NotEqual ,
expectedMSG : "account IDs shouldn't match" ,
2024-12-11 12:58:45 +01:00
expectedUserRole : types . UserRoleOwner ,
2024-10-12 08:35:51 +02:00
expectedDomain : privateDomain ,
2024-12-11 12:58:45 +01:00
expectedDomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
expectedPrimaryDomainStatus : true ,
expectedCreatedBy : "pvt-domain-user" ,
expectedUsers : [ ] string { "pvt-domain-user" } ,
2022-03-09 13:31:42 +01:00
} ,
2024-10-12 08:35:51 +02:00
{
name : "New Regular User With Existing Private Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : privateDomain ,
UserId : "new-pvt-domain-user" ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
} ,
inputUpdateAttrs : true ,
inputInitUserParams : privateInitAccount ,
testingFunc : require . Equal ,
expectedMSG : "account IDs should match" ,
2024-12-11 12:58:45 +01:00
expectedUserRole : types . UserRoleUser ,
2024-10-12 08:35:51 +02:00
expectedDomain : privateDomain ,
2024-12-11 12:58:45 +01:00
expectedDomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
expectedPrimaryDomainStatus : true ,
expectedCreatedBy : defaultInitAccount . UserId ,
expectedUsers : [ ] string { defaultInitAccount . UserId , "new-pvt-domain-user" } ,
} ,
{
name : "Existing User With Existing Reclassified Private Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : defaultInitAccount . Domain ,
UserId : defaultInitAccount . UserId ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
} ,
inputInitUserParams : defaultInitAccount ,
testingFunc : require . Equal ,
expectedMSG : "account IDs should match" ,
2024-12-11 12:58:45 +01:00
expectedUserRole : types . UserRoleOwner ,
2024-10-12 08:35:51 +02:00
expectedDomain : defaultInitAccount . Domain ,
2024-12-11 12:58:45 +01:00
expectedDomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
expectedPrimaryDomainStatus : true ,
expectedCreatedBy : defaultInitAccount . UserId ,
expectedUsers : [ ] string { defaultInitAccount . UserId } ,
} ,
{
name : "Existing Account Id With Existing Reclassified Private Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : defaultInitAccount . Domain ,
UserId : defaultInitAccount . UserId ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
} ,
inputUpdateClaimAccount : true ,
inputInitUserParams : defaultInitAccount ,
testingFunc : require . Equal ,
expectedMSG : "account IDs should match" ,
2024-12-11 12:58:45 +01:00
expectedUserRole : types . UserRoleOwner ,
2024-10-12 08:35:51 +02:00
expectedDomain : defaultInitAccount . Domain ,
2024-12-11 12:58:45 +01:00
expectedDomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
expectedPrimaryDomainStatus : true ,
expectedCreatedBy : defaultInitAccount . UserId ,
expectedUsers : [ ] string { defaultInitAccount . UserId } ,
} ,
{
name : "User With Private Category And Empty Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : "" ,
UserId : "pvt-domain-user" ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . PrivateCategory ,
2024-10-12 08:35:51 +02:00
} ,
inputInitUserParams : defaultInitAccount ,
testingFunc : require . NotEqual ,
expectedMSG : "account IDs shouldn't match" ,
2024-12-11 12:58:45 +01:00
expectedUserRole : types . UserRoleOwner ,
2024-10-12 08:35:51 +02:00
expectedDomain : "" ,
expectedDomainCategory : "" ,
expectedPrimaryDomainStatus : false ,
expectedCreatedBy : "pvt-domain-user" ,
expectedUsers : [ ] string { "pvt-domain-user" } ,
2022-09-29 10:51:18 +02:00
} ,
}
2024-10-12 08:35:51 +02:00
for _ , testCase := range testCases {
2022-03-01 15:22:18 +01:00
t . Run ( testCase . name , func ( t * testing . T ) {
manager , err := createManager ( t )
require . NoError ( t , err , "unable to create account manager" )
2024-10-04 16:17:01 +02:00
accountID , err := manager . GetAccountIDByUserID ( context . Background ( ) , testCase . inputInitUserParams . UserId , testCase . inputInitUserParams . Domain )
2022-03-01 15:22:18 +01:00
require . NoError ( t , err , "create init user failed" )
2024-09-27 16:10:50 +02:00
initAccount , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
require . NoError ( t , err , "get init account failed" )
2022-03-01 15:22:18 +01:00
if testCase . inputUpdateAttrs {
2024-10-12 08:35:51 +02:00
err = manager . updateAccountDomainAttributesIfNotUpToDate ( context . Background ( ) , initAccount . Id , jwtclaims . AuthorizationClaims { UserId : testCase . inputInitUserParams . UserId , Domain : testCase . inputInitUserParams . Domain , DomainCategory : testCase . inputInitUserParams . DomainCategory } , true )
2022-03-01 15:22:18 +01:00
require . NoError ( t , err , "update init user failed" )
}
2022-03-09 13:31:42 +01:00
if testCase . inputUpdateClaimAccount {
testCase . inputClaims . AccountId = initAccount . Id
}
2024-09-27 16:10:50 +02:00
accountID , _ , err = manager . GetAccountIDFromToken ( context . Background ( ) , testCase . inputClaims )
2022-03-01 15:22:18 +01:00
require . NoError ( t , err , "support function failed" )
2024-09-27 16:10:50 +02:00
account , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
require . NoError ( t , err , "get account failed" )
2022-06-09 13:14:34 +02:00
verifyNewAccountHasDefaultFields ( t , account , testCase . expectedCreatedBy , testCase . inputClaims . Domain , testCase . expectedUsers )
verifyCanAddPeerToAccount ( t , manager , account , testCase . expectedCreatedBy )
2022-03-01 15:22:18 +01:00
testCase . testingFunc ( t , initAccount . Id , account . Id , testCase . expectedMSG )
2022-03-10 13:47:36 +01:00
require . EqualValues ( t , testCase . expectedUserRole , account . Users [ testCase . inputClaims . UserId ] . Role , "expected user role should match" )
require . EqualValues ( t , testCase . expectedDomainCategory , account . DomainCategory , "expected account domain category should match" )
require . EqualValues ( t , testCase . expectedPrimaryDomainStatus , account . IsDomainPrimaryAccount , "expected account primary status should match" )
2022-09-29 10:51:18 +02:00
require . EqualValues ( t , testCase . expectedDomain , account . Domain , "expected account domain should match" )
2022-03-01 15:22:18 +01:00
} )
}
}
2022-05-05 08:58:34 +02:00
2023-06-27 16:51:05 +02:00
func TestDefaultAccountManager_GetGroupsFromTheToken ( t * testing . T ) {
userId := "user-id"
domain := "test.domain"
2024-10-04 16:17:01 +02:00
_ = newAccountWithId ( context . Background ( ) , "" , userId , domain )
2023-06-27 16:51:05 +02:00
manager , err := createManager ( t )
require . NoError ( t , err , "unable to create account manager" )
2024-10-04 16:17:01 +02:00
accountID , err := manager . GetAccountIDByUserID ( context . Background ( ) , userId , domain )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "create init user failed" )
2023-07-22 13:54:08 +02:00
// as initAccount was created without account id we have to take the id after account initialization
2024-10-04 16:17:01 +02:00
// that happens inside the GetAccountIDByUserID where the id is getting generated
2023-07-22 13:54:08 +02:00
// it is important to set the id as it help to avoid creating additional account with empty Id and re-pointing indices to it
2024-10-04 16:17:01 +02:00
initAccount , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
2024-09-27 16:10:50 +02:00
require . NoError ( t , err , "get init account failed" )
2023-06-27 16:51:05 +02:00
claims := jwtclaims . AuthorizationClaims {
2023-07-22 13:54:08 +02:00
AccountId : accountID , // is empty as it is based on accountID right after initialization of initAccount
2023-06-27 16:51:05 +02:00
Domain : domain ,
UserId : userId ,
DomainCategory : "test-category" ,
Raw : jwt . MapClaims { "idp-groups" : [ ] interface { } { "group1" , "group2" } } ,
}
t . Run ( "JWT groups disabled" , func ( t * testing . T ) {
2024-09-27 16:10:50 +02:00
accountID , _ , err := manager . GetAccountIDFromToken ( context . Background ( ) , claims )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "get account by token failed" )
2024-09-27 16:10:50 +02:00
account , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
require . NoError ( t , err , "get account failed" )
2023-06-27 16:51:05 +02:00
require . Len ( t , account . Groups , 1 , "only ALL group should exists" )
} )
t . Run ( "JWT groups enabled without claim name" , func ( t * testing . T ) {
initAccount . Settings . JWTGroupsEnabled = true
2024-07-03 11:33:02 +02:00
err := manager . Store . SaveAccount ( context . Background ( ) , initAccount )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "save account failed" )
2024-07-03 11:33:02 +02:00
require . Len ( t , manager . Store . GetAllAccounts ( context . Background ( ) ) , 1 , "only one account should exist" )
2023-06-27 16:51:05 +02:00
2024-09-27 16:10:50 +02:00
accountID , _ , err := manager . GetAccountIDFromToken ( context . Background ( ) , claims )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "get account by token failed" )
2024-09-27 16:10:50 +02:00
account , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
require . NoError ( t , err , "get account failed" )
2023-06-27 16:51:05 +02:00
require . Len ( t , account . Groups , 1 , "if group claim is not set no group added from JWT" )
} )
t . Run ( "JWT groups enabled" , func ( t * testing . T ) {
initAccount . Settings . JWTGroupsEnabled = true
initAccount . Settings . JWTGroupsClaimName = "idp-groups"
2024-07-03 11:33:02 +02:00
err := manager . Store . SaveAccount ( context . Background ( ) , initAccount )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "save account failed" )
2024-07-03 11:33:02 +02:00
require . Len ( t , manager . Store . GetAllAccounts ( context . Background ( ) ) , 1 , "only one account should exist" )
2023-06-27 16:51:05 +02:00
2024-09-27 16:10:50 +02:00
accountID , _ , err := manager . GetAccountIDFromToken ( context . Background ( ) , claims )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "get account by token failed" )
2024-09-27 16:10:50 +02:00
account , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
require . NoError ( t , err , "get account failed" )
2023-06-27 16:51:05 +02:00
require . Len ( t , account . Groups , 3 , "groups should be added to the account" )
2024-03-27 18:48:48 +01:00
groupsByNames := map [ string ] * group . Group { }
2023-06-27 16:51:05 +02:00
for _ , g := range account . Groups {
groupsByNames [ g . Name ] = g
}
g1 , ok := groupsByNames [ "group1" ]
require . True ( t , ok , "group1 should be added to the account" )
require . Equal ( t , g1 . Name , "group1" , "group1 name should match" )
2024-03-27 18:48:48 +01:00
require . Equal ( t , g1 . Issued , group . GroupIssuedJWT , "group1 issued should match" )
2023-06-27 16:51:05 +02:00
g2 , ok := groupsByNames [ "group2" ]
require . True ( t , ok , "group2 should be added to the account" )
require . Equal ( t , g2 . Name , "group2" , "group2 name should match" )
2024-03-27 18:48:48 +01:00
require . Equal ( t , g2 . Issued , group . GroupIssuedJWT , "group2 issued should match" )
2023-06-27 16:51:05 +02:00
} )
}
2023-03-16 15:57:44 +01:00
func TestAccountManager_GetAccountFromPAT ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
store , cleanup , err := store . NewTestStoreFromSQL ( context . Background ( ) , "" , t . TempDir ( ) )
if err != nil {
t . Fatalf ( "Error when creating store: %s" , err )
}
t . Cleanup ( cleanup )
2024-07-03 11:33:02 +02:00
account := newAccountWithId ( context . Background ( ) , "account_id" , "testuser" , "" )
2023-03-16 15:57:44 +01:00
token := "nbp_9999EUDNdkeusjentDLSJEn1902u84390W6W"
hashedToken := sha256 . Sum256 ( [ ] byte ( token ) )
2023-03-29 15:21:53 +02:00
encodedHashedToken := b64 . StdEncoding . EncodeToString ( hashedToken [ : ] )
2024-12-11 12:58:45 +01:00
account . Users [ "someUser" ] = & types . User {
2023-03-21 13:34:48 +01:00
Id : "someUser" ,
2024-12-11 12:58:45 +01:00
PATs : map [ string ] * types . PersonalAccessToken {
2023-03-29 15:21:53 +02:00
"tokenId" : {
2023-03-21 13:34:48 +01:00
ID : "tokenId" ,
2023-03-29 15:21:53 +02:00
HashedToken : encodedHashedToken ,
2023-03-20 16:14:55 +01:00
} ,
} ,
2023-03-16 15:57:44 +01:00
}
2024-12-11 12:58:45 +01:00
err = store . SaveAccount ( context . Background ( ) , account )
2023-03-20 11:44:12 +01:00
if err != nil {
t . Fatalf ( "Error when saving account: %s" , err )
}
2023-03-16 15:57:44 +01:00
am := DefaultAccountManager {
2023-03-21 13:34:48 +01:00
Store : store ,
2023-03-16 15:57:44 +01:00
}
2024-07-03 11:33:02 +02:00
account , user , pat , err := am . GetAccountFromPAT ( context . Background ( ) , token )
2023-03-16 15:57:44 +01:00
if err != nil {
t . Fatalf ( "Error when getting Account from PAT: %s" , err )
}
assert . Equal ( t , "account_id" , account . Id )
assert . Equal ( t , "someUser" , user . Id )
2023-03-29 15:21:53 +02:00
assert . Equal ( t , account . Users [ "someUser" ] . PATs [ "tokenId" ] , pat )
2023-03-16 15:57:44 +01:00
}
2023-03-30 16:43:39 +02:00
func TestDefaultAccountManager_MarkPATUsed ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
store , cleanup , err := store . NewTestStoreFromSQL ( context . Background ( ) , "" , t . TempDir ( ) )
if err != nil {
t . Fatalf ( "Error when creating store: %s" , err )
}
t . Cleanup ( cleanup )
2024-07-03 11:33:02 +02:00
account := newAccountWithId ( context . Background ( ) , "account_id" , "testuser" , "" )
2023-03-30 16:43:39 +02:00
token := "nbp_9999EUDNdkeusjentDLSJEn1902u84390W6W"
hashedToken := sha256 . Sum256 ( [ ] byte ( token ) )
encodedHashedToken := b64 . StdEncoding . EncodeToString ( hashedToken [ : ] )
2024-12-11 12:58:45 +01:00
account . Users [ "someUser" ] = & types . User {
2023-03-30 16:43:39 +02:00
Id : "someUser" ,
2024-12-11 12:58:45 +01:00
PATs : map [ string ] * types . PersonalAccessToken {
2023-03-30 16:43:39 +02:00
"tokenId" : {
ID : "tokenId" ,
HashedToken : encodedHashedToken ,
LastUsed : time . Time { } ,
} ,
} ,
}
2024-12-11 12:58:45 +01:00
err = store . SaveAccount ( context . Background ( ) , account )
2023-03-30 16:43:39 +02:00
if err != nil {
t . Fatalf ( "Error when saving account: %s" , err )
}
am := DefaultAccountManager {
Store : store ,
}
2024-07-03 11:33:02 +02:00
err = am . MarkPATUsed ( context . Background ( ) , "tokenId" )
2023-03-30 16:43:39 +02:00
if err != nil {
t . Fatalf ( "Error when marking PAT used: %s" , err )
}
2024-07-03 11:33:02 +02:00
account , err = am . Store . GetAccount ( context . Background ( ) , "account_id" )
2023-03-30 16:43:39 +02:00
if err != nil {
t . Fatalf ( "Error when getting account: %s" , err )
}
assert . True ( t , ! account . Users [ "someUser" ] . PATs [ "tokenId" ] . LastUsed . IsZero ( ) )
}
2022-03-01 15:22:18 +01:00
func TestAccountManager_PrivateAccount ( t * testing . T ) {
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
userId := "test_user"
2024-07-03 11:33:02 +02:00
account , err := manager . GetOrCreateAccountByUser ( context . Background ( ) , userId , "" )
2022-03-01 15:22:18 +01:00
if err != nil {
t . Fatal ( err )
}
if account == nil {
t . Fatalf ( "expected to create an account for a user %s" , userId )
}
2024-07-03 11:33:02 +02:00
account , err = manager . Store . GetAccountByUser ( context . Background ( ) , userId )
2022-03-01 15:22:18 +01:00
if err != nil {
t . Errorf ( "expected to get existing account after creation, no account was found for a user %s" , userId )
}
if account != nil && account . Users [ userId ] == nil {
2023-11-07 13:37:57 +01:00
t . Fatalf ( "expected to create an account for a user %s but no user was found after creation under the account %s" , userId , account . Id )
2021-08-20 15:18:29 +02:00
}
2021-08-20 15:44:18 +02:00
}
2022-02-11 17:18:18 +01:00
func TestAccountManager_SetOrUpdateDomain ( t * testing . T ) {
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
userId := "test_user"
domain := "hotmail.com"
2024-07-03 11:33:02 +02:00
account , err := manager . GetOrCreateAccountByUser ( context . Background ( ) , userId , domain )
2022-02-11 17:18:18 +01:00
if err != nil {
t . Fatal ( err )
}
if account == nil {
t . Fatalf ( "expected to create an account for a user %s" , userId )
}
2024-03-27 18:48:48 +01:00
if account != nil && account . Domain != domain {
2022-02-11 17:18:18 +01:00
t . Errorf ( "setting account domain failed, expected %s, got %s" , domain , account . Domain )
}
domain = "gmail.com"
2024-07-03 11:33:02 +02:00
account , err = manager . GetOrCreateAccountByUser ( context . Background ( ) , userId , domain )
2022-02-11 17:18:18 +01:00
if err != nil {
t . Fatalf ( "got the following error while retrieving existing acc: %v" , err )
}
if account == nil {
t . Fatalf ( "expected to get an account for a user %s" , userId )
}
2024-03-27 18:48:48 +01:00
if account != nil && account . Domain != domain {
2022-02-11 17:18:18 +01:00
t . Errorf ( "updating domain. expected %s got %s" , domain , account . Domain )
}
}
2024-10-04 16:17:01 +02:00
func TestAccountManager_GetAccountByUserID ( t * testing . T ) {
2022-01-24 11:21:30 +01:00
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
userId := "test_user"
2024-10-04 16:17:01 +02:00
accountID , err := manager . GetAccountIDByUserID ( context . Background ( ) , userId , "" )
2022-01-24 11:21:30 +01:00
if err != nil {
t . Fatal ( err )
}
2024-09-27 16:10:50 +02:00
if accountID == "" {
2022-01-24 11:21:30 +01:00
t . Fatalf ( "expected to create an account for a user %s" , userId )
2024-03-27 18:48:48 +01:00
return
2022-01-24 11:21:30 +01:00
}
2024-12-11 12:58:45 +01:00
exists , err := manager . Store . AccountExists ( context . Background ( ) , store . LockingStrengthShare , accountID )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err )
assert . True ( t , exists , "expected to get existing account after creation using userid" )
2022-01-24 11:21:30 +01:00
2024-10-04 16:17:01 +02:00
_ , err = manager . GetAccountIDByUserID ( context . Background ( ) , "" , "" )
2022-01-24 11:21:30 +01:00
if err == nil {
2024-10-04 16:17:01 +02:00
t . Errorf ( "expected an error when user ID is empty" )
2022-01-24 11:21:30 +01:00
}
}
2024-12-11 12:58:45 +01:00
func createAccount ( am * DefaultAccountManager , accountID , userID , domain string ) ( * types . Account , error ) {
2024-07-03 11:33:02 +02:00
account := newAccountWithId ( context . Background ( ) , accountID , userID , domain )
err := am . Store . SaveAccount ( context . Background ( ) , account )
2022-06-09 13:14:34 +02:00
if err != nil {
return nil , err
}
return account , nil
}
2021-08-20 15:44:18 +02:00
func TestAccountManager_GetAccount ( t * testing . T ) {
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
expectedId := "test_account"
2021-12-27 13:17:15 +01:00
userId := "account_creator"
2022-06-09 13:14:34 +02:00
account , err := createAccount ( manager , expectedId , userId , "" )
2021-08-20 15:44:18 +02:00
if err != nil {
t . Fatal ( err )
}
2022-05-21 15:21:39 +02:00
// AddAccount has been already tested so we can assume it is correct and compare results
2024-07-03 11:33:02 +02:00
getAccount , err := manager . Store . GetAccount ( context . Background ( ) , account . Id )
2021-08-20 15:44:18 +02:00
if err != nil {
t . Fatal ( err )
return
}
if account . Id != getAccount . Id {
2021-08-20 22:33:43 +02:00
t . Errorf ( "expected account.Id %s, got %s" , account . Id , getAccount . Id )
2021-08-20 15:44:18 +02:00
}
for _ , peer := range account . Peers {
2023-02-03 10:33:28 +01:00
if _ , ok := getAccount . Peers [ peer . ID ] ; ! ok {
t . Errorf ( "expected account to have peer %s, not found" , peer . ID )
2021-08-20 15:44:18 +02:00
}
}
for _ , key := range account . SetupKeys {
if _ , ok := getAccount . SetupKeys [ key . Key ] ; ! ok {
t . Errorf ( "expected account to have setup key %s, not found" , key . Key )
}
}
2021-08-20 15:18:29 +02:00
}
2023-11-28 14:23:38 +01:00
func TestAccountManager_DeleteAccount ( t * testing . T ) {
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
expectedId := "test_account"
userId := "account_creator"
account , err := createAccount ( manager , expectedId , userId , "" )
if err != nil {
t . Fatal ( err )
}
2024-07-03 11:33:02 +02:00
err = manager . DeleteAccount ( context . Background ( ) , account . Id , userId )
2023-11-28 14:23:38 +01:00
if err != nil {
t . Fatal ( err )
}
2024-07-03 11:33:02 +02:00
getAccount , err := manager . Store . GetAccount ( context . Background ( ) , account . Id )
2023-11-28 14:23:38 +01:00
if err == nil {
t . Fatal ( fmt . Errorf ( "expected to get an error when trying to get deleted account, got %v" , getAccount ) )
}
}
2024-11-07 17:23:35 +01:00
func BenchmarkTest_GetAccountWithclaims ( b * testing . B ) {
claims := jwtclaims . AuthorizationClaims {
Domain : "example.com" ,
UserId : "pvt-domain-user" ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . PrivateCategory ,
2024-11-07 17:23:35 +01:00
}
publicClaims := jwtclaims . AuthorizationClaims {
Domain : "test.com" ,
UserId : "public-domain-user" ,
2024-12-11 12:58:45 +01:00
DomainCategory : types . PublicCategory ,
2024-11-07 17:23:35 +01:00
}
am , err := createManager ( b )
if err != nil {
b . Fatal ( err )
return
}
id , err := am . getAccountIDWithAuthorizationClaims ( context . Background ( ) , claims )
if err != nil {
b . Fatal ( err )
}
pid , err := am . getAccountIDWithAuthorizationClaims ( context . Background ( ) , publicClaims )
if err != nil {
b . Fatal ( err )
}
users := genUsers ( "priv" , 100 )
acc , err := am . Store . GetAccount ( context . Background ( ) , id )
if err != nil {
b . Fatal ( err )
}
acc . Users = users
err = am . Store . SaveAccount ( context . Background ( ) , acc )
if err != nil {
b . Fatal ( err )
}
userP := genUsers ( "pub" , 100 )
pacc , err := am . Store . GetAccount ( context . Background ( ) , pid )
if err != nil {
b . Fatal ( err )
}
pacc . Users = userP
err = am . Store . SaveAccount ( context . Background ( ) , pacc )
if err != nil {
b . Fatal ( err )
}
b . Run ( "public without account ID" , func ( b * testing . B ) {
2024-11-28 14:59:53 +01:00
// b.ResetTimer()
2024-11-07 17:23:35 +01:00
for i := 0 ; i < b . N ; i ++ {
_ , err := am . getAccountIDWithAuthorizationClaims ( context . Background ( ) , publicClaims )
if err != nil {
b . Fatal ( err )
}
}
} )
b . Run ( "private without account ID" , func ( b * testing . B ) {
2024-11-28 14:59:53 +01:00
// b.ResetTimer()
2024-11-07 17:23:35 +01:00
for i := 0 ; i < b . N ; i ++ {
_ , err := am . getAccountIDWithAuthorizationClaims ( context . Background ( ) , claims )
if err != nil {
b . Fatal ( err )
}
}
} )
b . Run ( "private with account ID" , func ( b * testing . B ) {
claims . AccountId = id
2024-11-28 14:59:53 +01:00
// b.ResetTimer()
2024-11-07 17:23:35 +01:00
for i := 0 ; i < b . N ; i ++ {
_ , err := am . getAccountIDWithAuthorizationClaims ( context . Background ( ) , claims )
if err != nil {
b . Fatal ( err )
}
}
} )
}
2024-12-11 12:58:45 +01:00
func genUsers ( p string , n int ) map [ string ] * types . User {
users := map [ string ] * types . User { }
2024-11-07 17:23:35 +01:00
now := time . Now ( )
for i := 0 ; i < n ; i ++ {
2024-12-11 12:58:45 +01:00
users [ fmt . Sprintf ( "%s-%d" , p , i ) ] = & types . User {
2024-11-07 17:23:35 +01:00
Id : fmt . Sprintf ( "%s-%d" , p , i ) ,
2024-12-11 12:58:45 +01:00
Role : types . UserRoleAdmin ,
2024-11-07 17:23:35 +01:00
LastLogin : now ,
CreatedAt : now ,
Issued : "api" ,
AutoGroups : [ ] string { "one" , "two" , "three" , "four" , "five" , "six" , "seven" , "eight" , "nine" , "ten" } ,
}
}
return users
}
2021-08-20 15:18:29 +02:00
func TestAccountManager_AddPeer ( t * testing . T ) {
2021-08-20 15:44:18 +02:00
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
2021-08-20 15:18:29 +02:00
2024-01-25 09:50:27 +01:00
userID := "testingUser"
2023-06-27 17:17:24 +02:00
account , err := createAccount ( manager , "test_account" , userID , "netbird.cloud" )
2021-08-20 15:18:29 +02:00
if err != nil {
t . Fatal ( err )
}
2022-05-21 15:21:39 +02:00
serial := account . Network . CurrentSerial ( ) // should be 0
2022-01-14 14:34:27 +01:00
2024-12-11 12:58:45 +01:00
setupKey , err := manager . CreateSetupKey ( context . Background ( ) , account . Id , "test-key" , types . SetupKeyReusable , time . Hour , nil , 999 , userID , false )
2023-06-27 17:17:24 +02:00
if err != nil {
t . Fatal ( "error creating setup key" )
2021-08-20 15:44:18 +02:00
return
}
2021-08-20 15:18:29 +02:00
2022-03-10 18:18:38 +01:00
if account . Network . Serial != 0 {
t . Errorf ( "expecting account network to have an initial Serial=0" )
2022-01-14 14:34:27 +01:00
return
}
2022-01-16 17:10:36 +01:00
key , err := wgtypes . GeneratePrivateKey ( )
2021-08-20 15:18:29 +02:00
if err != nil {
t . Fatal ( err )
2021-08-20 15:44:18 +02:00
return
}
expectedPeerKey := key . PublicKey ( ) . String ( )
2024-07-03 11:33:02 +02:00
peer , _ , _ , err := manager . AddPeer ( context . Background ( ) , setupKey . Key , "" , & nbpeer . Peer {
2021-08-24 11:50:19 +02:00
Key : expectedPeerKey ,
2023-11-28 13:45:26 +01:00
Meta : nbpeer . PeerSystemMeta { Hostname : expectedPeerKey } ,
2021-08-24 11:50:19 +02:00
} )
2021-08-20 15:44:18 +02:00
if err != nil {
t . Errorf ( "expecting peer to be added, got failure %v" , err )
return
}
2024-07-03 11:33:02 +02:00
account , err = manager . Store . GetAccount ( context . Background ( ) , account . Id )
2022-01-14 14:34:27 +01:00
if err != nil {
t . Fatal ( err )
return
}
2021-08-20 15:44:18 +02:00
if peer . Key != expectedPeerKey {
t . Errorf ( "expecting just added peer to have key = %s, got %s" , expectedPeerKey , peer . Key )
}
2022-05-29 22:43:39 +02:00
if ! account . Network . Net . Contains ( peer . IP ) {
t . Errorf ( "expecting just added peer's IP %s to be in a network range %s" , peer . IP . String ( ) , account . Network . Net . String ( ) )
2022-05-05 20:02:15 +02:00
}
if account . Network . CurrentSerial ( ) != 1 {
t . Errorf ( "expecting Network Serial=%d to be incremented by 1 and be equal to %d when adding new peer to account" , serial , account . Network . CurrentSerial ( ) )
}
2023-01-24 10:17:24 +01:00
ev := getEvent ( t , account . Id , manager , activity . PeerAddedWithSetupKey )
2023-01-02 15:11:32 +01:00
assert . NotNil ( t , ev )
assert . Equal ( t , account . Id , ev . AccountID )
assert . Equal ( t , peer . Name , ev . Meta [ "name" ] )
assert . Equal ( t , peer . FQDN ( account . Domain ) , ev . Meta [ "fqdn" ] )
assert . Equal ( t , setupKey . Id , ev . InitiatorID )
2023-02-03 10:33:28 +01:00
assert . Equal ( t , peer . ID , ev . TargetID )
2023-01-02 15:11:32 +01:00
assert . Equal ( t , peer . IP . String ( ) , fmt . Sprint ( ev . Meta [ "ip" ] ) )
2022-05-05 20:02:15 +02:00
}
func TestAccountManager_AddPeerWithUserID ( t * testing . T ) {
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
2024-07-03 11:33:02 +02:00
account , err := manager . GetOrCreateAccountByUser ( context . Background ( ) , userID , "netbird.cloud" )
2022-05-05 20:02:15 +02:00
if err != nil {
t . Fatal ( err )
}
2022-05-21 15:21:39 +02:00
serial := account . Network . CurrentSerial ( ) // should be 0
2022-05-05 20:02:15 +02:00
if account . Network . Serial != 0 {
t . Errorf ( "expecting account network to have an initial Serial=0" )
return
}
key , err := wgtypes . GeneratePrivateKey ( )
if err != nil {
t . Fatal ( err )
return
}
expectedPeerKey := key . PublicKey ( ) . String ( )
2023-01-02 15:11:32 +01:00
expectedUserID := userID
2022-05-05 20:02:15 +02:00
2024-07-03 11:33:02 +02:00
peer , _ , _ , err := manager . AddPeer ( context . Background ( ) , "" , userID , & nbpeer . Peer {
2022-05-05 20:02:15 +02:00
Key : expectedPeerKey ,
2023-11-28 13:45:26 +01:00
Meta : nbpeer . PeerSystemMeta { Hostname : expectedPeerKey } ,
2022-05-05 20:02:15 +02:00
} )
if err != nil {
t . Errorf ( "expecting peer to be added, got failure %v, account users: %v" , err , account . CreatedBy )
return
}
2024-07-03 11:33:02 +02:00
account , err = manager . Store . GetAccount ( context . Background ( ) , account . Id )
2022-05-05 20:02:15 +02:00
if err != nil {
t . Fatal ( err )
return
}
2021-08-20 15:44:18 +02:00
if peer . Key != expectedPeerKey {
2022-05-05 20:02:15 +02:00
t . Errorf ( "expecting just added peer to have key = %s, got %s" , expectedPeerKey , peer . Key )
}
2022-05-29 22:43:39 +02:00
if ! account . Network . Net . Contains ( peer . IP ) {
t . Errorf ( "expecting just added peer's IP %s to be in a network range %s" , peer . IP . String ( ) , account . Network . Net . String ( ) )
2021-08-20 15:18:29 +02:00
}
2023-01-02 15:11:32 +01:00
if peer . UserID != expectedUserID {
t . Errorf ( "expecting just added peer to have UserID = %s, got %s" , expectedUserID , peer . UserID )
2022-05-05 20:02:15 +02:00
}
2022-03-10 18:18:38 +01:00
if account . Network . CurrentSerial ( ) != 1 {
t . Errorf ( "expecting Network Serial=%d to be incremented by 1 and be equal to %d when adding new peer to account" , serial , account . Network . CurrentSerial ( ) )
2022-01-14 14:34:27 +01:00
}
2023-01-02 15:11:32 +01:00
2023-01-24 10:17:24 +01:00
ev := getEvent ( t , account . Id , manager , activity . PeerAddedByUser )
2023-01-02 15:11:32 +01:00
assert . NotNil ( t , ev )
assert . Equal ( t , account . Id , ev . AccountID )
assert . Equal ( t , peer . Name , ev . Meta [ "name" ] )
assert . Equal ( t , peer . FQDN ( account . Domain ) , ev . Meta [ "fqdn" ] )
assert . Equal ( t , userID , ev . InitiatorID )
2023-02-03 10:33:28 +01:00
assert . Equal ( t , peer . ID , ev . TargetID )
2023-01-02 15:11:32 +01:00
assert . Equal ( t , peer . IP . String ( ) , fmt . Sprint ( ev . Meta [ "ip" ] ) )
2021-08-20 15:44:18 +02:00
}
2022-01-14 14:34:27 +01:00
2024-10-23 12:05:02 +02:00
func TestAccountManager_NetworkUpdates_SaveGroup ( t * testing . T ) {
manager , account , peer1 , peer2 , peer3 := setupNetworkMapTest ( t )
2023-01-02 15:11:32 +01:00
2024-10-23 12:05:02 +02:00
group := group . Group {
ID : "groupA" ,
Name : "GroupA" ,
Peers : [ ] string { } ,
2022-06-04 22:02:22 +02:00
}
2024-10-23 12:05:02 +02:00
if err := manager . SaveGroup ( context . Background ( ) , account . Id , userID , & group ) ; err != nil {
t . Errorf ( "save group: %v" , err )
2022-06-04 22:02:22 +02:00
return
}
2024-12-11 12:58:45 +01:00
_ , err := manager . SavePolicy ( context . Background ( ) , account . Id , userID , & types . Policy {
2024-10-23 12:05:02 +02:00
Enabled : true ,
2024-12-11 12:58:45 +01:00
Rules : [ ] * types . PolicyRule {
2024-10-23 12:05:02 +02:00
{
Enabled : true ,
Sources : [ ] string { "groupA" } ,
Destinations : [ ] string { "groupA" } ,
Bidirectional : true ,
2024-12-11 12:58:45 +01:00
Action : types . PolicyTrafficActionAccept ,
2024-10-23 12:05:02 +02:00
} ,
} ,
2024-11-26 10:46:05 +01:00
} )
2024-10-23 12:05:02 +02:00
require . NoError ( t , err )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
updMsg := manager . peersUpdateManager . CreateChannel ( context . Background ( ) , peer1 . ID )
defer manager . peersUpdateManager . CloseChannel ( context . Background ( ) , peer1 . ID )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
wg := sync . WaitGroup { }
wg . Add ( 1 )
go func ( ) {
defer wg . Done ( )
message := <- updMsg
networkMap := message . Update . GetNetworkMap ( )
if len ( networkMap . RemotePeers ) != 2 {
t . Errorf ( "mismatch peers count: 2 expected, got %v" , len ( networkMap . RemotePeers ) )
2022-06-04 22:02:22 +02:00
}
2024-10-23 12:05:02 +02:00
} ( )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
group . Peers = [ ] string { peer1 . ID , peer2 . ID , peer3 . ID }
if err := manager . SaveGroup ( context . Background ( ) , account . Id , userID , & group ) ; err != nil {
t . Errorf ( "save group: %v" , err )
return
2022-06-04 22:02:22 +02:00
}
2024-10-23 12:05:02 +02:00
wg . Wait ( )
}
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
func TestAccountManager_NetworkUpdates_DeletePolicy ( t * testing . T ) {
manager , account , peer1 , _ , _ := setupNetworkMapTest ( t )
2022-06-04 22:02:22 +02:00
2024-07-03 11:33:02 +02:00
updMsg := manager . peersUpdateManager . CreateChannel ( context . Background ( ) , peer1 . ID )
defer manager . peersUpdateManager . CloseChannel ( context . Background ( ) , peer1 . ID )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
wg := sync . WaitGroup { }
wg . Add ( 1 )
go func ( ) {
defer wg . Done ( )
message := <- updMsg
networkMap := message . Update . GetNetworkMap ( )
if len ( networkMap . RemotePeers ) != 0 {
t . Errorf ( "mismatch peers count: 0 expected, got %v" , len ( networkMap . RemotePeers ) )
}
} ( )
if err := manager . DeletePolicy ( context . Background ( ) , account . Id , account . Policies [ 0 ] . ID , userID ) ; err != nil {
t . Errorf ( "delete default rule: %v" , err )
return
}
wg . Wait ( )
}
func TestAccountManager_NetworkUpdates_SavePolicy ( t * testing . T ) {
manager , account , peer1 , peer2 , _ := setupNetworkMapTest ( t )
2024-03-27 18:48:48 +01:00
group := group . Group {
2024-10-23 12:05:02 +02:00
ID : "groupA" ,
2022-06-04 22:02:22 +02:00
Name : "GroupA" ,
2024-10-23 12:05:02 +02:00
Peers : [ ] string { peer1 . ID , peer2 . ID } ,
}
if err := manager . SaveGroup ( context . Background ( ) , account . Id , userID , & group ) ; err != nil {
t . Errorf ( "save group: %v" , err )
return
2022-06-04 22:02:22 +02:00
}
2024-10-23 12:05:02 +02:00
updMsg := manager . peersUpdateManager . CreateChannel ( context . Background ( ) , peer1 . ID )
defer manager . peersUpdateManager . CloseChannel ( context . Background ( ) , peer1 . ID )
2022-06-04 22:02:22 +02:00
wg := sync . WaitGroup { }
2024-10-23 12:05:02 +02:00
wg . Add ( 1 )
go func ( ) {
defer wg . Done ( )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
message := <- updMsg
networkMap := message . Update . GetNetworkMap ( )
if len ( networkMap . RemotePeers ) != 2 {
t . Errorf ( "mismatch peers count: 2 expected, got %v" , len ( networkMap . RemotePeers ) )
2022-06-04 22:02:22 +02:00
}
2024-10-23 12:05:02 +02:00
} ( )
2022-06-04 22:02:22 +02:00
2024-12-11 12:58:45 +01:00
_ , err := manager . SavePolicy ( context . Background ( ) , account . Id , userID , & types . Policy {
2024-11-26 10:46:05 +01:00
Enabled : true ,
2024-12-11 12:58:45 +01:00
Rules : [ ] * types . PolicyRule {
2024-11-26 10:46:05 +01:00
{
Enabled : true ,
Sources : [ ] string { "groupA" } ,
Destinations : [ ] string { "groupA" } ,
Bidirectional : true ,
2024-12-11 12:58:45 +01:00
Action : types . PolicyTrafficActionAccept ,
2024-11-26 10:46:05 +01:00
} ,
} ,
} )
if err != nil {
2024-10-23 12:05:02 +02:00
t . Errorf ( "delete default rule: %v" , err )
return
}
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
wg . Wait ( )
}
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
func TestAccountManager_NetworkUpdates_DeletePeer ( t * testing . T ) {
manager , account , peer1 , _ , peer3 := setupNetworkMapTest ( t )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
group := group . Group {
ID : "groupA" ,
Name : "GroupA" ,
Peers : [ ] string { peer1 . ID , peer3 . ID } ,
}
if err := manager . SaveGroup ( context . Background ( ) , account . Id , userID , & group ) ; err != nil {
t . Errorf ( "save group: %v" , err )
return
}
2022-06-04 22:02:22 +02:00
2024-12-11 12:58:45 +01:00
_ , err := manager . SavePolicy ( context . Background ( ) , account . Id , userID , & types . Policy {
2024-10-23 12:05:02 +02:00
Enabled : true ,
2024-12-11 12:58:45 +01:00
Rules : [ ] * types . PolicyRule {
2024-10-23 12:05:02 +02:00
{
Enabled : true ,
Sources : [ ] string { "groupA" } ,
Destinations : [ ] string { "groupA" } ,
Bidirectional : true ,
2024-12-11 12:58:45 +01:00
Action : types . PolicyTrafficActionAccept ,
2024-10-23 12:05:02 +02:00
} ,
} ,
2024-11-26 10:46:05 +01:00
} )
if err != nil {
2024-10-23 12:05:02 +02:00
t . Errorf ( "save policy: %v" , err )
return
}
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
updMsg := manager . peersUpdateManager . CreateChannel ( context . Background ( ) , peer1 . ID )
defer manager . peersUpdateManager . CloseChannel ( context . Background ( ) , peer1 . ID )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
wg := sync . WaitGroup { }
wg . Add ( 1 )
go func ( ) {
defer wg . Done ( )
message := <- updMsg
networkMap := message . Update . GetNetworkMap ( )
if len ( networkMap . RemotePeers ) != 1 {
t . Errorf ( "mismatch peers count: 1 expected, got %v" , len ( networkMap . RemotePeers ) )
2022-06-04 22:02:22 +02:00
}
2024-10-23 12:05:02 +02:00
} ( )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
if err := manager . DeletePeer ( context . Background ( ) , account . Id , peer3 . ID , userID ) ; err != nil {
t . Errorf ( "delete peer: %v" , err )
return
}
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
wg . Wait ( )
}
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
func TestAccountManager_NetworkUpdates_DeleteGroup ( t * testing . T ) {
manager , account , peer1 , peer2 , peer3 := setupNetworkMapTest ( t )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
updMsg := manager . peersUpdateManager . CreateChannel ( context . Background ( ) , peer1 . ID )
defer manager . peersUpdateManager . CloseChannel ( context . Background ( ) , peer1 . ID )
2022-06-04 22:02:22 +02:00
2024-11-15 18:09:32 +01:00
err := manager . SaveGroup ( context . Background ( ) , account . Id , userID , & group . Group {
2024-10-23 12:05:02 +02:00
ID : "groupA" ,
Name : "GroupA" ,
Peers : [ ] string { peer1 . ID , peer2 . ID , peer3 . ID } ,
2024-11-15 18:09:32 +01:00
} )
require . NoError ( t , err , "failed to save group" )
2022-06-04 22:02:22 +02:00
2024-11-26 10:46:05 +01:00
if err := manager . DeletePolicy ( context . Background ( ) , account . Id , account . Policies [ 0 ] . ID , userID ) ; err != nil {
t . Errorf ( "delete default rule: %v" , err )
return
}
2024-12-11 12:58:45 +01:00
policy , err := manager . SavePolicy ( context . Background ( ) , account . Id , userID , & types . Policy {
2024-10-23 12:05:02 +02:00
Enabled : true ,
2024-12-11 12:58:45 +01:00
Rules : [ ] * types . PolicyRule {
2024-10-23 12:05:02 +02:00
{
Enabled : true ,
Sources : [ ] string { "groupA" } ,
Destinations : [ ] string { "groupA" } ,
Bidirectional : true ,
2024-12-11 12:58:45 +01:00
Action : types . PolicyTrafficActionAccept ,
2024-10-23 12:05:02 +02:00
} ,
} ,
2024-11-26 10:46:05 +01:00
} )
if err != nil {
2024-10-23 12:05:02 +02:00
t . Errorf ( "save policy: %v" , err )
return
}
2023-07-14 20:45:40 +02:00
2024-10-23 12:05:02 +02:00
wg := sync . WaitGroup { }
wg . Add ( 1 )
go func ( ) {
defer wg . Done ( )
message := <- updMsg
networkMap := message . Update . GetNetworkMap ( )
if len ( networkMap . RemotePeers ) != 0 {
t . Errorf ( "mismatch peers count: 0 expected, got %v" , len ( networkMap . RemotePeers ) )
2022-06-04 22:02:22 +02:00
}
2024-10-23 12:05:02 +02:00
} ( )
2022-06-04 22:02:22 +02:00
2024-10-23 12:05:02 +02:00
// clean policy is pre requirement for delete group
if err := manager . DeletePolicy ( context . Background ( ) , account . Id , policy . ID , userID ) ; err != nil {
t . Errorf ( "delete default rule: %v" , err )
return
}
2024-11-15 18:09:32 +01:00
if err := manager . DeleteGroup ( context . Background ( ) , account . Id , userID , "groupA" ) ; err != nil {
2024-10-23 12:05:02 +02:00
t . Errorf ( "delete group: %v" , err )
return
}
wg . Wait ( )
2022-06-04 22:02:22 +02:00
}
2022-01-14 14:34:27 +01:00
func TestAccountManager_DeletePeer ( t * testing . T ) {
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
2024-05-16 18:28:37 +02:00
2023-01-02 15:11:32 +01:00
userID := "account_creator"
account , err := createAccount ( manager , "test_account" , userID , "netbird.cloud" )
2022-01-14 14:34:27 +01:00
if err != nil {
t . Fatal ( err )
}
2024-12-11 12:58:45 +01:00
setupKey , err := manager . CreateSetupKey ( context . Background ( ) , account . Id , "test-key" , types . SetupKeyReusable , time . Hour , nil , 999 , userID , false )
2023-06-27 17:17:24 +02:00
if err != nil {
t . Fatal ( "error creating setup key" )
return
2022-01-14 14:34:27 +01:00
}
key , err := wgtypes . GenerateKey ( )
if err != nil {
t . Fatal ( err )
return
}
peerKey := key . PublicKey ( ) . String ( )
2024-07-03 11:33:02 +02:00
peer , _ , _ , err := manager . AddPeer ( context . Background ( ) , setupKey . Key , "" , & nbpeer . Peer {
2022-01-14 14:34:27 +01:00
Key : peerKey ,
2023-11-28 13:45:26 +01:00
Meta : nbpeer . PeerSystemMeta { Hostname : peerKey } ,
2022-01-14 14:34:27 +01:00
} )
if err != nil {
t . Errorf ( "expecting peer to be added, got failure %v" , err )
return
}
2024-07-03 11:33:02 +02:00
err = manager . DeletePeer ( context . Background ( ) , account . Id , peerKey , userID )
2022-01-14 14:34:27 +01:00
if err != nil {
return
}
2024-07-03 11:33:02 +02:00
account , err = manager . Store . GetAccount ( context . Background ( ) , account . Id )
2022-01-14 14:34:27 +01:00
if err != nil {
t . Fatal ( err )
return
}
2022-03-10 18:18:38 +01:00
if account . Network . CurrentSerial ( ) != 2 {
2023-11-01 17:11:16 +01:00
t . Errorf ( "expecting Network Serial=%d to be incremented and be equal to 2 after adding and deleting a peer" , account . Network . CurrentSerial ( ) )
2022-01-14 14:34:27 +01:00
}
2023-01-02 15:11:32 +01:00
2023-01-24 10:17:24 +01:00
ev := getEvent ( t , account . Id , manager , activity . PeerRemovedByUser )
2023-01-02 15:11:32 +01:00
assert . NotNil ( t , ev )
assert . Equal ( t , account . Id , ev . AccountID )
assert . Equal ( t , peer . Name , ev . Meta [ "name" ] )
assert . Equal ( t , peer . FQDN ( account . Domain ) , ev . Meta [ "fqdn" ] )
assert . Equal ( t , userID , ev . InitiatorID )
assert . Equal ( t , peer . IP . String ( ) , ev . TargetID )
assert . Equal ( t , peer . IP . String ( ) , fmt . Sprint ( ev . Meta [ "ip" ] ) )
2022-01-14 14:34:27 +01:00
}
2023-03-13 15:14:18 +01:00
2023-01-24 10:17:24 +01:00
func getEvent ( t * testing . T , accountID string , manager AccountManager , eventType activity . Activity ) * activity . Event {
2023-11-10 16:33:13 +01:00
t . Helper ( )
2023-01-24 10:17:24 +01:00
for {
select {
case <- time . After ( time . Second ) :
t . Fatal ( "no PeerAddedWithSetupKey event was generated" )
default :
2024-07-03 11:33:02 +02:00
events , err := manager . GetEvents ( context . Background ( ) , accountID , userID )
2023-01-24 10:17:24 +01:00
if err != nil {
t . Fatal ( err )
}
for _ , event := range events {
if event . Activity == eventType {
return event
}
}
}
}
}
2022-01-14 14:34:27 +01:00
2022-05-05 08:58:34 +02:00
func TestGetUsersFromAccount ( t * testing . T ) {
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
}
2024-12-11 12:58:45 +01:00
users := map [ string ] * types . User { "1" : { Id : "1" , Role : types . UserRoleOwner } , "2" : { Id : "2" , Role : "user" } , "3" : { Id : "3" , Role : "user" } }
2022-05-05 08:58:34 +02:00
accountId := "test_account_id"
2022-06-09 13:14:34 +02:00
account , err := createAccount ( manager , accountId , users [ "1" ] . Id , "" )
2022-05-05 08:58:34 +02:00
if err != nil {
t . Fatal ( err )
}
// add a user to the account
for _ , user := range users {
account . Users [ user . Id ] = user
}
2024-07-03 11:33:02 +02:00
userInfos , err := manager . GetUsersFromAccount ( context . Background ( ) , accountId , "1" )
2022-05-05 08:58:34 +02:00
if err != nil {
t . Fatal ( err )
}
for _ , userInfo := range userInfos {
id := userInfo . ID
assert . Equal ( t , userInfo . ID , users [ id ] . Id )
2022-05-29 22:43:39 +02:00
assert . Equal ( t , userInfo . Role , string ( users [ id ] . Role ) )
2022-05-05 08:58:34 +02:00
assert . Equal ( t , userInfo . Name , "" )
assert . Equal ( t , userInfo . Email , "" )
}
}
2022-11-07 12:10:56 +01:00
func TestFileStore_GetRoutesByPrefix ( t * testing . T ) {
_ , prefix , err := route . ParseNetwork ( "192.168.64.0/24" )
if err != nil {
t . Fatal ( err )
}
2024-12-11 12:58:45 +01:00
account := & types . Account {
2024-05-06 14:47:49 +02:00
Routes : map [ route . ID ] * route . Route {
2022-11-07 12:10:56 +01:00
"route-1" : {
ID : "route-1" ,
Network : prefix ,
NetID : "network-1" ,
Description : "network-1" ,
Peer : "peer-1" ,
NetworkType : 0 ,
Masquerade : false ,
Metric : 999 ,
Enabled : true ,
} ,
"route-2" : {
ID : "route-2" ,
Network : prefix ,
NetID : "network-1" ,
Description : "network-1" ,
Peer : "peer-2" ,
NetworkType : 0 ,
Masquerade : false ,
Metric : 999 ,
Enabled : true ,
} ,
} ,
}
2024-06-13 13:24:24 +02:00
routes := account . GetRoutesByPrefixOrDomains ( prefix , nil )
2022-11-07 12:10:56 +01:00
assert . Len ( t , routes , 2 )
2024-05-06 14:47:49 +02:00
routeIDs := make ( map [ route . ID ] struct { } , 2 )
2022-11-07 12:10:56 +01:00
for _ , r := range routes {
routeIDs [ r . ID ] = struct { } { }
}
2024-05-06 14:47:49 +02:00
assert . Contains ( t , routeIDs , route . ID ( "route-1" ) )
assert . Contains ( t , routeIDs , route . ID ( "route-2" ) )
2022-11-07 12:10:56 +01:00
}
2022-12-06 10:11:57 +01:00
func TestAccount_GetRoutesToSync ( t * testing . T ) {
2022-11-07 12:10:56 +01:00
_ , prefix , err := route . ParseNetwork ( "192.168.64.0/24" )
if err != nil {
t . Fatal ( err )
}
2022-12-08 15:15:50 +01:00
_ , prefix2 , err := route . ParseNetwork ( "192.168.0.0/24" )
if err != nil {
t . Fatal ( err )
}
2024-12-11 12:58:45 +01:00
account := & types . Account {
2023-11-28 13:45:26 +01:00
Peers : map [ string ] * nbpeer . Peer {
"peer-1" : { Key : "peer-1" , Meta : nbpeer . PeerSystemMeta { GoOS : "linux" } } , "peer-2" : { Key : "peer-2" , Meta : nbpeer . PeerSystemMeta { GoOS : "linux" } } , "peer-3" : { Key : "peer-1" , Meta : nbpeer . PeerSystemMeta { GoOS : "linux" } } ,
2022-11-07 12:10:56 +01:00
} ,
2024-03-27 18:48:48 +01:00
Groups : map [ string ] * group . Group { "group1" : { ID : "group1" , Peers : [ ] string { "peer-1" , "peer-2" } } } ,
2024-05-06 14:47:49 +02:00
Routes : map [ route . ID ] * route . Route {
2022-11-07 12:10:56 +01:00
"route-1" : {
ID : "route-1" ,
Network : prefix ,
NetID : "network-1" ,
Description : "network-1" ,
Peer : "peer-1" ,
NetworkType : 0 ,
Masquerade : false ,
Metric : 999 ,
Enabled : true ,
2022-12-06 10:11:57 +01:00
Groups : [ ] string { "group1" } ,
2022-11-07 12:10:56 +01:00
} ,
"route-2" : {
ID : "route-2" ,
2022-12-08 15:15:50 +01:00
Network : prefix2 ,
NetID : "network-2" ,
Description : "network-2" ,
Peer : "peer-2" ,
NetworkType : 0 ,
Masquerade : false ,
Metric : 999 ,
Enabled : true ,
Groups : [ ] string { "group1" } ,
} ,
"route-3" : {
ID : "route-3" ,
2022-11-07 12:10:56 +01:00
Network : prefix ,
NetID : "network-1" ,
Description : "network-1" ,
Peer : "peer-2" ,
NetworkType : 0 ,
Masquerade : false ,
Metric : 999 ,
Enabled : true ,
2022-12-06 10:11:57 +01:00
Groups : [ ] string { "group1" } ,
2022-11-07 12:10:56 +01:00
} ,
} ,
}
2024-12-11 12:58:45 +01:00
routes := account . GetRoutesToSync ( context . Background ( ) , "peer-2" , [ ] * nbpeer . Peer { { Key : "peer-1" } , { Key : "peer-3" } } )
2022-11-07 12:10:56 +01:00
assert . Len ( t , routes , 2 )
2024-05-06 14:47:49 +02:00
routeIDs := make ( map [ route . ID ] struct { } , 2 )
2022-11-07 12:10:56 +01:00
for _ , r := range routes {
routeIDs [ r . ID ] = struct { } { }
}
2024-05-06 14:47:49 +02:00
assert . Contains ( t , routeIDs , route . ID ( "route-2" ) )
assert . Contains ( t , routeIDs , route . ID ( "route-3" ) )
2022-11-07 12:10:56 +01:00
2024-12-11 12:58:45 +01:00
emptyRoutes := account . GetRoutesToSync ( context . Background ( ) , "peer-3" , [ ] * nbpeer . Peer { { Key : "peer-1" } , { Key : "peer-2" } } )
2022-12-06 10:11:57 +01:00
assert . Len ( t , emptyRoutes , 0 )
2022-11-07 12:10:56 +01:00
}
2022-11-07 17:37:28 +01:00
func TestAccount_Copy ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2022-11-07 17:37:28 +01:00
Id : "account1" ,
CreatedBy : "tester" ,
2024-03-02 13:49:40 +01:00
CreatedAt : time . Now ( ) . UTC ( ) ,
2022-11-07 17:37:28 +01:00
Domain : "test.com" ,
DomainCategory : "public" ,
IsDomainPrimaryAccount : true ,
2024-12-11 12:58:45 +01:00
SetupKeys : map [ string ] * types . SetupKey {
2022-11-07 17:37:28 +01:00
"setup1" : {
Id : "setup1" ,
AutoGroups : [ ] string { "group1" } ,
} ,
} ,
2024-12-11 12:58:45 +01:00
Network : & types . Network {
2023-10-12 15:42:36 +02:00
Identifier : "net1" ,
2022-11-07 17:37:28 +01:00
} ,
2023-11-28 13:45:26 +01:00
Peers : map [ string ] * nbpeer . Peer {
2022-11-07 17:37:28 +01:00
"peer1" : {
Key : "key1" ,
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-08-22 17:56:39 +02:00
LastSeen : time . Now ( ) ,
Connected : true ,
LoginExpired : false ,
} ,
2022-11-07 17:37:28 +01:00
} ,
} ,
2024-12-11 12:58:45 +01:00
Users : map [ string ] * types . User {
2022-11-07 17:37:28 +01:00
"user1" : {
Id : "user1" ,
2024-12-11 12:58:45 +01:00
Role : types . UserRoleAdmin ,
2022-11-07 17:37:28 +01:00
AutoGroups : [ ] string { "group1" } ,
2024-12-11 12:58:45 +01:00
PATs : map [ string ] * types . PersonalAccessToken {
2023-03-20 16:14:55 +01:00
"pat1" : {
2023-03-08 12:21:44 +01:00
ID : "pat1" ,
2023-03-27 16:28:49 +02:00
Name : "First PAT" ,
2023-03-08 12:21:44 +01:00
HashedToken : "SoMeHaShEdToKeN" ,
2023-04-03 15:09:35 +02:00
ExpirationDate : time . Now ( ) . UTC ( ) . AddDate ( 0 , 0 , 7 ) ,
2023-03-08 12:21:44 +01:00
CreatedBy : "user1" ,
2023-04-03 15:09:35 +02:00
CreatedAt : time . Now ( ) . UTC ( ) ,
LastUsed : time . Now ( ) . UTC ( ) ,
2023-03-08 12:21:44 +01:00
} ,
} ,
2022-11-07 17:37:28 +01:00
} ,
} ,
2024-03-27 18:48:48 +01:00
Groups : map [ string ] * group . Group {
2022-11-07 17:37:28 +01:00
"group1" : {
2023-08-22 17:56:39 +02:00
ID : "group1" ,
Peers : [ ] string { "peer1" } ,
2022-11-07 17:37:28 +01:00
} ,
} ,
2024-12-11 12:58:45 +01:00
Policies : [ ] * types . Policy {
2023-03-13 15:14:18 +01:00
{
2024-02-20 09:59:56 +01:00
ID : "policy1" ,
Enabled : true ,
2024-12-11 12:58:45 +01:00
Rules : make ( [ ] * types . PolicyRule , 0 ) ,
2024-02-20 09:59:56 +01:00
SourcePostureChecks : make ( [ ] string , 0 ) ,
2023-03-13 15:14:18 +01:00
} ,
} ,
2024-05-06 14:47:49 +02:00
Routes : map [ route . ID ] * route . Route {
2022-11-07 17:37:28 +01:00
"route1" : {
2024-10-02 13:41:00 +02:00
ID : "route1" ,
PeerGroups : [ ] string { } ,
Groups : [ ] string { "group1" } ,
AccessControlGroups : [ ] string { } ,
2022-11-07 17:37:28 +01:00
} ,
} ,
NameServerGroups : map [ string ] * nbdns . NameServerGroup {
"nsGroup1" : {
2023-08-22 17:56:39 +02:00
ID : "nsGroup1" ,
Domains : [ ] string { } ,
Groups : [ ] string { } ,
NameServers : [ ] nbdns . NameServer { } ,
2022-11-07 17:37:28 +01:00
} ,
} ,
2024-12-11 12:58:45 +01:00
DNSSettings : types . DNSSettings { DisabledManagementGroups : [ ] string { } } ,
2024-02-20 09:59:56 +01:00
PostureChecks : [ ] * posture . Checks {
{
ID : "posture Checks1" ,
} ,
} ,
2024-12-11 12:58:45 +01:00
Settings : & types . Settings { } ,
Networks : [ ] * networkTypes . Network {
2024-12-10 11:20:48 +01:00
{
ID : "network1" ,
} ,
} ,
2024-12-11 12:58:45 +01:00
NetworkRouters : [ ] * routerTypes . NetworkRouter {
2024-12-10 17:26:23 +01:00
{
ID : "router1" ,
NetworkID : "network1" ,
PeerGroups : [ ] string { "group1" } ,
Masquerade : false ,
Metric : 0 ,
} ,
} ,
2024-12-11 12:58:45 +01:00
NetworkResources : [ ] * resourceTypes . NetworkResource {
2024-12-10 17:26:23 +01:00
{
ID : "resource1" ,
NetworkID : "network1" ,
Name : "resource" ,
Type : "Subnet" ,
Address : "172.12.6.1/24" ,
} ,
} ,
2022-11-07 17:37:28 +01:00
}
err := hasNilField ( account )
if err != nil {
t . Fatal ( err )
}
accountCopy := account . Copy ( )
2023-08-22 17:56:39 +02:00
accBytes , err := json . Marshal ( account )
if err != nil {
t . Fatal ( err )
}
2023-11-07 13:37:57 +01:00
account . Peers [ "peer1" ] . Status . Connected = false // we change original object to confirm that copy won't change
2023-08-22 17:56:39 +02:00
accCopyBytes , err := json . Marshal ( accountCopy )
if err != nil {
t . Fatal ( err )
}
assert . Equal ( t , string ( accBytes ) , string ( accCopyBytes ) , "account copy returned a different value than expected" )
2022-11-07 17:37:28 +01:00
}
// hasNilField validates pointers, maps and slices if they are nil
2023-08-22 17:56:39 +02:00
// TODO: make it check nested fields too
2022-11-07 17:37:28 +01:00
func hasNilField ( x interface { } ) error {
rv := reflect . ValueOf ( x )
rv = rv . Elem ( )
for i := 0 ; i < rv . NumField ( ) ; i ++ {
2023-10-12 15:42:36 +02:00
// skip gorm internal fields
if json , ok := rv . Type ( ) . Field ( i ) . Tag . Lookup ( "json" ) ; ok && json == "-" {
continue
}
2022-11-07 17:37:28 +01:00
if f := rv . Field ( i ) ; f . IsValid ( ) {
k := f . Kind ( )
switch k {
case reflect . Ptr :
if f . IsNil ( ) {
return fmt . Errorf ( "field %s is nil" , f . String ( ) )
}
case reflect . Map , reflect . Slice :
if f . Len ( ) == 0 || f . IsNil ( ) {
return fmt . Errorf ( "field %s is nil" , f . String ( ) )
}
}
}
}
return nil
}
2023-03-13 15:14:18 +01:00
2023-02-16 12:00:41 +01:00
func TestDefaultAccountManager_DefaultAccountSettings ( t * testing . T ) {
manager , err := createManager ( t )
require . NoError ( t , err , "unable to create account manager" )
2024-10-04 16:17:01 +02:00
accountID , err := manager . GetAccountIDByUserID ( context . Background ( ) , userID , "" )
2023-02-16 12:00:41 +01:00
require . NoError ( t , err , "unable to create an account" )
2024-12-11 12:58:45 +01:00
settings , err := manager . Store . GetAccountSettings ( context . Background ( ) , store . LockingStrengthShare , accountID )
2024-09-27 16:10:50 +02:00
require . NoError ( t , err , "unable to get account settings" )
assert . NotNil ( t , settings )
assert . Equal ( t , settings . PeerLoginExpirationEnabled , true )
assert . Equal ( t , settings . PeerLoginExpiration , 24 * time . Hour )
2023-02-16 12:00:41 +01:00
}
2023-03-13 15:14:18 +01:00
2023-02-27 16:44:26 +01:00
func TestDefaultAccountManager_UpdatePeer_PeerLoginExpiration ( t * testing . T ) {
manager , err := createManager ( t )
require . NoError ( t , err , "unable to create account manager" )
2024-05-16 18:28:37 +02:00
2024-10-04 16:17:01 +02:00
_ , err = manager . GetAccountIDByUserID ( context . Background ( ) , userID , "" )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "unable to create an account" )
key , err := wgtypes . GenerateKey ( )
require . NoError ( t , err , "unable to generate WireGuard key" )
2024-07-03 11:33:02 +02:00
peer , _ , _ , err := manager . AddPeer ( context . Background ( ) , "" , userID , & nbpeer . Peer {
2023-02-27 16:44:26 +01:00
Key : key . PublicKey ( ) . String ( ) ,
2023-11-28 13:45:26 +01:00
Meta : nbpeer . PeerSystemMeta { Hostname : "test-peer" } ,
2023-02-27 16:44:26 +01:00
LoginExpirationEnabled : true ,
} )
require . NoError ( t , err , "unable to add peer" )
2024-05-07 14:30:03 +02:00
2024-10-04 16:17:01 +02:00
accountID , err := manager . GetAccountIDByUserID ( context . Background ( ) , userID , "" )
2024-09-27 16:10:50 +02:00
require . NoError ( t , err , "unable to get the account" )
account , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
2024-05-07 14:30:03 +02:00
require . NoError ( t , err , "unable to get the account" )
2024-09-27 16:10:50 +02:00
2024-07-03 11:33:02 +02:00
err = manager . MarkPeerConnected ( context . Background ( ) , key . PublicKey ( ) . String ( ) , true , nil , account )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "unable to mark peer connected" )
2024-09-27 16:10:50 +02:00
2024-12-11 12:58:45 +01:00
account , err = manager . UpdateAccountSettings ( context . Background ( ) , accountID , userID , & types . Settings {
2023-02-27 16:44:26 +01:00
PeerLoginExpiration : time . Hour ,
2023-03-13 15:14:18 +01:00
PeerLoginExpirationEnabled : true ,
} )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "expecting to update account settings successfully but got error" )
wg := & sync . WaitGroup { }
wg . Add ( 2 )
manager . peerLoginExpiry = & MockScheduler {
2024-07-03 11:33:02 +02:00
CancelFunc : func ( ctx context . Context , IDs [ ] string ) {
2023-02-27 16:44:26 +01:00
wg . Done ( )
} ,
2024-07-03 11:33:02 +02:00
ScheduleFunc : func ( ctx context . Context , in time . Duration , ID string , job func ( ) ( nextRunIn time . Duration , reschedule bool ) ) {
2023-02-27 16:44:26 +01:00
wg . Done ( )
} ,
}
// disable expiration first
update := peer . Copy ( )
update . LoginExpirationEnabled = false
2024-07-03 11:33:02 +02:00
_ , err = manager . UpdatePeer ( context . Background ( ) , account . Id , userID , update )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "unable to update peer" )
// enabling expiration should trigger the routine
update . LoginExpirationEnabled = true
2024-07-03 11:33:02 +02:00
_ , err = manager . UpdatePeer ( context . Background ( ) , account . Id , userID , update )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "unable to update peer" )
failed := waitTimeout ( wg , time . Second )
if failed {
t . Fatal ( "timeout while waiting for test to finish" )
}
}
func TestDefaultAccountManager_MarkPeerConnected_PeerLoginExpiration ( t * testing . T ) {
manager , err := createManager ( t )
require . NoError ( t , err , "unable to create account manager" )
2024-05-16 18:28:37 +02:00
2024-10-04 16:17:01 +02:00
accountID , err := manager . GetAccountIDByUserID ( context . Background ( ) , userID , "" )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "unable to create an account" )
key , err := wgtypes . GenerateKey ( )
require . NoError ( t , err , "unable to generate WireGuard key" )
2024-07-03 11:33:02 +02:00
_ , _ , _ , err = manager . AddPeer ( context . Background ( ) , "" , userID , & nbpeer . Peer {
2023-02-27 16:44:26 +01:00
Key : key . PublicKey ( ) . String ( ) ,
2023-11-28 13:45:26 +01:00
Meta : nbpeer . PeerSystemMeta { Hostname : "test-peer" } ,
2023-02-27 16:44:26 +01:00
LoginExpirationEnabled : true ,
} )
require . NoError ( t , err , "unable to add peer" )
2024-12-11 12:58:45 +01:00
_ , err = manager . UpdateAccountSettings ( context . Background ( ) , accountID , userID , & types . Settings {
2023-02-27 16:44:26 +01:00
PeerLoginExpiration : time . Hour ,
2023-03-13 15:14:18 +01:00
PeerLoginExpirationEnabled : true ,
} )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "expecting to update account settings successfully but got error" )
wg := & sync . WaitGroup { }
wg . Add ( 2 )
manager . peerLoginExpiry = & MockScheduler {
2024-07-03 11:33:02 +02:00
CancelFunc : func ( ctx context . Context , IDs [ ] string ) {
2023-02-27 16:44:26 +01:00
wg . Done ( )
} ,
2024-07-03 11:33:02 +02:00
ScheduleFunc : func ( ctx context . Context , in time . Duration , ID string , job func ( ) ( nextRunIn time . Duration , reschedule bool ) ) {
2023-02-27 16:44:26 +01:00
wg . Done ( )
} ,
}
2024-10-04 16:17:01 +02:00
accountID , err = manager . GetAccountIDByUserID ( context . Background ( ) , userID , "" )
2024-05-07 14:30:03 +02:00
require . NoError ( t , err , "unable to get the account" )
2024-09-27 16:10:50 +02:00
account , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
require . NoError ( t , err , "unable to get the account" )
2023-02-27 16:44:26 +01:00
// when we mark peer as connected, the peer login expiration routine should trigger
2024-07-03 11:33:02 +02:00
err = manager . MarkPeerConnected ( context . Background ( ) , key . PublicKey ( ) . String ( ) , true , nil , account )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "unable to mark peer connected" )
failed := waitTimeout ( wg , time . Second )
if failed {
t . Fatal ( "timeout while waiting for test to finish" )
}
}
func TestDefaultAccountManager_UpdateAccountSettings_PeerLoginExpiration ( t * testing . T ) {
manager , err := createManager ( t )
require . NoError ( t , err , "unable to create account manager" )
2024-05-16 18:28:37 +02:00
2024-10-04 16:17:01 +02:00
_ , err = manager . GetAccountIDByUserID ( context . Background ( ) , userID , "" )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "unable to create an account" )
key , err := wgtypes . GenerateKey ( )
require . NoError ( t , err , "unable to generate WireGuard key" )
2024-07-03 11:33:02 +02:00
_ , _ , _ , err = manager . AddPeer ( context . Background ( ) , "" , userID , & nbpeer . Peer {
2023-02-27 16:44:26 +01:00
Key : key . PublicKey ( ) . String ( ) ,
2023-11-28 13:45:26 +01:00
Meta : nbpeer . PeerSystemMeta { Hostname : "test-peer" } ,
2023-02-27 16:44:26 +01:00
LoginExpirationEnabled : true ,
} )
require . NoError ( t , err , "unable to add peer" )
2024-05-07 14:30:03 +02:00
2024-10-04 16:17:01 +02:00
accountID , err := manager . GetAccountIDByUserID ( context . Background ( ) , userID , "" )
2024-05-07 14:30:03 +02:00
require . NoError ( t , err , "unable to get the account" )
2024-09-27 16:10:50 +02:00
account , err := manager . Store . GetAccount ( context . Background ( ) , accountID )
require . NoError ( t , err , "unable to get the account" )
2024-07-03 11:33:02 +02:00
err = manager . MarkPeerConnected ( context . Background ( ) , key . PublicKey ( ) . String ( ) , true , nil , account )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "unable to mark peer connected" )
wg := & sync . WaitGroup { }
wg . Add ( 2 )
manager . peerLoginExpiry = & MockScheduler {
2024-07-03 11:33:02 +02:00
CancelFunc : func ( ctx context . Context , IDs [ ] string ) {
2023-02-27 16:44:26 +01:00
wg . Done ( )
} ,
2024-07-03 11:33:02 +02:00
ScheduleFunc : func ( ctx context . Context , in time . Duration , ID string , job func ( ) ( nextRunIn time . Duration , reschedule bool ) ) {
2023-02-27 16:44:26 +01:00
wg . Done ( )
} ,
}
// enabling PeerLoginExpirationEnabled should trigger the expiration job
2024-12-11 12:58:45 +01:00
account , err = manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & types . Settings {
2023-02-27 16:44:26 +01:00
PeerLoginExpiration : time . Hour ,
2023-03-13 15:14:18 +01:00
PeerLoginExpirationEnabled : true ,
} )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "expecting to update account settings successfully but got error" )
failed := waitTimeout ( wg , time . Second )
if failed {
t . Fatal ( "timeout while waiting for test to finish" )
}
wg . Add ( 1 )
// disabling PeerLoginExpirationEnabled should trigger cancel
2024-12-11 12:58:45 +01:00
_ , err = manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & types . Settings {
2023-02-27 16:44:26 +01:00
PeerLoginExpiration : time . Hour ,
2023-03-13 15:14:18 +01:00
PeerLoginExpirationEnabled : false ,
} )
2023-02-27 16:44:26 +01:00
require . NoError ( t , err , "expecting to update account settings successfully but got error" )
failed = waitTimeout ( wg , time . Second )
if failed {
t . Fatal ( "timeout while waiting for test to finish" )
}
}
2023-02-16 12:00:41 +01:00
func TestDefaultAccountManager_UpdateAccountSettings ( t * testing . T ) {
manager , err := createManager ( t )
require . NoError ( t , err , "unable to create account manager" )
2024-10-04 16:17:01 +02:00
accountID , err := manager . GetAccountIDByUserID ( context . Background ( ) , userID , "" )
2023-02-16 12:00:41 +01:00
require . NoError ( t , err , "unable to create an account" )
2024-12-11 12:58:45 +01:00
updated , err := manager . UpdateAccountSettings ( context . Background ( ) , accountID , userID , & types . Settings {
2023-02-16 12:00:41 +01:00
PeerLoginExpiration : time . Hour ,
2023-03-13 15:14:18 +01:00
PeerLoginExpirationEnabled : false ,
} )
2023-02-16 12:00:41 +01:00
require . NoError ( t , err , "expecting to update account settings successfully but got error" )
assert . False ( t , updated . Settings . PeerLoginExpirationEnabled )
assert . Equal ( t , updated . Settings . PeerLoginExpiration , time . Hour )
2024-12-11 12:58:45 +01:00
settings , err := manager . Store . GetAccountSettings ( context . Background ( ) , store . LockingStrengthShare , accountID )
2024-09-27 16:10:50 +02:00
require . NoError ( t , err , "unable to get account settings" )
2023-02-16 12:00:41 +01:00
2024-09-27 16:10:50 +02:00
assert . False ( t , settings . PeerLoginExpirationEnabled )
assert . Equal ( t , settings . PeerLoginExpiration , time . Hour )
2024-12-11 12:58:45 +01:00
_ , err = manager . UpdateAccountSettings ( context . Background ( ) , accountID , userID , & types . Settings {
2023-02-16 12:00:41 +01:00
PeerLoginExpiration : time . Second ,
2023-03-13 15:14:18 +01:00
PeerLoginExpirationEnabled : false ,
} )
2023-02-16 12:00:41 +01:00
require . Error ( t , err , "expecting to fail when providing PeerLoginExpiration less than one hour" )
2024-12-11 12:58:45 +01:00
_ , err = manager . UpdateAccountSettings ( context . Background ( ) , accountID , userID , & types . Settings {
2023-02-16 12:00:41 +01:00
PeerLoginExpiration : time . Hour * 24 * 181 ,
2023-03-13 15:14:18 +01:00
PeerLoginExpirationEnabled : false ,
} )
2023-02-16 12:00:41 +01:00
require . Error ( t , err , "expecting to fail when providing PeerLoginExpiration more than 180 days" )
}
2022-11-07 17:37:28 +01:00
2023-02-27 16:44:26 +01:00
func TestAccount_GetExpiredPeers ( t * testing . T ) {
type test struct {
name string
2023-11-28 13:45:26 +01:00
peers map [ string ] * nbpeer . Peer
2023-02-27 16:44:26 +01:00
expectedPeers map [ string ] struct { }
}
testCases := [ ] test {
{
name : "Peers with login expiration disabled, no expired peers" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-02-27 16:44:26 +01:00
"peer-1" : {
LoginExpirationEnabled : false ,
} ,
"peer-2" : {
LoginExpirationEnabled : false ,
} ,
} ,
expectedPeers : map [ string ] struct { } { } ,
} ,
{
name : "Two peers expired" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-02-27 16:44:26 +01:00
"peer-1" : {
ID : "peer-1" ,
LoginExpirationEnabled : true ,
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-04-03 15:09:35 +02:00
LastSeen : time . Now ( ) . UTC ( ) ,
2023-02-27 16:44:26 +01:00
Connected : true ,
LoginExpired : false ,
} ,
2023-04-03 15:09:35 +02:00
LastLogin : time . Now ( ) . UTC ( ) . Add ( - 30 * time . Minute ) ,
2023-03-02 12:45:10 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
"peer-2" : {
ID : "peer-2" ,
LoginExpirationEnabled : true ,
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-04-03 15:09:35 +02:00
LastSeen : time . Now ( ) . UTC ( ) ,
2023-02-27 16:44:26 +01:00
Connected : true ,
LoginExpired : false ,
} ,
2023-04-03 15:09:35 +02:00
LastLogin : time . Now ( ) . UTC ( ) . Add ( - 2 * time . Hour ) ,
2023-03-02 12:45:10 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
"peer-3" : {
ID : "peer-3" ,
LoginExpirationEnabled : true ,
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-04-03 15:09:35 +02:00
LastSeen : time . Now ( ) . UTC ( ) ,
2023-02-27 16:44:26 +01:00
Connected : true ,
LoginExpired : false ,
} ,
2023-04-03 15:09:35 +02:00
LastLogin : time . Now ( ) . UTC ( ) . Add ( - 1 * time . Hour ) ,
2023-03-02 12:45:10 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
} ,
expectedPeers : map [ string ] struct { } {
"peer-2" : { } ,
"peer-3" : { } ,
} ,
} ,
}
for _ , testCase := range testCases {
t . Run ( testCase . name , func ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2023-02-27 16:44:26 +01:00
Peers : testCase . peers ,
2024-12-11 12:58:45 +01:00
Settings : & types . Settings {
2023-02-27 16:44:26 +01:00
PeerLoginExpirationEnabled : true ,
PeerLoginExpiration : time . Hour ,
} ,
}
expiredPeers := account . GetExpiredPeers ( )
assert . Len ( t , expiredPeers , len ( testCase . expectedPeers ) )
for _ , peer := range expiredPeers {
if _ , ok := testCase . expectedPeers [ peer . ID ] ; ! ok {
t . Fatalf ( "expected to have peer %s expired" , peer . ID )
}
}
} )
}
}
2024-10-13 14:52:43 +02:00
func TestAccount_GetInactivePeers ( t * testing . T ) {
type test struct {
name string
peers map [ string ] * nbpeer . Peer
expectedPeers map [ string ] struct { }
}
testCases := [ ] test {
{
name : "Peers with inactivity expiration disabled, no expired peers" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
InactivityExpirationEnabled : false ,
} ,
"peer-2" : {
InactivityExpirationEnabled : false ,
} ,
} ,
expectedPeers : map [ string ] struct { } { } ,
} ,
{
name : "Two peers expired" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
ID : "peer-1" ,
InactivityExpirationEnabled : true ,
Status : & nbpeer . PeerStatus {
LastSeen : time . Now ( ) . UTC ( ) . Add ( - 45 * time . Second ) ,
Connected : false ,
LoginExpired : false ,
} ,
LastLogin : time . Now ( ) . UTC ( ) . Add ( - 30 * time . Minute ) ,
UserID : userID ,
} ,
"peer-2" : {
ID : "peer-2" ,
InactivityExpirationEnabled : true ,
Status : & nbpeer . PeerStatus {
LastSeen : time . Now ( ) . UTC ( ) . Add ( - 45 * time . Second ) ,
Connected : false ,
LoginExpired : false ,
} ,
LastLogin : time . Now ( ) . UTC ( ) . Add ( - 2 * time . Hour ) ,
UserID : userID ,
} ,
"peer-3" : {
ID : "peer-3" ,
InactivityExpirationEnabled : true ,
Status : & nbpeer . PeerStatus {
LastSeen : time . Now ( ) . UTC ( ) ,
Connected : true ,
LoginExpired : false ,
} ,
LastLogin : time . Now ( ) . UTC ( ) . Add ( - 1 * time . Hour ) ,
UserID : userID ,
} ,
} ,
expectedPeers : map [ string ] struct { } {
"peer-1" : { } ,
"peer-2" : { } ,
} ,
} ,
}
for _ , testCase := range testCases {
t . Run ( testCase . name , func ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2024-10-13 14:52:43 +02:00
Peers : testCase . peers ,
2024-12-11 12:58:45 +01:00
Settings : & types . Settings {
2024-10-13 14:52:43 +02:00
PeerInactivityExpirationEnabled : true ,
PeerInactivityExpiration : time . Second ,
} ,
}
expiredPeers := account . GetInactivePeers ( )
assert . Len ( t , expiredPeers , len ( testCase . expectedPeers ) )
for _ , peer := range expiredPeers {
if _ , ok := testCase . expectedPeers [ peer . ID ] ; ! ok {
t . Fatalf ( "expected to have peer %s expired" , peer . ID )
}
}
} )
}
}
2023-02-27 16:44:26 +01:00
func TestAccount_GetPeersWithExpiration ( t * testing . T ) {
type test struct {
name string
2023-11-28 13:45:26 +01:00
peers map [ string ] * nbpeer . Peer
2023-02-27 16:44:26 +01:00
expectedPeers map [ string ] struct { }
}
testCases := [ ] test {
{
name : "No account peers, no peers with expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer { } ,
2023-02-27 16:44:26 +01:00
expectedPeers : map [ string ] struct { } { } ,
} ,
{
name : "Peers with login expiration disabled, no peers with expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-02-27 16:44:26 +01:00
"peer-1" : {
LoginExpirationEnabled : false ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
"peer-2" : {
LoginExpirationEnabled : false ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
} ,
expectedPeers : map [ string ] struct { } { } ,
} ,
{
name : "Peers with login expiration enabled, return peers with expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-02-27 16:44:26 +01:00
"peer-1" : {
ID : "peer-1" ,
LoginExpirationEnabled : true ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
"peer-2" : {
LoginExpirationEnabled : false ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
} ,
expectedPeers : map [ string ] struct { } {
"peer-1" : { } ,
} ,
} ,
}
for _ , testCase := range testCases {
t . Run ( testCase . name , func ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2023-02-27 16:44:26 +01:00
Peers : testCase . peers ,
}
actual := account . GetPeersWithExpiration ( )
assert . Len ( t , actual , len ( testCase . expectedPeers ) )
if len ( testCase . expectedPeers ) > 0 {
for k := range testCase . expectedPeers {
contains := false
for _ , peer := range actual {
if k == peer . ID {
contains = true
}
}
assert . True ( t , contains )
}
}
} )
}
}
2024-10-13 14:52:43 +02:00
func TestAccount_GetPeersWithInactivity ( t * testing . T ) {
type test struct {
name string
peers map [ string ] * nbpeer . Peer
expectedPeers map [ string ] struct { }
}
testCases := [ ] test {
{
name : "No account peers, no peers with expiration" ,
peers : map [ string ] * nbpeer . Peer { } ,
expectedPeers : map [ string ] struct { } { } ,
} ,
{
name : "Peers with login expiration disabled, no peers with expiration" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
InactivityExpirationEnabled : false ,
UserID : userID ,
} ,
"peer-2" : {
InactivityExpirationEnabled : false ,
UserID : userID ,
} ,
} ,
expectedPeers : map [ string ] struct { } { } ,
} ,
{
name : "Peers with login expiration enabled, return peers with expiration" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
ID : "peer-1" ,
InactivityExpirationEnabled : true ,
UserID : userID ,
} ,
"peer-2" : {
InactivityExpirationEnabled : false ,
UserID : userID ,
} ,
} ,
expectedPeers : map [ string ] struct { } {
"peer-1" : { } ,
} ,
} ,
}
for _ , testCase := range testCases {
t . Run ( testCase . name , func ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2024-10-13 14:52:43 +02:00
Peers : testCase . peers ,
}
actual := account . GetPeersWithInactivity ( )
assert . Len ( t , actual , len ( testCase . expectedPeers ) )
if len ( testCase . expectedPeers ) > 0 {
for k := range testCase . expectedPeers {
contains := false
for _ , peer := range actual {
if k == peer . ID {
contains = true
}
}
assert . True ( t , contains )
}
}
} )
}
}
2023-02-27 16:44:26 +01:00
func TestAccount_GetNextPeerExpiration ( t * testing . T ) {
type test struct {
name string
2023-11-28 13:45:26 +01:00
peers map [ string ] * nbpeer . Peer
2023-02-27 16:44:26 +01:00
expiration time . Duration
expirationEnabled bool
expectedNextRun bool
expectedNextExpiration time . Duration
}
expectedNextExpiration := time . Minute
testCases := [ ] test {
{
name : "No peers, no expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer { } ,
2023-02-27 16:44:26 +01:00
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
{
name : "No connected peers, no expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-02-27 16:44:26 +01:00
"peer-1" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-02-27 16:44:26 +01:00
Connected : false ,
} ,
LoginExpirationEnabled : true ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
"peer-2" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-02-27 16:44:26 +01:00
Connected : true ,
} ,
LoginExpirationEnabled : false ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
} ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
{
name : "Connected peers with disabled expiration, no expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-02-27 16:44:26 +01:00
"peer-1" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-02-27 16:44:26 +01:00
Connected : true ,
} ,
LoginExpirationEnabled : false ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
"peer-2" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-02-27 16:44:26 +01:00
Connected : true ,
} ,
LoginExpirationEnabled : false ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
} ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
{
name : "Expired peers, no expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-02-27 16:44:26 +01:00
"peer-1" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-02-27 16:44:26 +01:00
Connected : true ,
LoginExpired : true ,
} ,
LoginExpirationEnabled : true ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
"peer-2" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-02-27 16:44:26 +01:00
Connected : true ,
LoginExpired : true ,
} ,
LoginExpirationEnabled : true ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
} ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
{
name : "To be expired peer, return expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-02-27 16:44:26 +01:00
"peer-1" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-02-27 16:44:26 +01:00
Connected : true ,
LoginExpired : false ,
} ,
LoginExpirationEnabled : true ,
2023-04-03 15:09:35 +02:00
LastLogin : time . Now ( ) . UTC ( ) ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
"peer-2" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-02-27 16:44:26 +01:00
Connected : true ,
LoginExpired : true ,
} ,
LoginExpirationEnabled : true ,
2023-03-23 17:47:53 +01:00
UserID : userID ,
2023-02-27 16:44:26 +01:00
} ,
} ,
expiration : time . Minute ,
expirationEnabled : false ,
expectedNextRun : true ,
expectedNextExpiration : expectedNextExpiration ,
} ,
2023-03-23 17:47:53 +01:00
{
name : "Peers added with setup keys, no expiration" ,
2023-11-28 13:45:26 +01:00
peers : map [ string ] * nbpeer . Peer {
2023-03-23 17:47:53 +01:00
"peer-1" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-03-23 17:47:53 +01:00
Connected : true ,
LoginExpired : false ,
} ,
LoginExpirationEnabled : true ,
} ,
"peer-2" : {
2023-11-28 13:45:26 +01:00
Status : & nbpeer . PeerStatus {
2023-03-23 17:47:53 +01:00
Connected : true ,
LoginExpired : false ,
} ,
LoginExpirationEnabled : true ,
} ,
} ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
2023-02-27 16:44:26 +01:00
}
for _ , testCase := range testCases {
t . Run ( testCase . name , func ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2023-02-27 16:44:26 +01:00
Peers : testCase . peers ,
2024-12-11 12:58:45 +01:00
Settings : & types . Settings { PeerLoginExpiration : testCase . expiration , PeerLoginExpirationEnabled : testCase . expirationEnabled } ,
2023-02-27 16:44:26 +01:00
}
expiration , ok := account . GetNextPeerExpiration ( )
assert . Equal ( t , ok , testCase . expectedNextRun )
if testCase . expectedNextRun {
assert . True ( t , expiration >= 0 && expiration <= testCase . expectedNextExpiration )
} else {
assert . Equal ( t , expiration , testCase . expectedNextExpiration )
}
} )
}
}
2024-10-13 14:52:43 +02:00
func TestAccount_GetNextInactivePeerExpiration ( t * testing . T ) {
type test struct {
name string
peers map [ string ] * nbpeer . Peer
expiration time . Duration
expirationEnabled bool
expectedNextRun bool
expectedNextExpiration time . Duration
}
expectedNextExpiration := time . Minute
testCases := [ ] test {
{
name : "No peers, no expiration" ,
peers : map [ string ] * nbpeer . Peer { } ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
{
name : "No connected peers, no expiration" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
Status : & nbpeer . PeerStatus {
Connected : false ,
} ,
InactivityExpirationEnabled : false ,
UserID : userID ,
} ,
"peer-2" : {
Status : & nbpeer . PeerStatus {
Connected : false ,
} ,
InactivityExpirationEnabled : false ,
UserID : userID ,
} ,
} ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
{
name : "Connected peers with disabled expiration, no expiration" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
Status : & nbpeer . PeerStatus {
Connected : true ,
} ,
InactivityExpirationEnabled : false ,
UserID : userID ,
} ,
"peer-2" : {
Status : & nbpeer . PeerStatus {
Connected : true ,
} ,
InactivityExpirationEnabled : false ,
UserID : userID ,
} ,
} ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
{
name : "Expired peers, no expiration" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
Status : & nbpeer . PeerStatus {
Connected : true ,
LoginExpired : true ,
} ,
InactivityExpirationEnabled : true ,
UserID : userID ,
} ,
"peer-2" : {
Status : & nbpeer . PeerStatus {
Connected : true ,
LoginExpired : true ,
} ,
InactivityExpirationEnabled : true ,
UserID : userID ,
} ,
} ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
{
name : "To be expired peer, return expiration" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
Status : & nbpeer . PeerStatus {
Connected : false ,
LoginExpired : false ,
LastSeen : time . Now ( ) . Add ( - 1 * time . Second ) ,
} ,
InactivityExpirationEnabled : true ,
LastLogin : time . Now ( ) . UTC ( ) ,
UserID : userID ,
} ,
"peer-2" : {
Status : & nbpeer . PeerStatus {
Connected : true ,
LoginExpired : true ,
} ,
InactivityExpirationEnabled : true ,
UserID : userID ,
} ,
} ,
expiration : time . Minute ,
expirationEnabled : false ,
expectedNextRun : true ,
expectedNextExpiration : expectedNextExpiration ,
} ,
{
name : "Peers added with setup keys, no expiration" ,
peers : map [ string ] * nbpeer . Peer {
"peer-1" : {
Status : & nbpeer . PeerStatus {
Connected : true ,
LoginExpired : false ,
} ,
InactivityExpirationEnabled : true ,
} ,
"peer-2" : {
Status : & nbpeer . PeerStatus {
Connected : true ,
LoginExpired : false ,
} ,
InactivityExpirationEnabled : true ,
} ,
} ,
expiration : time . Second ,
expirationEnabled : false ,
expectedNextRun : false ,
expectedNextExpiration : time . Duration ( 0 ) ,
} ,
}
for _ , testCase := range testCases {
t . Run ( testCase . name , func ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2024-10-13 14:52:43 +02:00
Peers : testCase . peers ,
2024-12-11 12:58:45 +01:00
Settings : & types . Settings { PeerInactivityExpiration : testCase . expiration , PeerInactivityExpirationEnabled : testCase . expirationEnabled } ,
2024-10-13 14:52:43 +02:00
}
expiration , ok := account . GetNextInactivePeerExpiration ( )
assert . Equal ( t , testCase . expectedNextRun , ok )
if testCase . expectedNextRun {
assert . True ( t , expiration >= 0 && expiration <= testCase . expectedNextExpiration )
} else {
assert . Equal ( t , expiration , testCase . expectedNextExpiration )
}
} )
}
}
2023-08-18 15:36:05 +02:00
func TestAccount_SetJWTGroups ( t * testing . T ) {
2024-10-04 16:17:01 +02:00
manager , err := createManager ( t )
require . NoError ( t , err , "unable to create account manager" )
2023-08-07 17:44:51 +02:00
// create a new account
2024-12-11 12:58:45 +01:00
account := & types . Account {
2024-10-04 16:17:01 +02:00
Id : "accountID" ,
2023-11-28 13:45:26 +01:00
Peers : map [ string ] * nbpeer . Peer {
2023-08-07 17:44:51 +02:00
"peer1" : { ID : "peer1" , Key : "key1" , UserID : "user1" } ,
"peer2" : { ID : "peer2" , Key : "key2" , UserID : "user1" } ,
"peer3" : { ID : "peer3" , Key : "key3" , UserID : "user1" } ,
"peer4" : { ID : "peer4" , Key : "key4" , UserID : "user2" } ,
"peer5" : { ID : "peer5" , Key : "key5" , UserID : "user2" } ,
} ,
2024-03-27 18:48:48 +01:00
Groups : map [ string ] * group . Group {
"group1" : { ID : "group1" , Name : "group1" , Issued : group . GroupIssuedAPI , Peers : [ ] string { } } ,
2023-08-07 17:44:51 +02:00
} ,
2024-12-11 12:58:45 +01:00
Settings : & types . Settings { GroupsPropagationEnabled : true , JWTGroupsEnabled : true , JWTGroupsClaimName : "groups" } ,
Users : map [ string ] * types . User {
2024-10-04 16:17:01 +02:00
"user1" : { Id : "user1" , AccountID : "accountID" } ,
"user2" : { Id : "user2" , AccountID : "accountID" } ,
2023-08-07 17:44:51 +02:00
} ,
}
2024-10-04 16:17:01 +02:00
assert . NoError ( t , manager . Store . SaveAccount ( context . Background ( ) , account ) , "unable to save account" )
2024-06-13 08:55:09 +02:00
t . Run ( "empty jwt groups" , func ( t * testing . T ) {
2024-10-04 16:17:01 +02:00
claims := jwtclaims . AuthorizationClaims {
UserId : "user1" ,
Raw : jwt . MapClaims { "groups" : [ ] interface { } { } } ,
}
err := manager . syncJWTGroups ( context . Background ( ) , "accountID" , claims )
assert . NoError ( t , err , "unable to sync jwt groups" )
2024-12-11 12:58:45 +01:00
user , err := manager . Store . GetUserByUserID ( context . Background ( ) , store . LockingStrengthShare , "user1" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get user" )
assert . Empty ( t , user . AutoGroups , "auto groups must be empty" )
2023-08-07 17:44:51 +02:00
} )
2024-06-13 08:55:09 +02:00
t . Run ( "jwt match existing api group" , func ( t * testing . T ) {
2024-10-04 16:17:01 +02:00
claims := jwtclaims . AuthorizationClaims {
UserId : "user1" ,
Raw : jwt . MapClaims { "groups" : [ ] interface { } { "group1" } } ,
}
err := manager . syncJWTGroups ( context . Background ( ) , "accountID" , claims )
assert . NoError ( t , err , "unable to sync jwt groups" )
2024-12-11 12:58:45 +01:00
user , err := manager . Store . GetUserByUserID ( context . Background ( ) , store . LockingStrengthShare , "user1" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get user" )
assert . Len ( t , user . AutoGroups , 0 )
2024-12-11 12:58:45 +01:00
group1 , err := manager . Store . GetGroupByID ( context . Background ( ) , store . LockingStrengthShare , "accountID" , "group1" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get group" )
assert . Equal ( t , group1 . Issued , group . GroupIssuedAPI , "group should be api issued" )
2024-06-13 08:55:09 +02:00
} )
t . Run ( "jwt match existing api group in user auto groups" , func ( t * testing . T ) {
account . Users [ "user1" ] . AutoGroups = [ ] string { "group1" }
2024-12-11 12:58:45 +01:00
assert . NoError ( t , manager . Store . SaveUser ( context . Background ( ) , store . LockingStrengthUpdate , account . Users [ "user1" ] ) )
2024-06-13 08:55:09 +02:00
2024-10-04 16:17:01 +02:00
claims := jwtclaims . AuthorizationClaims {
UserId : "user1" ,
Raw : jwt . MapClaims { "groups" : [ ] interface { } { "group1" } } ,
}
err = manager . syncJWTGroups ( context . Background ( ) , "accountID" , claims )
assert . NoError ( t , err , "unable to sync jwt groups" )
2024-12-11 12:58:45 +01:00
user , err := manager . Store . GetUserByUserID ( context . Background ( ) , store . LockingStrengthShare , "user1" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get user" )
assert . Len ( t , user . AutoGroups , 1 )
2024-12-11 12:58:45 +01:00
group1 , err := manager . Store . GetGroupByID ( context . Background ( ) , store . LockingStrengthShare , "accountID" , "group1" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get group" )
assert . Equal ( t , group1 . Issued , group . GroupIssuedAPI , "group should be api issued" )
2024-06-13 08:55:09 +02:00
} )
2023-08-07 17:44:51 +02:00
t . Run ( "add jwt group" , func ( t * testing . T ) {
2024-10-04 16:17:01 +02:00
claims := jwtclaims . AuthorizationClaims {
UserId : "user1" ,
Raw : jwt . MapClaims { "groups" : [ ] interface { } { "group1" , "group2" } } ,
}
err = manager . syncJWTGroups ( context . Background ( ) , "accountID" , claims )
assert . NoError ( t , err , "unable to sync jwt groups" )
2024-12-11 12:58:45 +01:00
user , err := manager . Store . GetUserByUserID ( context . Background ( ) , store . LockingStrengthShare , "user1" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get user" )
assert . Len ( t , user . AutoGroups , 2 , "groups count should not be change" )
2023-08-07 17:44:51 +02:00
} )
t . Run ( "existed group not update" , func ( t * testing . T ) {
2024-10-04 16:17:01 +02:00
claims := jwtclaims . AuthorizationClaims {
UserId : "user1" ,
Raw : jwt . MapClaims { "groups" : [ ] interface { } { "group2" } } ,
}
err = manager . syncJWTGroups ( context . Background ( ) , "accountID" , claims )
assert . NoError ( t , err , "unable to sync jwt groups" )
2024-12-11 12:58:45 +01:00
user , err := manager . Store . GetUserByUserID ( context . Background ( ) , store . LockingStrengthShare , "user1" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get user" )
assert . Len ( t , user . AutoGroups , 2 , "groups count should not be change" )
2023-08-07 17:44:51 +02:00
} )
t . Run ( "add new group" , func ( t * testing . T ) {
2024-10-04 16:17:01 +02:00
claims := jwtclaims . AuthorizationClaims {
UserId : "user2" ,
Raw : jwt . MapClaims { "groups" : [ ] interface { } { "group1" , "group3" } } ,
}
err = manager . syncJWTGroups ( context . Background ( ) , "accountID" , claims )
assert . NoError ( t , err , "unable to sync jwt groups" )
2024-12-11 12:58:45 +01:00
groups , err := manager . Store . GetAccountGroups ( context . Background ( ) , store . LockingStrengthShare , "accountID" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err )
assert . Len ( t , groups , 3 , "new group3 should be added" )
2024-12-11 12:58:45 +01:00
user , err := manager . Store . GetUserByUserID ( context . Background ( ) , store . LockingStrengthShare , "user2" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get user" )
assert . Len ( t , user . AutoGroups , 1 , "new group should be added" )
2023-08-07 17:44:51 +02:00
} )
2024-07-26 16:33:54 +02:00
t . Run ( "remove all JWT groups" , func ( t * testing . T ) {
2024-10-04 16:17:01 +02:00
claims := jwtclaims . AuthorizationClaims {
UserId : "user1" ,
Raw : jwt . MapClaims { "groups" : [ ] interface { } { } } ,
}
err = manager . syncJWTGroups ( context . Background ( ) , "accountID" , claims )
assert . NoError ( t , err , "unable to sync jwt groups" )
2024-12-11 12:58:45 +01:00
user , err := manager . Store . GetUserByUserID ( context . Background ( ) , store . LockingStrengthShare , "user1" )
2024-10-04 16:17:01 +02:00
assert . NoError ( t , err , "unable to get user" )
assert . Len ( t , user . AutoGroups , 1 , "only non-JWT groups should remain" )
assert . Contains ( t , user . AutoGroups , "group1" , " group1 should still be present" )
2024-07-26 16:33:54 +02:00
} )
2023-08-07 17:44:51 +02:00
}
func TestAccount_UserGroupsAddToPeers ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2023-11-28 13:45:26 +01:00
Peers : map [ string ] * nbpeer . Peer {
2023-08-07 17:44:51 +02:00
"peer1" : { ID : "peer1" , Key : "key1" , UserID : "user1" } ,
"peer2" : { ID : "peer2" , Key : "key2" , UserID : "user1" } ,
"peer3" : { ID : "peer3" , Key : "key3" , UserID : "user1" } ,
"peer4" : { ID : "peer4" , Key : "key4" , UserID : "user2" } ,
"peer5" : { ID : "peer5" , Key : "key5" , UserID : "user2" } ,
} ,
2024-03-27 18:48:48 +01:00
Groups : map [ string ] * group . Group {
"group1" : { ID : "group1" , Name : "group1" , Issued : group . GroupIssuedAPI , Peers : [ ] string { } } ,
"group2" : { ID : "group2" , Name : "group2" , Issued : group . GroupIssuedAPI , Peers : [ ] string { } } ,
"group3" : { ID : "group3" , Name : "group3" , Issued : group . GroupIssuedAPI , Peers : [ ] string { } } ,
2023-08-07 17:44:51 +02:00
} ,
2024-12-11 12:58:45 +01:00
Users : map [ string ] * types . User { "user1" : { Id : "user1" } , "user2" : { Id : "user2" } } ,
2023-08-07 17:44:51 +02:00
}
t . Run ( "add groups" , func ( t * testing . T ) {
account . UserGroupsAddToPeers ( "user1" , "group1" , "group2" )
assert . ElementsMatch ( t , account . Groups [ "group1" ] . Peers , [ ] string { "peer1" , "peer2" , "peer3" } , "group1 contains users peers" )
assert . ElementsMatch ( t , account . Groups [ "group2" ] . Peers , [ ] string { "peer1" , "peer2" , "peer3" } , "group2 contains users peers" )
} )
t . Run ( "add same groups" , func ( t * testing . T ) {
account . UserGroupsAddToPeers ( "user1" , "group1" , "group2" )
assert . Len ( t , account . Groups [ "group1" ] . Peers , 3 , "peers amount in group1 didn't change" )
assert . Len ( t , account . Groups [ "group2" ] . Peers , 3 , "peers amount in group2 didn't change" )
} )
t . Run ( "add second user peers" , func ( t * testing . T ) {
account . UserGroupsAddToPeers ( "user2" , "group2" )
assert . ElementsMatch ( t , account . Groups [ "group2" ] . Peers ,
[ ] string { "peer1" , "peer2" , "peer3" , "peer4" , "peer5" } , "group2 contains first and second user peers" )
} )
}
func TestAccount_UserGroupsRemoveFromPeers ( t * testing . T ) {
2024-12-11 12:58:45 +01:00
account := & types . Account {
2023-11-28 13:45:26 +01:00
Peers : map [ string ] * nbpeer . Peer {
2023-08-07 17:44:51 +02:00
"peer1" : { ID : "peer1" , Key : "key1" , UserID : "user1" } ,
"peer2" : { ID : "peer2" , Key : "key2" , UserID : "user1" } ,
"peer3" : { ID : "peer3" , Key : "key3" , UserID : "user1" } ,
"peer4" : { ID : "peer4" , Key : "key4" , UserID : "user2" } ,
"peer5" : { ID : "peer5" , Key : "key5" , UserID : "user2" } ,
} ,
2024-03-27 18:48:48 +01:00
Groups : map [ string ] * group . Group {
"group1" : { ID : "group1" , Name : "group1" , Issued : group . GroupIssuedAPI , Peers : [ ] string { "peer1" , "peer2" , "peer3" } } ,
"group2" : { ID : "group2" , Name : "group2" , Issued : group . GroupIssuedAPI , Peers : [ ] string { "peer1" , "peer2" , "peer3" , "peer4" , "peer5" } } ,
"group3" : { ID : "group3" , Name : "group3" , Issued : group . GroupIssuedAPI , Peers : [ ] string { "peer4" , "peer5" } } ,
2023-08-07 17:44:51 +02:00
} ,
2024-12-11 12:58:45 +01:00
Users : map [ string ] * types . User { "user1" : { Id : "user1" } , "user2" : { Id : "user2" } } ,
2023-08-07 17:44:51 +02:00
}
t . Run ( "remove groups" , func ( t * testing . T ) {
account . UserGroupsRemoveFromPeers ( "user1" , "group1" , "group2" )
assert . Empty ( t , account . Groups [ "group1" ] . Peers , "remove all peers from group1" )
assert . ElementsMatch ( t , account . Groups [ "group2" ] . Peers , [ ] string { "peer4" , "peer5" } , "group2 contains only second users peers" )
} )
t . Run ( "remove group with no peers" , func ( t * testing . T ) {
account . UserGroupsRemoveFromPeers ( "user1" , "group3" )
assert . Len ( t , account . Groups [ "group3" ] . Peers , 2 , "peers amount should not change" )
} )
}
2024-08-07 10:52:31 +02:00
type TB interface {
Cleanup ( func ( ) )
Helper ( )
TempDir ( ) string
}
func createManager ( t TB ) ( * DefaultAccountManager , error ) {
2023-11-10 16:33:13 +01:00
t . Helper ( )
2024-05-16 18:28:37 +02:00
2021-08-20 15:44:18 +02:00
store , err := createStore ( t )
if err != nil {
return nil , err
}
2023-01-02 15:11:32 +01:00
eventStore := & activity . InMemoryEventStore { }
2024-05-16 18:28:37 +02:00
2024-08-07 10:52:31 +02:00
metrics , err := telemetry . NewDefaultAppMetrics ( context . Background ( ) )
if err != nil {
return nil , err
}
manager , err := BuildManager ( context . Background ( ) , store , NewPeersUpdateManager ( nil ) , nil , "" , "netbird.cloud" , eventStore , nil , false , MocIntegratedValidator { } , metrics )
2024-05-16 18:28:37 +02:00
if err != nil {
return nil , err
}
return manager , nil
2021-08-20 15:18:29 +02:00
}
2024-12-11 12:58:45 +01:00
func createStore ( t TB ) ( store . Store , error ) {
2023-11-10 16:33:13 +01:00
t . Helper ( )
2021-08-20 15:18:29 +02:00
dataDir := t . TempDir ( )
2024-12-11 12:58:45 +01:00
store , cleanUp , err := store . NewTestStoreFromSQL ( context . Background ( ) , "" , dataDir )
2021-08-20 15:18:29 +02:00
if err != nil {
return nil , err
}
2024-05-16 18:28:37 +02:00
t . Cleanup ( cleanUp )
2021-08-20 15:18:29 +02:00
return store , nil
}
2023-02-27 16:44:26 +01:00
func waitTimeout ( wg * sync . WaitGroup , timeout time . Duration ) bool {
c := make ( chan struct { } )
go func ( ) {
defer close ( c )
wg . Wait ( )
} ( )
select {
case <- c :
return false
case <- time . After ( timeout ) :
return true
}
}
2024-10-23 12:05:02 +02:00
2024-12-11 12:58:45 +01:00
func setupNetworkMapTest ( t * testing . T ) ( * DefaultAccountManager , * types . Account , * nbpeer . Peer , * nbpeer . Peer , * nbpeer . Peer ) {
2024-10-23 12:05:02 +02:00
t . Helper ( )
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
}
account , err := createAccount ( manager , "test_account" , userID , "" )
if err != nil {
t . Fatal ( err )
}
2024-12-11 12:58:45 +01:00
setupKey , err := manager . CreateSetupKey ( context . Background ( ) , account . Id , "test-key" , types . SetupKeyReusable , time . Hour , nil , 999 , userID , false )
2024-10-23 12:05:02 +02:00
if err != nil {
t . Fatal ( "error creating setup key" )
}
2024-12-11 12:58:45 +01:00
getPeer := func ( manager * DefaultAccountManager , setupKey * types . SetupKey ) * nbpeer . Peer {
2024-10-23 12:05:02 +02:00
key , err := wgtypes . GeneratePrivateKey ( )
if err != nil {
t . Fatal ( err )
}
expectedPeerKey := key . PublicKey ( ) . String ( )
peer , _ , _ , err := manager . AddPeer ( context . Background ( ) , setupKey . Key , "" , & nbpeer . Peer {
Key : expectedPeerKey ,
Meta : nbpeer . PeerSystemMeta { Hostname : expectedPeerKey } ,
Status : & nbpeer . PeerStatus {
Connected : true ,
LastSeen : time . Now ( ) . UTC ( ) ,
} ,
} )
if err != nil {
t . Fatalf ( "expecting peer to be added, got failure %v" , err )
}
return peer
}
peer1 := getPeer ( manager , setupKey )
peer2 := getPeer ( manager , setupKey )
peer3 := getPeer ( manager , setupKey )
return manager , account , peer1 , peer2 , peer3
}
func peerShouldNotReceiveUpdate ( t * testing . T , updateMessage <- chan * UpdateMessage ) {
t . Helper ( )
select {
case msg := <- updateMessage :
t . Errorf ( "Unexpected message received: %+v" , msg )
case <- time . After ( 500 * time . Millisecond ) :
return
}
}
func peerShouldReceiveUpdate ( t * testing . T , updateMessage <- chan * UpdateMessage ) {
t . Helper ( )
select {
case msg := <- updateMessage :
if msg == nil {
t . Errorf ( "Received nil update message, expected valid message" )
}
case <- time . After ( 500 * time . Millisecond ) :
t . Error ( "Timed out waiting for update message" )
}
}
2024-11-28 14:59:53 +01:00
func BenchmarkSyncAndMarkPeer ( b * testing . B ) {
benchCases := [ ] struct {
2024-11-28 19:22:01 +01:00
name string
peers int
groups int
// We need different expectations for CI/CD and local runs because of the different performance characteristics
minMsPerOpLocal float64
maxMsPerOpLocal float64
minMsPerOpCICD float64
maxMsPerOpCICD float64
2024-11-28 14:59:53 +01:00
} {
2024-12-04 14:09:04 +01:00
{ "Small" , 50 , 5 , 1 , 3 , 3 , 10 } ,
2024-11-28 19:22:01 +01:00
{ "Medium" , 500 , 100 , 7 , 13 , 10 , 60 } ,
{ "Large" , 5000 , 200 , 65 , 80 , 60 , 170 } ,
2024-12-04 14:09:04 +01:00
{ "Small single" , 50 , 10 , 1 , 3 , 3 , 60 } ,
2024-11-28 19:22:01 +01:00
{ "Medium single" , 500 , 10 , 7 , 13 , 10 , 26 } ,
{ "Large 5" , 5000 , 15 , 65 , 80 , 60 , 170 } ,
2024-11-28 14:59:53 +01:00
}
log . SetOutput ( io . Discard )
defer log . SetOutput ( os . Stderr )
for _ , bc := range benchCases {
b . Run ( bc . name , func ( b * testing . B ) {
manager , accountID , _ , err := setupTestAccountManager ( b , bc . peers , bc . groups )
if err != nil {
b . Fatalf ( "Failed to setup test account manager: %v" , err )
}
ctx := context . Background ( )
account , err := manager . Store . GetAccount ( ctx , accountID )
if err != nil {
b . Fatalf ( "Failed to get account: %v" , err )
}
peerChannels := make ( map [ string ] chan * UpdateMessage )
for peerID := range account . Peers {
peerChannels [ peerID ] = make ( chan * UpdateMessage , channelBufferSize )
}
manager . peersUpdateManager . peerChannels = peerChannels
b . ResetTimer ( )
start := time . Now ( )
for i := 0 ; i < b . N ; i ++ {
_ , _ , _ , err := manager . SyncAndMarkPeer ( context . Background ( ) , account . Id , account . Peers [ "peer-1" ] . Key , nbpeer . PeerSystemMeta { Hostname : strconv . Itoa ( i ) } , net . IP { 1 , 1 , 1 , 1 } )
assert . NoError ( b , err )
}
duration := time . Since ( start )
msPerOp := float64 ( duration . Nanoseconds ( ) ) / float64 ( b . N ) / 1e6
b . ReportMetric ( msPerOp , "ms/op" )
2024-11-28 19:22:01 +01:00
minExpected := bc . minMsPerOpLocal
maxExpected := bc . maxMsPerOpLocal
if os . Getenv ( "CI" ) == "true" {
minExpected = bc . minMsPerOpCICD
maxExpected = bc . maxMsPerOpCICD
2024-11-28 14:59:53 +01:00
}
2024-11-28 19:22:01 +01:00
if msPerOp < minExpected {
b . Fatalf ( "Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)" , bc . name , msPerOp , minExpected )
}
if msPerOp > maxExpected {
b . Fatalf ( "Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)" , bc . name , msPerOp , maxExpected )
2024-11-28 14:59:53 +01:00
}
} )
}
}
func BenchmarkLoginPeer_ExistingPeer ( b * testing . B ) {
benchCases := [ ] struct {
2024-11-28 19:22:01 +01:00
name string
peers int
groups int
// We need different expectations for CI/CD and local runs because of the different performance characteristics
minMsPerOpLocal float64
maxMsPerOpLocal float64
minMsPerOpCICD float64
maxMsPerOpCICD float64
2024-11-28 14:59:53 +01:00
} {
2024-11-28 19:22:01 +01:00
{ "Small" , 50 , 5 , 102 , 110 , 102 , 120 } ,
{ "Medium" , 500 , 100 , 105 , 140 , 105 , 170 } ,
{ "Large" , 5000 , 200 , 160 , 200 , 160 , 270 } ,
{ "Small single" , 50 , 10 , 102 , 110 , 102 , 120 } ,
{ "Medium single" , 500 , 10 , 105 , 140 , 105 , 170 } ,
{ "Large 5" , 5000 , 15 , 160 , 200 , 160 , 270 } ,
2024-11-28 14:59:53 +01:00
}
log . SetOutput ( io . Discard )
defer log . SetOutput ( os . Stderr )
for _ , bc := range benchCases {
b . Run ( bc . name , func ( b * testing . B ) {
manager , accountID , _ , err := setupTestAccountManager ( b , bc . peers , bc . groups )
if err != nil {
b . Fatalf ( "Failed to setup test account manager: %v" , err )
}
ctx := context . Background ( )
account , err := manager . Store . GetAccount ( ctx , accountID )
if err != nil {
b . Fatalf ( "Failed to get account: %v" , err )
}
peerChannels := make ( map [ string ] chan * UpdateMessage )
for peerID := range account . Peers {
peerChannels [ peerID ] = make ( chan * UpdateMessage , channelBufferSize )
}
manager . peersUpdateManager . peerChannels = peerChannels
b . ResetTimer ( )
start := time . Now ( )
for i := 0 ; i < b . N ; i ++ {
_ , _ , _ , err := manager . LoginPeer ( context . Background ( ) , PeerLogin {
WireGuardPubKey : account . Peers [ "peer-1" ] . Key ,
SSHKey : "someKey" ,
Meta : nbpeer . PeerSystemMeta { Hostname : strconv . Itoa ( i ) } ,
UserID : "regular_user" ,
SetupKey : "" ,
ConnectionIP : net . IP { 1 , 1 , 1 , 1 } ,
} )
assert . NoError ( b , err )
}
duration := time . Since ( start )
msPerOp := float64 ( duration . Nanoseconds ( ) ) / float64 ( b . N ) / 1e6
b . ReportMetric ( msPerOp , "ms/op" )
2024-11-28 19:22:01 +01:00
minExpected := bc . minMsPerOpLocal
maxExpected := bc . maxMsPerOpLocal
if os . Getenv ( "CI" ) == "true" {
minExpected = bc . minMsPerOpCICD
maxExpected = bc . maxMsPerOpCICD
}
if msPerOp < minExpected {
b . Fatalf ( "Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)" , bc . name , msPerOp , minExpected )
2024-11-28 14:59:53 +01:00
}
2024-11-28 19:22:01 +01:00
if msPerOp > maxExpected {
b . Fatalf ( "Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)" , bc . name , msPerOp , maxExpected )
2024-11-28 14:59:53 +01:00
}
} )
}
}
func BenchmarkLoginPeer_NewPeer ( b * testing . B ) {
benchCases := [ ] struct {
2024-11-28 19:22:01 +01:00
name string
peers int
groups int
// We need different expectations for CI/CD and local runs because of the different performance characteristics
minMsPerOpLocal float64
maxMsPerOpLocal float64
minMsPerOpCICD float64
maxMsPerOpCICD float64
2024-11-28 14:59:53 +01:00
} {
2024-11-28 19:22:01 +01:00
{ "Small" , 50 , 5 , 107 , 120 , 107 , 140 } ,
{ "Medium" , 500 , 100 , 105 , 140 , 105 , 170 } ,
2024-12-04 14:09:04 +01:00
{ "Large" , 5000 , 200 , 180 , 220 , 180 , 340 } ,
2024-11-28 19:22:01 +01:00
{ "Small single" , 50 , 10 , 107 , 120 , 105 , 140 } ,
{ "Medium single" , 500 , 10 , 105 , 140 , 105 , 170 } ,
2024-12-04 14:09:04 +01:00
{ "Large 5" , 5000 , 15 , 180 , 220 , 180 , 340 } ,
2024-11-28 14:59:53 +01:00
}
log . SetOutput ( io . Discard )
defer log . SetOutput ( os . Stderr )
for _ , bc := range benchCases {
b . Run ( bc . name , func ( b * testing . B ) {
manager , accountID , _ , err := setupTestAccountManager ( b , bc . peers , bc . groups )
if err != nil {
b . Fatalf ( "Failed to setup test account manager: %v" , err )
}
ctx := context . Background ( )
account , err := manager . Store . GetAccount ( ctx , accountID )
if err != nil {
b . Fatalf ( "Failed to get account: %v" , err )
}
peerChannels := make ( map [ string ] chan * UpdateMessage )
for peerID := range account . Peers {
peerChannels [ peerID ] = make ( chan * UpdateMessage , channelBufferSize )
}
manager . peersUpdateManager . peerChannels = peerChannels
b . ResetTimer ( )
start := time . Now ( )
for i := 0 ; i < b . N ; i ++ {
_ , _ , _ , err := manager . LoginPeer ( context . Background ( ) , PeerLogin {
WireGuardPubKey : "some-new-key" + strconv . Itoa ( i ) ,
SSHKey : "someKey" ,
Meta : nbpeer . PeerSystemMeta { Hostname : strconv . Itoa ( i ) } ,
UserID : "regular_user" ,
SetupKey : "" ,
ConnectionIP : net . IP { 1 , 1 , 1 , 1 } ,
} )
assert . NoError ( b , err )
}
duration := time . Since ( start )
msPerOp := float64 ( duration . Nanoseconds ( ) ) / float64 ( b . N ) / 1e6
b . ReportMetric ( msPerOp , "ms/op" )
2024-11-28 19:22:01 +01:00
minExpected := bc . minMsPerOpLocal
maxExpected := bc . maxMsPerOpLocal
if os . Getenv ( "CI" ) == "true" {
minExpected = bc . minMsPerOpCICD
maxExpected = bc . maxMsPerOpCICD
}
if msPerOp < minExpected {
b . Fatalf ( "Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)" , bc . name , msPerOp , minExpected )
2024-11-28 14:59:53 +01:00
}
2024-11-28 19:22:01 +01:00
if msPerOp > maxExpected {
b . Fatalf ( "Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)" , bc . name , msPerOp , maxExpected )
2024-11-28 14:59:53 +01:00
}
} )
}
}