From 0343c5f239c34987abfcb7bf7f9808faf8f6bc65 Mon Sep 17 00:00:00 2001 From: Givi Khojanashvili Date: Wed, 12 Apr 2023 11:39:17 +0400 Subject: [PATCH] Rollback simple ACL rules processing. (#803) --- management/server/account.go | 2 +- management/server/file_store.go | 4 +- management/server/peer.go | 96 ++++++++++++++++++++++++++++++++- management/server/peer_test.go | 2 + 4 files changed, 98 insertions(+), 6 deletions(-) diff --git a/management/server/account.go b/management/server/account.go index 416584774..b9a096015 100644 --- a/management/server/account.go +++ b/management/server/account.go @@ -283,7 +283,7 @@ func (a *Account) GetGroup(groupID string) *Group { // GetPeerNetworkMap returns a group by ID if exists, nil otherwise func (a *Account) GetPeerNetworkMap(peerID, dnsDomain string) *NetworkMap { - aclPeers, _ := a.getPeersByPolicy(peerID) + aclPeers := a.getPeersByACL(peerID) // exclude expired peers var peersToConnect []*Peer var expiredPeers []*Peer diff --git a/management/server/file_store.go b/management/server/file_store.go index 1765eb917..1f20ba4fa 100644 --- a/management/server/file_store.go +++ b/management/server/file_store.go @@ -286,9 +286,7 @@ func (s *FileStore) SaveAccount(account *Account) error { s.PrivateDomain2AccountID[accountCopy.Domain] = accountCopy.Id } - if accountCopy.Rules == nil { - accountCopy.Rules = make(map[string]*Rule) - } + accountCopy.Rules = make(map[string]*Rule) for _, policy := range accountCopy.Policies { for _, rule := range policy.Rules { accountCopy.Rules[rule.ID] = rule.ToRule() diff --git a/management/server/peer.go b/management/server/peer.go index a223308b0..0c18f1124 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -209,7 +209,7 @@ func (am *DefaultAccountManager) GetPeers(accountID, userID string) ([]*Peer, er // fetch all the peers that have access to the user's peers for _, peer := range peers { // TODO: use firewall rules - aclPeers, _ := account.getPeersByPolicy(peer.ID) + aclPeers := account.getPeersByACL(peer.ID) for _, p := range aclPeers { peersMap[p.ID] = p } @@ -816,7 +816,7 @@ func (am *DefaultAccountManager) GetPeer(accountID, peerID, userID string) (*Pee } for _, p := range userPeers { - aclPeers, _ := account.getPeersByPolicy(p.ID) + aclPeers := account.getPeersByACL(p.ID) for _, aclPeer := range aclPeers { if aclPeer.ID == peerID { return peer, nil @@ -833,6 +833,98 @@ func updatePeerMeta(peer *Peer, meta PeerSystemMeta, account *Account) *Peer { return peer } +// GetPeerRules returns a list of source or destination rules of a given peer. +func (a *Account) GetPeerRules(peerID string) (srcRules []*Rule, dstRules []*Rule) { + // Rules are group based so there is no direct access to peers. + // First, find all groups that the given peer belongs to + peerGroups := make(map[string]struct{}) + + for s, group := range a.Groups { + for _, peer := range group.Peers { + if peerID == peer { + peerGroups[s] = struct{}{} + break + } + } + } + + // Second, find all rules that have discovered source and destination groups + srcRulesMap := make(map[string]*Rule) + dstRulesMap := make(map[string]*Rule) + for _, rule := range a.Rules { + for _, g := range rule.Source { + if _, ok := peerGroups[g]; ok && srcRulesMap[rule.ID] == nil { + srcRules = append(srcRules, rule) + srcRulesMap[rule.ID] = rule + } + } + for _, g := range rule.Destination { + if _, ok := peerGroups[g]; ok && dstRulesMap[rule.ID] == nil { + dstRules = append(dstRules, rule) + dstRulesMap[rule.ID] = rule + } + } + } + + return srcRules, dstRules +} + +// getPeersByACL returns all peers that given peer has access to. +func (a *Account) getPeersByACL(peerID string) []*Peer { + var peers []*Peer + srcRules, dstRules := a.GetPeerRules(peerID) + + groups := map[string]*Group{} + for _, r := range srcRules { + if r.Disabled { + continue + } + if r.Flow == TrafficFlowBidirect { + for _, gid := range r.Destination { + if group, ok := a.Groups[gid]; ok { + groups[gid] = group + } + } + } + } + + for _, r := range dstRules { + if r.Disabled { + continue + } + if r.Flow == TrafficFlowBidirect { + for _, gid := range r.Source { + if group, ok := a.Groups[gid]; ok { + groups[gid] = group + } + } + } + } + + peersSet := make(map[string]struct{}) + for _, g := range groups { + for _, pid := range g.Peers { + peer, ok := a.Peers[pid] + if !ok { + log.Warnf( + "peer %s found in group %s but doesn't belong to account %s", + pid, + g.ID, + a.Id, + ) + continue + } + // exclude original peer + if _, ok := peersSet[peer.ID]; peer.ID != peerID && !ok { + peersSet[peer.ID] = struct{}{} + peers = append(peers, peer.Copy()) + } + } + } + + return peers +} + // updateAccountPeers updates all peers that belong to an account. // Should be called when changes have to be synced to peers. func (am *DefaultAccountManager) updateAccountPeers(account *Account) error { diff --git a/management/server/peer_test.go b/management/server/peer_test.go index b10a66e12..9dbd28d29 100644 --- a/management/server/peer_test.go +++ b/management/server/peer_test.go @@ -136,6 +136,8 @@ func TestAccountManager_GetNetworkMap(t *testing.T) { } func TestAccountManager_GetNetworkMapWithPolicy(t *testing.T) { + // TODO: disable until we start use policy again + t.Skip() manager, err := createManager(t) if err != nil { t.Fatal(err)