diff --git a/go.mod b/go.mod index cf2a23758..8120efe54 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,7 @@ require ( github.com/miekg/dns v1.1.59 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/nadoo/ipset v0.5.0 - github.com/netbirdio/management-integrations/integrations v0.0.0-20250718071730-f4d133556ff5 + github.com/netbirdio/management-integrations/integrations v0.0.0-20250718161635-83fb99b09b5a github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20250514131221-a464fd5f30cb github.com/okta/okta-sdk-golang/v2 v2.18.0 github.com/oschwald/maxminddb-golang v1.12.0 diff --git a/go.sum b/go.sum index 699a832dd..c9938908e 100644 --- a/go.sum +++ b/go.sum @@ -503,8 +503,8 @@ github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944 h1:TDtJKmM6S github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944/go.mod h1:sHA6TRxjQ6RLbnI+3R4DZo2Eseg/iKiPRfNmcuNySVQ= github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e h1:PURA50S8u4mF6RrkYYCAvvPCixhqqEiEy3Ej6avh04c= github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e/go.mod h1:YMLU7qbKfVjmEv7EoZPIVEI+kNYxWCdPK3VS0BU+U4Q= -github.com/netbirdio/management-integrations/integrations v0.0.0-20250718071730-f4d133556ff5 h1:Zfn8d83OVyELCdxgprcyXR3D8uqoxHtXE9PUxVXDx/w= -github.com/netbirdio/management-integrations/integrations v0.0.0-20250718071730-f4d133556ff5/go.mod h1:Gi9raplYzCCyh07Olw/DVfCJTFgpr1WCXJ/Q+8TSA9Q= +github.com/netbirdio/management-integrations/integrations v0.0.0-20250718161635-83fb99b09b5a h1:Kmq74+axAiJrD98+uAr53sIuj/zwMrak05Ofoy4SWYU= +github.com/netbirdio/management-integrations/integrations v0.0.0-20250718161635-83fb99b09b5a/go.mod h1:Gi9raplYzCCyh07Olw/DVfCJTFgpr1WCXJ/Q+8TSA9Q= github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502 h1:3tHlFmhTdX9axERMVN63dqyFqnvuD+EMJHzM7mNGON8= github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20250514131221-a464fd5f30cb h1:Cr6age+ePALqlSvtp7wc6lYY97XN7rkD1K4XEDmY+TU= diff --git a/management/server/account/manager.go b/management/server/account/manager.go index f8aa2756a..8c7e95e3d 100644 --- a/management/server/account/manager.go +++ b/management/server/account/manager.go @@ -101,7 +101,7 @@ type Manager interface { DeletePostureChecks(ctx context.Context, accountID, postureChecksID, userID string) error ListPostureChecks(ctx context.Context, accountID, userID string) ([]*posture.Checks, error) GetIdpManager() idp.Manager - UpdateIntegratedValidatorGroups(ctx context.Context, accountID string, userID string, groups []string) error + UpdateIntegratedValidator(ctx context.Context, accountID, userID, validator string, groups []string) error GroupValidation(ctx context.Context, accountId string, groups []string) (bool, error) GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, error) SyncAndMarkPeer(ctx context.Context, accountID string, peerPubKey string, meta nbpeer.PeerSystemMeta, realIP net.IP) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) diff --git a/management/server/integrated_validator.go b/management/server/integrated_validator.go index e3e474411..b89739be9 100644 --- a/management/server/integrated_validator.go +++ b/management/server/integrated_validator.go @@ -3,6 +3,7 @@ package server import ( "context" "errors" + "fmt" log "github.com/sirupsen/logrus" @@ -12,34 +13,44 @@ import ( "github.com/netbirdio/netbird/management/server/types" ) -// UpdateIntegratedValidatorGroups updates the integrated validator groups for a specified account. +// UpdateIntegratedValidator updates the integrated validator groups for a specified account. // It retrieves the account associated with the provided userID, then updates the integrated validator groups // with the provided list of group ids. The updated account is then saved. // // Parameters: // - accountID: The ID of the account for which integrated validator groups are to be updated. // - userID: The ID of the user whose account is being updated. +// - validator: The validator type to use, or empty to remove. // - groups: A slice of strings representing the ids of integrated validator groups to be updated. // // Returns: // - error: An error if any occurred during the process, otherwise returns nil -func (am *DefaultAccountManager) UpdateIntegratedValidatorGroups(ctx context.Context, accountID string, userID string, groups []string) error { - ok, err := am.GroupValidation(ctx, accountID, groups) - if err != nil { - log.WithContext(ctx).Debugf("error validating groups: %s", err.Error()) - return err +func (am *DefaultAccountManager) UpdateIntegratedValidator(ctx context.Context, accountID, userID, validator string, groups []string) error { + if validator != "" && len(groups) == 0 { + return fmt.Errorf("at least one group must be specified for validator") } - if !ok { - log.WithContext(ctx).Debugf("invalid groups") - return errors.New("invalid groups") + if validator != "" { + ok, err := am.GroupValidation(ctx, accountID, groups) + if err != nil { + log.WithContext(ctx).Debugf("error validating groups: %s", err.Error()) + return err + } + + if !ok { + log.WithContext(ctx).Debugf("invalid groups") + return errors.New("invalid groups") + } + } else { + // ensure groups is empty + groups = []string{} } unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() return am.Store.ExecuteInTransaction(ctx, func(transaction store.Store) error { - a, err := transaction.GetAccountByUser(ctx, userID) + a, err := transaction.GetAccount(ctx, accountID) if err != nil { return err } @@ -52,6 +63,8 @@ func (am *DefaultAccountManager) UpdateIntegratedValidatorGroups(ctx context.Con extra = &types.ExtraSettings{} a.Settings.Extra = extra } + + extra.IntegratedValidator = validator extra.IntegratedValidatorGroups = groups return transaction.SaveAccount(ctx, a) }) @@ -99,7 +112,7 @@ func (am *DefaultAccountManager) GetValidatedPeers(ctx context.Context, accountI return nil, err } - return am.integratedPeerValidator.GetValidatedPeers(accountID, groups, peers, settings.Extra) + return am.integratedPeerValidator.GetValidatedPeers(ctx, accountID, groups, peers, settings.Extra) } type MockIntegratedValidator struct { @@ -118,7 +131,7 @@ func (a MockIntegratedValidator) ValidatePeer(_ context.Context, update *nbpeer. return update, false, nil } -func (a MockIntegratedValidator) GetValidatedPeers(accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *types.ExtraSettings) (map[string]struct{}, error) { +func (a MockIntegratedValidator) GetValidatedPeers(_ context.Context, accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *types.ExtraSettings) (map[string]struct{}, error) { validatedPeers := make(map[string]struct{}) for _, peer := range peers { validatedPeers[peer.ID] = struct{}{} @@ -134,7 +147,7 @@ func (MockIntegratedValidator) IsNotValidPeer(_ context.Context, accountID strin return false, false, nil } -func (MockIntegratedValidator) PeerDeleted(_ context.Context, _, _ string) error { +func (MockIntegratedValidator) PeerDeleted(_ context.Context, _, _ string, extraSettings *types.ExtraSettings) error { return nil } diff --git a/management/server/integrations/integrated_validator/interface.go b/management/server/integrations/integrated_validator/interface.go index 245c0168f..4d4a8cdf6 100644 --- a/management/server/integrations/integrated_validator/interface.go +++ b/management/server/integrations/integrated_validator/interface.go @@ -14,8 +14,8 @@ type IntegratedValidator interface { ValidatePeer(ctx context.Context, update *nbpeer.Peer, peer *nbpeer.Peer, userID string, accountID string, dnsDomain string, peersGroup []string, extraSettings *types.ExtraSettings) (*nbpeer.Peer, bool, error) PreparePeer(ctx context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings) *nbpeer.Peer IsNotValidPeer(ctx context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings) (bool, bool, error) - GetValidatedPeers(accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *types.ExtraSettings) (map[string]struct{}, error) - PeerDeleted(ctx context.Context, accountID, peerID string) error + GetValidatedPeers(ctx context.Context, accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *types.ExtraSettings) (map[string]struct{}, error) + PeerDeleted(ctx context.Context, accountID, peerID string, extraSettings *types.ExtraSettings) error SetPeerInvalidationListener(fn func(accountID string)) Stop(ctx context.Context) ValidateFlowResponse(ctx context.Context, peerKey string, flowResponse *proto.PKCEAuthorizationFlow) *proto.PKCEAuthorizationFlow diff --git a/management/server/mock_server/account_mock.go b/management/server/mock_server/account_mock.go index b1ec66286..a16e3652c 100644 --- a/management/server/mock_server/account_mock.go +++ b/management/server/mock_server/account_mock.go @@ -102,7 +102,7 @@ type MockAccountManager struct { DeletePostureChecksFunc func(ctx context.Context, accountID, postureChecksID, userID string) error ListPostureChecksFunc func(ctx context.Context, accountID, userID string) ([]*posture.Checks, error) GetIdpManagerFunc func() idp.Manager - UpdateIntegratedValidatorGroupsFunc func(ctx context.Context, accountID string, userID string, groups []string) error + UpdateIntegratedValidatorFunc func(ctx context.Context, accountID, userID, validator string, groups []string) error GroupValidationFunc func(ctx context.Context, accountId string, groups []string) (bool, error) SyncPeerMetaFunc func(ctx context.Context, peerPubKey string, meta nbpeer.PeerSystemMeta) error FindExistingPostureCheckFunc func(accountID string, checks *posture.ChecksDefinition) (*posture.Checks, error) @@ -769,10 +769,10 @@ func (am *MockAccountManager) GetIdpManager() idp.Manager { return nil } -// UpdateIntegratedValidatorGroups mocks UpdateIntegratedApprovalGroups of the AccountManager interface -func (am *MockAccountManager) UpdateIntegratedValidatorGroups(ctx context.Context, accountID string, userID string, groups []string) error { - if am.UpdateIntegratedValidatorGroupsFunc != nil { - return am.UpdateIntegratedValidatorGroupsFunc(ctx, accountID, userID, groups) +// UpdateIntegratedValidator mocks UpdateIntegratedApprovalGroups of the AccountManager interface +func (am *MockAccountManager) UpdateIntegratedValidator(ctx context.Context, accountID, userID, validator string, groups []string) error { + if am.UpdateIntegratedValidatorFunc != nil { + return am.UpdateIntegratedValidatorFunc(ctx, accountID, userID, validator, groups) } return status.Errorf(codes.Unimplemented, "method UpdateIntegratedValidatorGroups is not implemented") } diff --git a/management/server/peer.go b/management/server/peer.go index c6ade83c0..8f3eb2331 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -87,7 +87,7 @@ func (am *DefaultAccountManager) getUserAccessiblePeers(ctx context.Context, acc return nil, err } - approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(accountID, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) + approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(ctx, accountID, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) if err != nil { return nil, err } @@ -412,7 +412,7 @@ func (am *DefaultAccountManager) GetNetworkMap(ctx context.Context, peerID strin groups[groupID] = group.Peers } - validatedPeers, err := am.integratedPeerValidator.GetValidatedPeers(account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) + validatedPeers, err := am.integratedPeerValidator.GetValidatedPeers(ctx, account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) if err != nil { return nil, err } @@ -1036,7 +1036,7 @@ func (am *DefaultAccountManager) getValidatedPeerWithMap(ctx context.Context, is return nil, nil, nil, err } - approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) + approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(ctx, account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) if err != nil { return nil, nil, nil, err } @@ -1156,7 +1156,7 @@ func (am *DefaultAccountManager) checkIfUserOwnsPeer(ctx context.Context, accoun return nil, err } - approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(accountID, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) + approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(ctx, accountID, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) if err != nil { return nil, err } @@ -1204,7 +1204,7 @@ func (am *DefaultAccountManager) UpdateAccountPeers(ctx context.Context, account return } - approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) + approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(ctx, account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) if err != nil { log.WithContext(ctx).Errorf("failed to send out updates to peers, failed to get validate peers: %v", err) return @@ -1337,7 +1337,7 @@ func (am *DefaultAccountManager) UpdateAccountPeer(ctx context.Context, accountI return } - approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) + approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(ctx, account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) if err != nil { log.WithContext(ctx).Errorf("failed to send update to peer %s, failed to validate peers: %v", peerId, err) return @@ -1571,7 +1571,7 @@ func deletePeers(ctx context.Context, am *DefaultAccountManager, transaction sto } } - if err := am.integratedPeerValidator.PeerDeleted(ctx, accountID, peer.ID); err != nil { + if err := am.integratedPeerValidator.PeerDeleted(ctx, accountID, peer.ID, settings.Extra); err != nil { return nil, err } diff --git a/management/server/types/settings.go b/management/server/types/settings.go index a22a36b03..37c728bf8 100644 --- a/management/server/types/settings.go +++ b/management/server/types/settings.go @@ -77,6 +77,8 @@ type ExtraSettings struct { // PeerApprovalEnabled enables or disables the need for peers bo be approved by an administrator PeerApprovalEnabled bool + // IntegratedValidator is the string enum for the integrated validator type + IntegratedValidator string // IntegratedValidatorGroups list of group IDs to be used with integrated approval configurations IntegratedValidatorGroups []string `gorm:"serializer:json"` @@ -93,5 +95,10 @@ func (e *ExtraSettings) Copy() *ExtraSettings { return &ExtraSettings{ PeerApprovalEnabled: e.PeerApprovalEnabled, IntegratedValidatorGroups: append(cpGroup, e.IntegratedValidatorGroups...), + IntegratedValidator: e.IntegratedValidator, + FlowEnabled: e.FlowEnabled, + FlowPacketCounterEnabled: e.FlowPacketCounterEnabled, + FlowENCollectionEnabled: e.FlowENCollectionEnabled, + FlowDnsCollectionEnabled: e.FlowDnsCollectionEnabled, } }