mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
Add peer firewall to the receiving peer
This commit is contained in:
@@ -310,10 +310,10 @@ func (a *Account) GetPeerNetworkMap(
|
||||
var authorizedUsers map[string]map[string]struct{}
|
||||
var enableSSH bool
|
||||
if peer.ProxyEmbedded {
|
||||
aclPeers, firewallRules = a.GetProxyConnectionResources(ctx, exposedServices)
|
||||
aclPeers = a.GetProxyConnectionResources(ctx, exposedServices)
|
||||
} else {
|
||||
aclPeers, firewallRules, authorizedUsers, enableSSH = a.GetPeerConnectionResources(ctx, peer, validatedPeersMap, groupIDToUserIDs)
|
||||
proxyAclPeers, proxyFirewallRules := a.GetPeerProxyResources(exposedServices[peerID], proxyPeers)
|
||||
proxyAclPeers, proxyFirewallRules := a.GetPeerProxyResources(peerID, exposedServices[peerID], proxyPeers)
|
||||
aclPeers = append(aclPeers, proxyAclPeers...)
|
||||
firewallRules = append(firewallRules, proxyFirewallRules...)
|
||||
}
|
||||
@@ -408,9 +408,11 @@ func (a *Account) GetPeerNetworkMap(
|
||||
return nm
|
||||
}
|
||||
|
||||
func (a *Account) GetProxyConnectionResources(ctx context.Context, exposedServices map[string][]*reverseproxy.ReverseProxy) ([]*nbpeer.Peer, []*FirewallRule) {
|
||||
// GetProxyConnectionResources returns ACL peers for the proxy-embedded peer based on exposed services.
|
||||
// No firewall rules are generated here; the proxy peer is always a new on-demand client with a stateful
|
||||
// firewall, so OUT rules are unnecessary. Inbound rules are handled on the target/router peer side.
|
||||
func (a *Account) GetProxyConnectionResources(ctx context.Context, exposedServices map[string][]*reverseproxy.ReverseProxy) []*nbpeer.Peer {
|
||||
var aclPeers []*nbpeer.Peer
|
||||
var firewallRules []*FirewallRule
|
||||
|
||||
for _, peerServices := range exposedServices {
|
||||
for _, service := range peerServices {
|
||||
@@ -427,23 +429,18 @@ func (a *Account) GetProxyConnectionResources(ctx context.Context, exposedServic
|
||||
continue
|
||||
}
|
||||
aclPeers = append(aclPeers, tpeer)
|
||||
firewallRules = append(firewallRules, &FirewallRule{
|
||||
PolicyID: "proxy-" + service.ID,
|
||||
PeerIP: tpeer.IP.String(),
|
||||
Direction: FirewallRuleDirectionOUT,
|
||||
Action: "allow",
|
||||
Protocol: string(PolicyRuleProtocolTCP),
|
||||
PortRange: RulePortRange{Start: uint16(target.Port), End: uint16(target.Port)},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aclPeers, firewallRules
|
||||
return aclPeers
|
||||
}
|
||||
|
||||
func (a *Account) GetPeerProxyResources(services []*reverseproxy.ReverseProxy, proxyPeers []*nbpeer.Peer) ([]*nbpeer.Peer, []*FirewallRule) {
|
||||
// GetPeerProxyResources returns ACL peers and inbound firewall rules for a peer that is targeted by reverse proxy services.
|
||||
// Only IN rules are generated; OUT rules are omitted since proxy peers are always new clients with stateful firewalls.
|
||||
// Rules use PortRange only (not the legacy Port field) as this feature only targets current peer versions.
|
||||
func (a *Account) GetPeerProxyResources(peerID string, services []*reverseproxy.ReverseProxy, proxyPeers []*nbpeer.Peer) ([]*nbpeer.Peer, []*FirewallRule) {
|
||||
var aclPeers []*nbpeer.Peer
|
||||
var firewallRules []*FirewallRule
|
||||
|
||||
@@ -455,7 +452,24 @@ func (a *Account) GetPeerProxyResources(services []*reverseproxy.ReverseProxy, p
|
||||
if !target.Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
aclPeers = proxyPeers
|
||||
|
||||
needsPeerRules := (target.TargetType == reverseproxy.TargetTypePeer && target.TargetId == peerID) ||
|
||||
(target.TargetType == reverseproxy.TargetTypeResource && target.AccessLocal)
|
||||
|
||||
if needsPeerRules {
|
||||
for _, proxyPeer := range proxyPeers {
|
||||
firewallRules = append(firewallRules, &FirewallRule{
|
||||
PolicyID: "proxy-" + service.ID,
|
||||
PeerIP: proxyPeer.IP.String(),
|
||||
Direction: FirewallRuleDirectionIN,
|
||||
Action: "allow",
|
||||
Protocol: string(PolicyRuleProtocolTCP),
|
||||
PortRange: RulePortRange{Start: uint16(target.Port), End: uint16(target.Port)},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1914,7 +1928,7 @@ func (a *Account) GetPeerProxyRoutes(ctx context.Context, peer *nbpeer.Peer, pro
|
||||
for _, proxyPerResource := range proxies {
|
||||
for _, proxy := range proxyPerResource {
|
||||
for _, target := range proxy.Targets {
|
||||
if target.TargetType == reverseproxy.TargetTypeResource {
|
||||
if target.TargetType == reverseproxy.TargetTypeResource && !target.AccessLocal {
|
||||
resource, ok := resourcesMap[target.TargetId]
|
||||
if !ok {
|
||||
log.WithContext(ctx).Warnf("proxy target %s not found in resources map", target.TargetId)
|
||||
|
||||
@@ -70,7 +70,7 @@ func TestGetPeerNetworkMap_Golden(t *testing.T) {
|
||||
resourcePolicies := account.GetResourcePoliciesMap()
|
||||
routers := account.GetResourceRoutersMap()
|
||||
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, account.GetActiveGroupUsers())
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
normalizeAndSortNetworkMap(legacyNetworkMap)
|
||||
legacyJSON, err := json.MarshalIndent(toNetworkMapJSON(legacyNetworkMap), "", " ")
|
||||
require.NoError(t, err, "error marshaling legacy network map to JSON")
|
||||
@@ -115,7 +115,7 @@ func BenchmarkGetPeerNetworkMap(b *testing.B) {
|
||||
b.Run("old builder", func(b *testing.B) {
|
||||
for range b.N {
|
||||
for _, peerID := range peerIDs {
|
||||
_ = account.GetPeerNetworkMap(ctx, peerID, dns.CustomZone{}, nil, validatedPeersMap, nil, nil, nil, account.GetActiveGroupUsers())
|
||||
_ = account.GetPeerNetworkMap(ctx, peerID, dns.CustomZone{}, nil, validatedPeersMap, nil, nil, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -177,7 +177,7 @@ func TestGetPeerNetworkMap_Golden_WithNewPeer(t *testing.T) {
|
||||
resourcePolicies := account.GetResourcePoliciesMap()
|
||||
routers := account.GetResourceRoutersMap()
|
||||
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, account.GetActiveGroupUsers())
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
normalizeAndSortNetworkMap(legacyNetworkMap)
|
||||
legacyJSON, err := json.MarshalIndent(toNetworkMapJSON(legacyNetworkMap), "", " ")
|
||||
require.NoError(t, err, "error marshaling legacy network map to JSON")
|
||||
@@ -240,7 +240,7 @@ func BenchmarkGetPeerNetworkMap_AfterPeerAdded(b *testing.B) {
|
||||
b.Run("old builder after add", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, testingPeerID := range peerIDs {
|
||||
_ = account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, nil, nil, nil, account.GetActiveGroupUsers())
|
||||
_ = account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, nil, nil, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -317,7 +317,7 @@ func TestGetPeerNetworkMap_Golden_WithNewRoutingPeer(t *testing.T) {
|
||||
resourcePolicies := account.GetResourcePoliciesMap()
|
||||
routers := account.GetResourceRoutersMap()
|
||||
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, account.GetActiveGroupUsers())
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
normalizeAndSortNetworkMap(legacyNetworkMap)
|
||||
legacyJSON, err := json.MarshalIndent(toNetworkMapJSON(legacyNetworkMap), "", " ")
|
||||
require.NoError(t, err, "error marshaling legacy network map to JSON")
|
||||
@@ -402,7 +402,7 @@ func BenchmarkGetPeerNetworkMap_AfterRouterPeerAdded(b *testing.B) {
|
||||
b.Run("old builder after add", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, testingPeerID := range peerIDs {
|
||||
_ = account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, nil, nil, nil, account.GetActiveGroupUsers())
|
||||
_ = account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, nil, nil, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -458,7 +458,7 @@ func TestGetPeerNetworkMap_Golden_WithDeletedPeer(t *testing.T) {
|
||||
resourcePolicies := account.GetResourcePoliciesMap()
|
||||
routers := account.GetResourceRoutersMap()
|
||||
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, account.GetActiveGroupUsers())
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
normalizeAndSortNetworkMap(legacyNetworkMap)
|
||||
legacyJSON, err := json.MarshalIndent(toNetworkMapJSON(legacyNetworkMap), "", " ")
|
||||
require.NoError(t, err, "error marshaling legacy network map to JSON")
|
||||
@@ -537,7 +537,7 @@ func TestGetPeerNetworkMap_Golden_WithDeletedRouterPeer(t *testing.T) {
|
||||
resourcePolicies := account.GetResourcePoliciesMap()
|
||||
routers := account.GetResourceRoutersMap()
|
||||
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, account.GetActiveGroupUsers())
|
||||
legacyNetworkMap := account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, resourcePolicies, routers, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
normalizeAndSortNetworkMap(legacyNetworkMap)
|
||||
legacyJSON, err := json.MarshalIndent(toNetworkMapJSON(legacyNetworkMap), "", " ")
|
||||
require.NoError(t, err, "error marshaling legacy network map to JSON")
|
||||
@@ -597,7 +597,7 @@ func BenchmarkGetPeerNetworkMap_AfterPeerDeleted(b *testing.B) {
|
||||
b.Run("old builder after delete", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, testingPeerID := range peerIDs {
|
||||
_ = account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, nil, nil, nil, account.GetActiveGroupUsers())
|
||||
_ = account.GetPeerNetworkMap(ctx, testingPeerID, dns.CustomZone{}, nil, validatedPeersMap, nil, nil, nil, nil, account.GetActiveGroupUsers(), nil, nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
406
management/server/types/proxy_firewall_rules_test.go
Normal file
406
management/server/types/proxy_firewall_rules_test.go
Normal file
@@ -0,0 +1,406 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy"
|
||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
)
|
||||
|
||||
func TestGetProxyConnectionResources_PeerTarget(t *testing.T) {
|
||||
account := &Account{
|
||||
Peers: map[string]*nbpeer.Peer{
|
||||
"target-peer": {ID: "target-peer", IP: net.ParseIP("100.64.0.1")},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"target-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
aclPeers := account.GetProxyConnectionResources(context.Background(), exposedServices)
|
||||
|
||||
require.Len(t, aclPeers, 1)
|
||||
assert.Equal(t, "target-peer", aclPeers[0].ID)
|
||||
}
|
||||
|
||||
func TestGetProxyConnectionResources_DisabledService(t *testing.T) {
|
||||
account := &Account{
|
||||
Peers: map[string]*nbpeer.Peer{
|
||||
"target-peer": {ID: "target-peer", IP: net.ParseIP("100.64.0.1")},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"target-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: false,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
aclPeers := account.GetProxyConnectionResources(context.Background(), exposedServices)
|
||||
assert.Empty(t, aclPeers)
|
||||
}
|
||||
|
||||
func TestGetProxyConnectionResources_ResourceTargetSkipped(t *testing.T) {
|
||||
account := &Account{
|
||||
Peers: map[string]*nbpeer.Peer{
|
||||
"router-peer": {ID: "router-peer", IP: net.ParseIP("100.64.0.2")},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"router-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
aclPeers := account.GetProxyConnectionResources(context.Background(), exposedServices)
|
||||
assert.Empty(t, aclPeers, "resource targets should not add ACL peers via GetProxyConnectionResources")
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_PeerTarget(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
{ID: "proxy-peer-2", IP: net.ParseIP("100.64.0.11")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("target-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 2, "should include all proxy peers")
|
||||
require.Len(t, fwRules, 2, "should have one IN rule per proxy peer")
|
||||
|
||||
for i, rule := range fwRules {
|
||||
assert.Equal(t, "proxy-proxy-1", rule.PolicyID)
|
||||
assert.Equal(t, proxyPeers[i].IP.String(), rule.PeerIP)
|
||||
assert.Equal(t, FirewallRuleDirectionIN, rule.Direction)
|
||||
assert.Equal(t, "allow", rule.Action)
|
||||
assert.Equal(t, string(PolicyRuleProtocolTCP), rule.Protocol)
|
||||
assert.Equal(t, uint16(8080), rule.PortRange.Start)
|
||||
assert.Equal(t, uint16(8080), rule.PortRange.End)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_PeerTargetMismatch(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "other-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("target-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 1, "should still add proxy peers to ACL")
|
||||
assert.Empty(t, fwRules, "should not generate rules when target doesn't match this peer")
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_ResourceAccessLocal(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("router-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 1, "should include proxy peers in ACL")
|
||||
require.Len(t, fwRules, 1, "should generate IN rule for AccessLocal resource")
|
||||
|
||||
rule := fwRules[0]
|
||||
assert.Equal(t, "proxy-proxy-1", rule.PolicyID)
|
||||
assert.Equal(t, "100.64.0.10", rule.PeerIP)
|
||||
assert.Equal(t, FirewallRuleDirectionIN, rule.Direction)
|
||||
assert.Equal(t, uint16(443), rule.PortRange.Start)
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_ResourceWithoutAccessLocal(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("router-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 1, "should still include proxy peers in ACL")
|
||||
assert.Empty(t, fwRules, "should not generate peer rules when AccessLocal is false")
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_MixedTargets(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: true,
|
||||
},
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-2",
|
||||
Port: 8443,
|
||||
Enabled: true,
|
||||
AccessLocal: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("target-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 1)
|
||||
require.Len(t, fwRules, 2, "should have rules for peer target + AccessLocal resource")
|
||||
|
||||
ports := []uint16{fwRules[0].PortRange.Start, fwRules[1].PortRange.Start}
|
||||
assert.Contains(t, ports, uint16(8080), "should include peer target port")
|
||||
assert.Contains(t, ports, uint16(443), "should include AccessLocal resource port")
|
||||
}
|
||||
|
||||
func newProxyRoutesTestAccount() *Account {
|
||||
return &Account{
|
||||
Peers: map[string]*nbpeer.Peer{
|
||||
"router-peer": {ID: "router-peer", Key: "router-key", IP: net.ParseIP("100.64.0.2")},
|
||||
"proxy-peer": {ID: "proxy-peer", Key: "proxy-key", IP: net.ParseIP("100.64.0.10")},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPeerProxyRoutes_ResourceWithoutAccessLocal(t *testing.T) {
|
||||
account := newProxyRoutesTestAccount()
|
||||
proxyPeers := []*nbpeer.Peer{account.Peers["proxy-peer"]}
|
||||
|
||||
resourcesMap := map[string]*resourceTypes.NetworkResource{
|
||||
"resource-1": {
|
||||
ID: "resource-1",
|
||||
AccountID: "accountID",
|
||||
NetworkID: "net-1",
|
||||
Name: "web-service",
|
||||
Type: resourceTypes.Host,
|
||||
Prefix: netip.MustParsePrefix("192.168.1.100/32"),
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
routers := map[string]map[string]*routerTypes.NetworkRouter{
|
||||
"net-1": {
|
||||
"router-peer": {ID: "router-1", NetworkID: "net-1", Peer: "router-peer", Masquerade: true, Metric: 100},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"router-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
routes, routeFwRules, aclPeers := account.GetPeerProxyRoutes(context.Background(), account.Peers["proxy-peer"], exposedServices, resourcesMap, routers, proxyPeers)
|
||||
|
||||
require.NotEmpty(t, routes, "should generate routes for non-AccessLocal resource")
|
||||
require.NotEmpty(t, routeFwRules, "should generate route firewall rules for non-AccessLocal resource")
|
||||
require.NotEmpty(t, aclPeers, "should include router peer in ACL")
|
||||
|
||||
assert.Equal(t, uint16(443), routeFwRules[0].PortRange.Start)
|
||||
assert.Equal(t, "192.168.1.100/32", routeFwRules[0].Destination)
|
||||
}
|
||||
|
||||
func TestGetPeerProxyRoutes_ResourceWithAccessLocal(t *testing.T) {
|
||||
account := newProxyRoutesTestAccount()
|
||||
proxyPeers := []*nbpeer.Peer{account.Peers["proxy-peer"]}
|
||||
|
||||
resourcesMap := map[string]*resourceTypes.NetworkResource{
|
||||
"resource-1": {
|
||||
ID: "resource-1",
|
||||
AccountID: "accountID",
|
||||
NetworkID: "net-1",
|
||||
Name: "local-service",
|
||||
Type: resourceTypes.Host,
|
||||
Prefix: netip.MustParsePrefix("192.168.1.100/32"),
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
routers := map[string]map[string]*routerTypes.NetworkRouter{
|
||||
"net-1": {
|
||||
"router-peer": {ID: "router-1", NetworkID: "net-1", Peer: "router-peer", Masquerade: true, Metric: 100},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"router-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
routes, routeFwRules, aclPeers := account.GetPeerProxyRoutes(context.Background(), account.Peers["proxy-peer"], exposedServices, resourcesMap, routers, proxyPeers)
|
||||
|
||||
assert.Empty(t, routes, "should NOT generate routes for AccessLocal resource")
|
||||
assert.Empty(t, routeFwRules, "should NOT generate route firewall rules for AccessLocal resource")
|
||||
assert.Empty(t, aclPeers, "should NOT include router peer from route path for AccessLocal resource")
|
||||
}
|
||||
|
||||
func TestGetPeerProxyRoutes_PeerTargetSkipped(t *testing.T) {
|
||||
account := newProxyRoutesTestAccount()
|
||||
proxyPeers := []*nbpeer.Peer{account.Peers["proxy-peer"]}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"router-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
routes, routeFwRules, aclPeers := account.GetPeerProxyRoutes(context.Background(), account.Peers["proxy-peer"], exposedServices, nil, nil, proxyPeers)
|
||||
|
||||
assert.Empty(t, routes, "should NOT generate routes for peer targets")
|
||||
assert.Empty(t, routeFwRules, "should NOT generate route firewall rules for peer targets")
|
||||
assert.Empty(t, aclPeers)
|
||||
}
|
||||
Reference in New Issue
Block a user