Refactor peer account updates for efficiency

This commit is contained in:
bcmmbaga 2024-07-20 12:37:25 +03:00
parent 713c0341be
commit 26f089e30d
No known key found for this signature in database
GPG Key ID: 7249A19D20613553

View File

@ -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)
}