package server import ( "context" "crypto/hmac" "crypto/sha1" "encoding/base64" "testing" "time" "github.com/netbirdio/netbird/util" ) var TurnTestHost = &Host{ Proto: UDP, URI: "turn:turn.wiretrustee.com:77777", Username: "username", Password: "", } func TestTimeBasedAuthSecretsManager_GenerateCredentials(t *testing.T) { ttl := util.Duration{Duration: time.Hour} secret := "some_secret" peersManager := NewPeersUpdateManager(nil) tested := NewTimeBasedAuthSecretsManager(peersManager, &TURNConfig{ CredentialsTTL: ttl, Secret: secret, Turns: []*Host{TurnTestHost}, }) credentials := tested.GenerateCredentials() if credentials.Username == "" { t.Errorf("expected generated TURN username not to be empty, got empty") } if credentials.Password == "" { t.Errorf("expected generated TURN password not to be empty, got empty") } validateMAC(t, credentials.Username, credentials.Password, []byte(secret)) } func TestTimeBasedAuthSecretsManager_SetupRefresh(t *testing.T) { ttl := util.Duration{Duration: 2 * time.Second} secret := "some_secret" peersManager := NewPeersUpdateManager(nil) peer := "some_peer" updateChannel := peersManager.CreateChannel(context.Background(), peer) tested := NewTimeBasedAuthSecretsManager(peersManager, &TURNConfig{ CredentialsTTL: ttl, Secret: secret, Turns: []*Host{TurnTestHost}, }) tested.SetupRefresh(context.Background(), peer) if _, ok := tested.cancelMap[peer]; !ok { t.Errorf("expecting peer to be present in a cancel map, got not present") } var updates []*UpdateMessage loop: for timeout := time.After(5 * time.Second); ; { select { case update := <-updateChannel: updates = append(updates, update) case <-timeout: break loop } if len(updates) >= 2 { break loop } } if len(updates) < 2 { t.Errorf("expecting 2 peer credentials updates, got %v", len(updates)) } firstUpdate := updates[0].Update.GetWiretrusteeConfig().Turns[0] secondUpdate := updates[1].Update.GetWiretrusteeConfig().Turns[0] if firstUpdate.Password == secondUpdate.Password { t.Errorf("expecting first credential update password %v to be diffeerent from second, got equal", firstUpdate.Password) } } func TestTimeBasedAuthSecretsManager_CancelRefresh(t *testing.T) { ttl := util.Duration{Duration: time.Hour} secret := "some_secret" peersManager := NewPeersUpdateManager(nil) peer := "some_peer" tested := NewTimeBasedAuthSecretsManager(peersManager, &TURNConfig{ CredentialsTTL: ttl, Secret: secret, Turns: []*Host{TurnTestHost}, }) tested.SetupRefresh(context.Background(), peer) if _, ok := tested.cancelMap[peer]; !ok { t.Errorf("expecting peer to be present in a cancel map, got not present") } tested.CancelRefresh(peer) if _, ok := tested.cancelMap[peer]; ok { t.Errorf("expecting peer to be not present in a cancel map, got present") } } func validateMAC(t *testing.T, username string, actualMAC string, key []byte) { t.Helper() mac := hmac.New(sha1.New, key) _, err := mac.Write([]byte(username)) if err != nil { t.Fatal(err) } expectedMAC := mac.Sum(nil) decodedMAC, err := base64.StdEncoding.DecodeString(actualMAC) if err != nil { t.Fatal(err) } equal := hmac.Equal(decodedMAC, expectedMAC) if !equal { t.Errorf("expected password MAC to be %s. got %s", expectedMAC, decodedMAC) } }