From 5ea280666397a746ea0ef3597325ea1b5fd7cd5e Mon Sep 17 00:00:00 2001 From: Pascal Fischer <32096965+pascal-fischer@users.noreply.github.com> Date: Thu, 10 Apr 2025 11:06:52 +0200 Subject: [PATCH] [management] use permission modules (#3622) --- client/cmd/testutil_test.go | 2 +- client/internal/engine_test.go | 6 +- client/server/server_test.go | 5 +- management/client/client_test.go | 13 +- management/server/account.go | 29 ++-- management/server/account_test.go | 10 +- management/server/dns.go | 28 ++- management/server/dns_test.go | 5 +- management/server/event.go | 31 ++-- management/server/group.go | 38 ++--- management/server/groups/manager.go | 6 +- .../http/handlers/peers/peers_handler.go | 3 +- .../http/testing/testing_tools/tools.go | 11 +- management/server/management_proto_test.go | 6 +- management/server/management_test.go | 4 +- management/server/nameserver.go | 55 +++--- management/server/nameserver_test.go | 5 +- management/server/networks/manager.go | 12 +- management/server/networks/manager_test.go | 40 ++--- .../server/networks/resources/manager.go | 16 +- .../server/networks/resources/manager_test.go | 64 +++---- management/server/networks/routers/manager.go | 14 +- .../server/networks/routers/manager_test.go | 40 ++--- management/server/peer.go | 80 ++++----- management/server/peer_test.go | 13 +- management/server/peers/manager.go | 8 +- management/server/permissions/manager.go | 123 +++++--------- management/server/permissions/manager_mock.go | 82 +++++++++ .../server/permissions/modules/module.go | 19 +++ .../permissions/operations/operation.go | 8 + management/server/permissions/roles/admin.go | 21 +++ management/server/permissions/roles/owner.go | 14 ++ .../permissions/roles/role_permissions.go | 21 +++ management/server/permissions/roles/user.go | 14 ++ management/server/policy.go | 54 ++---- management/server/posture_checks.go | 54 ++---- management/server/route.go | 55 +++--- management/server/route_test.go | 5 +- management/server/settings/manager.go | 4 +- management/server/setupkey.go | 67 +++----- management/server/status/error.go | 15 ++ management/server/testdata/networks.sql | 4 + management/server/user.go | 160 ++++++++++-------- management/server/user_test.go | 102 +++++------ 44 files changed, 735 insertions(+), 631 deletions(-) create mode 100644 management/server/permissions/manager_mock.go create mode 100644 management/server/permissions/modules/module.go create mode 100644 management/server/permissions/operations/operation.go create mode 100644 management/server/permissions/roles/admin.go create mode 100644 management/server/permissions/roles/owner.go create mode 100644 management/server/permissions/roles/role_permissions.go create mode 100644 management/server/permissions/roles/user.go diff --git a/client/cmd/testutil_test.go b/client/cmd/testutil_test.go index 31bff26cb..70abe4abe 100644 --- a/client/cmd/testutil_test.go +++ b/client/cmd/testutil_test.go @@ -92,11 +92,11 @@ func startManagement(t *testing.T, config *types.Config, testFile string) (*grpc metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) - permissionsManagerMock := permissions.NewManagerMock() ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) + permissionsManagerMock := permissions.NewMockManager(ctrl) accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, iv, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) if err != nil { diff --git a/client/internal/engine_test.go b/client/internal/engine_test.go index 352abd62b..7afe0fcd6 100644 --- a/client/internal/engine_test.go +++ b/client/internal/engine_test.go @@ -1439,8 +1439,6 @@ func startManagement(t *testing.T, dataDir, testFile string) (*grpc.Server, stri metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) - permissionsManagerMock := permissions.NewManagerMock() - ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) @@ -1449,7 +1447,9 @@ func startManagement(t *testing.T, dataDir, testFile string) (*grpc.Server, stri Return(&types.Settings{}, nil). AnyTimes() - accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + permissionsManager := permissions.NewManager(store) + + accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) if err != nil { return nil, "", err } diff --git a/client/server/server_test.go b/client/server/server_test.go index 8ee8294cf..f2dff76fd 100644 --- a/client/server/server_test.go +++ b/client/server/server_test.go @@ -8,10 +8,11 @@ import ( "time" "github.com/golang/mock/gomock" - "github.com/netbirdio/management-integrations/integrations" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel" + "github.com/netbirdio/management-integrations/integrations" + log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "google.golang.org/grpc" @@ -200,10 +201,10 @@ func startManagement(t *testing.T, signalAddr string, counter *int) (*grpc.Serve metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) - permissionsManagerMock := permissions.NewManagerMock() ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) + permissionsManagerMock := permissions.NewMockManager(ctrl) accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) if err != nil { diff --git a/management/client/client_test.go b/management/client/client_test.go index 6c30ff371..b22a79930 100644 --- a/management/client/client_test.go +++ b/management/client/client_test.go @@ -75,7 +75,6 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) { metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) - permissionsManagerMock := permissions.NewManagerMock() ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) @@ -88,6 +87,18 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) { ). Return(&types.Settings{}, nil). AnyTimes() + permissionsManagerMock := permissions.NewMockManager(ctrl) + permissionsManagerMock. + EXPECT(). + ValidateUserPermissions( + gomock.Any(), + gomock.Any(), + gomock.Any(), + gomock.Any(), + gomock.Any(), + ). + Return(true, nil). + AnyTimes() accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) if err != nil { diff --git a/management/server/account.go b/management/server/account.go index 0b52df2f0..7aa96e626 100644 --- a/management/server/account.go +++ b/management/server/account.go @@ -30,6 +30,8 @@ import ( "github.com/netbirdio/netbird/management/server/integrations/port_forwarding" nbpeer "github.com/netbirdio/netbird/management/server/peer" "github.com/netbirdio/netbird/management/server/permissions" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/posture" "github.com/netbirdio/netbird/management/server/settings" "github.com/netbirdio/netbird/management/server/status" @@ -258,7 +260,7 @@ func (am *DefaultAccountManager) UpdateAccountSettings(ctx context.Context, acco return nil, err } - allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Settings, permissions.Write) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Settings, operations.Write) if err != nil { return nil, fmt.Errorf("failed to validate user permissions: %w", err) } @@ -508,7 +510,7 @@ func (am *DefaultAccountManager) DeleteAccount(ctx context.Context, accountID, u return err } - allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Accounts, permissions.Write) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Accounts, operations.Write) if err != nil { return fmt.Errorf("failed to validate user permissions: %w", err) } @@ -1021,13 +1023,12 @@ func (am *DefaultAccountManager) GetAccount(ctx context.Context, accountID strin // GetAccountByID returns an account associated with this account ID. func (am *DefaultAccountManager) GetAccountByID(ctx context.Context, accountID string, userID string) (*types.Account, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Accounts, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetAccount(ctx, accountID) @@ -1515,19 +1516,13 @@ func (am *DefaultAccountManager) getFreeDNSLabel(ctx context.Context, s store.St } func (am *DefaultAccountManager) GetAccountSettings(ctx context.Context, accountID string, userID string) (*types.Settings, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Settings, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err + if !allowed { + return nil, status.NewPermissionDeniedError() } - - if !user.HasAdminPower() && !user.IsServiceUser { - return nil, status.Errorf(status.PermissionDenied, "the user has no permission to access account data") - } - return am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID) } diff --git a/management/server/account_test.go b/management/server/account_test.go index 49a7464e3..cf4523e70 100644 --- a/management/server/account_test.go +++ b/management/server/account_test.go @@ -2794,13 +2794,13 @@ func TestAccount_UserGroupsRemoveFromPeers(t *testing.T) { }) } -//type TB interface { +// type TB interface { // Cleanup(func()) // Helper() // TempDir() string // Errorf(format string, args ...interface{}) // Fatalf(format string, args ...interface{}) -//} +// } func createManager(t testing.TB) (*DefaultAccountManager, error) { t.Helper() @@ -2816,8 +2816,6 @@ func createManager(t testing.TB) (*DefaultAccountManager, error) { return nil, err } - permissionsManagerMock := permissions.NewManagerMock() - ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) @@ -2831,7 +2829,9 @@ func createManager(t testing.TB) (*DefaultAccountManager, error) { Return(false, nil). AnyTimes() - manager, err := BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + permissionsManager := permissions.NewManager(store) + + manager, err := BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) if err != nil { return nil, err } diff --git a/management/server/dns.go b/management/server/dns.go index 8dcc59413..d457db773 100644 --- a/management/server/dns.go +++ b/management/server/dns.go @@ -10,6 +10,8 @@ import ( nbdns "github.com/netbirdio/netbird/dns" "github.com/netbirdio/netbird/management/proto" "github.com/netbirdio/netbird/management/server/activity" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -62,17 +64,12 @@ func (c *DNSConfigCache) SetNameServerGroup(key string, value *proto.NameServerG // GetDNSSettings validates a user role and returns the DNS settings for the provided account ID func (am *DefaultAccountManager) GetDNSSettings(ctx context.Context, accountID string, userID string) (*types.DNSSettings, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Dns, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetAccountDNSSettings(ctx, store.LockingStrengthShare, accountID) @@ -84,17 +81,12 @@ func (am *DefaultAccountManager) SaveDNSSettings(ctx context.Context, accountID return status.Errorf(status.InvalidArgument, "the dns settings provided are nil") } - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Dns, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err - } - - if !user.HasAdminPower() { - return status.NewAdminPermissionError() + if !allowed { + return status.NewPermissionDeniedError() } var updateAccountPeers bool diff --git a/management/server/dns_test.go b/management/server/dns_test.go index aeccc6187..8a0e0cd02 100644 --- a/management/server/dns_test.go +++ b/management/server/dns_test.go @@ -211,14 +211,13 @@ func createDNSManager(t *testing.T) (*DefaultAccountManager, error) { metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) - permissionsManagerMock := permissions.NewManagerMock() ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) - - return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.test", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + permissionsManager := permissions.NewManager(store) + return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.test", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) } func createDNSStore(t *testing.T) (store.Store, error) { diff --git a/management/server/event.go b/management/server/event.go index 58c6c70fb..6342bfedb 100644 --- a/management/server/event.go +++ b/management/server/event.go @@ -9,6 +9,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/netbirdio/netbird/management/server/activity" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -21,17 +23,12 @@ func isEnabled() bool { // GetEvents returns a list of activity events of an account func (am *DefaultAccountManager) GetEvents(ctx context.Context, accountID, userID string) ([]*activity.Event, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Events, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if !(user.HasAdminPower() || user.IsServiceUser) { - return nil, status.Errorf(status.PermissionDenied, "only users with admin power can view events") + if !allowed { + return nil, status.NewPermissionDeniedError() } events, err := am.eventStore.Get(ctx, accountID, 0, 10000, true) @@ -56,7 +53,7 @@ func (am *DefaultAccountManager) GetEvents(ctx context.Context, accountID, userI filtered = append(filtered, event) } - err = am.fillEventsWithUserInfo(ctx, events, accountID, user) + err = am.fillEventsWithUserInfo(ctx, events, accountID, userID) if err != nil { return nil, err } @@ -89,8 +86,8 @@ type eventUserInfo struct { accountId string } -func (am *DefaultAccountManager) fillEventsWithUserInfo(ctx context.Context, events []*activity.Event, accountId string, user *types.User) error { - eventUserInfo, err := am.getEventsUserInfo(ctx, events, accountId, user) +func (am *DefaultAccountManager) fillEventsWithUserInfo(ctx context.Context, events []*activity.Event, accountId string, userId string) error { + eventUserInfo, err := am.getEventsUserInfo(ctx, events, accountId, userId) if err != nil { return err } @@ -105,14 +102,14 @@ func (am *DefaultAccountManager) fillEventsWithUserInfo(ctx context.Context, eve return nil } -func (am *DefaultAccountManager) getEventsUserInfo(ctx context.Context, events []*activity.Event, accountId string, user *types.User) (map[string]eventUserInfo, error) { +func (am *DefaultAccountManager) getEventsUserInfo(ctx context.Context, events []*activity.Event, accountId string, userId string) (map[string]eventUserInfo, error) { accountUsers, err := am.Store.GetAccountUsers(ctx, store.LockingStrengthShare, accountId) if err != nil { return nil, err } // @note check whether using a external initiator user here is an issue - userInfos, err := am.BuildUserInfosForAccount(ctx, accountId, user.Id, accountUsers) + userInfos, err := am.BuildUserInfosForAccount(ctx, accountId, userId, accountUsers) if err != nil { return nil, err } @@ -146,10 +143,10 @@ func (am *DefaultAccountManager) getEventsUserInfo(ctx context.Context, events [ return eventUserInfos, nil } - return am.getEventsExternalUserInfo(ctx, externalUserIds, eventUserInfos, user) + return am.getEventsExternalUserInfo(ctx, externalUserIds, eventUserInfos, userId) } -func (am *DefaultAccountManager) getEventsExternalUserInfo(ctx context.Context, externalUserIds []string, eventUserInfos map[string]eventUserInfo, user *types.User) (map[string]eventUserInfo, error) { +func (am *DefaultAccountManager) getEventsExternalUserInfo(ctx context.Context, externalUserIds []string, eventUserInfos map[string]eventUserInfo, userId string) (map[string]eventUserInfo, error) { externalAccountId := "" fetched := make(map[string]struct{}) externalUsers := []*types.User{} @@ -182,7 +179,7 @@ func (am *DefaultAccountManager) getEventsExternalUserInfo(ctx context.Context, return eventUserInfos, nil } - externalUserInfos, err := am.BuildUserInfosForAccount(ctx, externalAccountId, user.Id, externalUsers) + externalUserInfos, err := am.BuildUserInfosForAccount(ctx, externalAccountId, userId, externalUsers) if err != nil { return nil, err } diff --git a/management/server/group.go b/management/server/group.go index 01ebb457c..c102cedb8 100644 --- a/management/server/group.go +++ b/management/server/group.go @@ -12,6 +12,8 @@ import ( nbdns "github.com/netbirdio/netbird/dns" "github.com/netbirdio/netbird/management/server/activity" routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -30,17 +32,13 @@ func (e *GroupLinkError) Error() string { // CheckGroupPermissions validates if a user has the necessary permissions to view groups func (am *DefaultAccountManager) CheckGroupPermissions(ctx context.Context, accountID, userID string) error { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Groups, operations.Read) if err != nil { return err } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err - } - - if user.IsRegularUser() { - return status.NewAdminPermissionError() + if !allowed { + return status.NewPermissionDeniedError() } return nil @@ -78,17 +76,12 @@ func (am *DefaultAccountManager) SaveGroup(ctx context.Context, accountID, userI // Note: This function does not acquire the global lock. // It is the caller's responsibility to ensure proper locking is in place before invoking this method. func (am *DefaultAccountManager) SaveGroups(ctx context.Context, accountID, userID string, groups []*types.Group) error { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Groups, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err - } - - if user.IsRegularUser() { - return status.NewAdminPermissionError() + if !allowed { + return status.NewPermissionDeniedError() } var eventsToStore []func() @@ -210,17 +203,12 @@ func (am *DefaultAccountManager) DeleteGroup(ctx context.Context, accountID, use // If an error occurs while deleting a group, the function skips it and continues deleting other groups. // Errors are collected and returned at the end. func (am *DefaultAccountManager) DeleteGroups(ctx context.Context, accountID, userID string, groupIDs []string) error { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Groups, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err - } - - if user.IsRegularUser() { - return status.NewAdminPermissionError() + if !allowed { + return status.NewPermissionDeniedError() } var allErrors error diff --git a/management/server/groups/manager.go b/management/server/groups/manager.go index 27698a085..48e28d4f8 100644 --- a/management/server/groups/manager.go +++ b/management/server/groups/manager.go @@ -8,6 +8,8 @@ import ( "github.com/netbirdio/netbird/management/server/activity" "github.com/netbirdio/netbird/management/server/http/api" "github.com/netbirdio/netbird/management/server/permissions" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" ) @@ -39,7 +41,7 @@ func NewManager(store store.Store, permissionsManager permissions.Manager, accou } func (m *managerImpl) GetAllGroups(ctx context.Context, accountID, userID string) ([]*types.Group, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Groups, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Groups, operations.Read) if err != nil { return nil, err } @@ -70,7 +72,7 @@ func (m *managerImpl) GetAllGroupsMap(ctx context.Context, accountID, userID str } func (m *managerImpl) AddResourceToGroup(ctx context.Context, accountID, userID, groupID string, resource *types.Resource) error { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Groups, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Groups, operations.Write) if err != nil { return err } diff --git a/management/server/http/handlers/peers/peers_handler.go b/management/server/http/handlers/peers/peers_handler.go index ae7255e5f..fa78836d8 100644 --- a/management/server/http/handlers/peers/peers_handler.go +++ b/management/server/http/handlers/peers/peers_handler.go @@ -10,6 +10,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/netbirdio/netbird/management/server/account" + "github.com/netbirdio/netbird/management/server/activity" nbcontext "github.com/netbirdio/netbird/management/server/context" "github.com/netbirdio/netbird/management/server/groups" "github.com/netbirdio/netbird/management/server/http/api" @@ -244,7 +245,7 @@ func (h *Handler) GetAccessiblePeers(w http.ResponseWriter, r *http.Request) { return } - account, err := h.accountManager.GetAccountByID(r.Context(), accountID, userID) + account, err := h.accountManager.GetAccountByID(r.Context(), accountID, activity.SystemInitiator) if err != nil { util.WriteError(r.Context(), err, w) return diff --git a/management/server/http/testing/testing_tools/tools.go b/management/server/http/testing/testing_tools/tools.go index 31ea06460..12e68e983 100644 --- a/management/server/http/testing/testing_tools/tools.go +++ b/management/server/http/testing/testing_tools/tools.go @@ -15,7 +15,6 @@ import ( "time" "github.com/golang-jwt/jwt" - "github.com/stretchr/testify/assert" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" @@ -123,9 +122,9 @@ func BuildApiBlackBoxWithDBState(t TB, sqlFile string, expectedPeerUpdate *serve validatorMock := server.MocIntegratedValidator{} proxyController := integrations.NewController(store) userManager := users.NewManager(store) - permissionsManagerMock := permissions.NewManagerMock() - settingsManager := settings.NewManager(store, userManager, integrations.NewManager(&activity.InMemoryEventStore{}), permissionsManagerMock) - am, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManagerMock) + permissionsManager := permissions.NewManager(store) + settingsManager := settings.NewManager(store, userManager, integrations.NewManager(&activity.InMemoryEventStore{}), permissionsManager) + am, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager) if err != nil { t.Fatalf("Failed to create manager: %v", err) } @@ -143,9 +142,9 @@ func BuildApiBlackBoxWithDBState(t TB, sqlFile string, expectedPeerUpdate *serve resourcesManagerMock := resources.NewManagerMock() routersManagerMock := routers.NewManagerMock() groupsManagerMock := groups.NewManagerMock() - peersManager := peers.NewManager(store, permissionsManagerMock) + peersManager := peers.NewManager(store, permissionsManager) - apiHandler, err := nbhttp.NewAPIHandler(context.Background(), am, networksManagerMock, resourcesManagerMock, routersManagerMock, groupsManagerMock, geoMock, authManagerMock, metrics, validatorMock, proxyController, permissionsManagerMock, peersManager, settingsManager) + apiHandler, err := nbhttp.NewAPIHandler(context.Background(), am, networksManagerMock, resourcesManagerMock, routersManagerMock, groupsManagerMock, geoMock, authManagerMock, metrics, validatorMock, proxyController, permissionsManager, peersManager, settingsManager) if err != nil { t.Fatalf("Failed to create API handler: %v", err) } diff --git a/management/server/management_proto_test.go b/management/server/management_proto_test.go index c87fe05ce..b85a43da4 100644 --- a/management/server/management_proto_test.go +++ b/management/server/management_proto_test.go @@ -432,8 +432,6 @@ func startManagementForTest(t *testing.T, testFile string, config *types.Config) metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) - permissionsManagerMock := permissions.NewManagerMock() - ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) @@ -443,8 +441,10 @@ func startManagementForTest(t *testing.T, testFile string, config *types.Config) AnyTimes(). Return(&types.Settings{}, nil) + permissionsManager := permissions.NewManager(store) + accountManager, err := BuildManager(ctx, store, peersUpdateManager, nil, "", "netbird.selfhosted", - eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) if err != nil { cleanup() diff --git a/management/server/management_test.go b/management/server/management_test.go index dd987c005..a4f9a5e38 100644 --- a/management/server/management_test.go +++ b/management/server/management_test.go @@ -195,7 +195,7 @@ func startServer( Return(&types.Settings{}, nil). AnyTimes() - permissionsManagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(str) accountManager, err := server.BuildManager( context.Background(), str, @@ -210,7 +210,7 @@ func startServer( metrics, port_forwarding.NewControllerMock(), settingsMockManager, - permissionsManagerMock, + permissionsManager, ) if err != nil { t.Fatalf("failed creating an account manager: %v", err) diff --git a/management/server/nameserver.go b/management/server/nameserver.go index b1cf2bc72..773377f7a 100644 --- a/management/server/nameserver.go +++ b/management/server/nameserver.go @@ -11,6 +11,8 @@ import ( nbdns "github.com/netbirdio/netbird/dns" "github.com/netbirdio/netbird/management/server/activity" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -20,17 +22,12 @@ const domainPattern = `^(?i)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,}$` // GetNameServerGroup gets a nameserver group object from account and nameserver group IDs func (am *DefaultAccountManager) GetNameServerGroup(ctx context.Context, accountID, userID, nsGroupID string) (*nbdns.NameServerGroup, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Nameservers, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetNameServerGroupByID(ctx, store.LockingStrengthShare, accountID, nsGroupID) @@ -41,13 +38,12 @@ func (am *DefaultAccountManager) CreateNameServerGroup(ctx context.Context, acco unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Nameservers, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err + if !allowed { + return nil, status.NewPermissionDeniedError() } newNSGroup := &nbdns.NameServerGroup{ @@ -103,13 +99,12 @@ func (am *DefaultAccountManager) SaveNameServerGroup(ctx context.Context, accoun return status.Errorf(status.InvalidArgument, "nameserver group provided is nil") } - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Nameservers, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err + if !allowed { + return status.NewPermissionDeniedError() } var updateAccountPeers bool @@ -154,13 +149,12 @@ func (am *DefaultAccountManager) DeleteNameServerGroup(ctx context.Context, acco unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Nameservers, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err + if !allowed { + return status.NewPermissionDeniedError() } var nsGroup *nbdns.NameServerGroup @@ -198,17 +192,12 @@ func (am *DefaultAccountManager) DeleteNameServerGroup(ctx context.Context, acco // ListNameServerGroups returns a list of nameserver groups from account func (am *DefaultAccountManager) ListNameServerGroups(ctx context.Context, accountID string, userID string) ([]*nbdns.NameServerGroup, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Nameservers, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetAccountNameServerGroups(ctx, store.LockingStrengthShare, accountID) diff --git a/management/server/nameserver_test.go b/management/server/nameserver_test.go index 13039ae63..dd1149a03 100644 --- a/management/server/nameserver_test.go +++ b/management/server/nameserver_test.go @@ -775,12 +775,11 @@ func createNSManager(t *testing.T) (*DefaultAccountManager, error) { metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) - permissionsManagerMock := permissions.NewManagerMock() ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) - - return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + permissionsManager := permissions.NewManager(store) + return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) } func createNSStore(t *testing.T) (store.Store, error) { diff --git a/management/server/networks/manager.go b/management/server/networks/manager.go index 609b68918..eba3a1fe1 100644 --- a/management/server/networks/manager.go +++ b/management/server/networks/manager.go @@ -12,6 +12,8 @@ import ( "github.com/netbirdio/netbird/management/server/networks/routers" "github.com/netbirdio/netbird/management/server/networks/types" "github.com/netbirdio/netbird/management/server/permissions" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" ) @@ -46,7 +48,7 @@ func NewManager(store store.Store, permissionsManager permissions.Manager, resou } func (m *managerImpl) GetAllNetworks(ctx context.Context, accountID, userID string) ([]*types.Network, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -58,7 +60,7 @@ func (m *managerImpl) GetAllNetworks(ctx context.Context, accountID, userID stri } func (m *managerImpl) CreateNetwork(ctx context.Context, userID string, network *types.Network) (*types.Network, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, network.AccountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, network.AccountID, userID, modules.Networks, operations.Write) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -82,7 +84,7 @@ func (m *managerImpl) CreateNetwork(ctx context.Context, userID string, network } func (m *managerImpl) GetNetwork(ctx context.Context, accountID, userID, networkID string) (*types.Network, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -94,7 +96,7 @@ func (m *managerImpl) GetNetwork(ctx context.Context, accountID, userID, network } func (m *managerImpl) UpdateNetwork(ctx context.Context, userID string, network *types.Network) (*types.Network, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, network.AccountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, network.AccountID, userID, modules.Networks, operations.Write) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -116,7 +118,7 @@ func (m *managerImpl) UpdateNetwork(ctx context.Context, userID string, network } func (m *managerImpl) DeleteNetwork(ctx context.Context, accountID, userID, networkID string) error { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Write) if err != nil { return status.NewPermissionValidationError(err) } diff --git a/management/server/networks/manager_test.go b/management/server/networks/manager_test.go index edd830c25..bf196fcb3 100644 --- a/management/server/networks/manager_test.go +++ b/management/server/networks/manager_test.go @@ -18,7 +18,7 @@ import ( func Test_GetAllNetworksReturnsNetworks(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" s, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../testdata/networks.sql", t.TempDir()) if err != nil { @@ -26,7 +26,7 @@ func Test_GetAllNetworksReturnsNetworks(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -41,7 +41,7 @@ func Test_GetAllNetworksReturnsNetworks(t *testing.T) { func Test_GetAllNetworksReturnsPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" s, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../testdata/networks.sql", t.TempDir()) if err != nil { @@ -49,7 +49,7 @@ func Test_GetAllNetworksReturnsPermissionDenied(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -63,7 +63,7 @@ func Test_GetAllNetworksReturnsPermissionDenied(t *testing.T) { func Test_GetNetworkReturnsNetwork(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" s, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../testdata/networks.sql", t.TempDir()) @@ -72,7 +72,7 @@ func Test_GetNetworkReturnsNetwork(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -86,7 +86,7 @@ func Test_GetNetworkReturnsNetwork(t *testing.T) { func Test_GetNetworkReturnsPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" s, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../testdata/networks.sql", t.TempDir()) @@ -95,7 +95,7 @@ func Test_GetNetworkReturnsPermissionDenied(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -108,7 +108,7 @@ func Test_GetNetworkReturnsPermissionDenied(t *testing.T) { func Test_CreateNetworkSuccessfully(t *testing.T) { ctx := context.Background() - userID := "allowedUser" + userID := "testAdminId" network := &types.Network{ AccountID: "testAccountId", Name: "new-network", @@ -120,7 +120,7 @@ func Test_CreateNetworkSuccessfully(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -133,7 +133,7 @@ func Test_CreateNetworkSuccessfully(t *testing.T) { func Test_CreateNetworkFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() - userID := "invalidUser" + userID := "testUserId" network := &types.Network{ AccountID: "testAccountId", Name: "new-network", @@ -145,7 +145,7 @@ func Test_CreateNetworkFailsWithPermissionDenied(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -159,7 +159,7 @@ func Test_CreateNetworkFailsWithPermissionDenied(t *testing.T) { func Test_DeleteNetworkSuccessfully(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" s, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../testdata/networks.sql", t.TempDir()) @@ -168,7 +168,7 @@ func Test_DeleteNetworkSuccessfully(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -181,7 +181,7 @@ func Test_DeleteNetworkSuccessfully(t *testing.T) { func Test_DeleteNetworkFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" s, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../testdata/networks.sql", t.TempDir()) @@ -190,7 +190,7 @@ func Test_DeleteNetworkFailsWithPermissionDenied(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -202,7 +202,7 @@ func Test_DeleteNetworkFailsWithPermissionDenied(t *testing.T) { func Test_UpdateNetworkSuccessfully(t *testing.T) { ctx := context.Background() - userID := "allowedUser" + userID := "testAdminId" network := &types.Network{ AccountID: "testAccountId", ID: "testNetworkId", @@ -215,7 +215,7 @@ func Test_UpdateNetworkSuccessfully(t *testing.T) { } t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) @@ -228,7 +228,7 @@ func Test_UpdateNetworkSuccessfully(t *testing.T) { func Test_UpdateNetworkFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() - userID := "invalidUser" + userID := "testUserId" network := &types.Network{ AccountID: "testAccountId", ID: "testNetworkId", @@ -242,7 +242,7 @@ func Test_UpdateNetworkFailsWithPermissionDenied(t *testing.T) { t.Cleanup(cleanUp) am := mock_server.MockAccountManager{} - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) groupsManager := groups.NewManagerMock() routerManager := routers.NewManagerMock() resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am) diff --git a/management/server/networks/resources/manager.go b/management/server/networks/resources/manager.go index acaacbfb9..9efd1fae6 100644 --- a/management/server/networks/resources/manager.go +++ b/management/server/networks/resources/manager.go @@ -10,6 +10,8 @@ import ( "github.com/netbirdio/netbird/management/server/groups" "github.com/netbirdio/netbird/management/server/networks/resources/types" "github.com/netbirdio/netbird/management/server/permissions" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" nbtypes "github.com/netbirdio/netbird/management/server/types" @@ -47,7 +49,7 @@ func NewManager(store store.Store, permissionsManager permissions.Manager, group } func (m *managerImpl) GetAllResourcesInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkResource, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -59,7 +61,7 @@ func (m *managerImpl) GetAllResourcesInNetwork(ctx context.Context, accountID, u } func (m *managerImpl) GetAllResourcesInAccount(ctx context.Context, accountID, userID string) ([]*types.NetworkResource, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -71,7 +73,7 @@ func (m *managerImpl) GetAllResourcesInAccount(ctx context.Context, accountID, u } func (m *managerImpl) GetAllResourceIDsInAccount(ctx context.Context, accountID, userID string) (map[string][]string, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -93,7 +95,7 @@ func (m *managerImpl) GetAllResourceIDsInAccount(ctx context.Context, accountID, } func (m *managerImpl) CreateResource(ctx context.Context, userID string, resource *types.NetworkResource) (*types.NetworkResource, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, resource.AccountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, resource.AccountID, userID, modules.Networks, operations.Write) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -164,7 +166,7 @@ func (m *managerImpl) CreateResource(ctx context.Context, userID string, resourc } func (m *managerImpl) GetResource(ctx context.Context, accountID, userID, networkID, resourceID string) (*types.NetworkResource, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -185,7 +187,7 @@ func (m *managerImpl) GetResource(ctx context.Context, accountID, userID, networ } func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resource *types.NetworkResource) (*types.NetworkResource, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, resource.AccountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, resource.AccountID, userID, modules.Networks, operations.Write) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -305,7 +307,7 @@ func (m *managerImpl) updateResourceGroups(ctx context.Context, transaction stor } func (m *managerImpl) DeleteResource(ctx context.Context, accountID, userID, networkID, resourceID string) error { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Write) if err != nil { return status.NewPermissionValidationError(err) } diff --git a/management/server/networks/resources/manager_test.go b/management/server/networks/resources/manager_test.go index 993cd65df..3a91b4af8 100644 --- a/management/server/networks/resources/manager_test.go +++ b/management/server/networks/resources/manager_test.go @@ -17,7 +17,7 @@ import ( func Test_GetAllResourcesInNetworkReturnsResources(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" store, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../../testdata/networks.sql", t.TempDir()) @@ -25,7 +25,7 @@ func Test_GetAllResourcesInNetworkReturnsResources(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -38,7 +38,7 @@ func Test_GetAllResourcesInNetworkReturnsResources(t *testing.T) { func Test_GetAllResourcesInNetworkReturnsPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" store, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../../testdata/networks.sql", t.TempDir()) @@ -46,7 +46,7 @@ func Test_GetAllResourcesInNetworkReturnsPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -59,14 +59,14 @@ func Test_GetAllResourcesInNetworkReturnsPermissionDenied(t *testing.T) { func Test_GetAllResourcesInAccountReturnsResources(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" store, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../../testdata/networks.sql", t.TempDir()) if err != nil { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -79,14 +79,14 @@ func Test_GetAllResourcesInAccountReturnsResources(t *testing.T) { func Test_GetAllResourcesInAccountReturnsPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" store, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../../testdata/networks.sql", t.TempDir()) if err != nil { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -100,7 +100,7 @@ func Test_GetAllResourcesInAccountReturnsPermissionDenied(t *testing.T) { func Test_GetResourceInNetworkReturnsResources(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" resourceID := "testResourceId" @@ -109,7 +109,7 @@ func Test_GetResourceInNetworkReturnsResources(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -122,7 +122,7 @@ func Test_GetResourceInNetworkReturnsResources(t *testing.T) { func Test_GetResourceInNetworkReturnsPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" resourceID := "testResourceId" @@ -131,7 +131,7 @@ func Test_GetResourceInNetworkReturnsPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -144,7 +144,7 @@ func Test_GetResourceInNetworkReturnsPermissionDenied(t *testing.T) { func Test_CreateResourceSuccessfully(t *testing.T) { ctx := context.Background() - userID := "allowedUser" + userID := "testAdminId" resource := &types.NetworkResource{ AccountID: "testAccountId", NetworkID: "testNetworkId", @@ -158,7 +158,7 @@ func Test_CreateResourceSuccessfully(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -170,7 +170,7 @@ func Test_CreateResourceSuccessfully(t *testing.T) { func Test_CreateResourceFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() - userID := "invalidUser" + userID := "testUserId" resource := &types.NetworkResource{ AccountID: "testAccountId", NetworkID: "testNetworkId", @@ -184,7 +184,7 @@ func Test_CreateResourceFailsWithPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -197,7 +197,7 @@ func Test_CreateResourceFailsWithPermissionDenied(t *testing.T) { func Test_CreateResourceFailsWithInvalidAddress(t *testing.T) { ctx := context.Background() - userID := "allowedUser" + userID := "testAdminId" resource := &types.NetworkResource{ AccountID: "testAccountId", NetworkID: "testNetworkId", @@ -211,7 +211,7 @@ func Test_CreateResourceFailsWithInvalidAddress(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -223,7 +223,7 @@ func Test_CreateResourceFailsWithInvalidAddress(t *testing.T) { func Test_CreateResourceFailsWithUsedName(t *testing.T) { ctx := context.Background() - userID := "allowedUser" + userID := "testAdminId" resource := &types.NetworkResource{ AccountID: "testAccountId", NetworkID: "testNetworkId", @@ -237,7 +237,7 @@ func Test_CreateResourceFailsWithUsedName(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -250,7 +250,7 @@ func Test_CreateResourceFailsWithUsedName(t *testing.T) { func Test_UpdateResourceSuccessfully(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" resourceID := "testResourceId" resource := &types.NetworkResource{ @@ -267,7 +267,7 @@ func Test_UpdateResourceSuccessfully(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -283,7 +283,7 @@ func Test_UpdateResourceSuccessfully(t *testing.T) { func Test_UpdateResourceFailsWithResourceNotFound(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" resourceID := "otherResourceId" resource := &types.NetworkResource{ @@ -299,7 +299,7 @@ func Test_UpdateResourceFailsWithResourceNotFound(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -312,7 +312,7 @@ func Test_UpdateResourceFailsWithResourceNotFound(t *testing.T) { func Test_UpdateResourceFailsWithNameInUse(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" resourceID := "testResourceId" resource := &types.NetworkResource{ @@ -329,7 +329,7 @@ func Test_UpdateResourceFailsWithNameInUse(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -342,7 +342,7 @@ func Test_UpdateResourceFailsWithNameInUse(t *testing.T) { func Test_UpdateResourceFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" resourceID := "testResourceId" resource := &types.NetworkResource{ @@ -358,7 +358,7 @@ func Test_UpdateResourceFailsWithPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -371,7 +371,7 @@ func Test_UpdateResourceFailsWithPermissionDenied(t *testing.T) { func Test_DeleteResourceSuccessfully(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" resourceID := "testResourceId" @@ -380,7 +380,7 @@ func Test_DeleteResourceSuccessfully(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) @@ -392,7 +392,7 @@ func Test_DeleteResourceSuccessfully(t *testing.T) { func Test_DeleteResourceFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" resourceID := "testResourceId" @@ -401,7 +401,7 @@ func Test_DeleteResourceFailsWithPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := mock_server.MockAccountManager{} groupsManager := groups.NewManagerMock() manager := NewManager(store, permissionsManager, groupsManager, &am) diff --git a/management/server/networks/routers/manager.go b/management/server/networks/routers/manager.go index 595fffd97..2c8f7f677 100644 --- a/management/server/networks/routers/manager.go +++ b/management/server/networks/routers/manager.go @@ -12,6 +12,8 @@ import ( "github.com/netbirdio/netbird/management/server/networks/routers/types" networkTypes "github.com/netbirdio/netbird/management/server/networks/types" "github.com/netbirdio/netbird/management/server/permissions" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" ) @@ -44,7 +46,7 @@ func NewManager(store store.Store, permissionsManager permissions.Manager, accou } func (m *managerImpl) GetAllRoutersInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkRouter, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -56,7 +58,7 @@ func (m *managerImpl) GetAllRoutersInNetwork(ctx context.Context, accountID, use } func (m *managerImpl) GetAllRoutersInAccount(ctx context.Context, accountID, userID string) (map[string][]*types.NetworkRouter, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -78,7 +80,7 @@ func (m *managerImpl) GetAllRoutersInAccount(ctx context.Context, accountID, use } func (m *managerImpl) CreateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, router.AccountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, router.AccountID, userID, modules.Networks, operations.Write) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -126,7 +128,7 @@ func (m *managerImpl) CreateRouter(ctx context.Context, userID string, router *t } func (m *managerImpl) GetRouter(ctx context.Context, accountID, userID, networkID, routerID string) (*types.NetworkRouter, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -147,7 +149,7 @@ func (m *managerImpl) GetRouter(ctx context.Context, accountID, userID, networkI } func (m *managerImpl) UpdateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error) { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, router.AccountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, router.AccountID, userID, modules.Networks, operations.Write) if err != nil { return nil, status.NewPermissionValidationError(err) } @@ -193,7 +195,7 @@ func (m *managerImpl) UpdateRouter(ctx context.Context, userID string, router *t } func (m *managerImpl) DeleteRouter(ctx context.Context, accountID, userID, networkID, routerID string) error { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Write) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Write) if err != nil { return status.NewPermissionValidationError(err) } diff --git a/management/server/networks/routers/manager_test.go b/management/server/networks/routers/manager_test.go index 47f5ad7e3..541643222 100644 --- a/management/server/networks/routers/manager_test.go +++ b/management/server/networks/routers/manager_test.go @@ -16,7 +16,7 @@ import ( func Test_GetAllRoutersInNetworkReturnsRouters(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" s, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../../testdata/networks.sql", t.TempDir()) @@ -24,7 +24,7 @@ func Test_GetAllRoutersInNetworkReturnsRouters(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -37,7 +37,7 @@ func Test_GetAllRoutersInNetworkReturnsRouters(t *testing.T) { func Test_GetAllRoutersInNetworkReturnsPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" s, cleanUp, err := store.NewTestStoreFromSQL(context.Background(), "../../testdata/networks.sql", t.TempDir()) @@ -45,7 +45,7 @@ func Test_GetAllRoutersInNetworkReturnsPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -58,7 +58,7 @@ func Test_GetAllRoutersInNetworkReturnsPermissionDenied(t *testing.T) { func Test_GetRouterReturnsRouter(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" resourceID := "testRouterId" @@ -67,7 +67,7 @@ func Test_GetRouterReturnsRouter(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -79,7 +79,7 @@ func Test_GetRouterReturnsRouter(t *testing.T) { func Test_GetRouterReturnsPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" resourceID := "testRouterId" @@ -88,7 +88,7 @@ func Test_GetRouterReturnsPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -100,7 +100,7 @@ func Test_GetRouterReturnsPermissionDenied(t *testing.T) { func Test_CreateRouterSuccessfully(t *testing.T) { ctx := context.Background() - userID := "allowedUser" + userID := "testAdminId" router, err := types.NewNetworkRouter("testAccountId", "testNetworkId", "testPeerId", []string{}, false, 9999, true) if err != nil { require.NoError(t, err) @@ -111,7 +111,7 @@ func Test_CreateRouterSuccessfully(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -126,7 +126,7 @@ func Test_CreateRouterSuccessfully(t *testing.T) { func Test_CreateRouterFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() - userID := "invalidUser" + userID := "testUserId" router, err := types.NewNetworkRouter("testAccountId", "testNetworkId", "testPeerId", []string{}, false, 9999, true) if err != nil { require.NoError(t, err) @@ -137,7 +137,7 @@ func Test_CreateRouterFailsWithPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -150,7 +150,7 @@ func Test_CreateRouterFailsWithPermissionDenied(t *testing.T) { func Test_DeleteRouterSuccessfully(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "allowedUser" + userID := "testAdminId" networkID := "testNetworkId" routerID := "testRouterId" @@ -159,7 +159,7 @@ func Test_DeleteRouterSuccessfully(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -170,7 +170,7 @@ func Test_DeleteRouterSuccessfully(t *testing.T) { func Test_DeleteRouterFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() accountID := "testAccountId" - userID := "invalidUser" + userID := "testUserId" networkID := "testNetworkId" routerID := "testRouterId" @@ -179,7 +179,7 @@ func Test_DeleteRouterFailsWithPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -190,7 +190,7 @@ func Test_DeleteRouterFailsWithPermissionDenied(t *testing.T) { func Test_UpdateRouterSuccessfully(t *testing.T) { ctx := context.Background() - userID := "allowedUser" + userID := "testAdminId" router, err := types.NewNetworkRouter("testAccountId", "testNetworkId", "testPeerId", []string{}, false, 1, true) if err != nil { require.NoError(t, err) @@ -201,7 +201,7 @@ func Test_UpdateRouterSuccessfully(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) @@ -212,7 +212,7 @@ func Test_UpdateRouterSuccessfully(t *testing.T) { func Test_UpdateRouterFailsWithPermissionDenied(t *testing.T) { ctx := context.Background() - userID := "invalidUser" + userID := "testUserId" router, err := types.NewNetworkRouter("testAccountId", "testNetworkId", "testPeerId", []string{}, false, 1, true) if err != nil { require.NoError(t, err) @@ -223,7 +223,7 @@ func Test_UpdateRouterFailsWithPermissionDenied(t *testing.T) { t.Fatal(err) } t.Cleanup(cleanUp) - permissionsManager := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := mock_server.MockAccountManager{} manager := NewManager(s, permissionsManager, &am) diff --git a/management/server/peer.go b/management/server/peer.go index e7d4b29f5..846f1dc61 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -17,6 +17,8 @@ import ( "github.com/netbirdio/netbird/management/domain" "github.com/netbirdio/netbird/management/server/geolocation" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/idp" "github.com/netbirdio/netbird/management/server/posture" @@ -37,17 +39,9 @@ func (am *DefaultAccountManager) GetPeers(ctx context.Context, accountID, userID return nil, err } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Read) if err != nil { - return nil, err - } - - if user.IsRegularUser() && settings.RegularUsersViewBlocked { - return []*nbpeer.Peer{}, nil + return nil, status.NewPermissionValidationError(err) } accountPeers, err := am.Store.GetAccountPeers(ctx, store.LockingStrengthShare, accountID, nameFilter, ipFilter) @@ -67,10 +61,19 @@ func (am *DefaultAccountManager) GetPeers(ctx context.Context, accountID, userID peersMap[peer.ID] = peer } - if user.IsAdminOrServiceUser() { + if allowed { return peers, nil } + settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID) + if err != nil { + return nil, fmt.Errorf("failed to get account settings: %w", err) + } + + if settings.RegularUsersViewBlocked { + return []*nbpeer.Peer{}, nil + } + account, err := am.requestBuffer.GetAccountWithBackpressure(ctx, accountID) if err != nil { return nil, err @@ -183,13 +186,12 @@ func (am *DefaultAccountManager) UpdatePeer(ctx context.Context, accountID, user unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err + if !allowed { + return nil, status.NewPermissionDeniedError() } var peer *nbpeer.Peer @@ -315,15 +317,12 @@ func (am *DefaultAccountManager) DeletePeer(ctx context.Context, accountID, peer unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - if userID != activity.SystemInitiator { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) - if err != nil { - return err - } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err - } + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Write) + if err != nil { + return status.NewPermissionValidationError(err) + } + if !allowed { + return status.NewPermissionDeniedError() } peerAccountID, err := am.Store.GetAccountIDByPeerID(ctx, store.LockingStrengthShare, peerID) @@ -1094,29 +1093,24 @@ func peerLoginExpired(ctx context.Context, peer *nbpeer.Peer, settings *types.Se // 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) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) - if err != nil { - return nil, err - } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID) - if err != nil { - return nil, err - } - - if user.IsRegularUser() && settings.RegularUsersViewBlocked { - return nil, status.Errorf(status.Internal, "user %s has no access to his own peer %s under account %s", userID, peerID, accountID) - } - peer, err := am.Store.GetPeerByID(ctx, store.LockingStrengthShare, accountID, peerID) if err != nil { return nil, err } + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Read) + if err != nil { + return nil, status.NewPermissionValidationError(err) + } + if allowed { + return peer, nil + } + + user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + if err != nil { + return nil, err + } + // if admin or user owns this peer, return peer if user.IsAdminOrServiceUser() || peer.UserID == userID { return peer, nil diff --git a/management/server/peer_test.go b/management/server/peer_test.go index b2563dcb0..0afaed829 100644 --- a/management/server/peer_test.go +++ b/management/server/peer_test.go @@ -1264,9 +1264,9 @@ func Test_RegisterPeerByUser(t *testing.T) { ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) + permissionsManager := permissions.NewManager(s) - permissionsManagerMock := permissions.NewManagerMock() - am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) assert.NoError(t, err) existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b" @@ -1333,9 +1333,9 @@ func Test_RegisterPeerBySetupKey(t *testing.T) { ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) + permissionsManager := permissions.NewManager(s) - permissionsManagerMock := permissions.NewManagerMock() - am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) assert.NoError(t, err) existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b" @@ -1406,8 +1406,9 @@ func Test_RegisterPeerRollbackOnFailure(t *testing.T) { t.Cleanup(ctrl.Finish) settingsMockManager := settings.NewMockManager(ctrl) - permissionsManagerMock := permissions.NewManagerMock() - am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + permissionsManager := permissions.NewManager(s) + + am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) assert.NoError(t, err) existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b" diff --git a/management/server/peers/manager.go b/management/server/peers/manager.go index b00c1761b..fe48bf576 100644 --- a/management/server/peers/manager.go +++ b/management/server/peers/manager.go @@ -8,6 +8,8 @@ import ( "github.com/netbirdio/netbird/management/server/peer" "github.com/netbirdio/netbird/management/server/permissions" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" ) @@ -31,7 +33,7 @@ func NewManager(store store.Store, permissionsManager permissions.Manager) Manag } func (m *managerImpl) GetPeer(ctx context.Context, accountID, userID, peerID string) (*peer.Peer, error) { - allowed, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Peers, permissions.Read) + allowed, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Read) if err != nil { return nil, fmt.Errorf("failed to validate user permissions: %w", err) } @@ -44,13 +46,13 @@ func (m *managerImpl) GetPeer(ctx context.Context, accountID, userID, peerID str } func (m *managerImpl) GetAllPeers(ctx context.Context, accountID, userID string) ([]*peer.Peer, error) { - allowed, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Peers, permissions.Read) + allowed, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Read) if err != nil { return nil, fmt.Errorf("failed to validate user permissions: %w", err) } if !allowed { - return nil, status.NewPermissionDeniedError() + return m.store.GetUserPeers(ctx, store.LockingStrengthShare, accountID, userID) } return m.store.GetAccountPeers(ctx, store.LockingStrengthShare, accountID, "", "") diff --git a/management/server/permissions/manager.go b/management/server/permissions/manager.go index 24ac09d1a..50a44eb0f 100644 --- a/management/server/permissions/manager.go +++ b/management/server/permissions/manager.go @@ -1,34 +1,24 @@ package permissions +//go:generate go run github.com/golang/mock/mockgen -package permissions -destination=manager_mock.go -source=./manager.go -build_flags=-mod=mod + import ( "context" - "errors" - "fmt" + log "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/management/server/activity" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" + "github.com/netbirdio/netbird/management/server/permissions/roles" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" ) -type Module string - -const ( - Networks Module = "networks" - Peers Module = "peers" - Groups Module = "groups" - Settings Module = "settings" - Accounts Module = "accounts" -) - -type Operation string - -const ( - Read Operation = "read" - Write Operation = "write" -) - type Manager interface { - ValidateUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error) + ValidateUserPermissions(ctx context.Context, accountID, userID string, module modules.Module, operation operations.Operation) (bool, error) + ValidateRoleModuleAccess(ctx context.Context, accountID string, role roles.RolePermissions, module modules.Module, operation operations.Operation) bool ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error } @@ -36,16 +26,23 @@ type managerImpl struct { store store.Store } -type managerMock struct { -} - func NewManager(store store.Store) Manager { return &managerImpl{ store: store, } } -func (m *managerImpl) ValidateUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error) { +func (m *managerImpl) ValidateUserPermissions( + ctx context.Context, + accountID string, + userID string, + module modules.Module, + operation operations.Operation, +) (bool, error) { + if userID == activity.SystemInitiator { + return true, nil + } + user, err := m.store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) if err != nil { return false, err @@ -55,49 +52,42 @@ func (m *managerImpl) ValidateUserPermissions(ctx context.Context, accountID, us return false, status.NewUserNotFoundError(userID) } + if user.IsBlocked() { + return false, status.NewUserBlockedError() + } + if err := m.ValidateAccountAccess(ctx, accountID, user, false); err != nil { return false, err } - switch module { - case Accounts: - if operation == Write && user.Role != types.UserRoleOwner { - return false, nil - } - return true, nil - default: + if operation == operations.Read && user.IsServiceUser { + return true, nil // this should be replaced by proper granular access role } - switch user.Role { - case types.UserRoleAdmin, types.UserRoleOwner: - return true, nil - case types.UserRoleUser: - return m.validateRegularUserPermissions(ctx, accountID, module, operation) - case types.UserRoleBillingAdmin: - return false, nil - default: - return false, errors.New("invalid role") + role, ok := roles.RolesMap[user.Role] + if !ok { + return false, status.NewUserRoleNotFoundError(string(user.Role)) } + + return m.ValidateRoleModuleAccess(ctx, accountID, role, module, operation), nil } -func (m *managerImpl) validateRegularUserPermissions(ctx context.Context, accountID string, module Module, operation Operation) (bool, error) { - settings, err := m.store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID) - if err != nil { - return false, fmt.Errorf("failed to get settings: %w", err) - } - if settings.RegularUsersViewBlocked { - return false, nil +func (m *managerImpl) ValidateRoleModuleAccess( + ctx context.Context, + accountID string, + role roles.RolePermissions, + module modules.Module, + operation operations.Operation, +) bool { + if permissions, ok := role.Permissions[module]; ok { + if allowed, exists := permissions[operation]; exists { + return allowed + } + log.WithContext(ctx).Tracef("operation %s not found on module %s for role %s", operation, module, role.Role) + return false } - if operation == Write { - return false, nil - } - - if module == Peers { - return true, nil - } - - return false, nil + return role.AutoAllowNew[operation] } func (m *managerImpl) ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error { @@ -106,24 +96,3 @@ func (m *managerImpl) ValidateAccountAccess(ctx context.Context, accountID strin } return nil } - -func NewManagerMock() Manager { - return &managerMock{} -} - -func (m *managerMock) ValidateUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error) { - switch userID { - case "a23efe53-63fb-11ec-90d6-0242ac120003", "allowedUser", "testingUser", "account_creator", "serviceUserID", "test_user": - return true, nil - default: - return false, nil - } -} - -func (m *managerMock) ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error { - // @note managers explicitly checked this, so should the mock - if user.AccountID != accountID { - return status.NewUserNotPartOfAccountError() - } - return nil -} diff --git a/management/server/permissions/manager_mock.go b/management/server/permissions/manager_mock.go new file mode 100644 index 000000000..266a24270 --- /dev/null +++ b/management/server/permissions/manager_mock.go @@ -0,0 +1,82 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./manager.go + +// Package permissions is a generated GoMock package. +package permissions + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + modules "github.com/netbirdio/netbird/management/server/permissions/modules" + operations "github.com/netbirdio/netbird/management/server/permissions/operations" + roles "github.com/netbirdio/netbird/management/server/permissions/roles" + types "github.com/netbirdio/netbird/management/server/types" +) + +// MockManager is a mock of Manager interface. +type MockManager struct { + ctrl *gomock.Controller + recorder *MockManagerMockRecorder +} + +// MockManagerMockRecorder is the mock recorder for MockManager. +type MockManagerMockRecorder struct { + mock *MockManager +} + +// NewMockManager creates a new mock instance. +func NewMockManager(ctrl *gomock.Controller) *MockManager { + mock := &MockManager{ctrl: ctrl} + mock.recorder = &MockManagerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockManager) EXPECT() *MockManagerMockRecorder { + return m.recorder +} + +// ValidateAccountAccess mocks base method. +func (m *MockManager) ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateAccountAccess", ctx, accountID, user, allowOwnerAndAdmin) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateAccountAccess indicates an expected call of ValidateAccountAccess. +func (mr *MockManagerMockRecorder) ValidateAccountAccess(ctx, accountID, user, allowOwnerAndAdmin interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAccountAccess", reflect.TypeOf((*MockManager)(nil).ValidateAccountAccess), ctx, accountID, user, allowOwnerAndAdmin) +} + +// ValidateRoleModuleAccess mocks base method. +func (m *MockManager) ValidateRoleModuleAccess(ctx context.Context, accountID string, role roles.RolePermissions, module modules.Module, operation operations.Operation) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateRoleModuleAccess", ctx, accountID, role, module, operation) + ret0, _ := ret[0].(bool) + return ret0 +} + +// ValidateRoleModuleAccess indicates an expected call of ValidateRoleModuleAccess. +func (mr *MockManagerMockRecorder) ValidateRoleModuleAccess(ctx, accountID, role, module, operation interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateRoleModuleAccess", reflect.TypeOf((*MockManager)(nil).ValidateRoleModuleAccess), ctx, accountID, role, module, operation) +} + +// ValidateUserPermissions mocks base method. +func (m *MockManager) ValidateUserPermissions(ctx context.Context, accountID, userID string, module modules.Module, operation operations.Operation) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateUserPermissions", ctx, accountID, userID, module, operation) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ValidateUserPermissions indicates an expected call of ValidateUserPermissions. +func (mr *MockManagerMockRecorder) ValidateUserPermissions(ctx, accountID, userID, module, operation interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateUserPermissions", reflect.TypeOf((*MockManager)(nil).ValidateUserPermissions), ctx, accountID, userID, module, operation) +} diff --git a/management/server/permissions/modules/module.go b/management/server/permissions/modules/module.go new file mode 100644 index 000000000..4c42b6190 --- /dev/null +++ b/management/server/permissions/modules/module.go @@ -0,0 +1,19 @@ +package modules + +type Module string + +const ( + Networks Module = "networks" + Peers Module = "peers" + Groups Module = "groups" + Settings Module = "settings" + Accounts Module = "accounts" + Dns Module = "dns" + Nameservers Module = "nameservers" + Events Module = "events" + Policies Module = "policies" + Routes Module = "routes" + Users Module = "users" + SetupKeys Module = "setup_keys" + Pats Module = "pats" +) diff --git a/management/server/permissions/operations/operation.go b/management/server/permissions/operations/operation.go new file mode 100644 index 000000000..af709de3a --- /dev/null +++ b/management/server/permissions/operations/operation.go @@ -0,0 +1,8 @@ +package operations + +type Operation string + +const ( + Read Operation = "read" + Write Operation = "write" +) diff --git a/management/server/permissions/roles/admin.go b/management/server/permissions/roles/admin.go new file mode 100644 index 000000000..a826d186a --- /dev/null +++ b/management/server/permissions/roles/admin.go @@ -0,0 +1,21 @@ +package roles + +import ( + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" + "github.com/netbirdio/netbird/management/server/types" +) + +var Admin = RolePermissions{ + Role: types.UserRoleAdmin, + AutoAllowNew: map[operations.Operation]bool{ + operations.Read: true, + operations.Write: true, + }, + Permissions: Permissions{ + modules.Accounts: { + operations.Read: true, + operations.Write: false, + }, + }, +} diff --git a/management/server/permissions/roles/owner.go b/management/server/permissions/roles/owner.go new file mode 100644 index 000000000..f739d18ea --- /dev/null +++ b/management/server/permissions/roles/owner.go @@ -0,0 +1,14 @@ +package roles + +import ( + "github.com/netbirdio/netbird/management/server/permissions/operations" + "github.com/netbirdio/netbird/management/server/types" +) + +var Owner = RolePermissions{ + Role: types.UserRoleOwner, + AutoAllowNew: map[operations.Operation]bool{ + operations.Read: true, + operations.Write: true, + }, +} diff --git a/management/server/permissions/roles/role_permissions.go b/management/server/permissions/roles/role_permissions.go new file mode 100644 index 000000000..dda7e6b99 --- /dev/null +++ b/management/server/permissions/roles/role_permissions.go @@ -0,0 +1,21 @@ +package roles + +import ( + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" + "github.com/netbirdio/netbird/management/server/types" +) + +type RolePermissions struct { + Role types.UserRole + Permissions Permissions + AutoAllowNew map[operations.Operation]bool +} + +type Permissions map[modules.Module]map[operations.Operation]bool + +var RolesMap = map[types.UserRole]RolePermissions{ + types.UserRoleOwner: Owner, + types.UserRoleAdmin: Admin, + types.UserRoleUser: User, +} diff --git a/management/server/permissions/roles/user.go b/management/server/permissions/roles/user.go new file mode 100644 index 000000000..6e8a9307b --- /dev/null +++ b/management/server/permissions/roles/user.go @@ -0,0 +1,14 @@ +package roles + +import ( + "github.com/netbirdio/netbird/management/server/permissions/operations" + "github.com/netbirdio/netbird/management/server/types" +) + +var User = RolePermissions{ + Role: types.UserRoleUser, + AutoAllowNew: map[operations.Operation]bool{ + operations.Read: false, + operations.Write: false, + }, +} diff --git a/management/server/policy.go b/management/server/policy.go index 15111ba06..8f56bd493 100644 --- a/management/server/policy.go +++ b/management/server/policy.go @@ -7,6 +7,8 @@ import ( "github.com/rs/xid" "github.com/netbirdio/netbird/management/proto" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -17,17 +19,12 @@ import ( // GetPolicy from the store func (am *DefaultAccountManager) GetPolicy(ctx context.Context, accountID, policyID, userID string) (*types.Policy, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Policies, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetPolicyByID(ctx, store.LockingStrengthShare, accountID, policyID) @@ -38,17 +35,12 @@ func (am *DefaultAccountManager) SavePolicy(ctx context.Context, accountID, user unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Policies, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } var isUpdate = policy.ID != "" @@ -95,17 +87,12 @@ func (am *DefaultAccountManager) DeletePolicy(ctx context.Context, accountID, po unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Policies, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err - } - - if user.IsRegularUser() { - return status.NewAdminPermissionError() + if !allowed { + return status.NewPermissionDeniedError() } var policy *types.Policy @@ -143,17 +130,12 @@ func (am *DefaultAccountManager) DeletePolicy(ctx context.Context, accountID, po // ListPolicies from the store. func (am *DefaultAccountManager) ListPolicies(ctx context.Context, accountID, userID string) ([]*types.Policy, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Policies, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetAccountPolicies(ctx, store.LockingStrengthShare, accountID) diff --git a/management/server/posture_checks.go b/management/server/posture_checks.go index 859ae6332..9b8067b8c 100644 --- a/management/server/posture_checks.go +++ b/management/server/posture_checks.go @@ -10,6 +10,8 @@ import ( "golang.org/x/exp/maps" "github.com/netbirdio/netbird/management/server/activity" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/posture" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" @@ -17,17 +19,12 @@ import ( ) func (am *DefaultAccountManager) GetPostureChecks(ctx context.Context, accountID, postureChecksID, userID string) (*posture.Checks, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Policies, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if !user.HasAdminPower() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetPostureChecksByID(ctx, store.LockingStrengthShare, accountID, postureChecksID) @@ -38,17 +35,12 @@ func (am *DefaultAccountManager) SavePostureChecks(ctx context.Context, accountI unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Policies, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if !user.HasAdminPower() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } var updateAccountPeers bool @@ -94,17 +86,12 @@ func (am *DefaultAccountManager) DeletePostureChecks(ctx context.Context, accoun unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Routes, operations.Read) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err - } - - if !user.HasAdminPower() { - return status.NewAdminPermissionError() + if !allowed { + return status.NewPermissionDeniedError() } var postureChecks *posture.Checks @@ -136,17 +123,12 @@ func (am *DefaultAccountManager) DeletePostureChecks(ctx context.Context, accoun // ListPostureChecks returns a list of posture checks. func (am *DefaultAccountManager) ListPostureChecks(ctx context.Context, accountID, userID string) ([]*posture.Checks, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Policies, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if !user.HasAdminPower() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetAccountPostureChecks(ctx, store.LockingStrengthShare, accountID) diff --git a/management/server/route.go b/management/server/route.go index abf20743a..453da92b3 100644 --- a/management/server/route.go +++ b/management/server/route.go @@ -8,6 +8,8 @@ import ( "github.com/rs/xid" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -20,17 +22,12 @@ import ( // GetRoute gets a route object from account and route IDs func (am *DefaultAccountManager) GetRoute(ctx context.Context, accountID string, routeID route.ID, userID string) (*route.Route, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Routes, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if !user.IsAdminOrServiceUser() { - return nil, status.Errorf(status.PermissionDenied, "only users with admin power can view Network Routes") + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetRouteByID(ctx, store.LockingStrengthShare, string(routeID), accountID) @@ -123,13 +120,12 @@ func (am *DefaultAccountManager) CreateRoute(ctx context.Context, accountID stri unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Routes, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err = am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err + if !allowed { + return nil, status.NewPermissionDeniedError() } account, err := am.Store.GetAccount(ctx, accountID) @@ -242,13 +238,12 @@ func (am *DefaultAccountManager) SaveRoute(ctx context.Context, accountID, userI return status.Errorf(status.InvalidArgument, "identifier should be between 1 and %d", route.MaxNetIDChar) } - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Routes, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err = am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err + if !allowed { + return status.NewPermissionDeniedError() } account, err := am.Store.GetAccount(ctx, accountID) @@ -318,13 +313,12 @@ func (am *DefaultAccountManager) DeleteRoute(ctx context.Context, accountID stri unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Routes, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err = am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err + if !allowed { + return status.NewPermissionDeniedError() } account, err := am.Store.GetAccount(ctx, accountID) @@ -354,17 +348,12 @@ func (am *DefaultAccountManager) DeleteRoute(ctx context.Context, accountID stri // ListRoutes returns a list of routes from account func (am *DefaultAccountManager) ListRoutes(ctx context.Context, accountID, userID string) ([]*route.Route, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Routes, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if !user.IsAdminOrServiceUser() { - return nil, status.Errorf(status.PermissionDenied, "only users with admin power can view Network Routes") + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetAccountRoutes(ctx, store.LockingStrengthShare, accountID) diff --git a/management/server/route_test.go b/management/server/route_test.go index 699c1304b..351dad8f7 100644 --- a/management/server/route_test.go +++ b/management/server/route_test.go @@ -1260,7 +1260,6 @@ func createRouterManager(t *testing.T) (*DefaultAccountManager, error) { metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) - permissionsManagerMock := permissions.NewManagerMock() ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) @@ -1283,7 +1282,9 @@ func createRouterManager(t *testing.T) (*DefaultAccountManager, error) { AnyTimes(). Return(&types.ExtraSettings{}, nil) - return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock) + permissionsManager := permissions.NewManager(store) + + return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager) } func createRouterStore(t *testing.T) (store.Store, error) { diff --git a/management/server/settings/manager.go b/management/server/settings/manager.go index 2b3f4877b..94392ebf7 100644 --- a/management/server/settings/manager.go +++ b/management/server/settings/manager.go @@ -9,6 +9,8 @@ import ( "github.com/netbirdio/netbird/management/server/activity" "github.com/netbirdio/netbird/management/server/integrations/extra_settings" "github.com/netbirdio/netbird/management/server/permissions" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -44,7 +46,7 @@ func (m *managerImpl) GetExtraSettingsManager() extra_settings.Manager { func (m *managerImpl) GetSettings(ctx context.Context, accountID, userID string) (*types.Settings, error) { if userID != activity.SystemInitiator { - ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Settings, permissions.Read) + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Settings, operations.Read) if err != nil { return nil, status.NewPermissionValidationError(err) } diff --git a/management/server/setupkey.go b/management/server/setupkey.go index 8b73a7d1e..f205a170f 100644 --- a/management/server/setupkey.go +++ b/management/server/setupkey.go @@ -8,6 +8,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/netbirdio/netbird/management/server/activity" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -56,17 +58,12 @@ func (am *DefaultAccountManager) CreateSetupKey(ctx context.Context, accountID s unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.SetupKeys, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } var setupKey *types.SetupKey @@ -113,17 +110,12 @@ func (am *DefaultAccountManager) SaveSetupKey(ctx context.Context, accountID str unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.SetupKeys, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } var oldKey *types.SetupKey @@ -175,17 +167,12 @@ func (am *DefaultAccountManager) SaveSetupKey(ctx context.Context, accountID str // ListSetupKeys returns a list of all setup keys of the account func (am *DefaultAccountManager) ListSetupKeys(ctx context.Context, accountID, userID string) ([]*types.SetupKey, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.SetupKeys, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } return am.Store.GetAccountSetupKeys(ctx, store.LockingStrengthShare, accountID) @@ -193,17 +180,12 @@ func (am *DefaultAccountManager) ListSetupKeys(ctx context.Context, accountID, u // GetSetupKey looks up a SetupKey by KeyID, returns NotFound error if not found. func (am *DefaultAccountManager) GetSetupKey(ctx context.Context, accountID, userID, keyID string) (*types.SetupKey, error) { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.SetupKeys, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return nil, err - } - - if user.IsRegularUser() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } setupKey, err := am.Store.GetSetupKeyByID(ctx, store.LockingStrengthShare, accountID, keyID) @@ -221,17 +203,12 @@ func (am *DefaultAccountManager) GetSetupKey(ctx context.Context, accountID, use // DeleteSetupKey removes the setup key from the account func (am *DefaultAccountManager) DeleteSetupKey(ctx context.Context, accountID, userID, keyID string) error { - user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.SetupKeys, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, user, false); err != nil { - return err - } - - if user.IsRegularUser() { - return status.NewAdminPermissionError() + if !allowed { + return status.NewPermissionDeniedError() } var deletedSetupKey *types.SetupKey diff --git a/management/server/status/error.go b/management/server/status/error.go index 5ab6f4e9e..8fbe0bad9 100644 --- a/management/server/status/error.go +++ b/management/server/status/error.go @@ -3,6 +3,8 @@ package status import ( "errors" "fmt" + + "github.com/netbirdio/netbird/management/server/permissions/operations" ) const ( @@ -98,6 +100,11 @@ func NewUserNotFoundError(userKey string) error { return Errorf(NotFound, "user: %s not found", userKey) } +// NewUserBlockedError creates a new Error with PermissionDenied type for a blocked user +func NewUserBlockedError() error { + return Errorf(PermissionDenied, "user is blocked") +} + // NewPeerNotRegisteredError creates a new Error with NotFound type for a missing peer func NewPeerNotRegisteredError() error { return Errorf(Unauthenticated, "peer is not registered") @@ -212,3 +219,11 @@ func NewPATNotFoundError(patID string) error { func NewExtraSettingsNotFoundError() error { return ErrExtraSettingsNotFound } + +func NewUserRoleNotFoundError(role string) error { + return Errorf(NotFound, "user role: %s not found", role) +} + +func NewOperationNotFoundError(operation operations.Operation) error { + return Errorf(NotFound, "operation: %s not found", operation) +} diff --git a/management/server/testdata/networks.sql b/management/server/testdata/networks.sql index 8138ce520..bcb202084 100644 --- a/management/server/testdata/networks.sql +++ b/management/server/testdata/networks.sql @@ -16,3 +16,7 @@ INSERT INTO network_routers VALUES('testRouterId','testNetworkId','testAccountId CREATE TABLE `network_resources` (`id` text,`network_id` text,`account_id` text,`name` text,`description` text,`type` text,`address` text,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_network_resources` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`)); INSERT INTO network_resources VALUES('testResourceId','testNetworkId','testAccountId','some-name','some-description','host','3.3.3.3/32'); INSERT INTO network_resources VALUES('anotherTestResourceId','testNetworkId','testAccountId','used-name','some-description','host','3.3.3.3/32'); + +CREATE TABLE `users` (`id` text,`account_id` text,`role` text,`is_service_user` numeric,`non_deletable` numeric,`service_user_name` text,`auto_groups` text,`blocked` numeric,`last_login` datetime DEFAULT NULL,`created_at` datetime,`issued` text DEFAULT "api",`integration_ref_id` integer,`integration_ref_integration_type` text,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_users_g` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`)); +INSERT INTO users VALUES('testUserId','testAccountId','user',0,0,'','[]',0,NULL,'2024-10-02 16:01:38.000000000+00:00','api',0,''); +INSERT INTO users VALUES('testAdminId','testAccountId','admin',0,0,'','[]',0,NULL,'2024-10-02 16:01:38.000000000+00:00','api',0,''); diff --git a/management/server/user.go b/management/server/user.go index c446bd8ea..3dee3f014 100644 --- a/management/server/user.go +++ b/management/server/user.go @@ -14,6 +14,8 @@ import ( nbContext "github.com/netbirdio/netbird/management/server/context" "github.com/netbirdio/netbird/management/server/idp" nbpeer "github.com/netbirdio/netbird/management/server/peer" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" @@ -25,17 +27,12 @@ func (am *DefaultAccountManager) createServiceUser(ctx context.Context, accountI unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() - initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Users, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { - return nil, err - } - - if !initiatorUser.HasAdminPower() { - return nil, status.NewAdminPermissionError() + if !allowed { + return nil, status.NewPermissionDeniedError() } if role == types.UserRoleOwner { @@ -88,12 +85,16 @@ func (am *DefaultAccountManager) inviteNewUser(ctx context.Context, accountID, u return nil, err } - initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Users, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) + } + if !allowed { + return nil, status.NewPermissionDeniedError() } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { + initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID) + if err != nil { return nil, err } @@ -237,12 +238,12 @@ func (am *DefaultAccountManager) DeleteUser(ctx context.Context, accountID, init return err } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { - return err + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Users, operations.Write) + if err != nil { + return status.NewPermissionValidationError(err) } - - if !initiatorUser.HasAdminPower() { - return status.NewAdminPermissionError() + if !allowed { + return status.NewPermissionDeniedError() } targetUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, targetUserID) @@ -294,13 +295,12 @@ func (am *DefaultAccountManager) InviteUser(ctx context.Context, accountID strin return status.Errorf(status.PreconditionFailed, "IdP manager must be enabled to send user invites") } - initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Users, operations.Write) if err != nil { - return err + return status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { - return err + if !allowed { + return status.NewPermissionDeniedError() } // check if the user is already registered with this ID @@ -342,12 +342,16 @@ func (am *DefaultAccountManager) CreatePAT(ctx context.Context, accountID string return nil, status.Errorf(status.InvalidArgument, "expiration has to be between 1 and 365") } - initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Pats, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) + } + if !allowed { + return nil, status.NewPermissionDeniedError() } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { + initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) + if err != nil { return nil, err } @@ -380,25 +384,29 @@ func (am *DefaultAccountManager) DeletePAT(ctx context.Context, accountID string unlock := am.Store.AcquireWriteLockByUID(ctx, accountID) defer unlock() + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Pats, operations.Write) + if err != nil { + return status.NewPermissionValidationError(err) + } + if !allowed { + return status.NewPermissionDeniedError() + } + initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) if err != nil { return err } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { - return err - } - - if initiatorUserID != targetUserID && initiatorUser.IsRegularUser() { - return status.NewAdminPermissionError() - } - - pat, err := am.Store.GetPATByID(ctx, store.LockingStrengthShare, targetUserID, tokenID) + targetUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, targetUserID) if err != nil { return err } - targetUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, targetUserID) + if initiatorUserID != targetUserID && !(initiatorUser.HasAdminPower() && targetUser.IsServiceUser) { + return status.NewAdminPermissionError() + } + + pat, err := am.Store.GetPATByID(ctx, store.LockingStrengthShare, targetUserID, tokenID) if err != nil { return err } @@ -415,16 +423,25 @@ func (am *DefaultAccountManager) DeletePAT(ctx context.Context, accountID string // GetPAT returns a specific PAT from a user func (am *DefaultAccountManager) GetPAT(ctx context.Context, accountID string, initiatorUserID string, targetUserID string, tokenID string) (*types.PersonalAccessToken, error) { + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Pats, operations.Read) + if err != nil { + return nil, status.NewPermissionValidationError(err) + } + if !allowed { + return nil, status.NewPermissionDeniedError() + } + initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) if err != nil { return nil, err } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { + targetUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, targetUserID) + if err != nil { return nil, err } - if initiatorUserID != targetUserID && initiatorUser.IsRegularUser() { + if initiatorUserID != targetUserID && !(initiatorUser.HasAdminPower() && targetUser.IsServiceUser) { return nil, status.NewAdminPermissionError() } @@ -433,16 +450,25 @@ func (am *DefaultAccountManager) GetPAT(ctx context.Context, accountID string, i // GetAllPATs returns all PATs for a user func (am *DefaultAccountManager) GetAllPATs(ctx context.Context, accountID string, initiatorUserID string, targetUserID string) ([]*types.PersonalAccessToken, error) { + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Pats, operations.Read) + if err != nil { + return nil, status.NewPermissionValidationError(err) + } + if !allowed { + return nil, status.NewPermissionDeniedError() + } + initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) if err != nil { return nil, err } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { + targetUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, targetUserID) + if err != nil { return nil, err } - if initiatorUserID != targetUserID && initiatorUser.IsRegularUser() { + if initiatorUserID != targetUserID && !(initiatorUser.HasAdminPower() && targetUser.IsServiceUser) { return nil, status.NewAdminPermissionError() } @@ -480,19 +506,13 @@ func (am *DefaultAccountManager) SaveOrAddUsers(ctx context.Context, accountID, return nil, nil //nolint:nilnil } - initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Users, operations.Write) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { - return nil, err + if !allowed { + return nil, status.NewPermissionDeniedError() } - - if !initiatorUser.HasAdminPower() || initiatorUser.IsBlocked() { - return nil, status.NewAdminPermissionError() - } - settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID) if err != nil { return nil, err @@ -513,6 +533,11 @@ func (am *DefaultAccountManager) SaveOrAddUsers(ctx context.Context, accountID, groupsMap[group.ID] = group } + initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) + if err != nil { + return nil, err + } + err = am.Store.ExecuteInTransaction(ctx, func(transaction store.Store) error { for _, update := range updates { if update == nil { @@ -795,18 +820,21 @@ func (am *DefaultAccountManager) GetOrCreateAccountByUser(ctx context.Context, u // GetUsersFromAccount performs a batched request for users from IDP by account ID apply filter on what data to return // based on provided user role. func (am *DefaultAccountManager) GetUsersFromAccount(ctx context.Context, accountID, initiatorUserID string) (map[string]*types.UserInfo, error) { - accountUsers, err := am.Store.GetAccountUsers(ctx, store.LockingStrengthShare, accountID) + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Users, operations.Read) if err != nil { - return nil, err + return nil, status.NewPermissionValidationError(err) + } + user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) + if err != nil { + return nil, fmt.Errorf("failed to get user: %w", err) } - initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) - if err != nil { - return nil, err - } - - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { - return nil, err + accountUsers := []*types.User{user} + if allowed { + accountUsers, err = am.Store.GetAccountUsers(ctx, store.LockingStrengthShare, accountID) + if err != nil { + return nil, err + } } return am.BuildUserInfosForAccount(ctx, accountID, initiatorUserID, accountUsers) @@ -977,19 +1005,19 @@ func (am *DefaultAccountManager) deleteUserFromIDP(ctx context.Context, targetUs // If an error occurs while deleting the user, the function skips it and continues deleting other users. // Errors are collected and returned at the end. func (am *DefaultAccountManager) DeleteRegularUsers(ctx context.Context, accountID, initiatorUserID string, targetUserIDs []string, userInfos map[string]*types.UserInfo) error { + allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, initiatorUserID, modules.Users, operations.Write) + if err != nil { + return status.NewPermissionValidationError(err) + } + if !allowed { + return status.NewPermissionDeniedError() + } + initiatorUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, initiatorUserID) if err != nil { return err } - if err := am.permissionsManager.ValidateAccountAccess(ctx, accountID, initiatorUser, false); err != nil { - return err - } - - if !initiatorUser.HasAdminPower() { - return status.NewAdminPermissionError() - } - var allErrors error var updateAccountPeers bool diff --git a/management/server/user_test.go b/management/server/user_test.go index d3344738b..c5da4ec88 100644 --- a/management/server/user_test.go +++ b/management/server/user_test.go @@ -59,11 +59,11 @@ func TestUser_CreatePAT_ForSameUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := DefaultAccountManager{ Store: s, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } pat, err := am.CreatePAT(context.Background(), mockAccountID, mockUserID, mockUserID, mockTokenName, mockExpiresIn) @@ -109,11 +109,11 @@ func TestUser_CreatePAT_ForDifferentUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } _, err = am.CreatePAT(context.Background(), mockAccountID, mockUserID, mockTargetUserId, mockTokenName, mockExpiresIn) @@ -137,11 +137,11 @@ func TestUser_CreatePAT_ForServiceUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } pat, err := am.CreatePAT(context.Background(), mockAccountID, mockUserID, mockTargetUserId, mockTokenName, mockExpiresIn) @@ -166,11 +166,11 @@ func TestUser_CreatePAT_WithWrongExpiration(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } _, err = am.CreatePAT(context.Background(), mockAccountID, mockUserID, mockUserID, mockTokenName, mockWrongExpiresIn) @@ -191,11 +191,11 @@ func TestUser_CreatePAT_WithEmptyName(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } _, err = am.CreatePAT(context.Background(), mockAccountID, mockUserID, mockUserID, mockEmptyTokenName, mockExpiresIn) @@ -218,17 +218,18 @@ func TestUser_DeletePAT(t *testing.T) { HashedToken: mockToken1, }, }, + Role: types.UserRoleAdmin, } err = store.SaveAccount(context.Background(), account) if err != nil { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } err = am.DeletePAT(context.Background(), mockAccountID, mockUserID, mockUserID, mockTokenID1) @@ -261,17 +262,18 @@ func TestUser_GetPAT(t *testing.T) { HashedToken: mockToken1, }, }, + Role: types.UserRoleAdmin, } err = store.SaveAccount(context.Background(), account) if err != nil { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } pat, err := am.GetPAT(context.Background(), mockAccountID, mockUserID, mockUserID, mockTokenID1) @@ -304,17 +306,18 @@ func TestUser_GetAllPATs(t *testing.T) { HashedToken: mockToken2, }, }, + Role: types.UserRoleAdmin, } err = store.SaveAccount(context.Background(), account) if err != nil { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } pats, err := am.GetAllPATs(context.Background(), mockAccountID, mockUserID, mockUserID) @@ -406,11 +409,11 @@ func TestUser_CreateServiceUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } user, err := am.createServiceUser(context.Background(), mockAccountID, mockUserID, mockRole, mockServiceUserName, false, []string{"group1", "group2"}) @@ -453,11 +456,11 @@ func TestUser_CreateUser_ServiceUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } user, err := am.CreateUser(context.Background(), mockAccountID, mockUserID, &types.UserInfo{ @@ -501,11 +504,11 @@ func TestUser_CreateUser_RegularUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } _, err = am.CreateUser(context.Background(), mockAccountID, mockUserID, &types.UserInfo{ @@ -532,12 +535,12 @@ func TestUser_InviteNewUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, cacheLoading: map[string]chan struct{}{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } cs, err := nbcache.NewStore(context.Background(), nbcache.DefaultIDPCacheExpirationMax, nbcache.DefaultIDPCacheCleanupInterval) @@ -640,11 +643,11 @@ func TestUser_DeleteUser_ServiceUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } err = am.DeleteUser(context.Background(), mockAccountID, mockUserID, mockServiceUserID) @@ -678,11 +681,11 @@ func TestUser_DeleteUser_SelfDelete(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } err = am.DeleteUser(context.Background(), mockAccountID, mockUserID, mockUserID) @@ -732,12 +735,11 @@ func TestUser_DeleteUser_regularUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ - Store: store, - eventStore: &activity.InMemoryEventStore{}, - integratedPeerValidator: MocIntegratedValidator{}, - permissionsManager: permissionsMananagerMock, + Store: store, + eventStore: &activity.InMemoryEventStore{}, + permissionsManager: permissionsManager, } testCases := []struct { @@ -842,12 +844,12 @@ func TestUser_DeleteUser_RegularUsers(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, integratedPeerValidator: MocIntegratedValidator{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } testCases := []struct { @@ -953,11 +955,11 @@ func TestDefaultAccountManager_GetUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } claims := nbcontext.UserAuth{ @@ -991,11 +993,11 @@ func TestDefaultAccountManager_ListUsers(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } users, err := am.ListUsers(context.Background(), mockAccountID) @@ -1080,11 +1082,11 @@ func TestDefaultAccountManager_ListUsers_DashboardPermissions(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } users, err := am.ListUsers(context.Background(), mockAccountID) @@ -1125,13 +1127,13 @@ func TestDefaultAccountManager_ExternalCache(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, idpManager: &idp.GoogleWorkspaceManager{}, // empty manager cacheLoading: map[string]chan struct{}{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } cacheStore, err := nbcache.NewStore(context.Background(), nbcache.DefaultIDPCacheExpirationMax, nbcache.DefaultIDPCacheCleanupInterval) @@ -1188,11 +1190,11 @@ func TestUser_GetUsersFromAccount_ForAdmin(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } users, err := am.GetUsersFromAccount(context.Background(), mockAccountID, mockUserID) @@ -1222,11 +1224,11 @@ func TestUser_GetUsersFromAccount_ForUser(t *testing.T) { t.Fatalf("Error when saving account: %s", err) } - permissionsMananagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(store) am := DefaultAccountManager{ Store: store, eventStore: &activity.InMemoryEventStore{}, - permissionsManager: permissionsMananagerMock, + permissionsManager: permissionsManager, } users, err := am.GetUsersFromAccount(context.Background(), mockAccountID, mockServiceUserID) @@ -1589,13 +1591,11 @@ func TestSaveOrAddUser_PreventAccountSwitch(t *testing.T) { account2 := newAccountWithId(context.Background(), "account2", "ownerAccount2", "") require.NoError(t, s.SaveAccount(context.Background(), account2)) - permissionsManagerMock := permissions.NewManagerMock() + permissionsManager := permissions.NewManager(s) am := DefaultAccountManager{ Store: s, eventStore: &activity.InMemoryEventStore{}, - idpManager: nil, - cacheLoading: map[string]chan struct{}{}, - permissionsManager: permissionsManagerMock, + permissionsManager: permissionsManager, } _, err = am.SaveOrAddUser(context.Background(), "account2", "ownerAccount2", account1.Users[targetId], true)