From 26f089e30dd09ad51c252c8989a25a4b1594f6d7 Mon Sep 17 00:00:00 2001 From: bcmmbaga Date: Sat, 20 Jul 2024 12:37:25 +0300 Subject: [PATCH] Refactor peer account updates for efficiency --- management/server/peer.go | 112 +++++++++++++++----------------------- 1 file changed, 43 insertions(+), 69 deletions(-) diff --git a/management/server/peer.go b/management/server/peer.go index b8605fbb7..5bb008a40 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net" + "slices" "strings" "time" @@ -211,13 +212,19 @@ func (am *DefaultAccountManager) UpdatePeer(ctx context.Context, accountID, user } account.UpdatePeer(peer) + expired, _ := peer.LoginExpired(account.Settings.PeerLoginExpiration) + if expired && peer.LoginExpirationEnabled { + account.Network.IncSerial() + } err = am.Store.SaveAccount(ctx, account) if err != nil { return nil, err } - am.updateAccountPeers(ctx, account) + if expired && peer.LoginExpirationEnabled { + am.updateAccountPeers(ctx, account) + } return peer, nil } @@ -289,7 +296,9 @@ func (am *DefaultAccountManager) DeletePeer(ctx context.Context, accountID, peer return err } - am.updateAccountPeers(ctx, account) + if isPeerInActiveGroup(account, peerID) { + am.updateAccountPeers(ctx, account) + } return nil } @@ -491,7 +500,12 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, setupKey, userID s } account.Peers[newPeer.ID] = newPeer - account.Network.IncSerial() + + updateAccountPeers := areGroupChangesAffectPeers(account, groupsToAdd) + if updateAccountPeers { + account.Network.IncSerial() + } + err = am.Store.SaveAccount(ctx, account) if err != nil { return nil, nil, nil, err @@ -509,7 +523,9 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, setupKey, userID s am.StoreEvent(ctx, opEvent.InitiatorID, opEvent.TargetID, opEvent.AccountID, opEvent.Activity, opEvent.Meta) - am.updateAccountPeers(ctx, account) + if updateAccountPeers { + am.updateAccountPeers(ctx, account) + } approvedPeersMap, err := am.GetValidatedPeers(account) if err != nil { @@ -537,33 +553,27 @@ func (am *DefaultAccountManager) SyncPeer(ctx context.Context, sync PeerSync, ac return nil, nil, nil, status.Errorf(status.PermissionDenied, "peer login has expired, please log in once more") } - peer, updated := updatePeerMeta(peer, sync.Meta, account) - if updated { - err = am.Store.SaveAccount(ctx, account) - if err != nil { - return nil, nil, nil, err - } - - if sync.UpdateAccountPeers { - am.updateAccountPeers(ctx, account) - } - } - peerNotValid, isStatusChanged, err := am.integratedPeerValidator.IsNotValidPeer(ctx, account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra) if err != nil { return nil, nil, nil, err } - var postureChecks []*posture.Checks - if peerNotValid { emptyMap := &NetworkMap{ Network: account.Network.Copy(), } - return peer, emptyMap, postureChecks, nil + return peer, emptyMap, nil, nil } - if isStatusChanged { + peer, peerMetaUpdated := updatePeerMeta(peer, sync.Meta, account) + if peerMetaUpdated { + err = am.Store.SaveAccount(ctx, account) + if err != nil { + return nil, nil, nil, err + } + } + + if isStatusChanged || (peerMetaUpdated && sync.UpdateAccountPeers) { am.updateAccountPeers(ctx, account) } @@ -571,7 +581,7 @@ func (am *DefaultAccountManager) SyncPeer(ctx context.Context, sync PeerSync, ac if err != nil { return nil, nil, nil, err } - postureChecks = am.getPeerPostureChecks(account, peer) + postureChecks := am.getPeerPostureChecks(account, peer) return peer, account.GetPeerNetworkMap(ctx, peer.ID, am.dnsDomain, validPeersMap), postureChecks, nil } @@ -801,57 +811,9 @@ func (am *DefaultAccountManager) checkAndUpdatePeerSSHKey(ctx context.Context, p return nil, err } - // trigger network map update - am.updateAccountPeers(ctx, account) - return peer, nil } -// UpdatePeerSSHKey updates peer's public SSH key -func (am *DefaultAccountManager) UpdatePeerSSHKey(ctx context.Context, peerID string, sshKey string) error { - if sshKey == "" { - log.WithContext(ctx).Debugf("empty SSH key provided for peer %s, skipping update", peerID) - return nil - } - - account, err := am.Store.GetAccountByPeerID(ctx, peerID) - if err != nil { - return err - } - - unlock := am.Store.AcquireAccountWriteLock(ctx, account.Id) - defer unlock() - - // ensure that we consider modification happened meanwhile (because we were outside the account lock when we fetched the account) - account, err = am.Store.GetAccount(ctx, account.Id) - if err != nil { - return err - } - - peer := account.GetPeer(peerID) - if peer == nil { - return status.Errorf(status.NotFound, "peer with ID %s not found", peerID) - } - - if peer.SSHKey == sshKey { - log.WithContext(ctx).Debugf("same SSH key provided for peer %s, skipping update", peerID) - return nil - } - - peer.SSHKey = sshKey - account.UpdatePeer(peer) - - err = am.Store.SaveAccount(ctx, account) - if err != nil { - return err - } - - // trigger network map update - am.updateAccountPeers(ctx, account) - - return nil -} - // GetPeer for a given accountID, peerID and userID error if not found. func (am *DefaultAccountManager) GetPeer(ctx context.Context, accountID, peerID, userID string) (*nbpeer.Peer, error) { unlock := am.Store.AcquireAccountWriteLock(ctx, accountID) @@ -935,3 +897,15 @@ func (am *DefaultAccountManager) updateAccountPeers(ctx context.Context, account am.peersUpdateManager.SendUpdate(ctx, peer.ID, &UpdateMessage{Update: update}) } } + +// IsPeerInActiveGroup checks if the given peer is part of a group that is used +// in an active DNS, route, or ACL configuration. +func isPeerInActiveGroup(account *Account, peerID string) bool { + peerGroupIDs := make([]string, 0) + for _, group := range account.Groups { + if slices.Contains(group.Peers, peerID) { + peerGroupIDs = append(peerGroupIDs, group.ID) + } + } + return areGroupChangesAffectPeers(account, peerGroupIDs) +}