[management] Generate network map for new network concept (#3044)

This commit is contained in:
Bethuel Mmbaga 2024-12-17 16:07:20 +03:00 committed by GitHub
parent cbd333a3e0
commit bcf32f215c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 748 additions and 7 deletions

View File

@ -6,6 +6,10 @@ import (
"net/netip"
"regexp"
nbDomain "github.com/netbirdio/netbird/management/domain"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
nbpeer "github.com/netbirdio/netbird/management/server/peer"
"github.com/netbirdio/netbird/route"
"github.com/rs/xid"
"github.com/netbirdio/netbird/management/server/http/api"
@ -88,9 +92,51 @@ func (n *NetworkResource) Copy() *NetworkResource {
Description: n.Description,
Type: n.Type,
Address: n.Address,
Domain: n.Domain,
Prefix: n.Prefix,
}
}
func (n *NetworkResource) ToRoute(peer *nbpeer.Peer, router *routerTypes.NetworkRouter) *route.Route {
r := &route.Route{
ID: route.ID(n.ID),
AccountID: n.AccountID,
KeepRoute: true,
NetID: route.NetID(n.Name),
Description: n.Description,
Peer: peer.Key,
PeerGroups: nil,
Masquerade: router.Masquerade,
Metric: router.Metric,
Enabled: true,
Groups: nil,
AccessControlGroups: nil,
}
if n.Type == host || n.Type == subnet {
r.Network = n.Prefix
r.NetworkType = route.IPv4Network
if n.Prefix.Addr().Is6() {
r.NetworkType = route.IPv6Network
}
}
if n.Type == domain {
domainList, err := nbDomain.FromStringList([]string{n.Domain})
if err != nil {
return nil
}
r.Domains = domainList
r.NetworkType = route.DomainNetwork
// add default placeholder for domain network
r.Network = netip.PrefixFrom(netip.AddrFrom4([4]byte{192, 0, 2, 0}), 32)
}
return r
}
// GetResourceType returns the type of the resource based on the address
func GetResourceType(address string) (NetworkResourceType, string, netip.Prefix, error) {
if prefix, err := netip.ParsePrefix(address); err == nil {

View File

@ -13,6 +13,9 @@ import (
"testing"
"time"
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
"github.com/rs/xid"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
@ -758,8 +761,66 @@ func setupTestAccountManager(b *testing.B, peers int, groups int) (*DefaultAccou
peerIndex := i*(peers/groups) + j
group.Peers = append(group.Peers, fmt.Sprintf("peer-%d", peerIndex))
}
// Create network, router and resource for this group
network := &networkTypes.Network{
ID: fmt.Sprintf("network-%d", i),
AccountID: account.Id,
Name: fmt.Sprintf("Network for Group %d", i),
}
account.Networks = append(account.Networks, network)
ips := account.GetTakenIPs()
peerIP, err := types.AllocatePeerIP(account.Network.Net, ips)
if err != nil {
return nil, "", "", err
}
peerKey, _ := wgtypes.GeneratePrivateKey()
peer := &nbpeer.Peer{
ID: fmt.Sprintf("peer-%d", len(account.Peers)+1),
DNSLabel: fmt.Sprintf("peer-%d", len(account.Peers)+1),
Key: peerKey.PublicKey().String(),
IP: peerIP,
Status: &nbpeer.PeerStatus{},
UserID: regularUser,
Meta: nbpeer.PeerSystemMeta{
Hostname: fmt.Sprintf("peer-%d", len(account.Peers)+1),
GoOS: "linux",
Kernel: "Linux",
Core: "21.04",
Platform: "x86_64",
OS: "Ubuntu",
WtVersion: "development",
UIVersion: "development",
},
}
account.Peers[peer.ID] = peer
group.Peers = append(group.Peers, peer.ID)
account.Groups[groupID] = group
router := &routerTypes.NetworkRouter{
ID: fmt.Sprintf("network-router-%d", i),
NetworkID: network.ID,
AccountID: account.Id,
Peer: peer.ID,
PeerGroups: []string{},
Masquerade: false,
Metric: 9999,
}
account.NetworkRouters = append(account.NetworkRouters, router)
resource := &resourceTypes.NetworkResource{
ID: fmt.Sprintf("network-resource-%d", i),
NetworkID: network.ID,
AccountID: account.Id,
Name: fmt.Sprintf("Network resource for Group %d", i),
Type: "host",
Address: "192.0.2.0/32",
}
account.NetworkResources = append(account.NetworkResources, resource)
// Create a policy for this group
policy := &types.Policy{
ID: fmt.Sprintf("policy-%d", i),
@ -767,11 +828,14 @@ func setupTestAccountManager(b *testing.B, peers int, groups int) (*DefaultAccou
Enabled: true,
Rules: []*types.PolicyRule{
{
ID: fmt.Sprintf("rule-%d", i),
Name: fmt.Sprintf("Rule for Group %d", i),
Enabled: true,
Sources: []string{groupID},
Destinations: []string{groupID},
ID: fmt.Sprintf("rule-%d", i),
Name: fmt.Sprintf("Rule for Group %d", i),
Enabled: true,
Sources: []string{groupID},
Destinations: []string{groupID},
DestinationResource: types.Resource{
ID: resource.ID,
},
Bidirectional: true,
Protocol: types.PolicyRuleProtocolALL,
Action: types.PolicyTrafficActionAccept,

View File

@ -9,6 +9,9 @@ import (
"testing"
"time"
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
"github.com/rs/xid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -1876,6 +1879,7 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
Action: "accept",
Destination: "192.0.2.0/32",
Protocol: "all",
Domains: domain.List{"example.com"},
IsDynamic: true,
},
{
@ -1883,6 +1887,7 @@ func TestAccount_getPeersRoutesFirewall(t *testing.T) {
Action: "accept",
Destination: "192.0.2.0/32",
Protocol: "all",
Domains: domain.List{"example.com"},
IsDynamic: true,
},
}
@ -2160,3 +2165,444 @@ func TestRouteAccountPeersUpdate(t *testing.T) {
}
})
}
func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) {
var (
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 := &types.Account{
Peers: map[string]*nbpeer.Peer{
"peerA": {
ID: "peerA",
IP: net.ParseIP("100.65.14.88"),
Key: "peerA",
Status: &nbpeer.PeerStatus{},
Meta: nbpeer.PeerSystemMeta{
GoOS: "linux",
},
},
"peerB": {
ID: "peerB",
IP: net.ParseIP(peerBIp),
Status: &nbpeer.PeerStatus{},
Meta: nbpeer.PeerSystemMeta{},
},
"peerC": {
ID: "peerC",
IP: net.ParseIP(peerCIp),
Status: &nbpeer.PeerStatus{},
},
"peerD": {
ID: "peerD",
IP: net.ParseIP("100.65.62.5"),
Key: "peerD",
Status: &nbpeer.PeerStatus{},
Meta: nbpeer.PeerSystemMeta{
GoOS: "linux",
},
},
"peerE": {
ID: "peerE",
IP: net.ParseIP("100.65.32.206"),
Key: "peerE",
Status: &nbpeer.PeerStatus{},
Meta: nbpeer.PeerSystemMeta{
GoOS: "linux",
},
},
"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(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]*types.Group{
"router1": {
ID: "router1",
Name: "router1",
Peers: []string{
"peerA",
},
},
"router2": {
ID: "router2",
Name: "router2",
Peers: []string{
"peerD",
},
},
"finance": {
ID: "finance",
Name: "Finance",
Peers: []string{
"peerF",
"peerG",
},
},
"dev": {
ID: "dev",
Name: "Dev",
Peers: []string{
"peerC",
"peerH",
"peerB",
},
Resources: []types.Resource{
{ID: "resource2"},
},
},
"qa": {
ID: "qa",
Name: "QA",
Peers: []string{
"peerJ",
"peerK",
},
},
"restrictQA": {
ID: "restrictQA",
Name: "restrictQA",
Peers: []string{
"peerJ",
},
Resources: []types.Resource{
{ID: "resource4"},
},
},
"unrestrictedQA": {
ID: "unrestrictedQA",
Name: "unrestrictedQA",
Peers: []string{
"peerK",
},
Resources: []types.Resource{
{ID: "resource4"},
},
},
"contractors": {
ID: "contractors",
Name: "Contractors",
Peers: []string{},
},
},
Networks: []*networkTypes.Network{
{
ID: "network1",
Name: "Finance Network",
},
{
ID: "network2",
Name: "Devs Network",
},
{
ID: "network3",
Name: "Contractors Network",
},
{
ID: "network4",
Name: "QA Network",
},
},
NetworkRouters: []*routerTypes.NetworkRouter{
{
ID: "router1",
NetworkID: "network1",
Peer: "peerE",
PeerGroups: nil,
Masquerade: false,
Metric: 9999,
},
{
ID: "router2",
NetworkID: "network2",
PeerGroups: []string{"router1", "router2"},
Masquerade: false,
Metric: 9999,
},
{
ID: "router3",
NetworkID: "network3",
Peer: "peerE",
PeerGroups: []string{},
},
{
ID: "router4",
NetworkID: "network4",
PeerGroups: []string{"router1"},
Masquerade: false,
Metric: 9999,
},
},
NetworkResources: []*resourceTypes.NetworkResource{
{
ID: "resource1",
NetworkID: "network1",
Name: "Resource 1",
Type: "subnet",
Prefix: netip.MustParsePrefix("10.10.10.0/24"),
},
{
ID: "resource2",
NetworkID: "network2",
Name: "Resource 2",
Type: "subnet",
Prefix: netip.MustParsePrefix("192.168.0.0/16"),
},
{
ID: "resource3",
NetworkID: "network3",
Name: "Resource 3",
Type: "domain",
Domain: "example.com",
},
{
ID: "resource4",
NetworkID: "network4",
Name: "Resource 4",
Type: "domain",
Domain: "example.com",
},
},
Policies: []*types.Policy{
{
ID: "policyResource1",
Name: "Policy for resource 1",
Enabled: true,
Rules: []*types.PolicyRule{
{
ID: "ruleResource1",
Name: "ruleResource1",
Bidirectional: true,
Enabled: true,
Protocol: types.PolicyRuleProtocolTCP,
Action: types.PolicyTrafficActionAccept,
PortRanges: []types.RulePortRange{
{
Start: 80,
End: 350,
}, {
Start: 80,
End: 350,
},
},
Sources: []string{
"finance",
},
DestinationResource: types.Resource{ID: "resource1"},
},
},
},
{
ID: "policyResource2",
Name: "Policy for resource 2",
Enabled: true,
Rules: []*types.PolicyRule{
{
ID: "ruleResource2",
Name: "ruleResource2",
Bidirectional: true,
Enabled: true,
Protocol: types.PolicyRuleProtocolALL,
Action: types.PolicyTrafficActionAccept,
Ports: []string{"80", "320"},
Sources: []string{"dev"},
Destinations: []string{"dev"},
},
},
},
{
ID: "policyResource3",
Name: "policyResource3",
Enabled: true,
Rules: []*types.PolicyRule{
{
ID: "ruleResource3",
Name: "ruleResource3",
Bidirectional: true,
Enabled: true,
Protocol: types.PolicyRuleProtocolTCP,
Action: types.PolicyTrafficActionAccept,
Ports: []string{"80"},
Sources: []string{"restrictQA"},
Destinations: []string{"restrictQA"},
},
},
},
{
ID: "policyResource4",
Name: "policyResource4",
Enabled: true,
Rules: []*types.PolicyRule{
{
ID: "ruleResource4",
Name: "ruleResource4",
Bidirectional: true,
Enabled: true,
Protocol: types.PolicyRuleProtocolALL,
Action: types.PolicyTrafficActionAccept,
Sources: []string{"unrestrictedQA"},
Destinations: []string{"unrestrictedQA"},
},
},
},
},
}
validatedPeers := make(map[string]struct{})
for p := range account.Peers {
validatedPeers[p] = struct{}{}
}
t.Run("validate applied policies for different network resources", func(t *testing.T) {
getNetworkResourceByID := func(account *types.Account, id string) *resourceTypes.NetworkResource {
for _, resource := range account.NetworkResources {
if resource.ID == id {
return resource
}
}
return nil
}
getNetworkRouterByID := func(account *types.Account, id string) *routerTypes.NetworkRouter {
for _, router := range account.NetworkRouters {
if router.ID == id {
return router
}
}
return nil
}
// Test case: Resource1 is directly applied to the policy (policyResource1)
peerE := account.GetPeer("peerE")
router1 := getNetworkRouterByID(account, "router1")
route1 := getNetworkResourceByID(account, "resource1").ToRoute(peerE, router1)
policies := account.GetPoliciesForNetworkResourceRoute(route1)
assert.Len(t, policies, 1, "resource1 should have exactly 1 policy applied directly")
// Test case: Resource2 is applied to an access control group (dev),
// which is part of the destination in the policy (policyResource2)
peerA := account.GetPeer("peerA")
router2 := getNetworkRouterByID(account, "router2")
route2 := getNetworkResourceByID(account, "resource2").ToRoute(peerA, router2)
policies = account.GetPoliciesForNetworkResourceRoute(route2)
assert.Len(t, policies, 1, "resource2 should have exactly 1 policy applied via access control group")
// Test case: Resource3 is not applied to any access control group or policy
router3 := getNetworkRouterByID(account, "router3")
route3 := getNetworkResourceByID(account, "resource3").ToRoute(peerE, router3)
policies = account.GetPoliciesForNetworkResourceRoute(route3)
assert.Len(t, policies, 0, "resource3 should have no policies applied")
// Test case: Resource4 is applied to the access control groups (restrictQA and unrestrictedQA),
// which is part of the destination in the policies (policyResource3 and policyResource4)
router4 := getNetworkRouterByID(account, "router4")
route4 := getNetworkResourceByID(account, "resource4").ToRoute(peerA, router4)
policies = account.GetPoliciesForNetworkResourceRoute(route4)
assert.Len(t, policies, 2, "resource4 should have exactly 2 policy applied via access control groups")
})
t.Run("validate routing peer firewall rules for network resources", func(t *testing.T) {
firewallRules := account.GetPeerNetworkResourceFirewallRules(context.Background(), "peerA", validatedPeers)
assert.Len(t, firewallRules, 4)
expectedFirewallRules := []*types.RouteFirewallRule{
{
SourceRanges: []string{
fmt.Sprintf(types.AllowedIPsFormat, peerCIp),
fmt.Sprintf(types.AllowedIPsFormat, peerHIp),
fmt.Sprintf(types.AllowedIPsFormat, peerBIp),
},
Action: "accept",
Destination: "192.168.0.0/16",
Protocol: "all",
Port: 80,
},
{
SourceRanges: []string{
fmt.Sprintf(types.AllowedIPsFormat, peerCIp),
fmt.Sprintf(types.AllowedIPsFormat, peerHIp),
fmt.Sprintf(types.AllowedIPsFormat, peerBIp),
},
Action: "accept",
Destination: "192.168.0.0/16",
Protocol: "all",
Port: 320,
},
}
additionalFirewallRules := []*types.RouteFirewallRule{
{
SourceRanges: []string{
fmt.Sprintf(types.AllowedIPsFormat, peerJIp),
},
Action: "accept",
Destination: "192.0.2.0/32",
Protocol: "tcp",
Port: 80,
Domains: domain.List{"example.com"},
IsDynamic: true,
},
{
SourceRanges: []string{
fmt.Sprintf(types.AllowedIPsFormat, peerKIp),
},
Action: "accept",
Destination: "192.0.2.0/32",
Protocol: "all",
Domains: domain.List{"example.com"},
IsDynamic: true,
},
}
assert.ElementsMatch(t, orderRuleSourceRanges(firewallRules), orderRuleSourceRanges(append(expectedFirewallRules, additionalFirewallRules...)))
// peerD is also the routing peer for resource2
firewallRules = account.GetPeerNetworkResourceFirewallRules(context.Background(), "peerD", validatedPeers)
assert.Len(t, firewallRules, 2)
assert.ElementsMatch(t, orderRuleSourceRanges(firewallRules), orderRuleSourceRanges(expectedFirewallRules))
// peerE is a single routing peer for resource1 and resource3
// PeerE should only receive rules for resource1 since resource3 has no applied policy
firewallRules = account.GetPeerNetworkResourceFirewallRules(context.Background(), "peerE", validatedPeers)
assert.Len(t, firewallRules, 1)
expectedFirewallRules = []*types.RouteFirewallRule{
{
SourceRanges: []string{"100.65.250.202/32", "100.65.13.186/32"},
Action: "accept",
Destination: "10.10.10.0/24",
Protocol: "tcp",
PortRange: types.RulePortRange{Start: 80, End: 350},
},
}
assert.ElementsMatch(t, orderRuleSourceRanges(firewallRules), orderRuleSourceRanges(expectedFirewallRules))
// peerC is part of distribution groups for resource2 but should not receive the firewall rules
firewallRules = account.GetPeerRoutesFirewallRules(context.Background(), "peerC", validatedPeers)
assert.Len(t, firewallRules, 0)
})
}

View File

@ -256,6 +256,9 @@ func (a *Account) GetPeerNetworkMap(
routesUpdate := a.GetRoutesToSync(ctx, peerID, peersToConnect)
routesFirewallRules := a.GetPeerRoutesFirewallRules(ctx, peerID, validatedPeersMap)
networkResourcesRoutes := a.GetNetworkResourcesRoutesToSync(ctx, peerID, peersToConnect)
networkResourcesFirewallRules := a.GetPeerNetworkResourceFirewallRules(ctx, peerID, validatedPeersMap)
dnsManagementStatus := a.getPeerDNSManagementStatus(peerID)
dnsUpdate := nbdns.Config{
ServiceEnable: dnsManagementStatus,
@ -274,11 +277,11 @@ func (a *Account) GetPeerNetworkMap(
nm := &NetworkMap{
Peers: peersToConnect,
Network: a.Network.Copy(),
Routes: routesUpdate,
Routes: slices.Concat(networkResourcesRoutes, routesUpdate),
DNSConfig: dnsUpdate,
OfflinePeers: expiredPeers,
FirewallRules: firewallRules,
RoutesFirewallRules: routesFirewallRules,
RoutesFirewallRules: slices.Concat(networkResourcesFirewallRules, routesFirewallRules),
}
if metrics != nil {
@ -1158,6 +1161,7 @@ func getDefaultPermit(route *route.Route) []*RouteFirewallRule {
Action: string(PolicyTrafficActionAccept),
Destination: route.Network.String(),
Protocol: string(PolicyRuleProtocolALL),
Domains: route.Domains,
IsDynamic: route.IsDynamic(),
}
@ -1198,3 +1202,176 @@ func GetAllRoutePoliciesFromGroups(account *Account, accessControlGroups []strin
return routePolicies
}
// getRoutingPeerNetworkResourcesRoutes returns the network resources routes associated with a routing peer ID for the account.
func (a *Account) getRoutingPeerNetworkResourcesRoutes(ctx context.Context, peerID string) []*route.Route {
var routes []*route.Route
peer := a.GetPeer(peerID)
if peer == nil {
log.WithContext(ctx).Errorf("peer %s that doesn't exist under account %s", peerID, a.Id)
return routes
}
// currently we support only linux routing peers
if peer.Meta.GoOS != "linux" {
return routes
}
for _, router := range a.NetworkRouters {
for _, groupID := range router.PeerGroups {
group := a.GetGroup(groupID)
if group == nil {
log.WithContext(ctx).Errorf("router %s has peers group %s that doesn't exist under account %s", router.ID, groupID, a.Id)
continue
}
for _, id := range group.Peers {
if id != peerID {
continue
}
resources := a.getNetworkResources(router.NetworkID)
routes = append(routes, a.getNetworkResourcesRoutes(resources, router, peer)...)
}
}
if router.Peer == peerID {
resources := a.getNetworkResources(router.NetworkID)
routes = append(routes, a.getNetworkResourcesRoutes(resources, router, peer)...)
}
}
return routes
}
// GetPeerNetworkResourceFirewallRules gets the network resources firewall rules associated with a routing peer ID for the account.
func (a *Account) GetPeerNetworkResourceFirewallRules(ctx context.Context, peerID string, validatedPeersMap map[string]struct{}) []*RouteFirewallRule {
routesFirewallRules := make([]*RouteFirewallRule, 0)
routes := a.getRoutingPeerNetworkResourcesRoutes(ctx, peerID)
for _, route := range routes {
resourceAppliedPolicies := a.GetPoliciesForNetworkResourceRoute(route)
distributionPeers := getPoliciesSourcePeers(resourceAppliedPolicies, a.Groups)
rules := a.getRouteFirewallRules(ctx, peerID, resourceAppliedPolicies, route, validatedPeersMap, distributionPeers)
routesFirewallRules = append(routesFirewallRules, rules...)
}
return routesFirewallRules
}
// getNetworkResourceGroups retrieves all groups associated with the given network resource route.
func (a *Account) getNetworkResourceGroups(route *route.Route) []*Group {
var networkResourceGroups []*Group
for _, group := range a.Groups {
for _, resource := range group.Resources {
if resource.ID == string(route.ID) {
networkResourceGroups = append(networkResourceGroups, group)
}
}
}
return networkResourceGroups
}
// GetNetworkResourcesRoutesToSync returns network routes for syncing with a specific peer and its ACL peers.
func (a *Account) GetNetworkResourcesRoutesToSync(ctx context.Context, peerID string, aclPeers []*nbpeer.Peer) []*route.Route {
routes := a.getRoutingPeerNetworkResourcesRoutes(ctx, peerID)
peerRoutesMembership := make(LookupMap)
for _, r := range routes {
peerRoutesMembership[string(r.GetHAUniqueID())] = struct{}{}
}
for _, peer := range aclPeers {
peerRoutes := a.getRoutingPeerNetworkResourcesRoutes(ctx, peer.ID)
filteredRoutes := a.filterRoutesFromPeersOfSameHAGroup(peerRoutes, peerRoutesMembership)
routes = append(routes, filteredRoutes...)
}
return routes
}
// getNetworkResources filters and returns a list of network resources associated with the given network ID.
func (a *Account) getNetworkResources(networkID string) []*resourceTypes.NetworkResource {
var resources []*resourceTypes.NetworkResource
for _, resource := range a.NetworkResources {
if resource.NetworkID == networkID {
resources = append(resources, resource)
}
}
return resources
}
// GetPoliciesForNetworkResourceRoute retrieves the list of policies that apply to a specific network resource route.
// A policy is deemed applicable if its destination groups include any of the given network resource groups
// or if its destination resource explicitly matches the provided route.
func (a *Account) GetPoliciesForNetworkResourceRoute(route *route.Route) []*Policy {
var resourceAppliedPolicies []*Policy
networkResourceGroups := a.getNetworkResourceGroups(route)
for _, policy := range a.Policies {
if !policy.Enabled {
continue
}
for _, rule := range policy.Rules {
if !rule.Enabled {
continue
}
for _, group := range networkResourceGroups {
if slices.Contains(rule.Destinations, group.ID) {
resourceAppliedPolicies = append(resourceAppliedPolicies, policy)
break
}
}
if rule.DestinationResource.ID == string(route.ID) {
resourceAppliedPolicies = append(resourceAppliedPolicies, policy)
}
}
}
return resourceAppliedPolicies
}
// getNetworkResourcesRoutes convert the network resources list to routes list.
func (a *Account) getNetworkResourcesRoutes(resources []*resourceTypes.NetworkResource, router *routerTypes.NetworkRouter, peer *nbpeer.Peer) []*route.Route {
routes := make([]*route.Route, 0, len(resources))
for _, resource := range resources {
resourceRoute := resource.ToRoute(peer, router)
resourceAppliedPolicies := a.GetPoliciesForNetworkResourceRoute(resourceRoute)
// distribute the resource routes only if there is policy applied to it
if len(resourceAppliedPolicies) > 0 {
routes = append(routes, resourceRoute)
}
}
return routes
}
// getPoliciesSourcePeers collects all unique peers from the source groups defined in the given policies.
func getPoliciesSourcePeers(policies []*Policy, groups map[string]*Group) map[string]struct{} {
sourcePeers := make(map[string]struct{})
for _, policy := range policies {
for _, rule := range policy.Rules {
for _, sourceGroup := range rule.Sources {
group := groups[sourceGroup]
if group == nil {
continue
}
for _, peer := range group.Peers {
sourcePeers[peer] = struct{}{}
}
}
}
}
return sourcePeers
}

View File

@ -53,6 +53,7 @@ func generateRouteFirewallRules(ctx context.Context, route *nbroute.Route, rule
Action: string(rule.Action),
Destination: route.Network.String(),
Protocol: string(rule.Protocol),
Domains: route.Domains,
IsDynamic: route.IsDynamic(),
}

View File

@ -1,5 +1,9 @@
package types
import (
"github.com/netbirdio/netbird/management/domain"
)
// RouteFirewallRule a firewall rule applicable for a routed network.
type RouteFirewallRule struct {
// SourceRanges IP ranges of the routing peers.
@ -20,6 +24,9 @@ type RouteFirewallRule struct {
// PortRange represents the range of ports for a firewall rule
PortRange RulePortRange
// Domains list of network domains for the routed traffic
Domains domain.List
// isDynamic indicates whether the rule is for DNS routing
IsDynamic bool
}