From db3deba181ebfd6ba8bd7e7873b5f8d7f29ea627 Mon Sep 17 00:00:00 2001 From: abhishek9686 Date: Sun, 7 Jul 2024 13:53:22 +0530 Subject: [PATCH] deprecate use of old admin fields --- auth/auth.go | 52 ++--------------------------------- auth/host_session.go | 38 ++++++++++++------------- controllers/ext_client.go | 2 +- controllers/user.go | 23 ++++------------ logic/auth.go | 6 ++-- logic/gateway.go | 2 +- logic/jwts.go | 10 +++---- logic/users.go | 10 ++++--- migrate/migrate.go | 6 ++-- models/user_mgmt.go | 5 ++-- pro/auth/azure-ad.go | 10 ++++--- pro/auth/github.go | 10 ++++--- pro/auth/google.go | 10 ++++--- pro/auth/oidc.go | 10 ++++--- pro/auth/register_callback.go | 3 +- pro/controllers/users.go | 6 ++-- 16 files changed, 75 insertions(+), 128 deletions(-) diff --git a/auth/auth.go b/auth/auth.go index d6ce8b4c..0f89fdc1 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -3,13 +3,11 @@ package auth import ( "encoding/base64" "encoding/json" - "fmt" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" "golang.org/x/crypto/bcrypt" - "golang.org/x/exp/slog" "golang.org/x/oauth2" ) @@ -55,55 +53,11 @@ func FetchPassValue(newValue string) (string, error) { return string(b64CurrentValue), nil } -// == private == - -func addUser(email string) error { - var hasSuperAdmin, err = logic.HasSuperAdmin() - if err != nil { - slog.Error("error checking for existence of admin user during OAuth login for", "email", email, "error", err) - return err - } // generate random password to adapt to current model - var newPass, fetchErr = FetchPassValue("") - if fetchErr != nil { - slog.Error("failed to get password", "error", fetchErr.Error()) - return fetchErr - } - var newUser = models.User{ - UserName: email, - Password: newPass, - } - if !hasSuperAdmin { // must be first attempt, create a superadmin - logger.Log(0, "creating superadmin") - if err = logic.CreateSuperAdmin(&newUser); err != nil { - slog.Error("error creating super admin from user", "email", email, "error", err) - } else { - slog.Info("superadmin created from user", "email", email) - } - } else { // otherwise add to db as admin..? - // TODO: add ability to add users with preemptive permissions - newUser.IsAdmin = false - if err = logic.CreateUser(&newUser); err != nil { - logger.Log(0, "error creating user,", email, "; user not added", "error", err.Error()) - } else { - logger.Log(0, "user created from ", email) - } - } - return nil -} - -func isUserIsAllowed(username, network string, shouldAddUser bool) (*models.User, error) { +func isUserIsAllowed(username, network string) (*models.User, error) { user, err := logic.GetUser(username) - if err != nil && shouldAddUser { // user must not exist, so try to make one - if err = addUser(username); err != nil { - logger.Log(0, "failed to add user", username, "during a node SSO network join on network", network) - // response := returnErrTemplate(user.UserName, "failed to add user", state, reqKeyIf) - // w.WriteHeader(http.StatusInternalServerError) - // w.Write(response) - return nil, fmt.Errorf("failed to add user to system") - } - logger.Log(0, "user", username, "was added during a node SSO network join on network", network) - user, _ = logic.GetUser(username) + if err != nil { // user must not exist, so try to make one + return &models.User{}, err } return user, nil diff --git a/auth/host_session.go b/auth/host_session.go index 0113351a..3ef4d137 100644 --- a/auth/host_session.go +++ b/auth/host_session.go @@ -85,24 +85,24 @@ func SessionHandler(conn *websocket.Conn) { return } req.Pass = req.Host.ID.String() - user, err := logic.GetUser(req.User) - if err != nil { - logger.Log(0, "failed to get user", req.User, "from database") - err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) - if err != nil { - logger.Log(0, "error during message writing:", err.Error()) - } - return - } - if !user.IsAdmin && !user.IsSuperAdmin { - logger.Log(0, "user", req.User, "is neither an admin or superadmin. denying registeration") - conn.WriteMessage(messageType, []byte("cannot register with a non-admin or non-superadmin")) - err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) - if err != nil { - logger.Log(0, "error during message writing:", err.Error()) - } - return - } + // user, err := logic.GetUser(req.User) + // if err != nil { + // logger.Log(0, "failed to get user", req.User, "from database") + // err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) + // if err != nil { + // logger.Log(0, "error during message writing:", err.Error()) + // } + // return + // } + // if !user.IsAdmin && !user.IsSuperAdmin { + // logger.Log(0, "user", req.User, "is neither an admin or superadmin. denying registeration") + // conn.WriteMessage(messageType, []byte("cannot register with a non-admin or non-superadmin")) + // err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) + // if err != nil { + // logger.Log(0, "error during message writing:", err.Error()) + // } + // return + // } if err = netcache.Set(stateStr, req); err != nil { // give the user's host access in the DB logger.Log(0, "machine failed to complete join on network,", registerMessage.Network, "-", err.Error()) @@ -201,7 +201,7 @@ func SessionHandler(conn *websocket.Conn) { for _, newNet := range currentNetworks { if !logic.StringSliceContains(hostNets, newNet) { if len(result.User) > 0 { - _, err := isUserIsAllowed(result.User, newNet, false) + _, err := isUserIsAllowed(result.User, newNet) if err != nil { logger.Log(0, "unauthorized user", result.User, "attempted to register to network", newNet) handleHostRegErr(conn, err) diff --git a/controllers/ext_client.go b/controllers/ext_client.go index eb5308bb..0f937aa2 100644 --- a/controllers/ext_client.go +++ b/controllers/ext_client.go @@ -403,7 +403,7 @@ func createExtClient(w http.ResponseWriter, r *http.Request) { return } userName = caller.UserName - if _, ok := caller.RemoteGwIDs[nodeid]; (!caller.IsAdmin && !caller.IsSuperAdmin) && !ok { + if _, ok := caller.RemoteGwIDs[nodeid]; (caller.PlatformRoleID != models.AdminRole && caller.PlatformRoleID != models.SuperAdminRole) && !ok { err = errors.New("permission denied") slog.Error("failed to create extclient", "error", err) logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden")) diff --git a/controllers/user.go b/controllers/user.go index f07ddb59..20f740b5 100644 --- a/controllers/user.go +++ b/controllers/user.go @@ -619,7 +619,7 @@ func transferSuperAdmin(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) return } - if !u.IsAdmin { + if u.PlatformRoleID != models.AdminRole { logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only admins can be promoted to superadmin role"), "forbidden")) return } @@ -628,16 +628,14 @@ func transferSuperAdmin(w http.ResponseWriter, r *http.Request) { return } - u.IsSuperAdmin = true - u.IsAdmin = false + u.PlatformRoleID = models.SuperAdminRole err = logic.UpsertUser(*u) if err != nil { slog.Error("error updating user to superadmin: ", "user", u.UserName, "error", err.Error()) logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) return } - caller.IsSuperAdmin = false - caller.IsAdmin = true + caller.PlatformRoleID = models.AdminRole err = logic.UpsertUser(*caller) if err != nil { slog.Error("error demoting user to admin: ", "user", caller.UserName, "error", err.Error()) @@ -666,11 +664,6 @@ func createUser(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) return } - callerUserRole, err := logic.GetRole(caller.PlatformRoleID) - if err != nil { - logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) - return - } var user models.User err = json.NewDecoder(r.Body).Decode(&user) if err != nil { @@ -707,20 +700,17 @@ func createUser(w http.ResponseWriter, r *http.Request) { return } - if callerUserRole.ID != models.SuperAdminRole && user.IsAdmin { + if caller.PlatformRoleID != models.SuperAdminRole && user.PlatformRoleID == models.AdminRole { err = errors.New("only superadmin can create admin users") slog.Error("error creating new user: ", "user", user.UserName, "error", err) logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden")) return } - if !servercfg.IsPro && !user.IsAdmin { + if !servercfg.IsPro && user.PlatformRoleID != models.AdminRole { logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("non-admins users can only be created on Pro version"), "forbidden")) return } - if userRole.ID == models.AdminRole { - user.IsAdmin = true - } err = logic.CreateUser(&user) if err != nil { slog.Error("error creating new user: ", "user", user.UserName, "error", err.Error()) @@ -1134,9 +1124,6 @@ func userInviteSignUp(w http.ResponseWriter, r *http.Request) { user.PlatformRoleID = userG.PlatformRole user.UserGroups[inviteGroupID] = struct{}{} } - if user.PlatformRoleID == models.AdminRole { - user.IsAdmin = true - } user.NetworkRoles = make(map[models.NetworkID]map[models.UserRole]struct{}) user.IsSuperAdmin = false err = logic.CreateUser(&user) diff --git a/logic/auth.go b/logic/auth.go index 8ec207aa..34d04f01 100644 --- a/logic/auth.go +++ b/logic/auth.go @@ -114,7 +114,7 @@ func CreateUser(user *models.User) error { // set password to encrypted password user.Password = string(hash) - tokenString, _ := CreateUserJWT(user.UserName, user.IsSuperAdmin, user.IsAdmin) + tokenString, _ := CreateUserJWT(user.UserName, user.PlatformRoleID) if tokenString == "" { logger.Log(0, "failed to generate token", err.Error()) return err @@ -147,8 +147,6 @@ func CreateSuperAdmin(u *models.User) error { return errors.New("superadmin user already exists") } u.PlatformRoleID = models.SuperAdminRole - u.IsSuperAdmin = true - u.IsAdmin = false return CreateUser(u) } @@ -177,7 +175,7 @@ func VerifyAuthRequest(authRequest models.UserAuthParams) (string, error) { } // Create a new JWT for the node - tokenString, err := CreateUserJWT(authRequest.UserName, result.IsSuperAdmin, result.IsAdmin) + tokenString, err := CreateUserJWT(authRequest.UserName, result.PlatformRoleID) if err != nil { slog.Error("error creating jwt", "error", err) return "", err diff --git a/logic/gateway.go b/logic/gateway.go index 154a2a8d..7b8489ed 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -264,7 +264,7 @@ func IsUserAllowedAccessToExtClient(username string, client models.ExtClient) bo if err != nil { return false } - if !user.IsAdmin && !user.IsSuperAdmin { + if user.PlatformRoleID != models.AdminRole && user.PlatformRoleID != models.SuperAdminRole { if user.UserName != client.OwnerID { return false } diff --git a/logic/jwts.go b/logic/jwts.go index f3838ec1..f43979f5 100644 --- a/logic/jwts.go +++ b/logic/jwts.go @@ -53,12 +53,11 @@ func CreateJWT(uuid string, macAddress string, network string) (response string, } // CreateUserJWT - creates a user jwt token -func CreateUserJWT(username string, issuperadmin, isadmin bool) (response string, err error) { +func CreateUserJWT(username string, role models.UserRole) (response string, err error) { expirationTime := time.Now().Add(servercfg.GetServerConfig().JwtValidityDuration) claims := &models.UserClaims{ - UserName: username, - IsSuperAdmin: issuperadmin, - IsAdmin: isadmin, + UserName: username, + Role: role, RegisteredClaims: jwt.RegisteredClaims{ Issuer: "Netmaker", Subject: fmt.Sprintf("user|%s", username), @@ -145,7 +144,8 @@ func VerifyUserToken(tokenString string) (username string, issuperadmin, isadmin return "", false, false, err } if user.UserName != "" { - return user.UserName, user.IsSuperAdmin, user.IsAdmin, nil + return user.UserName, user.PlatformRoleID == models.SuperAdminRole, + user.PlatformRoleID == models.AdminRole, nil } err = errors.New("user does not exist") } diff --git a/logic/users.go b/logic/users.go index 881878a9..051624e9 100644 --- a/logic/users.go +++ b/logic/users.go @@ -41,10 +41,12 @@ func GetReturnUser(username string) (models.ReturnUser, error) { // ToReturnUser - gets a user as a return user func ToReturnUser(user models.User) models.ReturnUser { return models.ReturnUser{ - UserName: user.UserName, - IsSuperAdmin: user.IsSuperAdmin, - IsAdmin: user.IsAdmin, - RemoteGwIDs: user.RemoteGwIDs, + UserName: user.UserName, + PlatformRoleID: user.PlatformRoleID, + UserGroups: user.UserGroups, + NetworkRoles: user.NetworkRoles, + RemoteGwIDs: user.RemoteGwIDs, + LastLoginTime: user.LastLoginTime, } } diff --git a/migrate/migrate.go b/migrate/migrate.go index a2593aa1..b154c66a 100644 --- a/migrate/migrate.go +++ b/migrate/migrate.go @@ -44,8 +44,7 @@ func assignSuperAdmin() { if err != nil { log.Fatal("error getting user", "user", owner, "error", err.Error()) } - user.IsSuperAdmin = true - user.IsAdmin = false + user.PlatformRoleID = models.SuperAdminRole err = logic.UpsertUser(*user) if err != nil { log.Fatal( @@ -65,8 +64,7 @@ func assignSuperAdmin() { slog.Error("error getting user", "user", u.UserName, "error", err.Error()) continue } - user.IsSuperAdmin = true - user.IsAdmin = false + user.PlatformRoleID = models.SuperAdminRole err = logic.UpsertUser(*user) if err != nil { slog.Error( diff --git a/models/user_mgmt.go b/models/user_mgmt.go index 3904f7cc..7a6878d9 100644 --- a/models/user_mgmt.go +++ b/models/user_mgmt.go @@ -126,9 +126,8 @@ type UserAuthParams struct { // UserClaims - user claims struct type UserClaims struct { - IsAdmin bool - IsSuperAdmin bool - UserName string + Role UserRole + UserName string jwt.RegisteredClaims } diff --git a/pro/auth/azure-ad.go b/pro/auth/azure-ad.go index 64c704b9..97d918d5 100644 --- a/pro/auth/azure-ad.go +++ b/pro/auth/azure-ad.go @@ -107,9 +107,6 @@ func handleAzureCallback(w http.ResponseWriter, r *http.Request) { user.PlatformRoleID = userG.PlatformRole user.UserGroups[inviteGroupID] = struct{}{} } - if user.PlatformRoleID == models.AdminRole { - user.IsAdmin = true - } if err = logic.CreateUser(user); err != nil { handleSomethingWentWrong(w) return @@ -136,7 +133,12 @@ func handleAzureCallback(w http.ResponseWriter, r *http.Request) { handleOauthUserNotFound(w) return } - if !(user.IsSuperAdmin || user.IsAdmin) { + userRole, err := logic.GetRole(user.PlatformRoleID) + if err != nil { + handleSomethingWentWrong(w) + return + } + if userRole.DenyDashboardAccess { handleOauthUserNotAllowed(w) return } diff --git a/pro/auth/github.go b/pro/auth/github.go index 21abd7ea..6cc2e666 100644 --- a/pro/auth/github.go +++ b/pro/auth/github.go @@ -107,9 +107,6 @@ func handleGithubCallback(w http.ResponseWriter, r *http.Request) { user.PlatformRoleID = userG.PlatformRole user.UserGroups[inviteGroupID] = struct{}{} } - if user.PlatformRoleID == models.AdminRole { - user.IsAdmin = true - } if err = logic.CreateUser(user); err != nil { handleSomethingWentWrong(w) return @@ -136,7 +133,12 @@ func handleGithubCallback(w http.ResponseWriter, r *http.Request) { handleOauthUserNotFound(w) return } - if !(user.IsSuperAdmin || user.IsAdmin) { + userRole, err := logic.GetRole(user.PlatformRoleID) + if err != nil { + handleSomethingWentWrong(w) + return + } + if userRole.DenyDashboardAccess { handleOauthUserNotAllowed(w) return } diff --git a/pro/auth/google.go b/pro/auth/google.go index cf127d20..5d90a5bc 100644 --- a/pro/auth/google.go +++ b/pro/auth/google.go @@ -108,9 +108,6 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) { user.PlatformRoleID = userG.PlatformRole user.UserGroups[inviteGroupID] = struct{}{} } - if user.PlatformRoleID == models.AdminRole { - user.IsAdmin = true - } if err = logic.CreateUser(user); err != nil { handleSomethingWentWrong(w) return @@ -139,7 +136,12 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) { handleOauthUserNotFound(w) return } - if !(user.IsSuperAdmin || user.IsAdmin) { + userRole, err := logic.GetRole(user.PlatformRoleID) + if err != nil { + handleSomethingWentWrong(w) + return + } + if userRole.DenyDashboardAccess { handleOauthUserNotAllowed(w) return } diff --git a/pro/auth/oidc.go b/pro/auth/oidc.go index a41b027e..452a15c8 100644 --- a/pro/auth/oidc.go +++ b/pro/auth/oidc.go @@ -119,9 +119,6 @@ func handleOIDCCallback(w http.ResponseWriter, r *http.Request) { user.PlatformRoleID = userG.PlatformRole user.UserGroups[inviteGroupID] = struct{}{} } - if user.PlatformRoleID == models.AdminRole { - user.IsAdmin = true - } if err = logic.CreateUser(user); err != nil { handleSomethingWentWrong(w) return @@ -148,7 +145,12 @@ func handleOIDCCallback(w http.ResponseWriter, r *http.Request) { handleOauthUserNotFound(w) return } - if !(user.IsSuperAdmin || user.IsAdmin) { + userRole, err := logic.GetRole(user.PlatformRoleID) + if err != nil { + handleSomethingWentWrong(w) + return + } + if userRole.DenyDashboardAccess { handleOauthUserNotAllowed(w) return } diff --git a/pro/auth/register_callback.go b/pro/auth/register_callback.go index c7edd958..a2085c40 100644 --- a/pro/auth/register_callback.go +++ b/pro/auth/register_callback.go @@ -10,6 +10,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/logic/pro/netcache" + "github.com/gravitl/netmaker/models" ) var ( @@ -73,7 +74,7 @@ func HandleHostSSOCallback(w http.ResponseWriter, r *http.Request) { handleOauthUserNotFound(w) return } - if !user.IsAdmin && !user.IsSuperAdmin { + if user.PlatformRoleID != models.AdminRole && user.PlatformRoleID != models.SuperAdminRole { response := returnErrTemplate(userClaims.getUserName(), "only admin users can register using SSO", state, reqKeyIf) w.WriteHeader(http.StatusForbidden) w.Write(response) diff --git a/pro/controllers/users.go b/pro/controllers/users.go index 1d6d2093..c303729c 100644 --- a/pro/controllers/users.go +++ b/pro/controllers/users.go @@ -55,7 +55,7 @@ func attachUserToRemoteAccessGw(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to fetch user %s, error: %v", username, err), "badrequest")) return } - if user.IsAdmin || user.IsSuperAdmin { + if user.PlatformRoleID == models.AdminRole || user.PlatformRoleID == models.SuperAdminRole { logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("superadmins/admins have access to all gateways"), "badrequest")) return } @@ -219,7 +219,7 @@ func getUserRemoteAccessGws(w http.ResponseWriter, r *http.Request) { slog.Error("failed to get node network", "error", err) } - if _, ok := user.RemoteGwIDs[node.ID.String()]; (!user.IsAdmin && !user.IsSuperAdmin) && ok { + if _, ok := user.RemoteGwIDs[node.ID.String()]; (user.PlatformRoleID != models.AdminRole && user.PlatformRoleID != models.SuperAdminRole) && ok { gws := userGws[node.Network] extClient.AllowedIPs = logic.GetExtclientAllowedIPs(extClient) gws = append(gws, models.UserRemoteGws{ @@ -260,7 +260,7 @@ func getUserRemoteAccessGws(w http.ResponseWriter, r *http.Request) { } // add remaining gw nodes to resp - if !user.IsAdmin && !user.IsSuperAdmin { + if user.PlatformRoleID != models.AdminRole && user.PlatformRoleID != models.SuperAdminRole { for gwID := range user.RemoteGwIDs { node, err := logic.GetNodeByID(gwID) if err != nil {