netmaker/logic/security.go
Abhishek K 719e0c254d
NET-551: User Mgmt Re-Design (#2547)
* add superadmin role, apis to create superadmin user

* apis to attach and remove user from remote access gateways

* add api to list user's remote client has gateway clients

* remove code related user groups

* remove networks and groups from user model

* refactor user CRUD operations

* fix network permission test

* add superadmin to authorize func

* remove user network and groups from cli

* api to transfer superadmin role

* add api to list users on a ingress gw

* restrict user access to resources on server

* deny request from remote access client if extclient is already created

* fix user tests

* fix static checks

* fix static checks

* add limits to extclient create handler

* set username to superadmin on if masterkey is used

* allow creation of extclients using masterkey

* add migration func to assign superadmin role for existing admin user

* check for superadmin on migration if users are present

* allowe masterkey to extcleint apis

* check ownerid

* format error, on jwt token verification failure return unauthorized rather than forbidden

* user update fix

* move user remote functionality to ee

* fix update user api

* security patch

* initalise ee user handlers

* allow user to use master key to update any user

* use slog

* fix auth user test

* table headers

* remove user role, it's covered in middleware

* setuser defaults fix
2023-09-01 14:27:08 +05:30

85 lines
2.2 KiB
Go

package logic
import (
"net/http"
"strings"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
)
const (
MasterUser = "masteradministrator"
Forbidden_Msg = "forbidden"
Forbidden_Err = models.Error(Forbidden_Msg)
Unauthorized_Msg = "unauthorized"
Unauthorized_Err = models.Error(Unauthorized_Msg)
)
// SecurityCheck - Check if user has appropriate permissions
func SecurityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
r.Header.Set("ismaster", "no")
bearerToken := r.Header.Get("Authorization")
username, err := UserPermissions(reqAdmin, bearerToken)
if err != nil {
ReturnErrorResponse(w, r, FormatError(err, err.Error()))
return
}
// detect masteradmin
if username == MasterUser {
r.Header.Set("ismaster", "yes")
}
r.Header.Set("user", username)
next.ServeHTTP(w, r)
}
}
// UserPermissions - checks token stuff
func UserPermissions(reqAdmin bool, token string) (string, error) {
var tokenSplit = strings.Split(token, " ")
var authToken = ""
if len(tokenSplit) < 2 {
return "", Unauthorized_Err
} else {
authToken = tokenSplit[1]
}
//all endpoints here require master so not as complicated
if authenticateMaster(authToken) {
// TODO log in as an actual admin user
return MasterUser, nil
}
username, issuperadmin, isadmin, err := VerifyUserToken(authToken)
if err != nil {
return username, Unauthorized_Err
}
if reqAdmin && !(issuperadmin || isadmin) {
return username, Forbidden_Err
}
return username, nil
}
// Consider a more secure way of setting master key
func authenticateMaster(tokenString string) bool {
return tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != ""
}
func ContinueIfUserMatch(next http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var errorResponse = models.ErrorResponse{
Code: http.StatusForbidden, Message: Forbidden_Msg,
}
var params = mux.Vars(r)
var requestedUser = params["username"]
if requestedUser != r.Header.Get("user") {
ReturnErrorResponse(w, r, errorResponse)
return
}
next.ServeHTTP(w, r)
}
}