mirror of
https://github.com/netbirdio/netbird.git
synced 2025-06-11 04:16:49 +02:00
* Refactor setup key handling to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * add lock to get account groups Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * add check for regular user Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * get only required groups for auto-group validation Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * add account lock and return auto groups map on validation Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * refactor account peers update Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor groups to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * refactor GetGroupByID and add NewGroupNotFoundError Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add AddPeer and RemovePeer methods to Group struct Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Preserve store engine in SqlStore transactions Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Run groups ops in transaction Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix missing group removed from setup key activity Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor posture checks to remove get and save account Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix refactor Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix sonar Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Change setup key log level to debug for missing group Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Retrieve modified peers once for group events Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor policy get and save account to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Retrieve policy groups and posture checks once for validation Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix typo Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add policy tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor anyGroupHasPeers to retrieve all groups once Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor dns settings to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add account locking and merge group deletion methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor name server groups to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add peer store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor ephemeral peers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add lock for peer store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor peer handlers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor peer to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix typo Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add locks and remove log Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * run peer ops in transaction Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * remove duplicate store method Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix peer fields updated after save Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Use update strength and simplify check Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * prevent changing ruleID when not empty Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * prevent duplicate rules during updates Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix lint Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor auth middleware Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor account methods and mock Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor user and PAT handling Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Remove db query context and fix get user by id Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix database transaction locking issue Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Use UTC time in test Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add account locks Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix prevent users from creating PATs for other users Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add store locks and prevent fetching setup keys peers when retrieving user peers with empty userID Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add missing tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor test names and remove duplicate TestPostgresql_SavePeerStatus Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add account locks and remove redundant ephemeral check Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Retrieve all groups for peers and restrict groups for regular users Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix store tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * use account object to get validated peers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Improve peer performance Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Get account direct from store without buffer Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add get peer groups tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Adjust benchmarks Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Adjust benchmarks Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * [management] Update benchmark workflow (#3181) * update local benchmark expectations * update cloud expectations * Add status error for generic result error Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Use integrated validator direct Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations * update expectations * update expectations * Refactor peer scheduler to retry every 3 seconds on errors Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations * fix validator * fix validator * fix validator * update timeouts * Refactor ToGroupsInfo to process slices of groups Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations * update expectations * update expectations * Bump integrations version Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor GetValidatedPeers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * go mod tidy Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Use peers and groups map for peers validation Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * remove mysql from api benchmark tests * Fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix blocked db calls on user auto groups update Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Skip user check for system initiated peer deletion Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Remove context in db calls Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * [management] Improve group peer/resource counting (#3192) * Fix sonar Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Adjust bench expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Rename GetAccountInfoFromPAT to GetTokenInfo Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Remove global account lock for ListUsers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * build userinfo after updating users in db Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * [management] Optimize user bulk deletion (#3315) * refactor building user infos Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * remove unused code Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor GetUsersFromAccount to return a map of UserInfo instead of a slice Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Export BuildUserInfosForAccount to account manager Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fetch account user info once for bulk users save Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Update user deletion expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Set max open conns for activity store Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Update bench expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> --------- Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> --------- Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> Co-authored-by: Pascal Fischer <32096965+pascal-fischer@users.noreply.github.com> Co-authored-by: Pascal Fischer <pascal@netbird.io> Co-authored-by: Pedro Costa <550684+pnmcosta@users.noreply.github.com>
204 lines
5.1 KiB
Go
204 lines
5.1 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/golang-jwt/jwt"
|
|
"github.com/netbirdio/netbird/management/server/util"
|
|
|
|
"github.com/netbirdio/netbird/management/server/http/middleware/bypass"
|
|
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
|
"github.com/netbirdio/netbird/management/server/types"
|
|
)
|
|
|
|
const (
|
|
audience = "audience"
|
|
userIDClaim = "userIDClaim"
|
|
accountID = "accountID"
|
|
domain = "domain"
|
|
domainCategory = "domainCategory"
|
|
userID = "userID"
|
|
tokenID = "tokenID"
|
|
PAT = "nbp_PAT"
|
|
JWT = "JWT"
|
|
wrongToken = "wrongToken"
|
|
)
|
|
|
|
var testAccount = &types.Account{
|
|
Id: accountID,
|
|
Domain: domain,
|
|
Users: map[string]*types.User{
|
|
userID: {
|
|
Id: userID,
|
|
AccountID: accountID,
|
|
PATs: map[string]*types.PersonalAccessToken{
|
|
tokenID: {
|
|
ID: tokenID,
|
|
Name: "My first token",
|
|
HashedToken: "someHash",
|
|
ExpirationDate: util.ToPtr(time.Now().UTC().AddDate(0, 0, 7)),
|
|
CreatedBy: userID,
|
|
CreatedAt: time.Now().UTC(),
|
|
LastUsed: util.ToPtr(time.Now().UTC()),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
func mockGetAccountInfoFromPAT(_ context.Context, token string) (user *types.User, pat *types.PersonalAccessToken, domain string, category string, err error) {
|
|
if token == PAT {
|
|
return testAccount.Users[userID], testAccount.Users[userID].PATs[tokenID], testAccount.Domain, testAccount.DomainCategory, nil
|
|
}
|
|
return nil, nil, "", "", fmt.Errorf("PAT invalid")
|
|
}
|
|
|
|
func mockValidateAndParseToken(_ context.Context, token string) (*jwt.Token, error) {
|
|
if token == JWT {
|
|
return &jwt.Token{
|
|
Claims: jwt.MapClaims{
|
|
userIDClaim: userID,
|
|
audience + jwtclaims.AccountIDSuffix: accountID,
|
|
},
|
|
Valid: true,
|
|
}, nil
|
|
}
|
|
return nil, fmt.Errorf("JWT invalid")
|
|
}
|
|
|
|
func mockMarkPATUsed(_ context.Context, token string) error {
|
|
if token == tokenID {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("Should never get reached")
|
|
}
|
|
|
|
func mockCheckUserAccessByJWTGroups(_ context.Context, claims jwtclaims.AuthorizationClaims) error {
|
|
if testAccount.Id != claims.AccountId {
|
|
return fmt.Errorf("account with id %s does not exist", claims.AccountId)
|
|
}
|
|
|
|
if _, ok := testAccount.Users[claims.UserId]; !ok {
|
|
return fmt.Errorf("user with id %s does not exist", claims.UserId)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func TestAuthMiddleware_Handler(t *testing.T) {
|
|
tt := []struct {
|
|
name string
|
|
path string
|
|
authHeader string
|
|
expectedStatusCode int
|
|
shouldBypassAuth bool
|
|
}{
|
|
{
|
|
name: "Valid PAT Token",
|
|
path: "/test",
|
|
authHeader: "Token " + PAT,
|
|
expectedStatusCode: 200,
|
|
},
|
|
{
|
|
name: "Invalid PAT Token",
|
|
path: "/test",
|
|
authHeader: "Token " + wrongToken,
|
|
expectedStatusCode: 401,
|
|
},
|
|
{
|
|
name: "Fallback to PAT Token",
|
|
path: "/test",
|
|
authHeader: "Bearer " + PAT,
|
|
expectedStatusCode: 200,
|
|
},
|
|
{
|
|
name: "Valid JWT Token",
|
|
path: "/test",
|
|
authHeader: "Bearer " + JWT,
|
|
expectedStatusCode: 200,
|
|
},
|
|
{
|
|
name: "Invalid JWT Token",
|
|
path: "/test",
|
|
authHeader: "Bearer " + wrongToken,
|
|
expectedStatusCode: 401,
|
|
},
|
|
{
|
|
name: "Basic Auth",
|
|
path: "/test",
|
|
authHeader: "Basic " + PAT,
|
|
expectedStatusCode: 401,
|
|
},
|
|
{
|
|
name: "Webhook Path Bypass",
|
|
path: "/webhook",
|
|
authHeader: "",
|
|
expectedStatusCode: 200,
|
|
shouldBypassAuth: true,
|
|
},
|
|
{
|
|
name: "Webhook Path Bypass with Subpath",
|
|
path: "/webhook/test",
|
|
authHeader: "",
|
|
expectedStatusCode: 200,
|
|
shouldBypassAuth: true,
|
|
},
|
|
{
|
|
name: "Different Webhook Path",
|
|
path: "/webhooktest",
|
|
authHeader: "",
|
|
expectedStatusCode: 401,
|
|
shouldBypassAuth: false,
|
|
},
|
|
}
|
|
|
|
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// do nothing
|
|
})
|
|
|
|
claimsExtractor := jwtclaims.NewClaimsExtractor(
|
|
jwtclaims.WithAudience(audience),
|
|
jwtclaims.WithUserIDClaim(userIDClaim),
|
|
)
|
|
|
|
authMiddleware := NewAuthMiddleware(
|
|
mockGetAccountInfoFromPAT,
|
|
mockValidateAndParseToken,
|
|
mockMarkPATUsed,
|
|
mockCheckUserAccessByJWTGroups,
|
|
claimsExtractor,
|
|
audience,
|
|
userIDClaim,
|
|
)
|
|
|
|
handlerToTest := authMiddleware.Handler(nextHandler)
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if tc.shouldBypassAuth {
|
|
err := bypass.AddBypassPath(tc.path)
|
|
if err != nil {
|
|
t.Fatalf("failed to add bypass path: %v", err)
|
|
}
|
|
}
|
|
|
|
req := httptest.NewRequest("GET", "http://testing"+tc.path, nil)
|
|
req.Header.Set("Authorization", tc.authHeader)
|
|
rec := httptest.NewRecorder()
|
|
|
|
handlerToTest.ServeHTTP(rec, req)
|
|
|
|
result := rec.Result()
|
|
defer result.Body.Close()
|
|
if result.StatusCode != tc.expectedStatusCode {
|
|
t.Errorf("expected status code %d, got %d", tc.expectedStatusCode, result.StatusCode)
|
|
}
|
|
})
|
|
}
|
|
}
|