From 57eac8824f06f9a63dc55df75c12d4248d9e1f4f Mon Sep 17 00:00:00 2001 From: bcmmbaga Date: Wed, 18 Dec 2024 17:37:38 +0300 Subject: [PATCH] wip: generate routes for resource with no policy Signed-off-by: bcmmbaga --- management/server/route_test.go | 83 +++++++++++++++++++ management/server/types/account.go | 128 ++++++++++++++++++++++++++--- management/server/types/policy.go | 9 ++ 3 files changed, 207 insertions(+), 13 deletions(-) diff --git a/management/server/route_test.go b/management/server/route_test.go index b7540cb77..c0de54954 100644 --- a/management/server/route_test.go +++ b/management/server/route_test.go @@ -2174,6 +2174,7 @@ func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) { peerHIp = "100.65.29.55" peerJIp = "100.65.29.65" peerKIp = "100.65.29.66" + peerMIp = "100.65.29.67" ) account := &types.Account{ @@ -2241,6 +2242,20 @@ func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) { IP: net.ParseIP(peerKIp), Status: &nbpeer.PeerStatus{}, }, + "peerL": { + ID: "peerL", + IP: net.ParseIP("100.65.19.186"), + Key: "peerL", + Status: &nbpeer.PeerStatus{}, + Meta: nbpeer.PeerSystemMeta{ + GoOS: "linux", + }, + }, + "peerM": { + ID: "peerM", + IP: net.ParseIP(peerMIp), + Status: &nbpeer.PeerStatus{}, + }, }, Groups: map[string]*types.Group{ "router1": { @@ -2310,6 +2325,11 @@ func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) { Name: "Contractors", Peers: []string{}, }, + "pipeline": { + ID: "pipeline", + Name: "Pipeline", + Peers: []string{"peerM"}, + }, }, Networks: []*networkTypes.Network{ { @@ -2328,6 +2348,10 @@ func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) { ID: "network4", Name: "QA Network", }, + { + ID: "network5", + Name: "Pipeline Network", + }, }, NetworkRouters: []*routerTypes.NetworkRouter{ { @@ -2358,6 +2382,13 @@ func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) { Masquerade: false, Metric: 9999, }, + { + ID: "router5", + NetworkID: "network5", + Peer: "peerL", + Masquerade: false, + Metric: 9999, + }, }, NetworkResources: []*resourceTypes.NetworkResource{ { @@ -2388,6 +2419,13 @@ func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) { Type: "domain", Domain: "example.com", }, + { + ID: "resource5", + NetworkID: "network5", + Name: "Resource 5", + Type: "host", + Prefix: netip.MustParsePrefix("10.12.12.1/32"), + }, }, Policies: []*types.Policy{ { @@ -2471,6 +2509,24 @@ func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) { }, }, }, + { + ID: "policyResource5", + Name: "policyResource5", + Enabled: true, + Rules: []*types.PolicyRule{ + { + ID: "ruleResource5", + Name: "ruleResource5", + Bidirectional: true, + Enabled: true, + Protocol: types.PolicyRuleProtocolTCP, + Action: types.PolicyTrafficActionAccept, + Ports: []string{"8080"}, + Sources: []string{"pipeline"}, + DestinationResource: types.Resource{ID: "resource5"}, + }, + }, + }, }, } @@ -2577,5 +2633,32 @@ func TestAccount_GetPeerNetworkResourceFirewallRules(t *testing.T) { // 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) + + // peerL is the single routing peer for resource5 + firewallRules = account.GetPeerNetworkResourceFirewallRules(context.Background(), "peerL", validatedPeers) + assert.Len(t, firewallRules, 1) + + expectedFirewallRules = []*types.RouteFirewallRule{ + { + SourceRanges: []string{"100.65.29.67/32"}, + Action: "accept", + Destination: "10.12.12.1/32", + Protocol: "tcp", + Port: 8080, + }, + } + assert.ElementsMatch(t, orderRuleSourceRanges(firewallRules), orderRuleSourceRanges(expectedFirewallRules)) + }) + + t.Run("validate routes for network resources", func(t *testing.T) { + routesToSync := account.GetNetworkResourcesRoutesToSync(context.Background(), "peerL", []*nbpeer.Peer{}) + assert.Len(t, routesToSync, 1) + + routesToSync = account.GetNetworkResourcesRoutesToSync(context.Background(), "peerM", []*nbpeer.Peer{}) + assert.Len(t, routesToSync, 1) + + //routesToSync = account.GetNetworkResourcesRoutesToSync(context.Background(), "peerC", []*nbpeer.Peer{}) + //assert.Len(t, routesToSync, 1) + }) } diff --git a/management/server/types/account.go b/management/server/types/account.go index 353369078..2ee553632 100644 --- a/management/server/types/account.go +++ b/management/server/types/account.go @@ -1278,16 +1278,100 @@ func (a *Account) getNetworkResourceGroups(resourceID string) []*Group { // 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{}{} - } + //routes := a.getRoutingPeerNetworkResourcesRoutes(ctx, peerID) + //peerRoutesMembership := make(LookupMap) + //for _, r := range routes { + // peerRoutesMembership[string(r.GetHAUniqueID())] = struct{}{} + //} + // + ////peersToConnect := make(map[string]struct{}) + // + resources := make([]*resourceTypes.NetworkResource, 0) - for _, peer := range aclPeers { - peerRoutes := a.getRoutingPeerNetworkResourcesRoutes(ctx, peer.ID) - filteredRoutes := a.filterRoutesFromPeersOfSameHAGroup(peerRoutes, peerRoutesMembership) - routes = append(routes, filteredRoutes...) + for _, resource := range a.NetworkResources { + + for _, router := range a.NetworkRouters { + if router.NetworkID == resource.NetworkID { + if router.Peer == peerID { + resources = append(resources, resource) + } + + for _, peerGroup := range router.PeerGroups { + g := a.Groups[peerGroup] + if g != nil { + if slices.Contains(router.PeerGroups, peerID) { + resources = append(resources, resource) + } + } + } + } + + } + + resourceAppliedPolicies := a.GetPoliciesForNetworkResource(resource.ID) + + for _, policy := range resourceAppliedPolicies { + sourceGroups := policy.SourceGroups() + + for _, sourceGroup := range sourceGroups { + group := a.GetGroup(sourceGroup) + if group == nil { + continue + } + + // peer is part of the policy source which is the distribution group for the resource + // peerID should be able to connect with routing peers + if slices.Contains(group.Peers, peerID) { + resources = append(resources, resource) + + // for _, groupID := range router.PeerGroups { + // g := a.GetGroup(groupID) + // if g != nil { + // for _, id := range g.Peers { + // peersToConnect[id] = struct{}{} + // } + // } + // } + // + // if router.Peer != "" { + // peersToConnect[router.Peer] = struct{}{} + // } + } + } + } + } + // + ////for _, peer := range aclPeers { + //// peerRoutes := a.getRoutingPeerNetworkResourcesRoutes(ctx, peer.ID) + //// filteredRoutes := a.filterRoutesFromPeersOfSameHAGroup(peerRoutes, peerRoutesMembership) + //// routes = append(routes, filteredRoutes...) + ////} + // + routes := make([]*route.Route, 0) + + for _, resource := range resources { + for _, router := range a.NetworkRouters { + if router.NetworkID == resource.NetworkID { + + resourceRoutingPeers := make([]string, 0) + for _, groupID := range router.PeerGroups { + group := a.GetGroup(groupID) + if group == nil { + continue + } + + resourceRoutingPeers = append(resourceRoutingPeers, group.Peers...) + } + + if router.Peer != "" { + resourceRoutingPeers = append(resourceRoutingPeers, router.Peer) + } + + for _, peerId := range resourceRoutingPeers { + routes = append(routes, a.getNetworkResourcesRoutesG(resources, router, peerId)...) + } + } + } } return routes @@ -1341,16 +1425,16 @@ func (a *Account) GetPoliciesForNetworkResource(resourceId string) []*Policy { func (a *Account) GetPoliciesAppliedInNetwork(networkID string) []string { networkResources := a.getNetworkResources(networkID) - policieIDs := map[string]struct{}{} + policiesIDs := map[string]struct{}{} for _, resource := range networkResources { resourceAppliedPolicies := a.GetPoliciesForNetworkResource(resource.ID) for _, policy := range resourceAppliedPolicies { - policieIDs[policy.ID] = struct{}{} + policiesIDs[policy.ID] = struct{}{} } } - result := make([]string, 0, len(policieIDs)) - for id := range policieIDs { + result := make([]string, 0, len(policiesIDs)) + for id := range policiesIDs { result = append(result, id) } @@ -1372,6 +1456,24 @@ func (a *Account) getNetworkResourcesRoutes(resources []*resourceTypes.NetworkRe return routes } +// getNetworkResourcesRoutes convert the network resources list to routes list. +func (a *Account) getNetworkResourcesRoutesG(resources []*resourceTypes.NetworkResource, router *routerTypes.NetworkRouter, peerId string) []*route.Route { + routes := make([]*route.Route, 0, len(resources)) + for _, resource := range resources { + resourceAppliedPolicies := a.GetPoliciesForNetworkResource(resource.ID) + + // distribute the resource routes only if there is policy applied to it + if len(resourceAppliedPolicies) > 0 { + peer := a.GetPeer(peerId) + if peer != nil { + routes = append(routes, resource.ToRoute(peer, router)) + } + } + } + + 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{}) diff --git a/management/server/types/policy.go b/management/server/types/policy.go index c0d84e6e0..c2b82d68a 100644 --- a/management/server/types/policy.go +++ b/management/server/types/policy.go @@ -114,3 +114,12 @@ func (p *Policy) RuleGroups() []string { return groups } + +// SourceGroups returns a slice of all unique source groups referenced in the policy's rules. +func (p *Policy) SourceGroups() []string { + groups := make([]string, 0) + for _, rule := range p.Rules { + groups = append(groups, rule.Sources...) + } + return groups +}