mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-01 19:19:07 +02:00
[client,management] Rewrite the SSH feature (#4015)
This commit is contained in:
@@ -15,6 +15,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
|
||||
cacheStore "github.com/eko/gocache/lib/v4/store"
|
||||
"github.com/eko/gocache/store/redis/v4"
|
||||
"github.com/rs/xid"
|
||||
@@ -25,6 +27,7 @@ import (
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
"github.com/netbirdio/netbird/formatter/hook"
|
||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map"
|
||||
nbconfig "github.com/netbirdio/netbird/management/internals/server/config"
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
nbcache "github.com/netbirdio/netbird/management/server/cache"
|
||||
@@ -81,6 +84,9 @@ type DefaultAccountManager struct {
|
||||
proxyController port_forwarding.Controller
|
||||
settingsManager settings.Manager
|
||||
|
||||
// config contains the management server configuration
|
||||
config *nbconfig.Config
|
||||
|
||||
// singleAccountMode indicates whether the instance has a single account.
|
||||
// If true, then every new user will end up under the same account.
|
||||
// This value will be set to false if management service has more than one account.
|
||||
@@ -171,6 +177,7 @@ func (am *DefaultAccountManager) getJWTGroupsChanges(user *types.User, groups []
|
||||
// BuildManager creates a new DefaultAccountManager with a provided Store
|
||||
func BuildManager(
|
||||
ctx context.Context,
|
||||
config *nbconfig.Config,
|
||||
store store.Store,
|
||||
networkMapController network_map.Controller,
|
||||
idpManager idp.Manager,
|
||||
@@ -192,6 +199,7 @@ func BuildManager(
|
||||
|
||||
am := &DefaultAccountManager{
|
||||
Store: store,
|
||||
config: config,
|
||||
geo: geo,
|
||||
networkMapController: networkMapController,
|
||||
idpManager: idpManager,
|
||||
@@ -1006,7 +1014,7 @@ func (am *DefaultAccountManager) removeUserFromCache(ctx context.Context, accoun
|
||||
}
|
||||
|
||||
// updateAccountDomainAttributesIfNotUpToDate updates the account domain attributes if they are not up to date and then, saves the account changes
|
||||
func (am *DefaultAccountManager) updateAccountDomainAttributesIfNotUpToDate(ctx context.Context, accountID string, userAuth nbcontext.UserAuth,
|
||||
func (am *DefaultAccountManager) updateAccountDomainAttributesIfNotUpToDate(ctx context.Context, accountID string, userAuth auth.UserAuth,
|
||||
primaryDomain bool,
|
||||
) error {
|
||||
if userAuth.Domain == "" {
|
||||
@@ -1055,7 +1063,7 @@ func (am *DefaultAccountManager) handleExistingUserAccount(
|
||||
ctx context.Context,
|
||||
userAccountID string,
|
||||
domainAccountID string,
|
||||
userAuth nbcontext.UserAuth,
|
||||
userAuth auth.UserAuth,
|
||||
) error {
|
||||
primaryDomain := domainAccountID == "" || userAccountID == domainAccountID
|
||||
err := am.updateAccountDomainAttributesIfNotUpToDate(ctx, userAccountID, userAuth, primaryDomain)
|
||||
@@ -1074,7 +1082,7 @@ func (am *DefaultAccountManager) handleExistingUserAccount(
|
||||
|
||||
// addNewPrivateAccount validates if there is an existing primary account for the domain, if so it adds the new user to that account,
|
||||
// otherwise it will create a new account and make it primary account for the domain.
|
||||
func (am *DefaultAccountManager) addNewPrivateAccount(ctx context.Context, domainAccountID string, userAuth nbcontext.UserAuth) (string, error) {
|
||||
func (am *DefaultAccountManager) addNewPrivateAccount(ctx context.Context, domainAccountID string, userAuth auth.UserAuth) (string, error) {
|
||||
if userAuth.UserId == "" {
|
||||
return "", fmt.Errorf("user ID is empty")
|
||||
}
|
||||
@@ -1105,7 +1113,7 @@ func (am *DefaultAccountManager) addNewPrivateAccount(ctx context.Context, domai
|
||||
return newAccount.Id, nil
|
||||
}
|
||||
|
||||
func (am *DefaultAccountManager) addNewUserToDomainAccount(ctx context.Context, domainAccountID string, userAuth nbcontext.UserAuth) (string, error) {
|
||||
func (am *DefaultAccountManager) addNewUserToDomainAccount(ctx context.Context, domainAccountID string, userAuth auth.UserAuth) (string, error) {
|
||||
newUser := types.NewRegularUser(userAuth.UserId)
|
||||
newUser.AccountID = domainAccountID
|
||||
|
||||
@@ -1217,7 +1225,7 @@ func (am *DefaultAccountManager) GetAccountOnboarding(ctx context.Context, accou
|
||||
|
||||
onboarding, err := am.Store.GetAccountOnboarding(ctx, accountID)
|
||||
if err != nil && err.Error() != status.NewAccountOnboardingNotFoundError(accountID).Error() {
|
||||
log.Errorf("failed to get account onboarding for accountssssssss %s: %v", accountID, err)
|
||||
log.Errorf("failed to get account onboarding for account %s: %v", accountID, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1269,7 +1277,7 @@ func (am *DefaultAccountManager) UpdateAccountOnboarding(ctx context.Context, ac
|
||||
return newOnboarding, nil
|
||||
}
|
||||
|
||||
func (am *DefaultAccountManager) GetAccountIDFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func (am *DefaultAccountManager) GetAccountIDFromUserAuth(ctx context.Context, userAuth auth.UserAuth) (string, string, error) {
|
||||
if userAuth.UserId == "" {
|
||||
return "", "", errors.New(emptyUserID)
|
||||
}
|
||||
@@ -1313,7 +1321,7 @@ func (am *DefaultAccountManager) GetAccountIDFromUserAuth(ctx context.Context, u
|
||||
// syncJWTGroups processes the JWT groups for a user, updates the account based on the groups,
|
||||
// and propagates changes to peers if group propagation is enabled.
|
||||
// requires userAuth to have been ValidateAndParseToken and EnsureUserAccessByJWTGroups by the AuthManager
|
||||
func (am *DefaultAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func (am *DefaultAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth auth.UserAuth) error {
|
||||
if userAuth.IsChild || userAuth.IsPAT {
|
||||
return nil
|
||||
}
|
||||
@@ -1471,7 +1479,7 @@ func (am *DefaultAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth
|
||||
// Existing user + Existing account + Existing domain reclassified Domain as private -> Nothing changes (index domain)
|
||||
//
|
||||
// UserAuth IsChild -> checks that account exists
|
||||
func (am *DefaultAccountManager) getAccountIDWithAuthorizationClaims(ctx context.Context, userAuth nbcontext.UserAuth) (string, error) {
|
||||
func (am *DefaultAccountManager) getAccountIDWithAuthorizationClaims(ctx context.Context, userAuth auth.UserAuth) (string, error) {
|
||||
log.WithContext(ctx).Tracef("getting account with authorization claims. User ID: \"%s\", Account ID: \"%s\", Domain: \"%s\", Domain Category: \"%s\"",
|
||||
userAuth.UserId, userAuth.AccountId, userAuth.Domain, userAuth.DomainCategory)
|
||||
|
||||
@@ -1550,7 +1558,7 @@ func (am *DefaultAccountManager) getPrivateDomainWithGlobalLock(ctx context.Cont
|
||||
return domainAccountID, cancel, nil
|
||||
}
|
||||
|
||||
func (am *DefaultAccountManager) handlePrivateAccountWithIDFromClaim(ctx context.Context, userAuth nbcontext.UserAuth) (string, error) {
|
||||
func (am *DefaultAccountManager) handlePrivateAccountWithIDFromClaim(ctx context.Context, userAuth auth.UserAuth) (string, error) {
|
||||
userAccountID, err := am.Store.GetAccountIDByUserID(ctx, store.LockingStrengthNone, userAuth.UserId)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Errorf("error getting account ID by user ID: %v", err)
|
||||
@@ -1598,7 +1606,7 @@ func handleNotFound(err error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func domainIsUpToDate(domain string, domainCategory string, userAuth nbcontext.UserAuth) bool {
|
||||
func domainIsUpToDate(domain string, domainCategory string, userAuth auth.UserAuth) bool {
|
||||
return domainCategory == types.PrivateCategory || userAuth.DomainCategory != types.PrivateCategory || domain != userAuth.Domain
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,11 @@ import (
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
nbcache "github.com/netbirdio/netbird/management/server/cache"
|
||||
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/peers/ephemeral"
|
||||
@@ -45,10 +46,10 @@ type Manager interface {
|
||||
GetAccountOnboarding(ctx context.Context, accountID string, userID string) (*types.AccountOnboarding, error)
|
||||
AccountExists(ctx context.Context, accountID string) (bool, error)
|
||||
GetAccountIDByUserID(ctx context.Context, userID, domain string) (string, error)
|
||||
GetAccountIDFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error)
|
||||
GetAccountIDFromUserAuth(ctx context.Context, userAuth auth.UserAuth) (string, string, error)
|
||||
DeleteAccount(ctx context.Context, accountID, userID string) error
|
||||
GetUserByID(ctx context.Context, id string) (*types.User, error)
|
||||
GetUserFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error)
|
||||
GetUserFromUserAuth(ctx context.Context, userAuth auth.UserAuth) (*types.User, error)
|
||||
ListUsers(ctx context.Context, accountID string) ([]*types.User, error)
|
||||
GetPeers(ctx context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error)
|
||||
MarkPeerConnected(ctx context.Context, peerKey string, connected bool, realIP net.IP, accountID string) error
|
||||
@@ -117,11 +118,11 @@ type Manager interface {
|
||||
UpdateAccountPeers(ctx context.Context, accountID string)
|
||||
BufferUpdateAccountPeers(ctx context.Context, accountID string)
|
||||
BuildUserInfosForAccount(ctx context.Context, accountID, initiatorUserID string, accountUsers []*types.User) (map[string]*types.UserInfo, error)
|
||||
SyncUserJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth) error
|
||||
SyncUserJWTGroups(ctx context.Context, userAuth auth.UserAuth) error
|
||||
GetStore() store.Store
|
||||
GetOrCreateAccountByPrivateDomain(ctx context.Context, initiatorId, domain string) (*types.Account, bool, error)
|
||||
UpdateToPrimaryAccount(ctx context.Context, accountId string) error
|
||||
GetOwnerInfo(ctx context.Context, accountId string) (*types.UserInfo, error)
|
||||
GetCurrentUserInfo(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error)
|
||||
GetCurrentUserInfo(ctx context.Context, userAuth auth.UserAuth) (*users.UserInfoWithPermissions, error)
|
||||
SetEphemeralManager(em ephemeral.Manager)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
nbAccount "github.com/netbirdio/netbird/management/server/account"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/cache"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/http/testing/testing_tools"
|
||||
"github.com/netbirdio/netbird/management/server/idp"
|
||||
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||
@@ -45,6 +44,7 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
"github.com/netbirdio/netbird/route"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
)
|
||||
|
||||
func verifyCanAddPeerToAccount(t *testing.T, manager nbAccount.Manager, account *types.Account, userID string) {
|
||||
@@ -445,7 +445,7 @@ func TestAccountManager_GetOrCreateAccountByUser(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
type initUserParams nbcontext.UserAuth
|
||||
type initUserParams auth.UserAuth
|
||||
|
||||
var (
|
||||
publicDomain = "public.com"
|
||||
@@ -468,7 +468,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
inputClaims nbcontext.UserAuth
|
||||
inputClaims auth.UserAuth
|
||||
inputInitUserParams initUserParams
|
||||
inputUpdateAttrs bool
|
||||
inputUpdateClaimAccount bool
|
||||
@@ -483,7 +483,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "New User With Public Domain",
|
||||
inputClaims: nbcontext.UserAuth{
|
||||
inputClaims: auth.UserAuth{
|
||||
Domain: publicDomain,
|
||||
UserId: "pub-domain-user",
|
||||
DomainCategory: types.PublicCategory,
|
||||
@@ -500,7 +500,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "New User With Unknown Domain",
|
||||
inputClaims: nbcontext.UserAuth{
|
||||
inputClaims: auth.UserAuth{
|
||||
Domain: unknownDomain,
|
||||
UserId: "unknown-domain-user",
|
||||
DomainCategory: types.UnknownCategory,
|
||||
@@ -517,7 +517,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "New User With Private Domain",
|
||||
inputClaims: nbcontext.UserAuth{
|
||||
inputClaims: auth.UserAuth{
|
||||
Domain: privateDomain,
|
||||
UserId: "pvt-domain-user",
|
||||
DomainCategory: types.PrivateCategory,
|
||||
@@ -534,7 +534,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "New Regular User With Existing Private Domain",
|
||||
inputClaims: nbcontext.UserAuth{
|
||||
inputClaims: auth.UserAuth{
|
||||
Domain: privateDomain,
|
||||
UserId: "new-pvt-domain-user",
|
||||
DomainCategory: types.PrivateCategory,
|
||||
@@ -552,7 +552,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Existing User With Existing Reclassified Private Domain",
|
||||
inputClaims: nbcontext.UserAuth{
|
||||
inputClaims: auth.UserAuth{
|
||||
Domain: defaultInitAccount.Domain,
|
||||
UserId: defaultInitAccount.UserId,
|
||||
DomainCategory: types.PrivateCategory,
|
||||
@@ -569,7 +569,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Existing Account Id With Existing Reclassified Private Domain",
|
||||
inputClaims: nbcontext.UserAuth{
|
||||
inputClaims: auth.UserAuth{
|
||||
Domain: defaultInitAccount.Domain,
|
||||
UserId: defaultInitAccount.UserId,
|
||||
DomainCategory: types.PrivateCategory,
|
||||
@@ -587,7 +587,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "User With Private Category And Empty Domain",
|
||||
inputClaims: nbcontext.UserAuth{
|
||||
inputClaims: auth.UserAuth{
|
||||
Domain: "",
|
||||
UserId: "pvt-domain-user",
|
||||
DomainCategory: types.PrivateCategory,
|
||||
@@ -616,7 +616,7 @@ func TestDefaultAccountManager_GetAccountIDFromToken(t *testing.T) {
|
||||
require.NoError(t, err, "get init account failed")
|
||||
|
||||
if testCase.inputUpdateAttrs {
|
||||
err = manager.updateAccountDomainAttributesIfNotUpToDate(context.Background(), initAccount.Id, nbcontext.UserAuth{UserId: testCase.inputInitUserParams.UserId, Domain: testCase.inputInitUserParams.Domain, DomainCategory: testCase.inputInitUserParams.DomainCategory}, true)
|
||||
err = manager.updateAccountDomainAttributesIfNotUpToDate(context.Background(), initAccount.Id, auth.UserAuth{UserId: testCase.inputInitUserParams.UserId, Domain: testCase.inputInitUserParams.Domain, DomainCategory: testCase.inputInitUserParams.DomainCategory}, true)
|
||||
require.NoError(t, err, "update init user failed")
|
||||
}
|
||||
|
||||
@@ -656,7 +656,7 @@ func TestDefaultAccountManager_SyncUserJWTGroups(t *testing.T) {
|
||||
// it is important to set the id as it help to avoid creating additional account with empty Id and re-pointing indices to it
|
||||
initAccount, err := manager.Store.GetAccount(context.Background(), accountID)
|
||||
require.NoError(t, err, "get init account failed")
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
AccountId: accountID, // is empty as it is based on accountID right after initialization of initAccount
|
||||
Domain: domain,
|
||||
UserId: userId,
|
||||
@@ -915,13 +915,13 @@ func TestAccountManager_DeleteAccount(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkTest_GetAccountWithclaims(b *testing.B) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
Domain: "example.com",
|
||||
UserId: "pvt-domain-user",
|
||||
DomainCategory: types.PrivateCategory,
|
||||
}
|
||||
|
||||
publicClaims := nbcontext.UserAuth{
|
||||
publicClaims := auth.UserAuth{
|
||||
Domain: "test.com",
|
||||
UserId: "public-domain-user",
|
||||
DomainCategory: types.PublicCategory,
|
||||
@@ -2709,7 +2709,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
assert.NoError(t, manager.Store.SaveAccount(context.Background(), account), "unable to save account")
|
||||
|
||||
t.Run("skip sync for token auth type", func(t *testing.T) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user1",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{"group3"},
|
||||
@@ -2724,7 +2724,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("empty jwt groups", func(t *testing.T) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user1",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{},
|
||||
@@ -2738,7 +2738,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("jwt match existing api group", func(t *testing.T) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user1",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{"group1"},
|
||||
@@ -2759,7 +2759,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
account.Users["user1"].AutoGroups = []string{"group1"}
|
||||
assert.NoError(t, manager.Store.SaveUser(context.Background(), account.Users["user1"]))
|
||||
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user1",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{"group1"},
|
||||
@@ -2777,7 +2777,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("add jwt group", func(t *testing.T) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user1",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{"group1", "group2"},
|
||||
@@ -2791,7 +2791,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("existed group not update", func(t *testing.T) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user1",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{"group2"},
|
||||
@@ -2805,7 +2805,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("add new group", func(t *testing.T) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user2",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{"group1", "group3"},
|
||||
@@ -2823,7 +2823,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("remove all JWT groups when list is empty", func(t *testing.T) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user1",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{},
|
||||
@@ -2838,7 +2838,7 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("remove all JWT groups when claim does not exist", func(t *testing.T) {
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: "user2",
|
||||
AccountId: "accountID",
|
||||
Groups: []string{},
|
||||
@@ -2959,7 +2959,7 @@ func createManager(t testing.TB) (*DefaultAccountManager, *update_channel.PeersU
|
||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock())
|
||||
manager, err := BuildManager(ctx, store, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
manager, err := BuildManager(ctx, nil, store, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -3692,7 +3692,7 @@ func TestAddNewUserToDomainAccountWithApproval(t *testing.T) {
|
||||
|
||||
// Test adding new user to existing account with approval required
|
||||
newUserID := "new-user-id"
|
||||
userAuth := nbcontext.UserAuth{
|
||||
userAuth := auth.UserAuth{
|
||||
UserId: newUserID,
|
||||
Domain: "example.com",
|
||||
DomainCategory: types.PrivateCategory,
|
||||
@@ -3722,7 +3722,7 @@ func TestAddNewUserToDomainAccountWithoutApproval(t *testing.T) {
|
||||
}
|
||||
|
||||
// Create a domain-based account without user approval
|
||||
ownerUserAuth := nbcontext.UserAuth{
|
||||
ownerUserAuth := auth.UserAuth{
|
||||
UserId: "owner-user",
|
||||
Domain: "example.com",
|
||||
DomainCategory: types.PrivateCategory,
|
||||
@@ -3741,7 +3741,7 @@ func TestAddNewUserToDomainAccountWithoutApproval(t *testing.T) {
|
||||
|
||||
// Test adding new user to existing account without approval required
|
||||
newUserID := "new-user-id"
|
||||
userAuth := nbcontext.UserAuth{
|
||||
userAuth := auth.UserAuth{
|
||||
UserId: newUserID,
|
||||
Domain: "example.com",
|
||||
DomainCategory: types.PrivateCategory,
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
)
|
||||
|
||||
const (
|
||||
// AccountIDSuffix suffix for the account id claim
|
||||
AccountIDSuffix = "wt_account_id"
|
||||
// DomainIDSuffix suffix for the domain id claim
|
||||
DomainIDSuffix = "wt_account_domain"
|
||||
// DomainCategorySuffix suffix for the domain category claim
|
||||
DomainCategorySuffix = "wt_account_domain_category"
|
||||
// UserIDClaim claim for the user id
|
||||
UserIDClaim = "sub"
|
||||
// LastLoginSuffix claim for the last login
|
||||
LastLoginSuffix = "nb_last_login"
|
||||
// Invited claim indicates that an incoming JWT is from a user that just accepted an invitation
|
||||
Invited = "nb_invited"
|
||||
)
|
||||
|
||||
var (
|
||||
errUserIDClaimEmpty = errors.New("user ID claim token value is empty")
|
||||
)
|
||||
|
||||
// ClaimsExtractor struct that holds the extract function
|
||||
type ClaimsExtractor struct {
|
||||
authAudience string
|
||||
userIDClaim string
|
||||
}
|
||||
|
||||
// ClaimsExtractorOption is a function that configures the ClaimsExtractor
|
||||
type ClaimsExtractorOption func(*ClaimsExtractor)
|
||||
|
||||
// WithAudience sets the audience for the extractor
|
||||
func WithAudience(audience string) ClaimsExtractorOption {
|
||||
return func(c *ClaimsExtractor) {
|
||||
c.authAudience = audience
|
||||
}
|
||||
}
|
||||
|
||||
// WithUserIDClaim sets the user id claim for the extractor
|
||||
func WithUserIDClaim(userIDClaim string) ClaimsExtractorOption {
|
||||
return func(c *ClaimsExtractor) {
|
||||
c.userIDClaim = userIDClaim
|
||||
}
|
||||
}
|
||||
|
||||
// NewClaimsExtractor returns an extractor, and if provided with a function with ExtractClaims signature,
|
||||
// then it will use that logic. Uses ExtractClaimsFromRequestContext by default
|
||||
func NewClaimsExtractor(options ...ClaimsExtractorOption) *ClaimsExtractor {
|
||||
ce := &ClaimsExtractor{}
|
||||
for _, option := range options {
|
||||
option(ce)
|
||||
}
|
||||
|
||||
if ce.userIDClaim == "" {
|
||||
ce.userIDClaim = UserIDClaim
|
||||
}
|
||||
return ce
|
||||
}
|
||||
|
||||
func parseTime(timeString string) time.Time {
|
||||
if timeString == "" {
|
||||
return time.Time{}
|
||||
}
|
||||
parsedTime, err := time.Parse(time.RFC3339, timeString)
|
||||
if err != nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return parsedTime
|
||||
}
|
||||
|
||||
func (c ClaimsExtractor) audienceClaim(claimName string) string {
|
||||
url, err := url.JoinPath(c.authAudience, claimName)
|
||||
if err != nil {
|
||||
return c.authAudience + claimName // as it was previously
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (c *ClaimsExtractor) ToUserAuth(token *jwt.Token) (nbcontext.UserAuth, error) {
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
userAuth := nbcontext.UserAuth{}
|
||||
|
||||
userID, ok := claims[c.userIDClaim].(string)
|
||||
if !ok {
|
||||
return userAuth, errUserIDClaimEmpty
|
||||
}
|
||||
userAuth.UserId = userID
|
||||
|
||||
if accountIDClaim, ok := claims[c.audienceClaim(AccountIDSuffix)]; ok {
|
||||
userAuth.AccountId = accountIDClaim.(string)
|
||||
}
|
||||
|
||||
if domainClaim, ok := claims[c.audienceClaim(DomainIDSuffix)]; ok {
|
||||
userAuth.Domain = domainClaim.(string)
|
||||
}
|
||||
|
||||
if domainCategoryClaim, ok := claims[c.audienceClaim(DomainCategorySuffix)]; ok {
|
||||
userAuth.DomainCategory = domainCategoryClaim.(string)
|
||||
}
|
||||
|
||||
if lastLoginClaimString, ok := claims[c.audienceClaim(LastLoginSuffix)]; ok {
|
||||
userAuth.LastLogin = parseTime(lastLoginClaimString.(string))
|
||||
}
|
||||
|
||||
if invitedBool, ok := claims[c.audienceClaim(Invited)]; ok {
|
||||
if value, ok := invitedBool.(bool); ok {
|
||||
userAuth.Invited = value
|
||||
}
|
||||
}
|
||||
|
||||
return userAuth, nil
|
||||
}
|
||||
|
||||
func (c *ClaimsExtractor) ToGroups(token *jwt.Token, claimName string) []string {
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
userJWTGroups := make([]string, 0)
|
||||
|
||||
if claim, ok := claims[claimName]; ok {
|
||||
if claimGroups, ok := claim.([]interface{}); ok {
|
||||
for _, g := range claimGroups {
|
||||
if group, ok := g.(string); ok {
|
||||
userJWTGroups = append(userJWTGroups, group)
|
||||
} else {
|
||||
log.Debugf("JWT claim %q contains a non-string group (type: %T): %v", claimName, g, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Debugf("JWT claim %q is not a string array", claimName)
|
||||
}
|
||||
|
||||
return userJWTGroups
|
||||
}
|
||||
@@ -1,288 +0,0 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Jwks is a collection of JSONWebKey obtained from Config.HttpServerConfig.AuthKeysLocation
|
||||
type Jwks struct {
|
||||
Keys []JSONWebKey `json:"keys"`
|
||||
expiresInTime time.Time
|
||||
}
|
||||
|
||||
// The supported elliptic curves types
|
||||
const (
|
||||
// p256 represents a cryptographic elliptical curve type.
|
||||
p256 = "P-256"
|
||||
|
||||
// p384 represents a cryptographic elliptical curve type.
|
||||
p384 = "P-384"
|
||||
|
||||
// p521 represents a cryptographic elliptical curve type.
|
||||
p521 = "P-521"
|
||||
)
|
||||
|
||||
// JSONWebKey is a representation of a Jason Web Key
|
||||
type JSONWebKey struct {
|
||||
Kty string `json:"kty"`
|
||||
Kid string `json:"kid"`
|
||||
Use string `json:"use"`
|
||||
N string `json:"n"`
|
||||
E string `json:"e"`
|
||||
Crv string `json:"crv"`
|
||||
X string `json:"x"`
|
||||
Y string `json:"y"`
|
||||
X5c []string `json:"x5c"`
|
||||
}
|
||||
|
||||
type Validator struct {
|
||||
lock sync.Mutex
|
||||
issuer string
|
||||
audienceList []string
|
||||
keysLocation string
|
||||
idpSignkeyRefreshEnabled bool
|
||||
keys *Jwks
|
||||
}
|
||||
|
||||
var (
|
||||
errKeyNotFound = errors.New("unable to find appropriate key")
|
||||
errTokenEmpty = errors.New("required authorization token not found")
|
||||
errTokenInvalid = errors.New("token is invalid")
|
||||
errTokenParsing = errors.New("token could not be parsed")
|
||||
)
|
||||
|
||||
func NewValidator(issuer string, audienceList []string, keysLocation string, idpSignkeyRefreshEnabled bool) *Validator {
|
||||
keys, err := getPemKeys(keysLocation)
|
||||
if err != nil {
|
||||
log.WithField("keysLocation", keysLocation).Errorf("could not get keys from location: %s", err)
|
||||
}
|
||||
|
||||
return &Validator{
|
||||
keys: keys,
|
||||
issuer: issuer,
|
||||
audienceList: audienceList,
|
||||
keysLocation: keysLocation,
|
||||
idpSignkeyRefreshEnabled: idpSignkeyRefreshEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
func (v *Validator) getKeyFunc(ctx context.Context) jwt.Keyfunc {
|
||||
return func(token *jwt.Token) (interface{}, error) {
|
||||
// If keys are rotated, verify the keys prior to token validation
|
||||
if v.idpSignkeyRefreshEnabled {
|
||||
// If the keys are invalid, retrieve new ones
|
||||
// @todo propose a separate go routine to regularly check these to prevent blocking when actually
|
||||
// validating the token
|
||||
if !v.keys.stillValid() {
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
|
||||
refreshedKeys, err := getPemKeys(v.keysLocation)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Debugf("cannot get JSONWebKey: %v, falling back to old keys", err)
|
||||
refreshedKeys = v.keys
|
||||
}
|
||||
|
||||
log.WithContext(ctx).Debugf("keys refreshed, new UTC expiration time: %s", refreshedKeys.expiresInTime.UTC())
|
||||
|
||||
v.keys = refreshedKeys
|
||||
}
|
||||
}
|
||||
|
||||
publicKey, err := getPublicKey(token, v.keys)
|
||||
if err == nil {
|
||||
return publicKey, nil
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("getPublicKey error: %s", err)
|
||||
if errors.Is(err, errKeyNotFound) && !v.idpSignkeyRefreshEnabled {
|
||||
msg = fmt.Sprintf("getPublicKey error: %s. You can enable key refresh by setting HttpServerConfig.IdpSignKeyRefreshEnabled to true in your management.json file and restart the service", err)
|
||||
}
|
||||
|
||||
log.WithContext(ctx).Error(msg)
|
||||
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateAndParse validates the token and returns the parsed token
|
||||
func (v *Validator) ValidateAndParse(ctx context.Context, token string) (*jwt.Token, error) {
|
||||
// If the token is empty...
|
||||
if token == "" {
|
||||
// If we get here, the required token is missing
|
||||
log.WithContext(ctx).Debugf(" Error: No credentials found (CredentialsOptional=false)")
|
||||
return nil, errTokenEmpty
|
||||
}
|
||||
|
||||
// Now parse the token
|
||||
parsedToken, err := jwt.Parse(
|
||||
token,
|
||||
v.getKeyFunc(ctx),
|
||||
jwt.WithAudience(v.audienceList...),
|
||||
jwt.WithIssuer(v.issuer),
|
||||
jwt.WithIssuedAt(),
|
||||
)
|
||||
|
||||
// Check if there was an error in parsing...
|
||||
if err != nil {
|
||||
err = fmt.Errorf("%w: %s", errTokenParsing, err)
|
||||
log.WithContext(ctx).Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if the parsed token is valid...
|
||||
if !parsedToken.Valid {
|
||||
log.WithContext(ctx).Debug(errTokenInvalid.Error())
|
||||
return nil, errTokenInvalid
|
||||
}
|
||||
|
||||
return parsedToken, nil
|
||||
}
|
||||
|
||||
// stillValid returns true if the JSONWebKey still valid and have enough time to be used
|
||||
func (jwks *Jwks) stillValid() bool {
|
||||
return !jwks.expiresInTime.IsZero() && time.Now().Add(5*time.Second).Before(jwks.expiresInTime)
|
||||
}
|
||||
|
||||
func getPemKeys(keysLocation string) (*Jwks, error) {
|
||||
jwks := &Jwks{}
|
||||
|
||||
url, err := url.ParseRequestURI(keysLocation)
|
||||
if err != nil {
|
||||
return jwks, err
|
||||
}
|
||||
|
||||
resp, err := http.Get(url.String())
|
||||
if err != nil {
|
||||
return jwks, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(jwks)
|
||||
if err != nil {
|
||||
return jwks, err
|
||||
}
|
||||
|
||||
cacheControlHeader := resp.Header.Get("Cache-Control")
|
||||
expiresIn := getMaxAgeFromCacheHeader(cacheControlHeader)
|
||||
jwks.expiresInTime = time.Now().Add(time.Duration(expiresIn) * time.Second)
|
||||
|
||||
return jwks, nil
|
||||
}
|
||||
|
||||
func getPublicKey(token *jwt.Token, jwks *Jwks) (interface{}, error) {
|
||||
// todo as we load the jkws when the server is starting, we should build a JKS map with the pem cert at the boot time
|
||||
for k := range jwks.Keys {
|
||||
if token.Header["kid"] != jwks.Keys[k].Kid {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(jwks.Keys[k].X5c) != 0 {
|
||||
cert := "-----BEGIN CERTIFICATE-----\n" + jwks.Keys[k].X5c[0] + "\n-----END CERTIFICATE-----"
|
||||
return jwt.ParseRSAPublicKeyFromPEM([]byte(cert))
|
||||
}
|
||||
|
||||
if jwks.Keys[k].Kty == "RSA" {
|
||||
return getPublicKeyFromRSA(jwks.Keys[k])
|
||||
}
|
||||
if jwks.Keys[k].Kty == "EC" {
|
||||
return getPublicKeyFromECDSA(jwks.Keys[k])
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errKeyNotFound
|
||||
}
|
||||
|
||||
func getPublicKeyFromECDSA(jwk JSONWebKey) (publicKey *ecdsa.PublicKey, err error) {
|
||||
if jwk.X == "" || jwk.Y == "" || jwk.Crv == "" {
|
||||
return nil, fmt.Errorf("ecdsa key incomplete")
|
||||
}
|
||||
|
||||
var xCoordinate []byte
|
||||
if xCoordinate, err = base64.RawURLEncoding.DecodeString(jwk.X); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var yCoordinate []byte
|
||||
if yCoordinate, err = base64.RawURLEncoding.DecodeString(jwk.Y); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
publicKey = &ecdsa.PublicKey{}
|
||||
|
||||
var curve elliptic.Curve
|
||||
switch jwk.Crv {
|
||||
case p256:
|
||||
curve = elliptic.P256()
|
||||
case p384:
|
||||
curve = elliptic.P384()
|
||||
case p521:
|
||||
curve = elliptic.P521()
|
||||
}
|
||||
|
||||
publicKey.Curve = curve
|
||||
publicKey.X = big.NewInt(0).SetBytes(xCoordinate)
|
||||
publicKey.Y = big.NewInt(0).SetBytes(yCoordinate)
|
||||
|
||||
return publicKey, nil
|
||||
}
|
||||
|
||||
func getPublicKeyFromRSA(jwk JSONWebKey) (*rsa.PublicKey, error) {
|
||||
decodedE, err := base64.RawURLEncoding.DecodeString(jwk.E)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
decodedN, err := base64.RawURLEncoding.DecodeString(jwk.N)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var n, e big.Int
|
||||
e.SetBytes(decodedE)
|
||||
n.SetBytes(decodedN)
|
||||
|
||||
return &rsa.PublicKey{
|
||||
E: int(e.Int64()),
|
||||
N: &n,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getMaxAgeFromCacheHeader extracts max-age directive from the Cache-Control header
|
||||
func getMaxAgeFromCacheHeader(cacheControl string) int {
|
||||
// Split into individual directives
|
||||
directives := strings.Split(cacheControl, ",")
|
||||
|
||||
for _, directive := range directives {
|
||||
directive = strings.TrimSpace(directive)
|
||||
if strings.HasPrefix(directive, "max-age=") {
|
||||
// Extract the max-age value
|
||||
maxAgeStr := strings.TrimPrefix(directive, "max-age=")
|
||||
maxAge, err := strconv.Atoi(maxAgeStr)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return maxAge
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -9,18 +9,19 @@ import (
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
|
||||
"github.com/netbirdio/netbird/base62"
|
||||
nbjwt "github.com/netbirdio/netbird/management/server/auth/jwt"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
nbjwt "github.com/netbirdio/netbird/shared/auth/jwt"
|
||||
)
|
||||
|
||||
var _ Manager = (*manager)(nil)
|
||||
|
||||
type Manager interface {
|
||||
ValidateAndParseToken(ctx context.Context, value string) (nbcontext.UserAuth, *jwt.Token, error)
|
||||
EnsureUserAccessByJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth, token *jwt.Token) (nbcontext.UserAuth, error)
|
||||
ValidateAndParseToken(ctx context.Context, value string) (auth.UserAuth, *jwt.Token, error)
|
||||
EnsureUserAccessByJWTGroups(ctx context.Context, userAuth auth.UserAuth, token *jwt.Token) (auth.UserAuth, error)
|
||||
MarkPATUsed(ctx context.Context, tokenID string) error
|
||||
GetPATInfo(ctx context.Context, token string) (user *types.User, pat *types.PersonalAccessToken, domain string, category string, err error)
|
||||
}
|
||||
@@ -55,20 +56,20 @@ func NewManager(store store.Store, issuer, audience, keysLocation, userIdClaim s
|
||||
}
|
||||
}
|
||||
|
||||
func (m *manager) ValidateAndParseToken(ctx context.Context, value string) (nbcontext.UserAuth, *jwt.Token, error) {
|
||||
func (m *manager) ValidateAndParseToken(ctx context.Context, value string) (auth.UserAuth, *jwt.Token, error) {
|
||||
token, err := m.validator.ValidateAndParse(ctx, value)
|
||||
if err != nil {
|
||||
return nbcontext.UserAuth{}, nil, err
|
||||
return auth.UserAuth{}, nil, err
|
||||
}
|
||||
|
||||
userAuth, err := m.extractor.ToUserAuth(token)
|
||||
if err != nil {
|
||||
return nbcontext.UserAuth{}, nil, err
|
||||
return auth.UserAuth{}, nil, err
|
||||
}
|
||||
return userAuth, token, err
|
||||
}
|
||||
|
||||
func (m *manager) EnsureUserAccessByJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth, token *jwt.Token) (nbcontext.UserAuth, error) {
|
||||
func (m *manager) EnsureUserAccessByJWTGroups(ctx context.Context, userAuth auth.UserAuth, token *jwt.Token) (auth.UserAuth, error) {
|
||||
if userAuth.IsChild || userAuth.IsPAT {
|
||||
return userAuth, nil
|
||||
}
|
||||
|
||||
@@ -3,9 +3,10 @@ package auth
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
@@ -15,18 +16,18 @@ var (
|
||||
|
||||
// @note really dislike this mocking approach but rather than have to do additional test refactoring.
|
||||
type MockManager struct {
|
||||
ValidateAndParseTokenFunc func(ctx context.Context, value string) (nbcontext.UserAuth, *jwt.Token, error)
|
||||
EnsureUserAccessByJWTGroupsFunc func(ctx context.Context, userAuth nbcontext.UserAuth, token *jwt.Token) (nbcontext.UserAuth, error)
|
||||
ValidateAndParseTokenFunc func(ctx context.Context, value string) (auth.UserAuth, *jwt.Token, error)
|
||||
EnsureUserAccessByJWTGroupsFunc func(ctx context.Context, userAuth auth.UserAuth, token *jwt.Token) (auth.UserAuth, error)
|
||||
MarkPATUsedFunc func(ctx context.Context, tokenID string) error
|
||||
GetPATInfoFunc func(ctx context.Context, token string) (user *types.User, pat *types.PersonalAccessToken, domain string, category string, err error)
|
||||
}
|
||||
|
||||
// EnsureUserAccessByJWTGroups implements Manager.
|
||||
func (m *MockManager) EnsureUserAccessByJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth, token *jwt.Token) (nbcontext.UserAuth, error) {
|
||||
func (m *MockManager) EnsureUserAccessByJWTGroups(ctx context.Context, userAuth auth.UserAuth, token *jwt.Token) (auth.UserAuth, error) {
|
||||
if m.EnsureUserAccessByJWTGroupsFunc != nil {
|
||||
return m.EnsureUserAccessByJWTGroupsFunc(ctx, userAuth, token)
|
||||
}
|
||||
return nbcontext.UserAuth{}, nil
|
||||
return auth.UserAuth{}, nil
|
||||
}
|
||||
|
||||
// GetPATInfo implements Manager.
|
||||
@@ -46,9 +47,9 @@ func (m *MockManager) MarkPATUsed(ctx context.Context, tokenID string) error {
|
||||
}
|
||||
|
||||
// ValidateAndParseToken implements Manager.
|
||||
func (m *MockManager) ValidateAndParseToken(ctx context.Context, value string) (nbcontext.UserAuth, *jwt.Token, error) {
|
||||
func (m *MockManager) ValidateAndParseToken(ctx context.Context, value string) (auth.UserAuth, *jwt.Token, error) {
|
||||
if m.ValidateAndParseTokenFunc != nil {
|
||||
return m.ValidateAndParseTokenFunc(ctx, value)
|
||||
}
|
||||
return nbcontext.UserAuth{}, &jwt.Token{}, nil
|
||||
return auth.UserAuth{}, &jwt.Token{}, nil
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/auth"
|
||||
nbjwt "github.com/netbirdio/netbird/management/server/auth/jwt"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
nbauth "github.com/netbirdio/netbird/shared/auth"
|
||||
nbjwt "github.com/netbirdio/netbird/shared/auth/jwt"
|
||||
)
|
||||
|
||||
func TestAuthManager_GetAccountInfoFromPAT(t *testing.T) {
|
||||
@@ -131,7 +131,7 @@ func TestAuthManager_EnsureUserAccessByJWTGroups(t *testing.T) {
|
||||
}
|
||||
|
||||
// this has been validated and parsed by ValidateAndParseToken
|
||||
userAuth := nbcontext.UserAuth{
|
||||
userAuth := nbauth.UserAuth{
|
||||
AccountId: account.Id,
|
||||
Domain: domain,
|
||||
UserId: userId,
|
||||
@@ -236,7 +236,7 @@ func TestAuthManager_ValidateAndParseToken(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
tokenFunc func() string
|
||||
expected *nbcontext.UserAuth // nil indicates expected error
|
||||
expected *nbauth.UserAuth // nil indicates expected error
|
||||
}{
|
||||
{
|
||||
name: "Valid with custom claims",
|
||||
@@ -258,7 +258,7 @@ func TestAuthManager_ValidateAndParseToken(t *testing.T) {
|
||||
tokenString, _ := token.SignedString(key)
|
||||
return tokenString
|
||||
},
|
||||
expected: &nbcontext.UserAuth{
|
||||
expected: &nbauth.UserAuth{
|
||||
UserId: "user-id|123",
|
||||
AccountId: "account-id|567",
|
||||
Domain: "http://localhost",
|
||||
@@ -282,7 +282,7 @@ func TestAuthManager_ValidateAndParseToken(t *testing.T) {
|
||||
tokenString, _ := token.SignedString(key)
|
||||
return tokenString
|
||||
},
|
||||
expected: &nbcontext.UserAuth{
|
||||
expected: &nbauth.UserAuth{
|
||||
UserId: "user-id|123",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,7 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
)
|
||||
|
||||
type key int
|
||||
@@ -13,45 +14,22 @@ const (
|
||||
UserAuthContextKey key = iota
|
||||
)
|
||||
|
||||
type UserAuth struct {
|
||||
// The account id the user is accessing
|
||||
AccountId string
|
||||
// The account domain
|
||||
Domain string
|
||||
// The account domain category, TBC values
|
||||
DomainCategory string
|
||||
// Indicates whether this user was invited, TBC logic
|
||||
Invited bool
|
||||
// Indicates whether this is a child account
|
||||
IsChild bool
|
||||
|
||||
// The user id
|
||||
UserId string
|
||||
// Last login time for this user
|
||||
LastLogin time.Time
|
||||
// The Groups the user belongs to on this account
|
||||
Groups []string
|
||||
|
||||
// Indicates whether this user has authenticated with a Personal Access Token
|
||||
IsPAT bool
|
||||
}
|
||||
|
||||
func GetUserAuthFromRequest(r *http.Request) (UserAuth, error) {
|
||||
func GetUserAuthFromRequest(r *http.Request) (auth.UserAuth, error) {
|
||||
return GetUserAuthFromContext(r.Context())
|
||||
}
|
||||
|
||||
func SetUserAuthInRequest(r *http.Request, userAuth UserAuth) *http.Request {
|
||||
func SetUserAuthInRequest(r *http.Request, userAuth auth.UserAuth) *http.Request {
|
||||
return r.WithContext(SetUserAuthInContext(r.Context(), userAuth))
|
||||
}
|
||||
|
||||
func GetUserAuthFromContext(ctx context.Context) (UserAuth, error) {
|
||||
if userAuth, ok := ctx.Value(UserAuthContextKey).(UserAuth); ok {
|
||||
func GetUserAuthFromContext(ctx context.Context) (auth.UserAuth, error) {
|
||||
if userAuth, ok := ctx.Value(UserAuthContextKey).(auth.UserAuth); ok {
|
||||
return userAuth, nil
|
||||
}
|
||||
return UserAuth{}, fmt.Errorf("user auth not in context")
|
||||
return auth.UserAuth{}, fmt.Errorf("user auth not in context")
|
||||
}
|
||||
|
||||
func SetUserAuthInContext(ctx context.Context, userAuth UserAuth) context.Context {
|
||||
func SetUserAuthInContext(ctx context.Context, userAuth auth.UserAuth) context.Context {
|
||||
//nolint
|
||||
ctx = context.WithValue(ctx, UserIDKey, userAuth.UserId)
|
||||
//nolint
|
||||
|
||||
@@ -224,7 +224,7 @@ func createDNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.test", port_forwarding.NewControllerMock())
|
||||
|
||||
return BuildManager(context.Background(), store, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
return BuildManager(context.Background(), nil, store, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
}
|
||||
|
||||
func createDNSStore(t *testing.T) (store.Store, error) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/settings"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
@@ -236,7 +237,7 @@ func TestAccounts_AccountsHandler(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: adminUser.Id,
|
||||
AccountId: accountID,
|
||||
Domain: "hotmail.com",
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
// dnsSettingsHandler is a handler that returns the DNS settings of the account
|
||||
|
||||
@@ -11,13 +11,14 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
)
|
||||
@@ -107,7 +108,7 @@ func TestDNSSettingsHandlers(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: testingDNSSettingsAccount.Users[testDNSSettingsUserID].Id,
|
||||
AccountId: testingDNSSettingsAccount.Id,
|
||||
Domain: testingDNSSettingsAccount.Domain,
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
)
|
||||
@@ -193,7 +194,7 @@ func TestNameserversHandlers(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
AccountId: testNSGroupAccountID,
|
||||
Domain: "hotmail.com",
|
||||
|
||||
@@ -14,11 +14,12 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
)
|
||||
|
||||
func initEventsTestData(account string, events ...*activity.Event) *handler {
|
||||
@@ -188,7 +189,7 @@ func TestEvents_GetEvents(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_account",
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
// handler is a handler that returns groups of the account
|
||||
|
||||
@@ -19,12 +19,13 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
var TestPeers = map[string]*nbpeer.Peer{
|
||||
@@ -122,7 +123,7 @@ func TestGetGroup(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
@@ -248,7 +249,7 @@ func TestWriteGroup(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
@@ -330,7 +331,7 @@ func TestDeleteGroup(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, nil)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
|
||||
@@ -12,15 +12,15 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/groups"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/networks"
|
||||
"github.com/netbirdio/netbird/management/server/networks/resources"
|
||||
"github.com/netbirdio/netbird/management/server/networks/routers"
|
||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||
"github.com/netbirdio/netbird/management/server/networks/types"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
nbtypes "github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
// handler is a handler that returns networks of the account
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/groups"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/networks/resources"
|
||||
"github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
)
|
||||
|
||||
type resourceHandler struct {
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/networks/routers"
|
||||
"github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
)
|
||||
|
||||
type routersHandler struct {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -296,7 +297,7 @@ func TestGetPeers(t *testing.T) {
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "admin_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
@@ -444,7 +445,7 @@ func TestGetAccessiblePeers(t *testing.T) {
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/peers/%s/accessible-peers", tc.peerID), nil)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: tc.callerUserID,
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
@@ -527,7 +528,7 @@ func TestPeersHandlerUpdatePeerIP(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodPut, fmt.Sprintf("/peers/%s", tc.peerID), bytes.NewBuffer([]byte(tc.requestBody)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: tc.callerUserID,
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
|
||||
@@ -16,12 +16,13 @@ import (
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"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/types"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/util"
|
||||
)
|
||||
|
||||
@@ -113,7 +114,7 @@ func TestGetCitiesByCountry(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, nil)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
@@ -206,7 +207,7 @@ func TestGetAllCountries(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, nil)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
|
||||
@@ -9,11 +9,11 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"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/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
// handler is a handler that returns policy of the account
|
||||
|
||||
@@ -14,10 +14,11 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
func initPoliciesTestData(policies ...*types.Policy) *handler {
|
||||
@@ -103,7 +104,7 @@ func TestPoliciesGetPolicy(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
@@ -267,7 +268,7 @@ func TestPoliciesWritePolicy(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||
"github.com/netbirdio/netbird/management/server/posture"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/posture"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
|
||||
@@ -16,9 +16,10 @@ import (
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/posture"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
@@ -175,7 +176,7 @@ func TestGetPostureCheck(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/posture-checks/"+tc.id, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
@@ -828,7 +829,7 @@ func TestPostureCheckUpdate(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
"github.com/netbirdio/netbird/route"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
@@ -493,7 +494,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: testAccountID,
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
// handler is a handler that returns a list of setup keys of the account
|
||||
|
||||
@@ -15,10 +15,11 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -163,7 +164,7 @@ func TestSetupKeysHandlers(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: adminUser.Id,
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "testAccountId",
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
// patHandler is the nameserver group handler of the account
|
||||
|
||||
@@ -17,10 +17,11 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -173,7 +174,7 @@ func TestTokenHandlers(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: existingUserID,
|
||||
Domain: testDomain,
|
||||
AccountId: existingAccountID,
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/permissions/roles"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/management/server/users"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
@@ -128,7 +129,7 @@ func initUsersTestData() *handler {
|
||||
|
||||
return nil
|
||||
},
|
||||
GetCurrentUserInfoFunc: func(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||
GetCurrentUserInfoFunc: func(ctx context.Context, userAuth auth.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||
switch userAuth.UserId {
|
||||
case "not-found":
|
||||
return nil, status.NewUserNotFoundError("not-found")
|
||||
@@ -225,7 +226,7 @@ func TestGetUsers(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, nil)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: existingUserID,
|
||||
Domain: testDomain,
|
||||
AccountId: existingAccountID,
|
||||
@@ -335,7 +336,7 @@ func TestUpdateUser(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: existingUserID,
|
||||
Domain: testDomain,
|
||||
AccountId: existingAccountID,
|
||||
@@ -432,7 +433,7 @@ func TestCreateUser(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
rr := httptest.NewRecorder()
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: existingUserID,
|
||||
Domain: testDomain,
|
||||
AccountId: existingAccountID,
|
||||
@@ -481,7 +482,7 @@ func TestInviteUser(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, nil)
|
||||
req = mux.SetURLVars(req, tc.requestVars)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: existingUserID,
|
||||
Domain: testDomain,
|
||||
AccountId: existingAccountID,
|
||||
@@ -540,7 +541,7 @@ func TestDeleteUser(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, nil)
|
||||
req = mux.SetURLVars(req, tc.requestVars)
|
||||
req = nbcontext.SetUserAuthInRequest(req, nbcontext.UserAuth{
|
||||
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
||||
UserId: existingUserID,
|
||||
Domain: testDomain,
|
||||
AccountId: existingAccountID,
|
||||
@@ -565,7 +566,7 @@ func TestCurrentUser(t *testing.T) {
|
||||
tt := []struct {
|
||||
name string
|
||||
expectedStatus int
|
||||
requestAuth nbcontext.UserAuth
|
||||
requestAuth auth.UserAuth
|
||||
expectedResult *api.User
|
||||
}{
|
||||
{
|
||||
@@ -574,27 +575,27 @@ func TestCurrentUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "user not found",
|
||||
requestAuth: nbcontext.UserAuth{UserId: "not-found"},
|
||||
requestAuth: auth.UserAuth{UserId: "not-found"},
|
||||
expectedStatus: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
name: "not of account",
|
||||
requestAuth: nbcontext.UserAuth{UserId: "not-of-account"},
|
||||
requestAuth: auth.UserAuth{UserId: "not-of-account"},
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
{
|
||||
name: "blocked user",
|
||||
requestAuth: nbcontext.UserAuth{UserId: "blocked-user"},
|
||||
requestAuth: auth.UserAuth{UserId: "blocked-user"},
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
{
|
||||
name: "service user",
|
||||
requestAuth: nbcontext.UserAuth{UserId: "service-user"},
|
||||
requestAuth: auth.UserAuth{UserId: "service-user"},
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
{
|
||||
name: "owner",
|
||||
requestAuth: nbcontext.UserAuth{UserId: "owner"},
|
||||
requestAuth: auth.UserAuth{UserId: "owner"},
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedResult: &api.User{
|
||||
Id: "owner",
|
||||
@@ -613,7 +614,7 @@ func TestCurrentUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "regular user",
|
||||
requestAuth: nbcontext.UserAuth{UserId: "regular-user"},
|
||||
requestAuth: auth.UserAuth{UserId: "regular-user"},
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedResult: &api.User{
|
||||
Id: "regular-user",
|
||||
@@ -632,7 +633,7 @@ func TestCurrentUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "admin user",
|
||||
requestAuth: nbcontext.UserAuth{UserId: "admin-user"},
|
||||
requestAuth: auth.UserAuth{UserId: "admin-user"},
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedResult: &api.User{
|
||||
Id: "admin-user",
|
||||
@@ -651,7 +652,7 @@ func TestCurrentUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "restricted user",
|
||||
requestAuth: nbcontext.UserAuth{UserId: "restricted-user"},
|
||||
requestAuth: auth.UserAuth{UserId: "restricted-user"},
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedResult: &api.User{
|
||||
Id: "restricted-user",
|
||||
@@ -783,7 +784,7 @@ func TestApproveUserEndpoint(t *testing.T) {
|
||||
req, err := http.NewRequest("POST", "/users/pending-user/approve", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
userAuth := nbcontext.UserAuth{
|
||||
userAuth := auth.UserAuth{
|
||||
AccountId: existingAccountID,
|
||||
UserId: tc.requestingUser.Id,
|
||||
}
|
||||
@@ -841,7 +842,7 @@ func TestRejectUserEndpoint(t *testing.T) {
|
||||
req, err := http.NewRequest("DELETE", "/users/pending-user/reject", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
userAuth := nbcontext.UserAuth{
|
||||
userAuth := auth.UserAuth{
|
||||
AccountId: existingAccountID,
|
||||
UserId: tc.requestingUser.Id,
|
||||
}
|
||||
|
||||
@@ -10,22 +10,23 @@ import (
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/auth"
|
||||
serverauth "github.com/netbirdio/netbird/management/server/auth"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/http/middleware/bypass"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
type EnsureAccountFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error)
|
||||
type SyncUserJWTGroupsFunc func(ctx context.Context, userAuth nbcontext.UserAuth) error
|
||||
type EnsureAccountFunc func(ctx context.Context, userAuth auth.UserAuth) (string, string, error)
|
||||
type SyncUserJWTGroupsFunc func(ctx context.Context, userAuth auth.UserAuth) error
|
||||
|
||||
type GetUserFromUserAuthFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error)
|
||||
type GetUserFromUserAuthFunc func(ctx context.Context, userAuth auth.UserAuth) (*types.User, error)
|
||||
|
||||
// AuthMiddleware middleware to verify personal access tokens (PAT) and JWT tokens
|
||||
type AuthMiddleware struct {
|
||||
authManager auth.Manager
|
||||
authManager serverauth.Manager
|
||||
ensureAccount EnsureAccountFunc
|
||||
getUserFromUserAuth GetUserFromUserAuthFunc
|
||||
syncUserJWTGroups SyncUserJWTGroupsFunc
|
||||
@@ -34,7 +35,7 @@ type AuthMiddleware struct {
|
||||
|
||||
// NewAuthMiddleware instance constructor
|
||||
func NewAuthMiddleware(
|
||||
authManager auth.Manager,
|
||||
authManager serverauth.Manager,
|
||||
ensureAccount EnsureAccountFunc,
|
||||
syncUserJWTGroups SyncUserJWTGroupsFunc,
|
||||
getUserFromUserAuth GetUserFromUserAuthFunc,
|
||||
@@ -61,18 +62,18 @@ func (m *AuthMiddleware) Handler(h http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
auth := strings.Split(r.Header.Get("Authorization"), " ")
|
||||
authType := strings.ToLower(auth[0])
|
||||
authHeader := strings.Split(r.Header.Get("Authorization"), " ")
|
||||
authType := strings.ToLower(authHeader[0])
|
||||
|
||||
// fallback to token when receive pat as bearer
|
||||
if len(auth) >= 2 && authType == "bearer" && strings.HasPrefix(auth[1], "nbp_") {
|
||||
if len(authHeader) >= 2 && authType == "bearer" && strings.HasPrefix(authHeader[1], "nbp_") {
|
||||
authType = "token"
|
||||
auth[0] = authType
|
||||
authHeader[0] = authType
|
||||
}
|
||||
|
||||
switch authType {
|
||||
case "bearer":
|
||||
request, err := m.checkJWTFromRequest(r, auth)
|
||||
request, err := m.checkJWTFromRequest(r, authHeader)
|
||||
if err != nil {
|
||||
log.WithContext(r.Context()).Errorf("Error when validating JWT: %s", err.Error())
|
||||
util.WriteError(r.Context(), status.Errorf(status.Unauthorized, "token invalid"), w)
|
||||
@@ -81,7 +82,7 @@ func (m *AuthMiddleware) Handler(h http.Handler) http.Handler {
|
||||
|
||||
h.ServeHTTP(w, request)
|
||||
case "token":
|
||||
request, err := m.checkPATFromRequest(r, auth)
|
||||
request, err := m.checkPATFromRequest(r, authHeader)
|
||||
if err != nil {
|
||||
log.WithContext(r.Context()).Debugf("Error when validating PAT: %s", err.Error())
|
||||
// Check if it's a status error, otherwise default to Unauthorized
|
||||
@@ -100,8 +101,8 @@ func (m *AuthMiddleware) Handler(h http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
// CheckJWTFromRequest checks if the JWT is valid
|
||||
func (m *AuthMiddleware) checkJWTFromRequest(r *http.Request, auth []string) (*http.Request, error) {
|
||||
token, err := getTokenFromJWTRequest(auth)
|
||||
func (m *AuthMiddleware) checkJWTFromRequest(r *http.Request, authHeaderParts []string) (*http.Request, error) {
|
||||
token, err := getTokenFromJWTRequest(authHeaderParts)
|
||||
|
||||
// If an error occurs, call the error handler and return an error
|
||||
if err != nil {
|
||||
@@ -151,8 +152,8 @@ func (m *AuthMiddleware) checkJWTFromRequest(r *http.Request, auth []string) (*h
|
||||
}
|
||||
|
||||
// CheckPATFromRequest checks if the PAT is valid
|
||||
func (m *AuthMiddleware) checkPATFromRequest(r *http.Request, auth []string) (*http.Request, error) {
|
||||
token, err := getTokenFromPATRequest(auth)
|
||||
func (m *AuthMiddleware) checkPATFromRequest(r *http.Request, authHeaderParts []string) (*http.Request, error) {
|
||||
token, err := getTokenFromPATRequest(authHeaderParts)
|
||||
if err != nil {
|
||||
return r, fmt.Errorf("error extracting token: %w", err)
|
||||
}
|
||||
@@ -177,7 +178,7 @@ func (m *AuthMiddleware) checkPATFromRequest(r *http.Request, auth []string) (*h
|
||||
return r, err
|
||||
}
|
||||
|
||||
userAuth := nbcontext.UserAuth{
|
||||
userAuth := auth.UserAuth{
|
||||
UserId: user.Id,
|
||||
AccountId: user.AccountID,
|
||||
Domain: accDomain,
|
||||
|
||||
@@ -12,11 +12,12 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/auth"
|
||||
nbjwt "github.com/netbirdio/netbird/management/server/auth/jwt"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/http/middleware/bypass"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
nbauth "github.com/netbirdio/netbird/shared/auth"
|
||||
nbjwt "github.com/netbirdio/netbird/shared/auth/jwt"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -75,9 +76,9 @@ func mockGetAccountInfoFromPAT(_ context.Context, token string) (user *types.Use
|
||||
return nil, nil, "", "", fmt.Errorf("PAT invalid")
|
||||
}
|
||||
|
||||
func mockValidateAndParseToken(_ context.Context, token string) (nbcontext.UserAuth, *jwt.Token, error) {
|
||||
func mockValidateAndParseToken(_ context.Context, token string) (nbauth.UserAuth, *jwt.Token, error) {
|
||||
if token == JWT {
|
||||
return nbcontext.UserAuth{
|
||||
return nbauth.UserAuth{
|
||||
UserId: userID,
|
||||
AccountId: accountID,
|
||||
Domain: testAccount.Domain,
|
||||
@@ -91,7 +92,7 @@ func mockValidateAndParseToken(_ context.Context, token string) (nbcontext.UserA
|
||||
Valid: true,
|
||||
}, nil
|
||||
}
|
||||
return nbcontext.UserAuth{}, nil, fmt.Errorf("JWT invalid")
|
||||
return nbauth.UserAuth{}, nil, fmt.Errorf("JWT invalid")
|
||||
}
|
||||
|
||||
func mockMarkPATUsed(_ context.Context, token string) error {
|
||||
@@ -101,7 +102,7 @@ func mockMarkPATUsed(_ context.Context, token string) error {
|
||||
return fmt.Errorf("Should never get reached")
|
||||
}
|
||||
|
||||
func mockEnsureUserAccessByJWTGroups(_ context.Context, userAuth nbcontext.UserAuth, token *jwt.Token) (nbcontext.UserAuth, error) {
|
||||
func mockEnsureUserAccessByJWTGroups(_ context.Context, userAuth nbauth.UserAuth, token *jwt.Token) (nbauth.UserAuth, error) {
|
||||
if userAuth.IsChild || userAuth.IsPAT {
|
||||
return userAuth, nil
|
||||
}
|
||||
@@ -197,13 +198,13 @@ func TestAuthMiddleware_Handler(t *testing.T) {
|
||||
|
||||
authMiddleware := NewAuthMiddleware(
|
||||
mockAuth,
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (string, string, error) {
|
||||
return userAuth.AccountId, userAuth.UserId, nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (*types.User, error) {
|
||||
return &types.User{}, nil
|
||||
},
|
||||
nil,
|
||||
@@ -255,13 +256,13 @@ func TestAuthMiddleware_RateLimiting(t *testing.T) {
|
||||
|
||||
authMiddleware := NewAuthMiddleware(
|
||||
mockAuth,
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (string, string, error) {
|
||||
return userAuth.AccountId, userAuth.UserId, nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (*types.User, error) {
|
||||
return &types.User{}, nil
|
||||
},
|
||||
rateLimitConfig,
|
||||
@@ -306,13 +307,13 @@ func TestAuthMiddleware_RateLimiting(t *testing.T) {
|
||||
|
||||
authMiddleware := NewAuthMiddleware(
|
||||
mockAuth,
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (string, string, error) {
|
||||
return userAuth.AccountId, userAuth.UserId, nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (*types.User, error) {
|
||||
return &types.User{}, nil
|
||||
},
|
||||
rateLimitConfig,
|
||||
@@ -348,13 +349,13 @@ func TestAuthMiddleware_RateLimiting(t *testing.T) {
|
||||
|
||||
authMiddleware := NewAuthMiddleware(
|
||||
mockAuth,
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (string, string, error) {
|
||||
return userAuth.AccountId, userAuth.UserId, nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (*types.User, error) {
|
||||
return &types.User{}, nil
|
||||
},
|
||||
rateLimitConfig,
|
||||
@@ -391,13 +392,13 @@ func TestAuthMiddleware_RateLimiting(t *testing.T) {
|
||||
|
||||
authMiddleware := NewAuthMiddleware(
|
||||
mockAuth,
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (string, string, error) {
|
||||
return userAuth.AccountId, userAuth.UserId, nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (*types.User, error) {
|
||||
return &types.User{}, nil
|
||||
},
|
||||
rateLimitConfig,
|
||||
@@ -454,13 +455,13 @@ func TestAuthMiddleware_RateLimiting(t *testing.T) {
|
||||
|
||||
authMiddleware := NewAuthMiddleware(
|
||||
mockAuth,
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (string, string, error) {
|
||||
return userAuth.AccountId, userAuth.UserId, nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (*types.User, error) {
|
||||
return &types.User{}, nil
|
||||
},
|
||||
rateLimitConfig,
|
||||
@@ -508,13 +509,13 @@ func TestAuthMiddleware_Handler_Child(t *testing.T) {
|
||||
name string
|
||||
path string
|
||||
authHeader string
|
||||
expectedUserAuth *nbcontext.UserAuth // nil expects 401 response status
|
||||
expectedUserAuth *nbauth.UserAuth // nil expects 401 response status
|
||||
}{
|
||||
{
|
||||
name: "Valid PAT Token",
|
||||
path: "/test",
|
||||
authHeader: "Token " + PAT,
|
||||
expectedUserAuth: &nbcontext.UserAuth{
|
||||
expectedUserAuth: &nbauth.UserAuth{
|
||||
AccountId: accountID,
|
||||
UserId: userID,
|
||||
Domain: testAccount.Domain,
|
||||
@@ -526,7 +527,7 @@ func TestAuthMiddleware_Handler_Child(t *testing.T) {
|
||||
name: "Valid PAT Token accesses child",
|
||||
path: "/test?account=xyz",
|
||||
authHeader: "Token " + PAT,
|
||||
expectedUserAuth: &nbcontext.UserAuth{
|
||||
expectedUserAuth: &nbauth.UserAuth{
|
||||
AccountId: "xyz",
|
||||
UserId: userID,
|
||||
Domain: testAccount.Domain,
|
||||
@@ -539,7 +540,7 @@ func TestAuthMiddleware_Handler_Child(t *testing.T) {
|
||||
name: "Valid JWT Token",
|
||||
path: "/test",
|
||||
authHeader: "Bearer " + JWT,
|
||||
expectedUserAuth: &nbcontext.UserAuth{
|
||||
expectedUserAuth: &nbauth.UserAuth{
|
||||
AccountId: accountID,
|
||||
UserId: userID,
|
||||
Domain: testAccount.Domain,
|
||||
@@ -551,7 +552,7 @@ func TestAuthMiddleware_Handler_Child(t *testing.T) {
|
||||
name: "Valid JWT Token with child",
|
||||
path: "/test?account=xyz",
|
||||
authHeader: "Bearer " + JWT,
|
||||
expectedUserAuth: &nbcontext.UserAuth{
|
||||
expectedUserAuth: &nbauth.UserAuth{
|
||||
AccountId: "xyz",
|
||||
UserId: userID,
|
||||
Domain: testAccount.Domain,
|
||||
@@ -570,13 +571,13 @@ func TestAuthMiddleware_Handler_Child(t *testing.T) {
|
||||
|
||||
authMiddleware := NewAuthMiddleware(
|
||||
mockAuth,
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (string, string, error) {
|
||||
return userAuth.AccountId, userAuth.UserId, nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error) {
|
||||
func(ctx context.Context, userAuth nbauth.UserAuth) (*types.User, error) {
|
||||
return &types.User{}, nil
|
||||
},
|
||||
nil,
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/netbirdio/management-integrations/integrations"
|
||||
|
||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map"
|
||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map/controller"
|
||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map/update_channel"
|
||||
@@ -18,8 +19,7 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/auth"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
serverauth "github.com/netbirdio/netbird/management/server/auth"
|
||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||
"github.com/netbirdio/netbird/management/server/groups"
|
||||
http2 "github.com/netbirdio/netbird/management/server/http"
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||
"github.com/netbirdio/netbird/management/server/users"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
)
|
||||
|
||||
func BuildApiBlackBoxWithDBState(t testing_tools.TB, sqlFile string, expectedPeerUpdate *network_map.UpdateMessage, validateUpdate bool) (http.Handler, account.Manager, chan struct{}) {
|
||||
@@ -71,14 +72,14 @@ func BuildApiBlackBoxWithDBState(t testing_tools.TB, sqlFile string, expectedPee
|
||||
ctx := context.Background()
|
||||
requestBuffer := server.NewAccountRequestBuffer(ctx, store)
|
||||
networkMapController := controller.NewController(ctx, store, metrics, peersUpdateManager, requestBuffer, server.MockIntegratedValidator{}, settingsManager, "", port_forwarding.NewControllerMock())
|
||||
am, err := server.BuildManager(ctx, store, networkMapController, nil, "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager, false)
|
||||
am, err := server.BuildManager(ctx, nil, store, networkMapController, nil, "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager, false)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create manager: %v", err)
|
||||
}
|
||||
|
||||
// @note this is required so that PAT's validate from store, but JWT's are mocked
|
||||
authManager := auth.NewManager(store, "", "", "", "", []string{}, false)
|
||||
authManagerMock := &auth.MockManager{
|
||||
authManager := serverauth.NewManager(store, "", "", "", "", []string{}, false)
|
||||
authManagerMock := &serverauth.MockManager{
|
||||
ValidateAndParseTokenFunc: mockValidateAndParseToken,
|
||||
EnsureUserAccessByJWTGroupsFunc: authManager.EnsureUserAccessByJWTGroups,
|
||||
MarkPATUsedFunc: authManager.MarkPATUsed,
|
||||
@@ -123,8 +124,8 @@ func peerShouldReceiveUpdate(t testing_tools.TB, updateMessage <-chan *network_m
|
||||
}
|
||||
}
|
||||
|
||||
func mockValidateAndParseToken(_ context.Context, token string) (nbcontext.UserAuth, *jwt.Token, error) {
|
||||
userAuth := nbcontext.UserAuth{}
|
||||
func mockValidateAndParseToken(_ context.Context, token string) (auth.UserAuth, *jwt.Token, error) {
|
||||
userAuth := auth.UserAuth{}
|
||||
|
||||
switch token {
|
||||
case "testUserId", "testAdminId", "testOwnerId", "testServiceUserId", "testServiceAdminId", "blockedUserId":
|
||||
|
||||
@@ -1,138 +1,137 @@
|
||||
package idp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||
)
|
||||
|
||||
|
||||
func TestNewPocketIdManager(t *testing.T) {
|
||||
type test struct {
|
||||
name string
|
||||
inputConfig PocketIdClientConfig
|
||||
assertErrFunc require.ErrorAssertionFunc
|
||||
assertErrFuncMessage string
|
||||
}
|
||||
type test struct {
|
||||
name string
|
||||
inputConfig PocketIdClientConfig
|
||||
assertErrFunc require.ErrorAssertionFunc
|
||||
assertErrFuncMessage string
|
||||
}
|
||||
|
||||
defaultTestConfig := PocketIdClientConfig{
|
||||
APIToken: "api_token",
|
||||
ManagementEndpoint: "http://localhost",
|
||||
}
|
||||
defaultTestConfig := PocketIdClientConfig{
|
||||
APIToken: "api_token",
|
||||
ManagementEndpoint: "http://localhost",
|
||||
}
|
||||
|
||||
tests := []test{
|
||||
{
|
||||
name: "Good Configuration",
|
||||
inputConfig: defaultTestConfig,
|
||||
assertErrFunc: require.NoError,
|
||||
assertErrFuncMessage: "shouldn't return error",
|
||||
},
|
||||
{
|
||||
name: "Missing ManagementEndpoint",
|
||||
inputConfig: PocketIdClientConfig{
|
||||
APIToken: defaultTestConfig.APIToken,
|
||||
ManagementEndpoint: "",
|
||||
},
|
||||
assertErrFunc: require.Error,
|
||||
assertErrFuncMessage: "should return error when field empty",
|
||||
},
|
||||
{
|
||||
name: "Missing APIToken",
|
||||
inputConfig: PocketIdClientConfig{
|
||||
APIToken: "",
|
||||
ManagementEndpoint: defaultTestConfig.ManagementEndpoint,
|
||||
},
|
||||
assertErrFunc: require.Error,
|
||||
assertErrFuncMessage: "should return error when field empty",
|
||||
},
|
||||
}
|
||||
tests := []test{
|
||||
{
|
||||
name: "Good Configuration",
|
||||
inputConfig: defaultTestConfig,
|
||||
assertErrFunc: require.NoError,
|
||||
assertErrFuncMessage: "shouldn't return error",
|
||||
},
|
||||
{
|
||||
name: "Missing ManagementEndpoint",
|
||||
inputConfig: PocketIdClientConfig{
|
||||
APIToken: defaultTestConfig.APIToken,
|
||||
ManagementEndpoint: "",
|
||||
},
|
||||
assertErrFunc: require.Error,
|
||||
assertErrFuncMessage: "should return error when field empty",
|
||||
},
|
||||
{
|
||||
name: "Missing APIToken",
|
||||
inputConfig: PocketIdClientConfig{
|
||||
APIToken: "",
|
||||
ManagementEndpoint: defaultTestConfig.ManagementEndpoint,
|
||||
},
|
||||
assertErrFunc: require.Error,
|
||||
assertErrFuncMessage: "should return error when field empty",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := NewPocketIdManager(tc.inputConfig, &telemetry.MockAppMetrics{})
|
||||
tc.assertErrFunc(t, err, tc.assertErrFuncMessage)
|
||||
})
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := NewPocketIdManager(tc.inputConfig, &telemetry.MockAppMetrics{})
|
||||
tc.assertErrFunc(t, err, tc.assertErrFuncMessage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPocketID_GetUserDataByID(t *testing.T) {
|
||||
client := &mockHTTPClient{code: 200, resBody: `{"id":"u1","email":"user1@example.com","displayName":"User One"}`}
|
||||
client := &mockHTTPClient{code: 200, resBody: `{"id":"u1","email":"user1@example.com","displayName":"User One"}`}
|
||||
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
|
||||
md := AppMetadata{WTAccountID: "acc1"}
|
||||
got, err := mgr.GetUserDataByID(context.Background(), "u1", md)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "u1", got.ID)
|
||||
assert.Equal(t, "user1@example.com", got.Email)
|
||||
assert.Equal(t, "User One", got.Name)
|
||||
assert.Equal(t, "acc1", got.AppMetadata.WTAccountID)
|
||||
md := AppMetadata{WTAccountID: "acc1"}
|
||||
got, err := mgr.GetUserDataByID(context.Background(), "u1", md)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "u1", got.ID)
|
||||
assert.Equal(t, "user1@example.com", got.Email)
|
||||
assert.Equal(t, "User One", got.Name)
|
||||
assert.Equal(t, "acc1", got.AppMetadata.WTAccountID)
|
||||
}
|
||||
|
||||
func TestPocketID_GetAccount_WithPagination(t *testing.T) {
|
||||
// Single page response with two users
|
||||
client := &mockHTTPClient{code: 200, resBody: `{"data":[{"id":"u1","email":"e1","displayName":"n1"},{"id":"u2","email":"e2","displayName":"n2"}],"pagination":{"currentPage":1,"itemsPerPage":100,"totalItems":2,"totalPages":1}}`}
|
||||
// Single page response with two users
|
||||
client := &mockHTTPClient{code: 200, resBody: `{"data":[{"id":"u1","email":"e1","displayName":"n1"},{"id":"u2","email":"e2","displayName":"n2"}],"pagination":{"currentPage":1,"itemsPerPage":100,"totalItems":2,"totalPages":1}}`}
|
||||
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
|
||||
users, err := mgr.GetAccount(context.Background(), "accX")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, users, 2)
|
||||
assert.Equal(t, "u1", users[0].ID)
|
||||
assert.Equal(t, "accX", users[0].AppMetadata.WTAccountID)
|
||||
assert.Equal(t, "u2", users[1].ID)
|
||||
users, err := mgr.GetAccount(context.Background(), "accX")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, users, 2)
|
||||
assert.Equal(t, "u1", users[0].ID)
|
||||
assert.Equal(t, "accX", users[0].AppMetadata.WTAccountID)
|
||||
assert.Equal(t, "u2", users[1].ID)
|
||||
}
|
||||
|
||||
func TestPocketID_GetAllAccounts_WithPagination(t *testing.T) {
|
||||
client := &mockHTTPClient{code: 200, resBody: `{"data":[{"id":"u1","email":"e1","displayName":"n1"},{"id":"u2","email":"e2","displayName":"n2"}],"pagination":{"currentPage":1,"itemsPerPage":100,"totalItems":2,"totalPages":1}}`}
|
||||
client := &mockHTTPClient{code: 200, resBody: `{"data":[{"id":"u1","email":"e1","displayName":"n1"},{"id":"u2","email":"e2","displayName":"n2"}],"pagination":{"currentPage":1,"itemsPerPage":100,"totalItems":2,"totalPages":1}}`}
|
||||
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
|
||||
accounts, err := mgr.GetAllAccounts(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Len(t, accounts[UnsetAccountID], 2)
|
||||
accounts, err := mgr.GetAllAccounts(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Len(t, accounts[UnsetAccountID], 2)
|
||||
}
|
||||
|
||||
func TestPocketID_CreateUser(t *testing.T) {
|
||||
client := &mockHTTPClient{code: 201, resBody: `{"id":"newid","email":"new@example.com","displayName":"New User"}`}
|
||||
client := &mockHTTPClient{code: 201, resBody: `{"id":"newid","email":"new@example.com","displayName":"New User"}`}
|
||||
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
|
||||
ud, err := mgr.CreateUser(context.Background(), "new@example.com", "New User", "acc1", "inviter@example.com")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "newid", ud.ID)
|
||||
assert.Equal(t, "new@example.com", ud.Email)
|
||||
assert.Equal(t, "New User", ud.Name)
|
||||
assert.Equal(t, "acc1", ud.AppMetadata.WTAccountID)
|
||||
if assert.NotNil(t, ud.AppMetadata.WTPendingInvite) {
|
||||
assert.True(t, *ud.AppMetadata.WTPendingInvite)
|
||||
}
|
||||
assert.Equal(t, "inviter@example.com", ud.AppMetadata.WTInvitedBy)
|
||||
ud, err := mgr.CreateUser(context.Background(), "new@example.com", "New User", "acc1", "inviter@example.com")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "newid", ud.ID)
|
||||
assert.Equal(t, "new@example.com", ud.Email)
|
||||
assert.Equal(t, "New User", ud.Name)
|
||||
assert.Equal(t, "acc1", ud.AppMetadata.WTAccountID)
|
||||
if assert.NotNil(t, ud.AppMetadata.WTPendingInvite) {
|
||||
assert.True(t, *ud.AppMetadata.WTPendingInvite)
|
||||
}
|
||||
assert.Equal(t, "inviter@example.com", ud.AppMetadata.WTInvitedBy)
|
||||
}
|
||||
|
||||
func TestPocketID_InviteAndDeleteUser(t *testing.T) {
|
||||
// Same mock for both calls; returns OK with empty JSON
|
||||
client := &mockHTTPClient{code: 200, resBody: `{}`}
|
||||
// Same mock for both calls; returns OK with empty JSON
|
||||
client := &mockHTTPClient{code: 200, resBody: `{}`}
|
||||
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
mgr, err := NewPocketIdManager(PocketIdClientConfig{APIToken: "tok", ManagementEndpoint: "http://localhost"}, nil)
|
||||
require.NoError(t, err)
|
||||
mgr.httpClient = client
|
||||
|
||||
err = mgr.InviteUserByID(context.Background(), "u1")
|
||||
require.NoError(t, err)
|
||||
err = mgr.InviteUserByID(context.Background(), "u1")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = mgr.DeleteUser(context.Background(), "u1")
|
||||
require.NoError(t, err)
|
||||
err = mgr.DeleteUser(context.Background(), "u1")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ func startManagementForTest(t *testing.T, testFile string, config *config.Config
|
||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock())
|
||||
accountManager, err := BuildManager(ctx, store, networkMapController, nil, "",
|
||||
accountManager, err := BuildManager(ctx, nil, store, networkMapController, nil, "",
|
||||
eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -209,6 +209,7 @@ func startServer(
|
||||
|
||||
accountManager, err := server.BuildManager(
|
||||
context.Background(),
|
||||
nil,
|
||||
str,
|
||||
networkMapController,
|
||||
nil,
|
||||
|
||||
@@ -2,6 +2,7 @@ package mock_server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
@@ -12,7 +13,6 @@ import (
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
"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/idp"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/management/server/peers/ephemeral"
|
||||
@@ -34,7 +34,7 @@ type MockAccountManager struct {
|
||||
GetSetupKeyFunc func(ctx context.Context, accountID, userID, keyID string) (*types.SetupKey, error)
|
||||
AccountExistsFunc func(ctx context.Context, accountID string) (bool, error)
|
||||
GetAccountIDByUserIdFunc func(ctx context.Context, userId, domain string) (string, error)
|
||||
GetUserFromUserAuthFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error)
|
||||
GetUserFromUserAuthFunc func(ctx context.Context, userAuth auth.UserAuth) (*types.User, error)
|
||||
ListUsersFunc func(ctx context.Context, accountID string) ([]*types.User, error)
|
||||
GetPeersFunc func(ctx context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error)
|
||||
MarkPeerConnectedFunc func(ctx context.Context, peerKey string, connected bool, realIP net.IP) error
|
||||
@@ -84,7 +84,7 @@ type MockAccountManager struct {
|
||||
DeleteNameServerGroupFunc func(ctx context.Context, accountID, nsGroupID, userID string) error
|
||||
ListNameServerGroupsFunc func(ctx context.Context, accountID string, userID string) ([]*nbdns.NameServerGroup, error)
|
||||
CreateUserFunc func(ctx context.Context, accountID, userID string, key *types.UserInfo) (*types.UserInfo, error)
|
||||
GetAccountIDFromUserAuthFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error)
|
||||
GetAccountIDFromUserAuthFunc func(ctx context.Context, userAuth auth.UserAuth) (string, string, error)
|
||||
DeleteAccountFunc func(ctx context.Context, accountID, userID string) error
|
||||
GetDNSDomainFunc func(settings *types.Settings) string
|
||||
StoreEventFunc func(ctx context.Context, initiatorID, targetID, accountID string, activityID activity.ActivityDescriber, meta map[string]any)
|
||||
@@ -119,7 +119,7 @@ type MockAccountManager struct {
|
||||
GetStoreFunc func() store.Store
|
||||
UpdateToPrimaryAccountFunc func(ctx context.Context, accountId string) error
|
||||
GetOwnerInfoFunc func(ctx context.Context, accountID string) (*types.UserInfo, error)
|
||||
GetCurrentUserInfoFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error)
|
||||
GetCurrentUserInfoFunc func(ctx context.Context, userAuth auth.UserAuth) (*users.UserInfoWithPermissions, error)
|
||||
GetAccountMetaFunc func(ctx context.Context, accountID, userID string) (*types.AccountMeta, error)
|
||||
GetAccountOnboardingFunc func(ctx context.Context, accountID, userID string) (*types.AccountOnboarding, error)
|
||||
UpdateAccountOnboardingFunc func(ctx context.Context, accountID, userID string, onboarding *types.AccountOnboarding) (*types.AccountOnboarding, error)
|
||||
@@ -470,7 +470,7 @@ func (am *MockAccountManager) UpdatePeerMeta(ctx context.Context, peerID string,
|
||||
}
|
||||
|
||||
// GetUser mock implementation of GetUser from server.AccountManager interface
|
||||
func (am *MockAccountManager) GetUserFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error) {
|
||||
func (am *MockAccountManager) GetUserFromUserAuth(ctx context.Context, userAuth auth.UserAuth) (*types.User, error) {
|
||||
if am.GetUserFromUserAuthFunc != nil {
|
||||
return am.GetUserFromUserAuthFunc(ctx, userAuth)
|
||||
}
|
||||
@@ -675,7 +675,7 @@ func (am *MockAccountManager) CreateUser(ctx context.Context, accountID, userID
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateUser is not implemented")
|
||||
}
|
||||
|
||||
func (am *MockAccountManager) GetAccountIDFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
|
||||
func (am *MockAccountManager) GetAccountIDFromUserAuth(ctx context.Context, userAuth auth.UserAuth) (string, string, error) {
|
||||
if am.GetAccountIDFromUserAuthFunc != nil {
|
||||
return am.GetAccountIDFromUserAuthFunc(ctx, userAuth)
|
||||
}
|
||||
@@ -937,7 +937,7 @@ func (am *MockAccountManager) BuildUserInfosForAccount(ctx context.Context, acco
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BuildUserInfosForAccount is not implemented")
|
||||
}
|
||||
|
||||
func (am *MockAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||
func (am *MockAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth auth.UserAuth) error {
|
||||
return status.Errorf(codes.Unimplemented, "method SyncUserJWTGroups is not implemented")
|
||||
}
|
||||
|
||||
@@ -969,7 +969,7 @@ func (am *MockAccountManager) GetOwnerInfo(ctx context.Context, accountId string
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetOwnerInfo is not implemented")
|
||||
}
|
||||
|
||||
func (am *MockAccountManager) GetCurrentUserInfo(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||
func (am *MockAccountManager) GetCurrentUserInfo(ctx context.Context, userAuth auth.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||
if am.GetCurrentUserInfoFunc != nil {
|
||||
return am.GetCurrentUserInfoFunc(ctx, userAuth)
|
||||
}
|
||||
|
||||
@@ -793,7 +793,7 @@ func createNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock())
|
||||
|
||||
return BuildManager(context.Background(), store, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
return BuildManager(context.Background(), nil, store, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
}
|
||||
|
||||
func createNSStore(t *testing.T) (store.Store, error) {
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
func Test_GetAllResourcesInNetworkReturnsResources(t *testing.T) {
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
|
||||
"github.com/rs/xid"
|
||||
|
||||
nbDomain "github.com/netbirdio/netbird/shared/management/domain"
|
||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/route"
|
||||
nbDomain "github.com/netbirdio/netbird/shared/management/domain"
|
||||
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
)
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
func Test_GetAllRoutersInNetworkReturnsRouters(t *testing.T) {
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/rs/xid"
|
||||
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/networks/types"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
)
|
||||
|
||||
type NetworkRouter struct {
|
||||
|
||||
@@ -1292,7 +1292,7 @@ func Test_RegisterPeerByUser(t *testing.T) {
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
||||
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock())
|
||||
|
||||
am, err := BuildManager(context.Background(), s, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
am, err := BuildManager(context.Background(), nil, s, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
||||
@@ -1377,7 +1377,7 @@ func Test_RegisterPeerBySetupKey(t *testing.T) {
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
||||
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock())
|
||||
|
||||
am, err := BuildManager(context.Background(), s, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
am, err := BuildManager(context.Background(), nil, s, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
||||
@@ -1530,7 +1530,7 @@ func Test_RegisterPeerRollbackOnFailure(t *testing.T) {
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
||||
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock())
|
||||
|
||||
am, err := BuildManager(context.Background(), s, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
am, err := BuildManager(context.Background(), nil, s, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
||||
@@ -1610,7 +1610,7 @@ func Test_LoginPeer(t *testing.T) {
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
||||
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock())
|
||||
|
||||
am, err := BuildManager(context.Background(), s, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
am, err := BuildManager(context.Background(), nil, s, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"regexp"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
|
||||
@@ -1292,7 +1292,7 @@ func createRouterManager(t *testing.T) (*DefaultAccountManager, *update_channel.
|
||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock())
|
||||
|
||||
am, err := BuildManager(context.Background(), store, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
am, err := BuildManager(context.Background(), nil, store, networkMapController, nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
"github.com/netbirdio/netbird/route"
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
)
|
||||
|
||||
// RouteFirewallRule a firewall rule applicable for a routed network.
|
||||
|
||||
@@ -7,12 +7,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
nbContext "github.com/netbirdio/netbird/management/server/context"
|
||||
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"
|
||||
@@ -175,9 +176,9 @@ func (am *DefaultAccountManager) GetUserByID(ctx context.Context, id string) (*t
|
||||
return am.Store.GetUserByUserID(ctx, store.LockingStrengthNone, id)
|
||||
}
|
||||
|
||||
// GetUser looks up a user by provided nbContext.UserAuths.
|
||||
// GetUser looks up a user by provided auth.UserAuths.
|
||||
// Expects account to have been created already.
|
||||
func (am *DefaultAccountManager) GetUserFromUserAuth(ctx context.Context, userAuth nbContext.UserAuth) (*types.User, error) {
|
||||
func (am *DefaultAccountManager) GetUserFromUserAuth(ctx context.Context, userAuth auth.UserAuth) (*types.User, error) {
|
||||
user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthNone, userAuth.UserId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -970,7 +971,7 @@ func (am *DefaultAccountManager) expireAndUpdatePeers(ctx context.Context, accou
|
||||
var peerIDs []string
|
||||
for _, peer := range peers {
|
||||
// nolint:staticcheck
|
||||
ctx = context.WithValue(ctx, nbContext.PeerIDKey, peer.Key)
|
||||
ctx = context.WithValue(ctx, nbcontext.PeerIDKey, peer.Key)
|
||||
|
||||
if peer.UserID == "" {
|
||||
// we do not want to expire peers that are added via setup key
|
||||
@@ -1214,7 +1215,7 @@ func validateUserInvite(invite *types.UserInfo) error {
|
||||
}
|
||||
|
||||
// GetCurrentUserInfo retrieves the account's current user info and permissions
|
||||
func (am *DefaultAccountManager) GetCurrentUserInfo(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||
func (am *DefaultAccountManager) GetCurrentUserInfo(ctx context.Context, userAuth auth.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||
accountID, userID := userAuth.AccountId, userAuth.UserId
|
||||
|
||||
user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthNone, userID)
|
||||
|
||||
@@ -11,12 +11,12 @@ import (
|
||||
"golang.org/x/exp/maps"
|
||||
|
||||
nbcache "github.com/netbirdio/netbird/management/server/cache"
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
"github.com/netbirdio/netbird/management/server/permissions/modules"
|
||||
"github.com/netbirdio/netbird/management/server/permissions/roles"
|
||||
"github.com/netbirdio/netbird/management/server/users"
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
@@ -966,7 +966,7 @@ func TestDefaultAccountManager_GetUser(t *testing.T) {
|
||||
permissionsManager: permissionsManager,
|
||||
}
|
||||
|
||||
claims := nbcontext.UserAuth{
|
||||
claims := auth.UserAuth{
|
||||
UserId: mockUserID,
|
||||
AccountId: mockAccountID,
|
||||
}
|
||||
@@ -1573,33 +1573,33 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
userAuth nbcontext.UserAuth
|
||||
userAuth auth.UserAuth
|
||||
expectedErr error
|
||||
expectedResult *users.UserInfoWithPermissions
|
||||
}{
|
||||
{
|
||||
name: "not found",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "not-found"},
|
||||
userAuth: auth.UserAuth{AccountId: account1.Id, UserId: "not-found"},
|
||||
expectedErr: status.NewUserNotFoundError("not-found"),
|
||||
},
|
||||
{
|
||||
name: "not part of account",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "account2Owner"},
|
||||
userAuth: auth.UserAuth{AccountId: account1.Id, UserId: "account2Owner"},
|
||||
expectedErr: status.NewUserNotPartOfAccountError(),
|
||||
},
|
||||
{
|
||||
name: "blocked",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "blocked-user"},
|
||||
userAuth: auth.UserAuth{AccountId: account1.Id, UserId: "blocked-user"},
|
||||
expectedErr: status.NewUserBlockedError(),
|
||||
},
|
||||
{
|
||||
name: "service user",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "service-user"},
|
||||
userAuth: auth.UserAuth{AccountId: account1.Id, UserId: "service-user"},
|
||||
expectedErr: status.NewPermissionDeniedError(),
|
||||
},
|
||||
{
|
||||
name: "owner user",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "account1Owner"},
|
||||
userAuth: auth.UserAuth{AccountId: account1.Id, UserId: "account1Owner"},
|
||||
expectedResult: &users.UserInfoWithPermissions{
|
||||
UserInfo: &types.UserInfo{
|
||||
ID: "account1Owner",
|
||||
@@ -1619,7 +1619,7 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "regular user",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "regular-user"},
|
||||
userAuth: auth.UserAuth{AccountId: account1.Id, UserId: "regular-user"},
|
||||
expectedResult: &users.UserInfoWithPermissions{
|
||||
UserInfo: &types.UserInfo{
|
||||
ID: "regular-user",
|
||||
@@ -1638,7 +1638,7 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "admin user",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "admin-user"},
|
||||
userAuth: auth.UserAuth{AccountId: account1.Id, UserId: "admin-user"},
|
||||
expectedResult: &users.UserInfoWithPermissions{
|
||||
UserInfo: &types.UserInfo{
|
||||
ID: "admin-user",
|
||||
@@ -1657,7 +1657,7 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "settings blocked regular user",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account2.Id, UserId: "settings-blocked-user"},
|
||||
userAuth: auth.UserAuth{AccountId: account2.Id, UserId: "settings-blocked-user"},
|
||||
expectedResult: &users.UserInfoWithPermissions{
|
||||
UserInfo: &types.UserInfo{
|
||||
ID: "settings-blocked-user",
|
||||
@@ -1678,7 +1678,7 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
||||
|
||||
{
|
||||
name: "settings blocked regular user child account",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account2.Id, UserId: "settings-blocked-user", IsChild: true},
|
||||
userAuth: auth.UserAuth{AccountId: account2.Id, UserId: "settings-blocked-user", IsChild: true},
|
||||
expectedResult: &users.UserInfoWithPermissions{
|
||||
UserInfo: &types.UserInfo{
|
||||
ID: "settings-blocked-user",
|
||||
@@ -1698,7 +1698,7 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "settings blocked owner user",
|
||||
userAuth: nbcontext.UserAuth{AccountId: account2.Id, UserId: "account2Owner"},
|
||||
userAuth: auth.UserAuth{AccountId: account2.Id, UserId: "account2Owner"},
|
||||
expectedResult: &users.UserInfoWithPermissions{
|
||||
UserInfo: &types.UserInfo{
|
||||
ID: "account2Owner",
|
||||
|
||||
Reference in New Issue
Block a user