mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-12 00:19:08 +02:00
Merge branch 'netbirdio:main' into main
This commit is contained in:
@@ -2989,18 +2989,21 @@ func peerShouldReceiveUpdate(t *testing.T, updateMessage <-chan *UpdateMessage)
|
||||
|
||||
func BenchmarkSyncAndMarkPeer(b *testing.B) {
|
||||
benchCases := []struct {
|
||||
name string
|
||||
peers int
|
||||
groups int
|
||||
minMsPerOp float64
|
||||
maxMsPerOp float64
|
||||
name string
|
||||
peers int
|
||||
groups int
|
||||
// We need different expectations for CI/CD and local runs because of the different performance characteristics
|
||||
minMsPerOpLocal float64
|
||||
maxMsPerOpLocal float64
|
||||
minMsPerOpCICD float64
|
||||
maxMsPerOpCICD float64
|
||||
}{
|
||||
{"Small", 50, 5, 1, 3},
|
||||
{"Medium", 500, 100, 7, 13},
|
||||
{"Large", 5000, 200, 65, 80},
|
||||
{"Small single", 50, 10, 1, 3},
|
||||
{"Medium single", 500, 10, 7, 13},
|
||||
{"Large 5", 5000, 15, 65, 80},
|
||||
{"Small", 50, 5, 1, 3, 4, 10},
|
||||
{"Medium", 500, 100, 7, 13, 10, 60},
|
||||
{"Large", 5000, 200, 65, 80, 60, 170},
|
||||
{"Small single", 50, 10, 1, 3, 4, 60},
|
||||
{"Medium single", 500, 10, 7, 13, 10, 26},
|
||||
{"Large 5", 5000, 15, 65, 80, 60, 170},
|
||||
}
|
||||
|
||||
log.SetOutput(io.Discard)
|
||||
@@ -3033,12 +3036,19 @@ func BenchmarkSyncAndMarkPeer(b *testing.B) {
|
||||
msPerOp := float64(duration.Nanoseconds()) / float64(b.N) / 1e6
|
||||
b.ReportMetric(msPerOp, "ms/op")
|
||||
|
||||
if msPerOp < bc.minMsPerOp {
|
||||
b.Fatalf("Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)", bc.name, msPerOp, bc.minMsPerOp)
|
||||
minExpected := bc.minMsPerOpLocal
|
||||
maxExpected := bc.maxMsPerOpLocal
|
||||
if os.Getenv("CI") == "true" {
|
||||
minExpected = bc.minMsPerOpCICD
|
||||
maxExpected = bc.maxMsPerOpCICD
|
||||
}
|
||||
|
||||
if msPerOp > bc.maxMsPerOp {
|
||||
b.Fatalf("Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)", bc.name, msPerOp, bc.maxMsPerOp)
|
||||
if msPerOp < minExpected {
|
||||
b.Fatalf("Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)", bc.name, msPerOp, minExpected)
|
||||
}
|
||||
|
||||
if msPerOp > maxExpected {
|
||||
b.Fatalf("Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)", bc.name, msPerOp, maxExpected)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -3046,18 +3056,21 @@ func BenchmarkSyncAndMarkPeer(b *testing.B) {
|
||||
|
||||
func BenchmarkLoginPeer_ExistingPeer(b *testing.B) {
|
||||
benchCases := []struct {
|
||||
name string
|
||||
peers int
|
||||
groups int
|
||||
minMsPerOp float64
|
||||
maxMsPerOp float64
|
||||
name string
|
||||
peers int
|
||||
groups int
|
||||
// We need different expectations for CI/CD and local runs because of the different performance characteristics
|
||||
minMsPerOpLocal float64
|
||||
maxMsPerOpLocal float64
|
||||
minMsPerOpCICD float64
|
||||
maxMsPerOpCICD float64
|
||||
}{
|
||||
{"Small", 50, 5, 102, 110},
|
||||
{"Medium", 500, 100, 105, 140},
|
||||
{"Large", 5000, 200, 160, 200},
|
||||
{"Small single", 50, 10, 102, 110},
|
||||
{"Medium single", 500, 10, 105, 140},
|
||||
{"Large 5", 5000, 15, 160, 200},
|
||||
{"Small", 50, 5, 102, 110, 102, 120},
|
||||
{"Medium", 500, 100, 105, 140, 105, 170},
|
||||
{"Large", 5000, 200, 160, 200, 160, 270},
|
||||
{"Small single", 50, 10, 102, 110, 102, 120},
|
||||
{"Medium single", 500, 10, 105, 140, 105, 170},
|
||||
{"Large 5", 5000, 15, 160, 200, 160, 270},
|
||||
}
|
||||
|
||||
log.SetOutput(io.Discard)
|
||||
@@ -3097,12 +3110,19 @@ func BenchmarkLoginPeer_ExistingPeer(b *testing.B) {
|
||||
msPerOp := float64(duration.Nanoseconds()) / float64(b.N) / 1e6
|
||||
b.ReportMetric(msPerOp, "ms/op")
|
||||
|
||||
if msPerOp < bc.minMsPerOp {
|
||||
b.Fatalf("Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)", bc.name, msPerOp, bc.minMsPerOp)
|
||||
minExpected := bc.minMsPerOpLocal
|
||||
maxExpected := bc.maxMsPerOpLocal
|
||||
if os.Getenv("CI") == "true" {
|
||||
minExpected = bc.minMsPerOpCICD
|
||||
maxExpected = bc.maxMsPerOpCICD
|
||||
}
|
||||
|
||||
if msPerOp > bc.maxMsPerOp {
|
||||
b.Fatalf("Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)", bc.name, msPerOp, bc.maxMsPerOp)
|
||||
if msPerOp < minExpected {
|
||||
b.Fatalf("Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)", bc.name, msPerOp, minExpected)
|
||||
}
|
||||
|
||||
if msPerOp > maxExpected {
|
||||
b.Fatalf("Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)", bc.name, msPerOp, maxExpected)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -3110,18 +3130,21 @@ func BenchmarkLoginPeer_ExistingPeer(b *testing.B) {
|
||||
|
||||
func BenchmarkLoginPeer_NewPeer(b *testing.B) {
|
||||
benchCases := []struct {
|
||||
name string
|
||||
peers int
|
||||
groups int
|
||||
minMsPerOp float64
|
||||
maxMsPerOp float64
|
||||
name string
|
||||
peers int
|
||||
groups int
|
||||
// We need different expectations for CI/CD and local runs because of the different performance characteristics
|
||||
minMsPerOpLocal float64
|
||||
maxMsPerOpLocal float64
|
||||
minMsPerOpCICD float64
|
||||
maxMsPerOpCICD float64
|
||||
}{
|
||||
{"Small", 50, 5, 107, 120},
|
||||
{"Medium", 500, 100, 105, 140},
|
||||
{"Large", 5000, 200, 180, 220},
|
||||
{"Small single", 50, 10, 107, 120},
|
||||
{"Medium single", 500, 10, 105, 140},
|
||||
{"Large 5", 5000, 15, 180, 220},
|
||||
{"Small", 50, 5, 107, 120, 107, 140},
|
||||
{"Medium", 500, 100, 105, 140, 105, 170},
|
||||
{"Large", 5000, 200, 180, 220, 180, 320},
|
||||
{"Small single", 50, 10, 107, 120, 105, 140},
|
||||
{"Medium single", 500, 10, 105, 140, 105, 170},
|
||||
{"Large 5", 5000, 15, 180, 220, 180, 320},
|
||||
}
|
||||
|
||||
log.SetOutput(io.Discard)
|
||||
@@ -3161,12 +3184,19 @@ func BenchmarkLoginPeer_NewPeer(b *testing.B) {
|
||||
msPerOp := float64(duration.Nanoseconds()) / float64(b.N) / 1e6
|
||||
b.ReportMetric(msPerOp, "ms/op")
|
||||
|
||||
if msPerOp < bc.minMsPerOp {
|
||||
b.Fatalf("Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)", bc.name, msPerOp, bc.minMsPerOp)
|
||||
minExpected := bc.minMsPerOpLocal
|
||||
maxExpected := bc.maxMsPerOpLocal
|
||||
if os.Getenv("CI") == "true" {
|
||||
minExpected = bc.minMsPerOpCICD
|
||||
maxExpected = bc.maxMsPerOpCICD
|
||||
}
|
||||
|
||||
if msPerOp > bc.maxMsPerOp {
|
||||
b.Fatalf("Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)", bc.name, msPerOp, bc.maxMsPerOp)
|
||||
if msPerOp < minExpected {
|
||||
b.Fatalf("Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)", bc.name, msPerOp, minExpected)
|
||||
}
|
||||
|
||||
if msPerOp > maxExpected {
|
||||
b.Fatalf("Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)", bc.name, msPerOp, maxExpected)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@ type JWTValidator struct {
|
||||
options Options
|
||||
}
|
||||
|
||||
var keyNotFound = errors.New("unable to find appropriate key")
|
||||
|
||||
// NewJWTValidator constructor
|
||||
func NewJWTValidator(ctx context.Context, issuer string, audienceList []string, keysLocation string, idpSignkeyRefreshEnabled bool) (*JWTValidator, error) {
|
||||
keys, err := getPemKeys(ctx, keysLocation)
|
||||
@@ -124,12 +126,18 @@ func NewJWTValidator(ctx context.Context, issuer string, audienceList []string,
|
||||
}
|
||||
|
||||
publicKey, err := getPublicKey(ctx, token, keys)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Errorf("getPublicKey error: %s", err)
|
||||
return nil, err
|
||||
if err == nil {
|
||||
return publicKey, nil
|
||||
}
|
||||
|
||||
return publicKey, nil
|
||||
msg := fmt.Sprintf("getPublicKey error: %s", err)
|
||||
if errors.Is(err, keyNotFound) && !idpSignkeyRefreshEnabled {
|
||||
msg = fmt.Sprintf("getPublicKey error: %s. You can enable key refresh by setting HttpServerConfig.IdpSignKeyRefreshEnabled to true in your management.json file and restart the service", err)
|
||||
}
|
||||
|
||||
log.WithContext(ctx).Error(msg)
|
||||
|
||||
return nil, err
|
||||
},
|
||||
EnableAuthOnOptions: false,
|
||||
}
|
||||
@@ -229,7 +237,7 @@ func getPublicKey(ctx context.Context, token *jwt.Token, jwks *Jwks) (interface{
|
||||
log.WithContext(ctx).Debugf("Key Type: %s not yet supported, please raise ticket!", jwks.Keys[k].Kty)
|
||||
}
|
||||
|
||||
return nil, errors.New("unable to find appropriate key")
|
||||
return nil, keyNotFound
|
||||
}
|
||||
|
||||
func getPublicKeyFromECDSA(jwk JSONWebKey) (publicKey *ecdsa.PublicKey, err error) {
|
||||
@@ -310,4 +318,3 @@ func getMaxAgeFromCacheHeader(ctx context.Context, cacheControl string) int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
+10
-16
@@ -477,7 +477,7 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, setupKey, userID s
|
||||
setupKeyName = sk.Name
|
||||
}
|
||||
|
||||
if strings.ToLower(peer.Meta.Hostname) == "iphone" || strings.ToLower(peer.Meta.Hostname) == "ipad" && userID != "" {
|
||||
if (strings.ToLower(peer.Meta.Hostname) == "iphone" || strings.ToLower(peer.Meta.Hostname) == "ipad") && userID != "" {
|
||||
if am.idpManager != nil {
|
||||
userdata, err := am.idpManager.GetUserDataByID(ctx, userID, idp.AppMetadata{WTAccountID: accountID})
|
||||
if err == nil && userdata != nil {
|
||||
@@ -678,10 +678,6 @@ func (am *DefaultAccountManager) SyncPeer(ctx context.Context, sync PeerSync, ac
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("failed to save peer: %w", err)
|
||||
}
|
||||
|
||||
if sync.UpdateAccountPeers {
|
||||
am.updateAccountPeers(ctx, account.Id)
|
||||
}
|
||||
}
|
||||
|
||||
peerNotValid, isStatusChanged, err := am.integratedPeerValidator.IsNotValidPeer(ctx, account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra)
|
||||
@@ -689,17 +685,20 @@ func (am *DefaultAccountManager) SyncPeer(ctx context.Context, sync PeerSync, ac
|
||||
return nil, nil, nil, fmt.Errorf("failed to validate peer: %w", err)
|
||||
}
|
||||
|
||||
var postureChecks []*posture.Checks
|
||||
postureChecks, err := am.getPeerPostureChecks(account, peer.ID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
if isStatusChanged || sync.UpdateAccountPeers || (updated && len(postureChecks) > 0) {
|
||||
am.updateAccountPeers(ctx, account.Id)
|
||||
}
|
||||
|
||||
if peerNotValid {
|
||||
emptyMap := &NetworkMap{
|
||||
Network: account.Network.Copy(),
|
||||
}
|
||||
return peer, emptyMap, postureChecks, nil
|
||||
}
|
||||
|
||||
if isStatusChanged {
|
||||
am.updateAccountPeers(ctx, account.Id)
|
||||
return peer, emptyMap, []*posture.Checks{}, nil
|
||||
}
|
||||
|
||||
validPeersMap, err := am.GetValidatedPeers(account)
|
||||
@@ -707,11 +706,6 @@ func (am *DefaultAccountManager) SyncPeer(ctx context.Context, sync PeerSync, ac
|
||||
return nil, nil, nil, fmt.Errorf("failed to get validated peers: %w", err)
|
||||
}
|
||||
|
||||
postureChecks, err = am.getPeerPostureChecks(account, peer.ID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
customZone := account.GetPeersCustomZone(ctx, am.dnsDomain)
|
||||
return peer, account.GetPeerNetworkMap(ctx, peer.ID, customZone, validPeersMap, am.metrics.AccountManagerMetrics()), postureChecks, nil
|
||||
}
|
||||
|
||||
@@ -835,18 +835,21 @@ func BenchmarkGetPeers(b *testing.B) {
|
||||
}
|
||||
func BenchmarkUpdateAccountPeers(b *testing.B) {
|
||||
benchCases := []struct {
|
||||
name string
|
||||
peers int
|
||||
groups int
|
||||
minMsPerOp float64
|
||||
maxMsPerOp float64
|
||||
name string
|
||||
peers int
|
||||
groups int
|
||||
// We need different expectations for CI/CD and local runs because of the different performance characteristics
|
||||
minMsPerOpLocal float64
|
||||
maxMsPerOpLocal float64
|
||||
minMsPerOpCICD float64
|
||||
maxMsPerOpCICD float64
|
||||
}{
|
||||
{"Small", 50, 5, 90, 120},
|
||||
{"Medium", 500, 100, 110, 140},
|
||||
{"Large", 5000, 200, 800, 1300},
|
||||
{"Small single", 50, 10, 90, 120},
|
||||
{"Medium single", 500, 10, 110, 170},
|
||||
{"Large 5", 5000, 15, 1300, 1800},
|
||||
{"Small", 50, 5, 90, 120, 90, 120},
|
||||
{"Medium", 500, 100, 110, 140, 120, 200},
|
||||
{"Large", 5000, 200, 800, 1300, 2500, 3600},
|
||||
{"Small single", 50, 10, 90, 120, 90, 120},
|
||||
{"Medium single", 500, 10, 110, 170, 120, 200},
|
||||
{"Large 5", 5000, 15, 1300, 1800, 5000, 6000},
|
||||
}
|
||||
|
||||
log.SetOutput(io.Discard)
|
||||
@@ -885,12 +888,19 @@ func BenchmarkUpdateAccountPeers(b *testing.B) {
|
||||
msPerOp := float64(duration.Nanoseconds()) / float64(b.N) / 1e6
|
||||
b.ReportMetric(msPerOp, "ms/op")
|
||||
|
||||
if msPerOp < bc.minMsPerOp {
|
||||
b.Fatalf("Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)", bc.name, msPerOp, bc.minMsPerOp)
|
||||
minExpected := bc.minMsPerOpLocal
|
||||
maxExpected := bc.maxMsPerOpLocal
|
||||
if os.Getenv("CI") == "true" {
|
||||
minExpected = bc.minMsPerOpCICD
|
||||
maxExpected = bc.maxMsPerOpCICD
|
||||
}
|
||||
|
||||
if msPerOp > bc.maxMsPerOp {
|
||||
b.Fatalf("Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)", bc.name, msPerOp, bc.maxMsPerOp)
|
||||
if msPerOp < minExpected {
|
||||
b.Fatalf("Benchmark %s failed: too fast (%.2f ms/op, minimum %.2f ms/op)", bc.name, msPerOp, minExpected)
|
||||
}
|
||||
|
||||
if msPerOp > maxExpected {
|
||||
b.Fatalf("Benchmark %s failed: too slow (%.2f ms/op, maximum %.2f ms/op)", bc.name, msPerOp, maxExpected)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+71
-14
@@ -417,27 +417,84 @@ func (a *Account) getPeerRoutesFirewallRules(ctx context.Context, peerID string,
|
||||
continue
|
||||
}
|
||||
|
||||
policies := getAllRoutePoliciesFromGroups(a, route.AccessControlGroups)
|
||||
for _, policy := range policies {
|
||||
if !policy.Enabled {
|
||||
continue
|
||||
}
|
||||
distributionPeers := a.getDistributionGroupsPeers(route)
|
||||
|
||||
for _, rule := range policy.Rules {
|
||||
if !rule.Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
distributionGroupPeers, _ := a.getAllPeersFromGroups(ctx, route.Groups, peerID, nil, validatedPeersMap)
|
||||
rules := generateRouteFirewallRules(ctx, route, rule, distributionGroupPeers, firewallRuleDirectionIN)
|
||||
routesFirewallRules = append(routesFirewallRules, rules...)
|
||||
}
|
||||
for _, accessGroup := range route.AccessControlGroups {
|
||||
policies := getAllRoutePoliciesFromGroups(a, []string{accessGroup})
|
||||
rules := a.getRouteFirewallRules(ctx, peerID, policies, route, validatedPeersMap, distributionPeers)
|
||||
routesFirewallRules = append(routesFirewallRules, rules...)
|
||||
}
|
||||
}
|
||||
|
||||
return routesFirewallRules
|
||||
}
|
||||
|
||||
func (a *Account) getRouteFirewallRules(ctx context.Context, peerID string, policies []*Policy, route *route.Route, validatedPeersMap map[string]struct{}, distributionPeers map[string]struct{}) []*RouteFirewallRule {
|
||||
var fwRules []*RouteFirewallRule
|
||||
for _, policy := range policies {
|
||||
if !policy.Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, rule := range policy.Rules {
|
||||
if !rule.Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
rulePeers := a.getRulePeers(rule, peerID, distributionPeers, validatedPeersMap)
|
||||
rules := generateRouteFirewallRules(ctx, route, rule, rulePeers, firewallRuleDirectionIN)
|
||||
fwRules = append(fwRules, rules...)
|
||||
}
|
||||
}
|
||||
return fwRules
|
||||
}
|
||||
|
||||
func (a *Account) getRulePeers(rule *PolicyRule, peerID string, distributionPeers map[string]struct{}, validatedPeersMap map[string]struct{}) []*nbpeer.Peer {
|
||||
distPeersWithPolicy := make(map[string]struct{})
|
||||
for _, id := range rule.Sources {
|
||||
group := a.Groups[id]
|
||||
if group == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, pID := range group.Peers {
|
||||
if pID == peerID {
|
||||
continue
|
||||
}
|
||||
_, distPeer := distributionPeers[pID]
|
||||
_, valid := validatedPeersMap[pID]
|
||||
if distPeer && valid {
|
||||
distPeersWithPolicy[pID] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
distributionGroupPeers := make([]*nbpeer.Peer, 0, len(distPeersWithPolicy))
|
||||
for pID := range distPeersWithPolicy {
|
||||
peer := a.Peers[pID]
|
||||
if peer == nil {
|
||||
continue
|
||||
}
|
||||
distributionGroupPeers = append(distributionGroupPeers, peer)
|
||||
}
|
||||
return distributionGroupPeers
|
||||
}
|
||||
|
||||
func (a *Account) getDistributionGroupsPeers(route *route.Route) map[string]struct{} {
|
||||
distPeers := make(map[string]struct{})
|
||||
for _, id := range route.Groups {
|
||||
group := a.Groups[id]
|
||||
if group == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, pID := range group.Peers {
|
||||
distPeers[pID] = struct{}{}
|
||||
}
|
||||
}
|
||||
return distPeers
|
||||
}
|
||||
|
||||
func getDefaultPermit(route *route.Route) []*RouteFirewallRule {
|
||||
var rules []*RouteFirewallRule
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -1486,6 +1487,8 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
peerBIp = "100.65.80.39"
|
||||
peerCIp = "100.65.254.139"
|
||||
peerHIp = "100.65.29.55"
|
||||
peerJIp = "100.65.29.65"
|
||||
peerKIp = "100.65.29.66"
|
||||
)
|
||||
|
||||
account := &Account{
|
||||
@@ -1541,6 +1544,16 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
IP: net.ParseIP(peerHIp),
|
||||
Status: &nbpeer.PeerStatus{},
|
||||
},
|
||||
"peerJ": {
|
||||
ID: "peerJ",
|
||||
IP: net.ParseIP(peerJIp),
|
||||
Status: &nbpeer.PeerStatus{},
|
||||
},
|
||||
"peerK": {
|
||||
ID: "peerK",
|
||||
IP: net.ParseIP(peerKIp),
|
||||
Status: &nbpeer.PeerStatus{},
|
||||
},
|
||||
},
|
||||
Groups: map[string]*nbgroup.Group{
|
||||
"routingPeer1": {
|
||||
@@ -1567,6 +1580,11 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
Name: "Route2",
|
||||
Peers: []string{},
|
||||
},
|
||||
"route4": {
|
||||
ID: "route4",
|
||||
Name: "route4",
|
||||
Peers: []string{},
|
||||
},
|
||||
"finance": {
|
||||
ID: "finance",
|
||||
Name: "Finance",
|
||||
@@ -1584,6 +1602,28 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
"peerB",
|
||||
},
|
||||
},
|
||||
"qa": {
|
||||
ID: "qa",
|
||||
Name: "QA",
|
||||
Peers: []string{
|
||||
"peerJ",
|
||||
"peerK",
|
||||
},
|
||||
},
|
||||
"restrictQA": {
|
||||
ID: "restrictQA",
|
||||
Name: "restrictQA",
|
||||
Peers: []string{
|
||||
"peerJ",
|
||||
},
|
||||
},
|
||||
"unrestrictedQA": {
|
||||
ID: "unrestrictedQA",
|
||||
Name: "unrestrictedQA",
|
||||
Peers: []string{
|
||||
"peerK",
|
||||
},
|
||||
},
|
||||
"contractors": {
|
||||
ID: "contractors",
|
||||
Name: "Contractors",
|
||||
@@ -1631,6 +1671,19 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
Groups: []string{"contractors"},
|
||||
AccessControlGroups: []string{},
|
||||
},
|
||||
"route4": {
|
||||
ID: "route4",
|
||||
Network: netip.MustParsePrefix("192.168.10.0/16"),
|
||||
NetID: "route4",
|
||||
NetworkType: route.IPv4Network,
|
||||
PeerGroups: []string{"routingPeer1"},
|
||||
Description: "Route4",
|
||||
Masquerade: false,
|
||||
Metric: 9999,
|
||||
Enabled: true,
|
||||
Groups: []string{"qa"},
|
||||
AccessControlGroups: []string{"route4"},
|
||||
},
|
||||
},
|
||||
Policies: []*Policy{
|
||||
{
|
||||
@@ -1685,6 +1738,49 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "RuleRoute4",
|
||||
Name: "RuleRoute4",
|
||||
Enabled: true,
|
||||
Rules: []*PolicyRule{
|
||||
{
|
||||
ID: "RuleRoute4",
|
||||
Name: "RuleRoute4",
|
||||
Bidirectional: true,
|
||||
Enabled: true,
|
||||
Protocol: PolicyRuleProtocolTCP,
|
||||
Action: PolicyTrafficActionAccept,
|
||||
Ports: []string{"80"},
|
||||
Sources: []string{
|
||||
"restrictQA",
|
||||
},
|
||||
Destinations: []string{
|
||||
"route4",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "RuleRoute5",
|
||||
Name: "RuleRoute5",
|
||||
Enabled: true,
|
||||
Rules: []*PolicyRule{
|
||||
{
|
||||
ID: "RuleRoute5",
|
||||
Name: "RuleRoute5",
|
||||
Bidirectional: true,
|
||||
Enabled: true,
|
||||
Protocol: PolicyRuleProtocolALL,
|
||||
Action: PolicyTrafficActionAccept,
|
||||
Sources: []string{
|
||||
"unrestrictedQA",
|
||||
},
|
||||
Destinations: []string{
|
||||
"route4",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1709,7 +1805,7 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
|
||||
t.Run("check peer routes firewall rules", func(t *testing.T) {
|
||||
routesFirewallRules := account.getPeerRoutesFirewallRules(context.Background(), "peerA", validatedPeers)
|
||||
assert.Len(t, routesFirewallRules, 2)
|
||||
assert.Len(t, routesFirewallRules, 4)
|
||||
|
||||
expectedRoutesFirewallRules := []*RouteFirewallRule{
|
||||
{
|
||||
@@ -1735,12 +1831,32 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
Port: 320,
|
||||
},
|
||||
}
|
||||
assert.ElementsMatch(t, routesFirewallRules, expectedRoutesFirewallRules)
|
||||
additionalFirewallRule := []*RouteFirewallRule{
|
||||
{
|
||||
SourceRanges: []string{
|
||||
fmt.Sprintf(AllowedIPsFormat, peerJIp),
|
||||
},
|
||||
Action: "accept",
|
||||
Destination: "192.168.10.0/16",
|
||||
Protocol: "tcp",
|
||||
Port: 80,
|
||||
},
|
||||
{
|
||||
SourceRanges: []string{
|
||||
fmt.Sprintf(AllowedIPsFormat, peerKIp),
|
||||
},
|
||||
Action: "accept",
|
||||
Destination: "192.168.10.0/16",
|
||||
Protocol: "all",
|
||||
},
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, orderRuleSourceRanges(routesFirewallRules), orderRuleSourceRanges(append(expectedRoutesFirewallRules, additionalFirewallRule...)))
|
||||
|
||||
// peerD is also the routing peer for route1, should contain same routes firewall rules as peerA
|
||||
routesFirewallRules = account.getPeerRoutesFirewallRules(context.Background(), "peerD", validatedPeers)
|
||||
assert.Len(t, routesFirewallRules, 2)
|
||||
assert.ElementsMatch(t, routesFirewallRules, expectedRoutesFirewallRules)
|
||||
assert.ElementsMatch(t, orderRuleSourceRanges(routesFirewallRules), orderRuleSourceRanges(expectedRoutesFirewallRules))
|
||||
|
||||
// peerE is a single routing peer for route 2 and route 3
|
||||
routesFirewallRules = account.getPeerRoutesFirewallRules(context.Background(), "peerE", validatedPeers)
|
||||
@@ -1769,7 +1885,7 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
IsDynamic: true,
|
||||
},
|
||||
}
|
||||
assert.ElementsMatch(t, routesFirewallRules, expectedRoutesFirewallRules)
|
||||
assert.ElementsMatch(t, orderRuleSourceRanges(routesFirewallRules), orderRuleSourceRanges(expectedRoutesFirewallRules))
|
||||
|
||||
// peerC is part of route1 distribution groups but should not receive the routes firewall rules
|
||||
routesFirewallRules = account.getPeerRoutesFirewallRules(context.Background(), "peerC", validatedPeers)
|
||||
@@ -1778,6 +1894,14 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// orderList is a helper function to sort a list of strings
|
||||
func orderRuleSourceRanges(ruleList []*RouteFirewallRule) []*RouteFirewallRule {
|
||||
for _, rule := range ruleList {
|
||||
sort.Strings(rule.SourceRanges)
|
||||
}
|
||||
return ruleList
|
||||
}
|
||||
|
||||
func TestRouteAccountPeersUpdate(t *testing.T) {
|
||||
manager, err := createRouterManager(t)
|
||||
require.NoError(t, err, "failed to create account manager")
|
||||
|
||||
Reference in New Issue
Block a user