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"
2022-05-05 08:58:34 +02:00
"net"
2022-11-07 17:37:28 +01:00
"reflect"
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-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-08-07 10:52:31 +02:00
"github.com/netbirdio/netbird/management/server/telemetry"
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 {
}
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-07-03 11:33:02 +02: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 , error ) {
2024-03-27 18:48:48 +01:00
return update , nil
}
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
2022-06-09 13:14:34 +02:00
func verifyCanAddPeerToAccount ( t * testing . T , manager AccountManager , account * 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 )
}
}
func verifyNewAccountHasDefaultFields ( t * testing . T , account * 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
accountSettings Settings
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" ,
accountSettings : Settings { PeerLoginExpirationEnabled : false , PeerLoginExpiration : time . Hour } ,
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" ,
accountSettings : Settings { PeerLoginExpirationEnabled : true , PeerLoginExpiration : time . Hour } ,
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 }
network := & Network {
2023-10-12 15:42:36 +02:00
Identifier : "network" ,
Net : net . IPNet { IP : netIP , Mask : netMask } ,
Dns : "netbird.selfhosted" ,
Serial : 0 ,
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
}
2022-10-13 18:26:31 +02:00
func TestDefaultAccountManager_GetAccountFromToken ( t * testing . T ) {
2022-03-01 15:22:18 +01:00
type initUserParams jwtclaims . AuthorizationClaims
type test struct {
2022-03-10 13:47:36 +01:00
name string
inputClaims jwtclaims . AuthorizationClaims
inputInitUserParams initUserParams
inputUpdateAttrs bool
inputUpdateClaimAccount bool
testingFunc require . ComparisonAssertionFunc
expectedMSG string
expectedUserRole UserRole
expectedDomainCategory string
2022-09-29 10:51:18 +02:00
expectedDomain string
2022-03-10 13:47:36 +01:00
expectedPrimaryDomainStatus bool
2022-06-09 13:14:34 +02:00
expectedCreatedBy string
expectedUsers [ ] string
2022-03-01 15:22:18 +01:00
}
var (
publicDomain = "public.com"
privateDomain = "private.com"
unknownDomain = "unknown.com"
)
defaultInitAccount := initUserParams {
Domain : publicDomain ,
UserId : "defaultUser" ,
}
testCase1 := test {
name : "New User With Public Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : publicDomain ,
UserId : "pub-domain-user" ,
DomainCategory : PublicCategory ,
} ,
2022-03-10 13:47:36 +01:00
inputInitUserParams : defaultInitAccount ,
testingFunc : require . NotEqual ,
expectedMSG : "account IDs shouldn't match" ,
2023-12-01 17:24:57 +01:00
expectedUserRole : UserRoleOwner ,
2022-03-10 13:47:36 +01:00
expectedDomainCategory : "" ,
2022-09-29 10:51:18 +02:00
expectedDomain : publicDomain ,
2022-03-10 13:47:36 +01:00
expectedPrimaryDomainStatus : false ,
2022-06-09 13:14:34 +02:00
expectedCreatedBy : "pub-domain-user" ,
expectedUsers : [ ] string { "pub-domain-user" } ,
2022-03-01 15:22:18 +01:00
}
initUnknown := defaultInitAccount
initUnknown . DomainCategory = UnknownCategory
initUnknown . Domain = unknownDomain
testCase2 := test {
name : "New User With Unknown Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : unknownDomain ,
UserId : "unknown-domain-user" ,
DomainCategory : UnknownCategory ,
} ,
2022-03-10 13:47:36 +01:00
inputInitUserParams : initUnknown ,
testingFunc : require . NotEqual ,
expectedMSG : "account IDs shouldn't match" ,
2023-12-01 17:24:57 +01:00
expectedUserRole : UserRoleOwner ,
2022-09-29 10:51:18 +02:00
expectedDomain : unknownDomain ,
2022-03-10 13:47:36 +01:00
expectedDomainCategory : "" ,
expectedPrimaryDomainStatus : false ,
2022-06-09 13:14:34 +02:00
expectedCreatedBy : "unknown-domain-user" ,
expectedUsers : [ ] string { "unknown-domain-user" } ,
2022-03-01 15:22:18 +01:00
}
testCase3 := test {
name : "New User With Private Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : privateDomain ,
UserId : "pvt-domain-user" ,
DomainCategory : PrivateCategory ,
} ,
2022-03-10 13:47:36 +01:00
inputInitUserParams : defaultInitAccount ,
testingFunc : require . NotEqual ,
expectedMSG : "account IDs shouldn't match" ,
2023-12-01 17:24:57 +01:00
expectedUserRole : UserRoleOwner ,
2022-09-29 10:51:18 +02:00
expectedDomain : privateDomain ,
2022-03-10 13:47:36 +01:00
expectedDomainCategory : PrivateCategory ,
expectedPrimaryDomainStatus : true ,
2022-06-09 13:14:34 +02:00
expectedCreatedBy : "pvt-domain-user" ,
expectedUsers : [ ] string { "pvt-domain-user" } ,
2022-03-01 15:22:18 +01:00
}
privateInitAccount := defaultInitAccount
privateInitAccount . Domain = privateDomain
privateInitAccount . DomainCategory = PrivateCategory
testCase4 := test {
name : "New Regular User With Existing Private Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : privateDomain ,
2022-06-09 13:14:34 +02:00
UserId : "new-pvt-domain-user" ,
2022-03-01 15:22:18 +01:00
DomainCategory : PrivateCategory ,
} ,
2022-03-10 13:47:36 +01:00
inputUpdateAttrs : true ,
inputInitUserParams : privateInitAccount ,
testingFunc : require . Equal ,
expectedMSG : "account IDs should match" ,
expectedUserRole : UserRoleUser ,
2022-09-29 10:51:18 +02:00
expectedDomain : privateDomain ,
2022-03-10 13:47:36 +01:00
expectedDomainCategory : PrivateCategory ,
expectedPrimaryDomainStatus : true ,
2022-06-09 13:14:34 +02:00
expectedCreatedBy : defaultInitAccount . UserId ,
expectedUsers : [ ] string { defaultInitAccount . UserId , "new-pvt-domain-user" } ,
2022-03-01 15:22:18 +01:00
}
testCase5 := test {
name : "Existing User With Existing Reclassified Private Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : defaultInitAccount . Domain ,
UserId : defaultInitAccount . UserId ,
DomainCategory : PrivateCategory ,
} ,
2022-03-10 13:47:36 +01:00
inputInitUserParams : defaultInitAccount ,
testingFunc : require . Equal ,
expectedMSG : "account IDs should match" ,
2023-12-01 17:24:57 +01:00
expectedUserRole : UserRoleOwner ,
2022-09-29 10:51:18 +02:00
expectedDomain : defaultInitAccount . Domain ,
2022-03-10 13:47:36 +01:00
expectedDomainCategory : PrivateCategory ,
expectedPrimaryDomainStatus : true ,
2022-06-09 13:14:34 +02:00
expectedCreatedBy : defaultInitAccount . UserId ,
expectedUsers : [ ] string { defaultInitAccount . UserId } ,
2022-03-01 15:22:18 +01:00
}
2022-03-09 13:31:42 +01:00
testCase6 := test {
name : "Existing Account Id With Existing Reclassified Private Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : defaultInitAccount . Domain ,
UserId : defaultInitAccount . UserId ,
DomainCategory : PrivateCategory ,
} ,
2022-03-10 13:47:36 +01:00
inputUpdateClaimAccount : true ,
inputInitUserParams : defaultInitAccount ,
testingFunc : require . Equal ,
expectedMSG : "account IDs should match" ,
2023-12-01 17:24:57 +01:00
expectedUserRole : UserRoleOwner ,
2022-09-29 10:51:18 +02:00
expectedDomain : defaultInitAccount . Domain ,
2022-03-10 13:47:36 +01:00
expectedDomainCategory : PrivateCategory ,
expectedPrimaryDomainStatus : true ,
2022-06-09 13:14:34 +02:00
expectedCreatedBy : defaultInitAccount . UserId ,
expectedUsers : [ ] string { defaultInitAccount . UserId } ,
2022-03-09 13:31:42 +01:00
}
2022-09-29 10:51:18 +02:00
testCase7 := test {
name : "User With Private Category And Empty Domain" ,
inputClaims : jwtclaims . AuthorizationClaims {
Domain : "" ,
UserId : "pvt-domain-user" ,
DomainCategory : PrivateCategory ,
} ,
inputInitUserParams : defaultInitAccount ,
testingFunc : require . NotEqual ,
expectedMSG : "account IDs shouldn't match" ,
2023-12-01 17:24:57 +01:00
expectedUserRole : UserRoleOwner ,
2022-09-29 10:51:18 +02:00
expectedDomain : "" ,
expectedDomainCategory : "" ,
expectedPrimaryDomainStatus : false ,
expectedCreatedBy : "pvt-domain-user" ,
expectedUsers : [ ] string { "pvt-domain-user" } ,
}
for _ , testCase := range [ ] test { testCase1 , testCase2 , testCase3 , testCase4 , testCase5 , testCase6 , testCase7 } {
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-07-03 11:33:02 +02:00
initAccount , err := manager . GetAccountByUserOrAccountID ( context . Background ( ) , testCase . inputInitUserParams . UserId , testCase . inputInitUserParams . AccountId , testCase . inputInitUserParams . Domain )
2022-03-01 15:22:18 +01:00
require . NoError ( t , err , "create init user failed" )
if testCase . inputUpdateAttrs {
2024-07-03 11:33:02 +02:00
err = manager . updateAccountDomainAttributes ( context . Background ( ) , initAccount , 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-07-03 11:33:02 +02:00
account , _ , err := manager . GetAccountFromToken ( context . Background ( ) , testCase . inputClaims )
2022-03-01 15:22:18 +01:00
require . NoError ( t , err , "support function 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-07-03 11:33:02 +02:00
initAccount := 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" )
accountID := initAccount . Id
2024-07-03 11:33:02 +02:00
acc , err := manager . GetAccountByUserOrAccountID ( context . Background ( ) , userId , accountID , 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
// that happens inside the GetAccountByUserOrAccountID where the id is getting generated
// it is important to set the id as it help to avoid creating additional account with empty Id and re-pointing indices to it
2023-10-12 15:42:36 +02:00
initAccount = acc
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-07-03 11:33:02 +02:00
account , _ , err := manager . GetAccountFromToken ( context . Background ( ) , claims )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "get account by token failed" )
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-07-03 11:33:02 +02:00
account , _ , err := manager . GetAccountFromToken ( context . Background ( ) , claims )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "get account by token failed" )
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-07-03 11:33:02 +02:00
account , _ , err := manager . GetAccountFromToken ( context . Background ( ) , claims )
2023-06-27 16:51:05 +02:00
require . NoError ( t , err , "get account by token failed" )
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 ) {
store := newStore ( t )
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 [ : ] )
2023-03-16 15:57:44 +01:00
account . Users [ "someUser" ] = & User {
2023-03-21 13:34:48 +01:00
Id : "someUser" ,
2023-03-20 16:14:55 +01:00
PATs : map [ string ] * 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-07-03 11:33:02 +02: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 ) {
store := newStore ( t )
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 [ : ] )
account . Users [ "someUser" ] = & User {
Id : "someUser" ,
PATs : map [ string ] * PersonalAccessToken {
"tokenId" : {
ID : "tokenId" ,
HashedToken : encodedHashedToken ,
LastUsed : time . Time { } ,
} ,
} ,
}
2024-07-03 11:33:02 +02: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 )
}
}
2022-01-24 11:21:30 +01:00
func TestAccountManager_GetAccountByUserOrAccountId ( 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 . GetAccountByUserOrAccountID ( context . Background ( ) , userId , "" , "" )
2022-01-24 11:21:30 +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
return
2022-01-24 11:21:30 +01:00
}
2024-07-03 11:33:02 +02:00
_ , err = manager . GetAccountByUserOrAccountID ( context . Background ( ) , "" , account . Id , "" )
2022-01-24 11:21:30 +01:00
if err != nil {
2024-03-27 18:48:48 +01:00
t . Errorf ( "expected to get existing account after creation using userid, no account was found for a account %s" , account . Id )
2022-01-24 11:21:30 +01:00
}
2024-07-03 11:33:02 +02:00
_ , err = manager . GetAccountByUserOrAccountID ( context . Background ( ) , "" , "" , "" )
2022-01-24 11:21:30 +01:00
if err == nil {
t . Errorf ( "expected an error when user and account IDs are empty" )
}
}
2022-06-09 13:14:34 +02:00
func createAccount ( am * DefaultAccountManager , accountID , userID , domain string ) ( * 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 ) )
}
}
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-07-03 11:33:02 +02:00
setupKey , err := manager . CreateSetupKey ( context . Background ( ) , account . Id , "test-key" , 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 ( )
2022-05-05 20:02:15 +02:00
expectedSetupKey := setupKey . Key
2021-08-20 15:44:18 +02:00
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 peer . SetupKey != expectedSetupKey {
t . Errorf ( "expecting just added peer to have SetupKey = %s, got %s" , expectedSetupKey , peer . SetupKey )
}
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
2022-06-04 22:02:22 +02:00
func TestAccountManager_NetworkUpdates ( t * testing . T ) {
manager , err := createManager ( t )
if err != nil {
t . Fatal ( err )
return
}
2023-01-02 15:11:32 +01:00
userID := "account_creator"
account , err := createAccount ( manager , "test_account" , userID , "" )
2022-06-04 22:02:22 +02:00
if err != nil {
t . Fatal ( err )
}
2024-07-03 11:33:02 +02:00
setupKey , err := manager . CreateSetupKey ( context . Background ( ) , account . Id , "test-key" , SetupKeyReusable , time . Hour , nil , 999 , userID , false )
2023-06-27 17:17:24 +02:00
if err != nil {
t . Fatal ( "error creating setup key" )
2022-06-04 22:02:22 +02:00
return
}
if account . Network . Serial != 0 {
t . Errorf ( "expecting account network to have an initial Serial=0" )
return
}
2023-11-28 13:45:26 +01:00
getPeer := func ( ) * nbpeer . Peer {
2022-06-04 22:02:22 +02:00
key , err := wgtypes . GeneratePrivateKey ( )
if err != nil {
t . Fatal ( err )
return nil
}
expectedPeerKey := key . PublicKey ( ) . String ( )
2024-07-03 11:33:02 +02:00
peer , _ , _ , err := manager . AddPeer ( context . Background ( ) , setupKey . Key , "" , & nbpeer . Peer {
2022-06-04 22:02:22 +02:00
Key : expectedPeerKey ,
2023-11-28 13:45:26 +01:00
Meta : nbpeer . PeerSystemMeta { Hostname : expectedPeerKey } ,
2022-06-04 22:02:22 +02:00
} )
if err != nil {
t . Fatalf ( "expecting peer1 to be added, got failure %v" , err )
return nil
}
return peer
}
peer1 := getPeer ( )
peer2 := getPeer ( )
peer3 := getPeer ( )
2024-07-03 11:33:02 +02:00
account , err = manager . Store . GetAccount ( context . Background ( ) , account . Id )
2022-06-04 22:02:22 +02:00
if err != nil {
t . Fatal ( err )
return
}
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-03-27 18:48:48 +01:00
group := group . Group {
2022-06-04 22:02:22 +02:00
ID : "group-id" ,
Name : "GroupA" ,
2023-02-03 10:33:28 +01:00
Peers : [ ] string { peer1 . ID , peer2 . ID , peer3 . ID } ,
2022-06-04 22:02:22 +02:00
}
2023-03-13 15:14:18 +01:00
policy := Policy {
Enabled : true ,
Rules : [ ] * PolicyRule {
{
2023-05-29 16:00:18 +02:00
Enabled : true ,
Sources : [ ] string { "group-id" } ,
Destinations : [ ] string { "group-id" } ,
Bidirectional : true ,
Action : PolicyTrafficActionAccept ,
2023-03-13 15:14:18 +01:00
} ,
} ,
}
2022-06-04 22:02:22 +02:00
wg := sync . WaitGroup { }
t . Run ( "save group update" , func ( t * testing . T ) {
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 ) )
}
} ( )
2024-07-03 11:33:02 +02:00
if err := manager . SaveGroup ( context . Background ( ) , account . Id , userID , & group ) ; err != nil {
2022-06-04 22:02:22 +02:00
t . Errorf ( "save group: %v" , err )
return
}
wg . Wait ( )
} )
2023-03-13 15:14:18 +01:00
t . Run ( "delete policy update" , func ( t * testing . T ) {
2022-06-04 22:02:22 +02:00
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 ) )
}
} ( )
2024-07-03 11:33:02 +02:00
if err := manager . DeletePolicy ( context . Background ( ) , account . Id , account . Policies [ 0 ] . ID , userID ) ; err != nil {
2022-06-04 22:02:22 +02:00
t . Errorf ( "delete default rule: %v" , err )
return
}
wg . Wait ( )
} )
2023-03-13 15:14:18 +01:00
t . Run ( "save policy update" , func ( t * testing . T ) {
2022-06-04 22:02:22 +02:00
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 ) )
}
} ( )
2024-07-03 11:33:02 +02:00
if err := manager . SavePolicy ( context . Background ( ) , account . Id , userID , & policy ) ; err != nil {
2022-06-04 22:02:22 +02:00
t . Errorf ( "delete default rule: %v" , err )
return
}
wg . Wait ( )
} )
t . Run ( "delete peer update" , func ( t * testing . T ) {
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 ) )
}
} ( )
2024-07-03 11:33:02 +02:00
if err := manager . DeletePeer ( context . Background ( ) , account . Id , peer3 . ID , userID ) ; err != nil {
2022-06-04 22:02:22 +02:00
t . Errorf ( "delete peer: %v" , err )
return
}
wg . Wait ( )
} )
t . Run ( "delete group update" , func ( t * testing . T ) {
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 ) )
}
} ( )
2023-07-14 20:45:40 +02:00
// clean policy is pre requirement for delete group
2024-07-03 11:33:02 +02:00
_ = manager . DeletePolicy ( context . Background ( ) , account . Id , policy . ID , userID )
2023-07-14 20:45:40 +02:00
2024-07-03 11:33:02 +02:00
if err := manager . DeleteGroup ( context . Background ( ) , account . Id , "" , group . ID ) ; err != nil {
2023-03-13 15:14:18 +01:00
t . Errorf ( "delete group: %v" , err )
2022-06-04 22:02:22 +02:00
return
}
wg . Wait ( )
} )
}
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-07-03 11:33:02 +02:00
setupKey , err := manager . CreateSetupKey ( context . Background ( ) , account . Id , "test-key" , 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 )
}
2023-12-01 17:24:57 +01:00
users := map [ string ] * User { "1" : { Id : "1" , Role : 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 )
}
account := & 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 )
}
2022-11-07 12:10:56 +01:00
account := & 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-07-03 11:33:02 +02: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-07-03 11:33:02 +02: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 ) {
account := & Account {
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 ,
SetupKeys : map [ string ] * SetupKey {
"setup1" : {
Id : "setup1" ,
AutoGroups : [ ] string { "group1" } ,
} ,
} ,
Network : & 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
} ,
} ,
Users : map [ string ] * User {
"user1" : {
Id : "user1" ,
Role : UserRoleAdmin ,
AutoGroups : [ ] string { "group1" } ,
2023-03-20 16:14:55 +01:00
PATs : map [ string ] * PersonalAccessToken {
"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
} ,
} ,
2023-03-13 15:14:18 +01:00
Policies : [ ] * Policy {
{
2024-02-20 09:59:56 +01:00
ID : "policy1" ,
Enabled : true ,
Rules : make ( [ ] * PolicyRule , 0 ) ,
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" : {
2023-09-28 14:32:36 +02:00
ID : "route1" ,
PeerGroups : [ ] string { } ,
Groups : [ ] string { "group1" } ,
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
} ,
} ,
2023-10-11 23:00:56 +02:00
DNSSettings : DNSSettings { DisabledManagementGroups : [ ] string { } } ,
2024-02-20 09:59:56 +01:00
PostureChecks : [ ] * posture . Checks {
{
ID : "posture Checks1" ,
} ,
} ,
Settings : & Settings { } ,
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-07-03 11:33:02 +02:00
account , err := manager . GetAccountByUserOrAccountID ( context . Background ( ) , userID , "" , "" )
2023-02-16 12:00:41 +01:00
require . NoError ( t , err , "unable to create an account" )
assert . NotNil ( t , account . Settings )
assert . Equal ( t , account . Settings . PeerLoginExpirationEnabled , true )
assert . Equal ( t , account . Settings . PeerLoginExpiration , 24 * time . Hour )
}
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-07-03 11:33:02 +02:00
_ , err = manager . GetAccountByUserOrAccountID ( 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-07-03 11:33:02 +02:00
account , err := manager . GetAccountByUserOrAccountID ( context . Background ( ) , userID , "" , "" )
2024-05-07 14:30:03 +02:00
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" )
2024-07-03 11:33:02 +02:00
account , err = manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & 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-07-03 11:33:02 +02:00
account , err := manager . GetAccountByUserOrAccountID ( 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-07-03 11:33:02 +02:00
_ , err = manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & 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-07-03 11:33:02 +02:00
account , err = manager . GetAccountByUserOrAccountID ( context . Background ( ) , userID , "" , "" )
2024-05-07 14:30:03 +02:00
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-07-03 11:33:02 +02:00
_ , err = manager . GetAccountByUserOrAccountID ( 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-07-03 11:33:02 +02:00
account , err := manager . GetAccountByUserOrAccountID ( context . Background ( ) , userID , "" , "" )
2024-05-07 14:30:03 +02:00
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-07-03 11:33:02 +02:00
account , err = manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & 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-07-03 11:33:02 +02:00
_ , err = manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & 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-07-03 11:33:02 +02:00
account , err := manager . GetAccountByUserOrAccountID ( context . Background ( ) , userID , "" , "" )
2023-02-16 12:00:41 +01:00
require . NoError ( t , err , "unable to create an account" )
2024-07-03 11:33:02 +02:00
updated , err := manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & 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-07-03 11:33:02 +02:00
account , err = manager . GetAccountByUserOrAccountID ( context . Background ( ) , "" , account . Id , "" )
2023-02-16 12:00:41 +01:00
require . NoError ( t , err , "unable to get account by ID" )
assert . False ( t , account . Settings . PeerLoginExpirationEnabled )
assert . Equal ( t , account . Settings . PeerLoginExpiration , time . Hour )
2024-07-03 11:33:02 +02:00
_ , err = manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & 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-07-03 11:33:02 +02:00
_ , err = manager . UpdateAccountSettings ( context . Background ( ) , account . Id , userID , & 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 ) {
account := & Account {
Peers : testCase . peers ,
Settings : & Settings {
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 )
}
}
} )
}
}
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 ) {
account := & Account {
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 )
}
}
} )
}
}
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 ,
SetupKey : "key" ,
} ,
"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 ,
SetupKey : "key" ,
} ,
} ,
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 ) {
account := & Account {
Peers : testCase . peers ,
Settings : & Settings { PeerLoginExpiration : testCase . expiration , PeerLoginExpirationEnabled : testCase . expirationEnabled } ,
}
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 )
}
} )
}
}
2023-08-18 15:36:05 +02:00
func TestAccount_SetJWTGroups ( t * testing . T ) {
2023-08-07 17:44:51 +02:00
// create a new account
account := & 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 { } } ,
2023-08-07 17:44:51 +02:00
} ,
Settings : & Settings { GroupsPropagationEnabled : true } ,
Users : map [ string ] * User {
"user1" : { Id : "user1" } ,
"user2" : { Id : "user2" } ,
} ,
}
2024-06-13 08:55:09 +02:00
t . Run ( "empty jwt groups" , func ( t * testing . T ) {
updated := account . SetJWTGroups ( "user1" , [ ] string { } )
2023-08-07 17:44:51 +02:00
assert . False ( t , updated , "account should not be updated" )
assert . Empty ( t , account . Users [ "user1" ] . AutoGroups , "auto groups must be empty" )
} )
2024-06-13 08:55:09 +02:00
t . Run ( "jwt match existing api group" , func ( t * testing . T ) {
updated := account . SetJWTGroups ( "user1" , [ ] string { "group1" } )
assert . False ( t , updated , "account should not be updated" )
assert . Equal ( t , 0 , len ( account . Users [ "user1" ] . AutoGroups ) )
assert . Equal ( t , account . Groups [ "group1" ] . Issued , group . GroupIssuedAPI , "group should be api issued" )
} )
t . Run ( "jwt match existing api group in user auto groups" , func ( t * testing . T ) {
account . Users [ "user1" ] . AutoGroups = [ ] string { "group1" }
updated := account . SetJWTGroups ( "user1" , [ ] string { "group1" } )
assert . False ( t , updated , "account should not be updated" )
assert . Equal ( t , 1 , len ( account . Users [ "user1" ] . AutoGroups ) )
assert . Equal ( t , account . Groups [ "group1" ] . Issued , group . GroupIssuedAPI , "group should be api issued" )
} )
2023-08-07 17:44:51 +02:00
t . Run ( "add jwt group" , func ( t * testing . T ) {
2023-08-18 15:36:05 +02:00
updated := account . SetJWTGroups ( "user1" , [ ] string { "group1" , "group2" } )
2023-08-07 17:44:51 +02:00
assert . True ( t , updated , "account should be updated" )
assert . Len ( t , account . Groups , 2 , "new group should be added" )
2024-06-13 08:55:09 +02:00
assert . Len ( t , account . Users [ "user1" ] . AutoGroups , 2 , "new group should be added" )
2023-08-07 17:44:51 +02:00
assert . Contains ( t , account . Groups , account . Users [ "user1" ] . AutoGroups [ 0 ] , "groups must contain group2 from user groups" )
} )
t . Run ( "existed group not update" , func ( t * testing . T ) {
2023-08-18 15:36:05 +02:00
updated := account . SetJWTGroups ( "user1" , [ ] string { "group2" } )
2023-08-07 17:44:51 +02:00
assert . False ( t , updated , "account should not be updated" )
assert . Len ( t , account . Groups , 2 , "groups count should not be changed" )
} )
t . Run ( "add new group" , func ( t * testing . T ) {
2023-08-18 15:36:05 +02:00
updated := account . SetJWTGroups ( "user2" , [ ] string { "group1" , "group3" } )
2023-08-07 17:44:51 +02:00
assert . True ( t , updated , "account should be updated" )
assert . Len ( t , account . Groups , 3 , "new group should be added" )
assert . Len ( t , account . Users [ "user2" ] . AutoGroups , 1 , "new group should be added" )
assert . Contains ( t , account . Groups , account . Users [ "user2" ] . AutoGroups [ 0 ] , "groups must contain group3 from user groups" )
} )
2024-07-26 16:33:54 +02:00
t . Run ( "remove all JWT groups" , func ( t * testing . T ) {
updated := account . SetJWTGroups ( "user1" , [ ] string { } )
assert . True ( t , updated , "account should be updated" )
assert . Len ( t , account . Users [ "user1" ] . AutoGroups , 1 , "only non-JWT groups should remain" )
assert . Contains ( t , account . Users [ "user1" ] . AutoGroups , "group1" , " group1 should still be present" )
} )
2023-08-07 17:44:51 +02:00
}
func TestAccount_UserGroupsAddToPeers ( t * testing . T ) {
account := & 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
} ,
Users : map [ string ] * User { "user1" : { Id : "user1" } , "user2" : { Id : "user2" } } ,
}
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 ) {
account := & 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
} ,
Users : map [ string ] * User { "user1" : { Id : "user1" } , "user2" : { Id : "user2" } } ,
}
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-08-07 10:52:31 +02:00
func createStore ( t TB ) ( Store , error ) {
2023-11-10 16:33:13 +01:00
t . Helper ( )
2021-08-20 15:18:29 +02:00
dataDir := t . TempDir ( )
2024-07-03 11:33:02 +02:00
store , cleanUp , err := NewTestStoreFromJson ( 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
}
}