netmaker/logic/security.go

207 lines
5.6 KiB
Go
Raw Normal View History

2022-09-15 01:26:31 +08:00
package logic
2021-12-07 05:45:27 +08:00
import (
"encoding/json"
"net/http"
"strings"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/database"
2022-09-14 03:25:56 +08:00
"github.com/gravitl/netmaker/logic/pro"
2021-12-07 05:45:27 +08:00
"github.com/gravitl/netmaker/models"
2022-09-14 03:25:56 +08:00
"github.com/gravitl/netmaker/models/promodels"
2021-12-07 05:45:27 +08:00
"github.com/gravitl/netmaker/servercfg"
)
2022-08-31 23:38:29 +08:00
const (
2022-09-15 01:26:31 +08:00
// ALL_NETWORK_ACCESS - represents all networks
ALL_NETWORK_ACCESS = "THIS_USER_HAS_ALL"
2022-08-31 23:38:29 +08:00
master_uname = "masteradministrator"
2022-09-15 01:26:31 +08:00
Unauthorized_Msg = "unauthorized"
Unauthorized_Err = models.Error(Unauthorized_Msg)
2022-08-31 23:38:29 +08:00
)
2022-09-15 01:26:31 +08:00
// SecurityCheck - Check if user has appropriate permissions
func SecurityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
2022-08-31 23:38:29 +08:00
2021-12-07 05:45:27 +08:00
return func(w http.ResponseWriter, r *http.Request) {
var errorResponse = models.ErrorResponse{
2022-09-15 01:26:31 +08:00
Code: http.StatusUnauthorized, Message: Unauthorized_Msg,
2021-12-07 05:45:27 +08:00
}
var params = mux.Vars(r)
bearerToken := r.Header.Get("Authorization")
2022-08-31 23:38:29 +08:00
// to have a custom DNS service adding entries
// we should refactor this, but is for the special case of an external service to query the DNS api
2021-12-07 23:56:39 +08:00
if strings.Contains(r.RequestURI, "/dns") && strings.ToUpper(r.Method) == "GET" && authenticateDNSToken(bearerToken) {
// do dns stuff
2021-12-07 05:45:27 +08:00
r.Header.Set("user", "nameserver")
networks, _ := json.Marshal([]string{ALL_NETWORK_ACCESS})
r.Header.Set("networks", string(networks))
next.ServeHTTP(w, r)
2021-12-08 00:15:01 +08:00
return
2021-12-07 05:45:27 +08:00
}
2022-08-31 23:38:29 +08:00
var networkName = params["networkname"]
if len(networkName) == 0 {
networkName = params["network"]
}
2022-09-15 01:26:31 +08:00
networks, username, err := UserPermissions(reqAdmin, networkName, bearerToken)
2021-12-07 05:45:27 +08:00
if err != nil {
2022-09-15 01:26:31 +08:00
ReturnErrorResponse(w, r, errorResponse)
2021-12-07 05:45:27 +08:00
return
}
networksJson, err := json.Marshal(&networks)
if err != nil {
2022-09-15 01:26:31 +08:00
ReturnErrorResponse(w, r, errorResponse)
2021-12-07 05:45:27 +08:00
return
}
r.Header.Set("user", username)
r.Header.Set("networks", string(networksJson))
next.ServeHTTP(w, r)
}
}
2022-09-15 01:26:31 +08:00
// NetUserSecurityCheck - Check if network user has appropriate permissions
func NetUserSecurityCheck(isNodes, isClients bool, next http.Handler) http.HandlerFunc {
2022-09-14 03:25:56 +08:00
return func(w http.ResponseWriter, r *http.Request) {
var errorResponse = models.ErrorResponse{
Code: http.StatusUnauthorized, Message: "unauthorized",
}
r.Header.Set("ismaster", "no")
var params = mux.Vars(r)
var netUserName = params["networkuser"]
var network = params["network"]
bearerToken := r.Header.Get("Authorization")
var tokenSplit = strings.Split(bearerToken, " ")
var authToken = ""
if len(tokenSplit) < 2 {
2022-09-15 01:26:31 +08:00
ReturnErrorResponse(w, r, errorResponse)
2022-09-14 03:25:56 +08:00
return
} else {
authToken = tokenSplit[1]
}
isMasterAuthenticated := authenticateMaster(authToken)
if isMasterAuthenticated {
r.Header.Set("user", "master token user")
r.Header.Set("ismaster", "yes")
next.ServeHTTP(w, r)
return
}
2022-09-15 01:26:31 +08:00
userName, _, isadmin, err := VerifyUserToken(authToken)
2022-09-14 03:25:56 +08:00
if err != nil {
2022-09-15 01:26:31 +08:00
ReturnErrorResponse(w, r, errorResponse)
2022-09-14 03:25:56 +08:00
return
}
r.Header.Set("user", userName)
if isadmin {
next.ServeHTTP(w, r)
return
}
if isNodes || isClients {
necessaryAccess := pro.NET_ADMIN
if isClients {
necessaryAccess = pro.CLIENT_ACCESS
}
if isNodes {
necessaryAccess = pro.NODE_ACCESS
}
u, err := pro.GetNetworkUser(network, promodels.NetworkUserID(userName))
if err != nil {
2022-09-15 01:26:31 +08:00
ReturnErrorResponse(w, r, errorResponse)
2022-09-14 03:25:56 +08:00
return
}
if u.AccessLevel > necessaryAccess {
2022-09-15 01:26:31 +08:00
ReturnErrorResponse(w, r, errorResponse)
2022-09-14 03:25:56 +08:00
return
}
} else if netUserName != userName {
2022-09-15 01:26:31 +08:00
ReturnErrorResponse(w, r, errorResponse)
2022-09-14 03:25:56 +08:00
return
}
next.ServeHTTP(w, r)
}
}
2022-09-15 01:26:31 +08:00
// UserPermissions - checks token stuff
func UserPermissions(reqAdmin bool, netname string, token string) ([]string, string, error) {
2021-12-07 05:45:27 +08:00
var tokenSplit = strings.Split(token, " ")
var authToken = ""
2022-08-31 23:38:29 +08:00
userNetworks := []string{}
2021-12-07 05:45:27 +08:00
if len(tokenSplit) < 2 {
2022-09-15 01:26:31 +08:00
return userNetworks, "", Unauthorized_Err
2021-12-07 05:45:27 +08:00
} else {
authToken = tokenSplit[1]
}
//all endpoints here require master so not as complicated
2022-08-31 23:38:29 +08:00
if authenticateMaster(authToken) {
return []string{ALL_NETWORK_ACCESS}, master_uname, nil
}
2022-09-15 01:26:31 +08:00
username, networks, isadmin, err := VerifyUserToken(authToken)
2022-08-31 23:38:29 +08:00
if err != nil {
2022-09-15 01:26:31 +08:00
return nil, username, Unauthorized_Err
2022-08-31 23:38:29 +08:00
}
if !isadmin && reqAdmin {
2022-09-15 01:26:31 +08:00
return nil, username, Unauthorized_Err
2021-12-07 05:45:27 +08:00
}
2022-08-31 23:38:29 +08:00
userNetworks = networks
if isadmin {
return []string{ALL_NETWORK_ACCESS}, username, nil
}
// check network admin access
if len(netname) > 0 && (!authenticateNetworkUser(netname, userNetworks) || len(userNetworks) == 0) {
2022-09-15 01:26:31 +08:00
return nil, username, Unauthorized_Err
2021-12-07 05:45:27 +08:00
}
2022-09-14 03:25:56 +08:00
if !pro.IsUserNetAdmin(netname, username) {
2022-09-15 01:26:31 +08:00
return nil, "", Unauthorized_Err
2022-09-14 03:25:56 +08:00
}
return userNetworks, username, nil
2021-12-07 05:45:27 +08:00
}
// Consider a more secure way of setting master key
2021-12-07 05:45:27 +08:00
func authenticateMaster(tokenString string) bool {
return tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != ""
2021-12-07 05:45:27 +08:00
}
2022-08-31 23:38:29 +08:00
func authenticateNetworkUser(network string, userNetworks []string) bool {
2022-09-15 01:26:31 +08:00
networkexists, err := NetworkExists(network)
2022-08-31 23:38:29 +08:00
if (err != nil && !database.IsEmptyRecord(err)) || !networkexists {
return false
}
2022-09-15 01:26:31 +08:00
return StringSliceContains(userNetworks, network)
2022-08-31 23:38:29 +08:00
}
2021-12-07 05:45:27 +08:00
//Consider a more secure way of setting master key
func authenticateDNSToken(tokenString string) bool {
tokens := strings.Split(tokenString, " ")
if len(tokens) < 2 {
return false
}
return tokens[1] == servercfg.GetDNSKey()
}
2021-12-07 23:56:39 +08:00
2022-09-15 01:26:31 +08:00
func ContinueIfUserMatch(next http.Handler) http.HandlerFunc {
2021-12-07 23:56:39 +08:00
return func(w http.ResponseWriter, r *http.Request) {
var errorResponse = models.ErrorResponse{
2022-09-15 01:26:31 +08:00
Code: http.StatusUnauthorized, Message: Unauthorized_Msg,
2021-12-07 23:56:39 +08:00
}
var params = mux.Vars(r)
var requestedUser = params["username"]
if requestedUser != r.Header.Get("user") {
2022-09-15 01:26:31 +08:00
ReturnErrorResponse(w, r, errorResponse)
2021-12-07 23:56:39 +08:00
return
}
next.ServeHTTP(w, r)
}
}