mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-07 16:54:16 +01:00
9bc7b9e897
This PR implements the following posture checks: * Agent minimum version allowed * OS minimum version allowed * Geo-location based on connection IP For the geo-based location, we rely on GeoLite2 databases which are free IP geolocation databases. MaxMind was tested and we provide a script that easily allows to download of all necessary files, see infrastructure_files/download-geolite2.sh. The OpenAPI spec should extensively cover the life cycle of current version posture checks.
811 lines
21 KiB
Go
811 lines
21 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"golang.org/x/exp/slices"
|
|
|
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
"github.com/netbirdio/netbird/management/server/posture"
|
|
)
|
|
|
|
func TestAccount_getPeersByPolicy(t *testing.T) {
|
|
account := &Account{
|
|
Peers: map[string]*nbpeer.Peer{
|
|
"peerA": {
|
|
ID: "peerA",
|
|
IP: net.ParseIP("100.65.14.88"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerB": {
|
|
ID: "peerB",
|
|
IP: net.ParseIP("100.65.80.39"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerC": {
|
|
ID: "peerC",
|
|
IP: net.ParseIP("100.65.254.139"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerD": {
|
|
ID: "peerD",
|
|
IP: net.ParseIP("100.65.62.5"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerE": {
|
|
ID: "peerE",
|
|
IP: net.ParseIP("100.65.32.206"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerF": {
|
|
ID: "peerF",
|
|
IP: net.ParseIP("100.65.250.202"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerG": {
|
|
ID: "peerG",
|
|
IP: net.ParseIP("100.65.13.186"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerH": {
|
|
ID: "peerH",
|
|
IP: net.ParseIP("100.65.29.55"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
},
|
|
Groups: map[string]*Group{
|
|
"GroupAll": {
|
|
ID: "GroupAll",
|
|
Name: "All",
|
|
Peers: []string{
|
|
"peerB",
|
|
"peerA",
|
|
"peerD",
|
|
"peerC",
|
|
"peerE",
|
|
"peerF",
|
|
"peerG",
|
|
"peerH",
|
|
},
|
|
},
|
|
"GroupSwarm": {
|
|
ID: "GroupSwarm",
|
|
Name: "swarm",
|
|
Peers: []string{
|
|
"peerB",
|
|
"peerA",
|
|
"peerD",
|
|
"peerE",
|
|
"peerG",
|
|
"peerH",
|
|
},
|
|
},
|
|
},
|
|
Policies: []*Policy{
|
|
{
|
|
ID: "RuleDefault",
|
|
Name: "Default",
|
|
Description: "This is a default rule that allows connections between all the resources",
|
|
Enabled: true,
|
|
Rules: []*PolicyRule{
|
|
{
|
|
ID: "RuleDefault",
|
|
Name: "Default",
|
|
Description: "This is a default rule that allows connections between all the resources",
|
|
Bidirectional: true,
|
|
Enabled: true,
|
|
Protocol: PolicyRuleProtocolALL,
|
|
Action: PolicyTrafficActionAccept,
|
|
Sources: []string{
|
|
"GroupAll",
|
|
},
|
|
Destinations: []string{
|
|
"GroupAll",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "RuleSwarm",
|
|
Name: "Swarm",
|
|
Description: "No description",
|
|
Enabled: true,
|
|
Rules: []*PolicyRule{
|
|
{
|
|
ID: "RuleSwarm",
|
|
Name: "Swarm",
|
|
Description: "No description",
|
|
Bidirectional: true,
|
|
Enabled: true,
|
|
Protocol: PolicyRuleProtocolALL,
|
|
Action: PolicyTrafficActionAccept,
|
|
Sources: []string{
|
|
"GroupSwarm",
|
|
"GroupAll",
|
|
},
|
|
Destinations: []string{
|
|
"GroupSwarm",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
t.Run("check that all peers get map", func(t *testing.T) {
|
|
for _, p := range account.Peers {
|
|
peers, firewallRules := account.getPeerConnectionResources(p.ID)
|
|
assert.GreaterOrEqual(t, len(peers), 2, "minimum number peers should present")
|
|
assert.GreaterOrEqual(t, len(firewallRules), 2, "minimum number of firewall rules should present")
|
|
}
|
|
})
|
|
|
|
t.Run("check first peer map details", func(t *testing.T) {
|
|
peers, firewallRules := account.getPeerConnectionResources("peerB")
|
|
assert.Len(t, peers, 7)
|
|
assert.Contains(t, peers, account.Peers["peerA"])
|
|
assert.Contains(t, peers, account.Peers["peerC"])
|
|
assert.Contains(t, peers, account.Peers["peerD"])
|
|
assert.Contains(t, peers, account.Peers["peerE"])
|
|
assert.Contains(t, peers, account.Peers["peerF"])
|
|
|
|
epectedFirewallRules := []*FirewallRule{
|
|
{
|
|
PeerIP: "0.0.0.0",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "0.0.0.0",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.14.88",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.14.88",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.254.139",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.254.139",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
|
|
{
|
|
PeerIP: "100.65.62.5",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.62.5",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
|
|
{
|
|
PeerIP: "100.65.32.206",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.32.206",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
|
|
{
|
|
PeerIP: "100.65.250.202",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.250.202",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
|
|
{
|
|
PeerIP: "100.65.13.186",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.13.186",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
|
|
{
|
|
PeerIP: "100.65.29.55",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.29.55",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
}
|
|
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
|
slices.SortFunc(epectedFirewallRules, sortFunc())
|
|
slices.SortFunc(firewallRules, sortFunc())
|
|
for i := range firewallRules {
|
|
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
|
account := &Account{
|
|
Peers: map[string]*nbpeer.Peer{
|
|
"peerA": {
|
|
ID: "peerA",
|
|
IP: net.ParseIP("100.65.14.88"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerB": {
|
|
ID: "peerB",
|
|
IP: net.ParseIP("100.65.80.39"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
"peerC": {
|
|
ID: "peerC",
|
|
IP: net.ParseIP("100.65.254.139"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
},
|
|
},
|
|
Groups: map[string]*Group{
|
|
"GroupAll": {
|
|
ID: "GroupAll",
|
|
Name: "All",
|
|
Peers: []string{
|
|
"peerB",
|
|
"peerA",
|
|
"peerC",
|
|
},
|
|
},
|
|
"GroupSwarm": {
|
|
ID: "GroupSwarm",
|
|
Name: "swarm",
|
|
Peers: []string{
|
|
"peerB",
|
|
},
|
|
},
|
|
"peerF": {
|
|
ID: "peerF",
|
|
Name: "dmz",
|
|
Peers: []string{
|
|
"peerC",
|
|
},
|
|
},
|
|
},
|
|
Policies: []*Policy{
|
|
{
|
|
ID: "RuleDefault",
|
|
Name: "Default",
|
|
Description: "This is a default rule that allows connections between all the resources",
|
|
Enabled: false,
|
|
Rules: []*PolicyRule{
|
|
{
|
|
ID: "RuleDefault",
|
|
Name: "Default",
|
|
Description: "This is a default rule that allows connections between all the resources",
|
|
Bidirectional: true,
|
|
Enabled: false,
|
|
Protocol: PolicyRuleProtocolALL,
|
|
Action: PolicyTrafficActionAccept,
|
|
Sources: []string{
|
|
"GroupAll",
|
|
},
|
|
Destinations: []string{
|
|
"GroupAll",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "RuleSwarm",
|
|
Name: "Swarm",
|
|
Description: "No description",
|
|
Enabled: true,
|
|
Rules: []*PolicyRule{
|
|
{
|
|
ID: "RuleSwarm",
|
|
Name: "Swarm",
|
|
Description: "No description",
|
|
Bidirectional: true,
|
|
Enabled: true,
|
|
Protocol: PolicyRuleProtocolALL,
|
|
Action: PolicyTrafficActionAccept,
|
|
Sources: []string{
|
|
"GroupSwarm",
|
|
},
|
|
Destinations: []string{
|
|
"peerF",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
t.Run("check first peer map", func(t *testing.T) {
|
|
peers, firewallRules := account.getPeerConnectionResources("peerB")
|
|
assert.Contains(t, peers, account.Peers["peerC"])
|
|
|
|
epectedFirewallRules := []*FirewallRule{
|
|
{
|
|
PeerIP: "100.65.254.139",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.254.139",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
}
|
|
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
|
slices.SortFunc(epectedFirewallRules, sortFunc())
|
|
slices.SortFunc(firewallRules, sortFunc())
|
|
for i := range firewallRules {
|
|
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
|
}
|
|
})
|
|
|
|
t.Run("check second peer map", func(t *testing.T) {
|
|
peers, firewallRules := account.getPeerConnectionResources("peerC")
|
|
assert.Contains(t, peers, account.Peers["peerB"])
|
|
|
|
epectedFirewallRules := []*FirewallRule{
|
|
{
|
|
PeerIP: "100.65.80.39",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
{
|
|
PeerIP: "100.65.80.39",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
}
|
|
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
|
slices.SortFunc(epectedFirewallRules, sortFunc())
|
|
slices.SortFunc(firewallRules, sortFunc())
|
|
for i := range firewallRules {
|
|
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
|
}
|
|
})
|
|
|
|
account.Policies[1].Rules[0].Bidirectional = false
|
|
|
|
t.Run("check first peer map directional only", func(t *testing.T) {
|
|
peers, firewallRules := account.getPeerConnectionResources("peerB")
|
|
assert.Contains(t, peers, account.Peers["peerC"])
|
|
|
|
epectedFirewallRules := []*FirewallRule{
|
|
{
|
|
PeerIP: "100.65.254.139",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
}
|
|
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
|
slices.SortFunc(epectedFirewallRules, sortFunc())
|
|
slices.SortFunc(firewallRules, sortFunc())
|
|
for i := range firewallRules {
|
|
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
|
}
|
|
})
|
|
|
|
t.Run("check second peer map directional only", func(t *testing.T) {
|
|
peers, firewallRules := account.getPeerConnectionResources("peerC")
|
|
assert.Contains(t, peers, account.Peers["peerB"])
|
|
|
|
epectedFirewallRules := []*FirewallRule{
|
|
{
|
|
PeerIP: "100.65.80.39",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "all",
|
|
Port: "",
|
|
},
|
|
}
|
|
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
|
slices.SortFunc(epectedFirewallRules, sortFunc())
|
|
slices.SortFunc(firewallRules, sortFunc())
|
|
for i := range firewallRules {
|
|
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestAccount_getPeersByPolicyPostureChecks(t *testing.T) {
|
|
account := &Account{
|
|
Peers: map[string]*nbpeer.Peer{
|
|
"peerA": {
|
|
ID: "peerA",
|
|
IP: net.ParseIP("100.65.14.88"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "linux",
|
|
KernelVersion: "6.6.7",
|
|
WtVersion: "0.25.9",
|
|
},
|
|
},
|
|
"peerB": {
|
|
ID: "peerB",
|
|
IP: net.ParseIP("100.65.80.39"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "linux",
|
|
KernelVersion: "6.6.1",
|
|
WtVersion: "0.23.0",
|
|
},
|
|
},
|
|
"peerC": {
|
|
ID: "peerC",
|
|
IP: net.ParseIP("100.65.254.139"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "linux",
|
|
KernelVersion: "6.6.1",
|
|
WtVersion: "0.25.8",
|
|
},
|
|
},
|
|
"peerD": {
|
|
ID: "peerD",
|
|
IP: net.ParseIP("100.65.62.5"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "linux",
|
|
KernelVersion: "6.6.0",
|
|
WtVersion: "0.25.9",
|
|
},
|
|
},
|
|
"peerE": {
|
|
ID: "peerE",
|
|
IP: net.ParseIP("100.65.32.206"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "linux",
|
|
KernelVersion: "6.6.1",
|
|
WtVersion: "0.24.0",
|
|
},
|
|
},
|
|
"peerF": {
|
|
ID: "peerF",
|
|
IP: net.ParseIP("100.65.250.202"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "linux",
|
|
KernelVersion: "6.6.1",
|
|
WtVersion: "0.25.9",
|
|
},
|
|
},
|
|
"peerG": {
|
|
ID: "peerG",
|
|
IP: net.ParseIP("100.65.13.186"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "linux",
|
|
KernelVersion: "6.6.1",
|
|
WtVersion: "0.23.2",
|
|
},
|
|
},
|
|
"peerH": {
|
|
ID: "peerH",
|
|
IP: net.ParseIP("100.65.29.55"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "linux",
|
|
KernelVersion: "6.6.1",
|
|
WtVersion: "0.23.1",
|
|
},
|
|
},
|
|
"peerI": {
|
|
ID: "peerI",
|
|
IP: net.ParseIP("100.65.21.56"),
|
|
Status: &nbpeer.PeerStatus{},
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
GoOS: "windows",
|
|
KernelVersion: "10.0.14393.2430",
|
|
WtVersion: "0.25.1",
|
|
},
|
|
},
|
|
},
|
|
Groups: map[string]*Group{
|
|
"GroupAll": {
|
|
ID: "GroupAll",
|
|
Name: "All",
|
|
Peers: []string{
|
|
"peerB",
|
|
"peerA",
|
|
"peerD",
|
|
"peerC",
|
|
"peerF",
|
|
"peerG",
|
|
"peerH",
|
|
"peerI",
|
|
},
|
|
},
|
|
"GroupSwarm": {
|
|
ID: "GroupSwarm",
|
|
Name: "swarm",
|
|
Peers: []string{
|
|
"peerB",
|
|
"peerA",
|
|
"peerD",
|
|
"peerE",
|
|
"peerG",
|
|
"peerH",
|
|
"peerI",
|
|
},
|
|
},
|
|
},
|
|
PostureChecks: []*posture.Checks{
|
|
{
|
|
ID: "PostureChecksDefault",
|
|
Name: "Default",
|
|
Description: "This is a posture checks that check if peer is running required versions",
|
|
Checks: posture.ChecksDefinition{
|
|
NBVersionCheck: &posture.NBVersionCheck{
|
|
MinVersion: "0.25",
|
|
},
|
|
OSVersionCheck: &posture.OSVersionCheck{
|
|
Linux: &posture.MinKernelVersionCheck{
|
|
MinKernelVersion: "6.6.0",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
account.Policies = append(account.Policies, &Policy{
|
|
ID: "PolicyPostureChecks",
|
|
Name: "",
|
|
Description: "This is the policy with posture checks applied",
|
|
Enabled: true,
|
|
Rules: []*PolicyRule{
|
|
{
|
|
ID: "RuleSwarm",
|
|
Name: "Swarm",
|
|
Enabled: true,
|
|
Action: PolicyTrafficActionAccept,
|
|
Destinations: []string{
|
|
"GroupSwarm",
|
|
},
|
|
Sources: []string{
|
|
"GroupAll",
|
|
},
|
|
Bidirectional: false,
|
|
Protocol: PolicyRuleProtocolTCP,
|
|
Ports: []string{"80"},
|
|
},
|
|
},
|
|
SourcePostureChecks: []string{
|
|
"PostureChecksDefault",
|
|
},
|
|
})
|
|
|
|
t.Run("verify peer's network map with default group peer list", func(t *testing.T) {
|
|
// peerB doesn't fulfill the NB posture check but is included in the destination group Swarm,
|
|
// will establish a connection with all source peers satisfying the NB posture check.
|
|
peers, firewallRules := account.getPeerConnectionResources("peerB")
|
|
assert.Len(t, peers, 4)
|
|
assert.Len(t, firewallRules, 4)
|
|
assert.Contains(t, peers, account.Peers["peerA"])
|
|
assert.Contains(t, peers, account.Peers["peerC"])
|
|
assert.Contains(t, peers, account.Peers["peerD"])
|
|
assert.Contains(t, peers, account.Peers["peerF"])
|
|
|
|
// peerC satisfy the NB posture check, should establish connection to all destination group peer's
|
|
// We expect a single permissive firewall rule which all outgoing connections
|
|
peers, firewallRules = account.getPeerConnectionResources("peerC")
|
|
assert.Len(t, peers, len(account.Groups["GroupSwarm"].Peers))
|
|
assert.Len(t, firewallRules, 1)
|
|
expectedFirewallRules := []*FirewallRule{
|
|
{
|
|
PeerIP: "0.0.0.0",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "tcp",
|
|
Port: "80",
|
|
},
|
|
}
|
|
assert.ElementsMatch(t, firewallRules, expectedFirewallRules)
|
|
|
|
// peerE doesn't fulfill the NB posture check and exists in only destination group Swarm,
|
|
// all source group peers satisfying the NB posture check should establish connection
|
|
peers, firewallRules = account.getPeerConnectionResources("peerE")
|
|
assert.Len(t, peers, 4)
|
|
assert.Len(t, firewallRules, 4)
|
|
assert.Contains(t, peers, account.Peers["peerA"])
|
|
assert.Contains(t, peers, account.Peers["peerC"])
|
|
assert.Contains(t, peers, account.Peers["peerD"])
|
|
assert.Contains(t, peers, account.Peers["peerF"])
|
|
|
|
// peerI doesn't fulfill the OS version posture check and exists in only destination group Swarm,
|
|
// all source group peers satisfying the NB posture check should establish connection
|
|
peers, firewallRules = account.getPeerConnectionResources("peerI")
|
|
assert.Len(t, peers, 4)
|
|
assert.Len(t, firewallRules, 4)
|
|
assert.Contains(t, peers, account.Peers["peerA"])
|
|
assert.Contains(t, peers, account.Peers["peerC"])
|
|
assert.Contains(t, peers, account.Peers["peerD"])
|
|
assert.Contains(t, peers, account.Peers["peerF"])
|
|
})
|
|
|
|
t.Run("verify peer's network map with modified group peer list", func(t *testing.T) {
|
|
// Removing peerB as the part of destination group Swarm
|
|
account.Groups["GroupSwarm"].Peers = []string{"peerA", "peerD", "peerE", "peerG", "peerH"}
|
|
|
|
// peerB doesn't satisfy the NB posture check, and doesn't exist in destination group peer's
|
|
// no connection should be established to any peer of destination group
|
|
peers, firewallRules := account.getPeerConnectionResources("peerB")
|
|
assert.Len(t, peers, 0)
|
|
assert.Len(t, firewallRules, 0)
|
|
|
|
// peerI doesn't satisfy the OS version posture check, and doesn't exist in destination group peer's
|
|
// no connection should be established to any peer of destination group
|
|
peers, firewallRules = account.getPeerConnectionResources("peerI")
|
|
assert.Len(t, peers, 0)
|
|
assert.Len(t, firewallRules, 0)
|
|
|
|
// peerC satisfy the NB posture check, should establish connection to all destination group peer's
|
|
// We expect a single permissive firewall rule which all outgoing connections
|
|
peers, firewallRules = account.getPeerConnectionResources("peerC")
|
|
assert.Len(t, peers, len(account.Groups["GroupSwarm"].Peers))
|
|
assert.Len(t, firewallRules, len(account.Groups["GroupSwarm"].Peers))
|
|
|
|
peerIDs := make([]string, 0, len(peers))
|
|
for _, peer := range peers {
|
|
peerIDs = append(peerIDs, peer.ID)
|
|
}
|
|
assert.ElementsMatch(t, peerIDs, account.Groups["GroupSwarm"].Peers)
|
|
|
|
// Removing peerF as the part of source group All
|
|
account.Groups["GroupAll"].Peers = []string{"peerB", "peerA", "peerD", "peerC", "peerG", "peerH"}
|
|
|
|
// peerE doesn't fulfill the NB posture check and exists in only destination group Swarm,
|
|
// all source group peers satisfying the NB posture check should establish connection
|
|
peers, firewallRules = account.getPeerConnectionResources("peerE")
|
|
assert.Len(t, peers, 3)
|
|
assert.Len(t, firewallRules, 3)
|
|
assert.Contains(t, peers, account.Peers["peerA"])
|
|
assert.Contains(t, peers, account.Peers["peerC"])
|
|
assert.Contains(t, peers, account.Peers["peerD"])
|
|
|
|
peers, firewallRules = account.getPeerConnectionResources("peerA")
|
|
assert.Len(t, peers, 5)
|
|
// assert peers from Group Swarm
|
|
assert.Contains(t, peers, account.Peers["peerD"])
|
|
assert.Contains(t, peers, account.Peers["peerE"])
|
|
assert.Contains(t, peers, account.Peers["peerG"])
|
|
assert.Contains(t, peers, account.Peers["peerH"])
|
|
|
|
// assert peers from Group All
|
|
assert.Contains(t, peers, account.Peers["peerC"])
|
|
|
|
expectedFirewallRules := []*FirewallRule{
|
|
{
|
|
PeerIP: "100.65.62.5",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "tcp",
|
|
Port: "80",
|
|
},
|
|
{
|
|
PeerIP: "100.65.32.206",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "tcp",
|
|
Port: "80",
|
|
},
|
|
{
|
|
PeerIP: "100.65.13.186",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "tcp",
|
|
Port: "80",
|
|
},
|
|
{
|
|
PeerIP: "100.65.29.55",
|
|
Direction: firewallRuleDirectionOUT,
|
|
Action: "accept",
|
|
Protocol: "tcp",
|
|
Port: "80",
|
|
},
|
|
{
|
|
PeerIP: "100.65.254.139",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "tcp",
|
|
Port: "80",
|
|
},
|
|
{
|
|
PeerIP: "100.65.62.5",
|
|
Direction: firewallRuleDirectionIN,
|
|
Action: "accept",
|
|
Protocol: "tcp",
|
|
Port: "80",
|
|
},
|
|
}
|
|
assert.Len(t, firewallRules, len(expectedFirewallRules))
|
|
assert.ElementsMatch(t, firewallRules, expectedFirewallRules)
|
|
})
|
|
}
|
|
|
|
func sortFunc() func(a *FirewallRule, b *FirewallRule) int {
|
|
return func(a, b *FirewallRule) int {
|
|
// Concatenate PeerIP and Direction as string for comparison
|
|
aStr := a.PeerIP + fmt.Sprintf("%d", a.Direction)
|
|
bStr := b.PeerIP + fmt.Sprintf("%d", b.Direction)
|
|
|
|
// Compare the concatenated strings
|
|
if aStr < bStr {
|
|
return -1 // a is less than b
|
|
}
|
|
if aStr > bStr {
|
|
return 1 // a is greater than b
|
|
}
|
|
return 0 // a is equal to b
|
|
}
|
|
}
|