mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-05 04:34:30 +08:00
adding security fixes
This commit is contained in:
parent
e49dcc0796
commit
8fc9dac969
5 changed files with 69 additions and 61 deletions
|
@ -181,7 +181,7 @@ func nodeauth(next http.Handler) http.HandlerFunc {
|
|||
func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Handler) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var errorResponse = models.ErrorResponse{
|
||||
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
|
||||
Code: http.StatusUnauthorized, Message: unauthorized_msg,
|
||||
}
|
||||
|
||||
var params = mux.Vars(r)
|
||||
|
@ -190,9 +190,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||
//check that the request is for a valid network
|
||||
//if (networkCheck && !networkexists) || err != nil {
|
||||
if networkCheck && !networkexists {
|
||||
errorResponse = models.ErrorResponse{
|
||||
Code: http.StatusNotFound, Message: "W1R3: This network does not exist. ",
|
||||
}
|
||||
returnErrorResponse(w, r, errorResponse)
|
||||
return
|
||||
} else {
|
||||
|
@ -210,9 +207,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||
if len(tokenSplit) > 1 {
|
||||
authToken = tokenSplit[1]
|
||||
} else {
|
||||
errorResponse = models.ErrorResponse{
|
||||
Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
|
||||
}
|
||||
returnErrorResponse(w, r, errorResponse)
|
||||
return
|
||||
}
|
||||
|
@ -229,9 +223,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||
var nodeID = ""
|
||||
username, networks, isadmin, errN := logic.VerifyUserToken(authToken)
|
||||
if errN != nil {
|
||||
errorResponse = models.ErrorResponse{
|
||||
Code: http.StatusUnauthorized, Message: "W1R3: Unauthorized, Invalid Token Processed.",
|
||||
}
|
||||
returnErrorResponse(w, r, errorResponse)
|
||||
return
|
||||
}
|
||||
|
@ -264,9 +255,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||
} else {
|
||||
node, err := logic.GetNodeByID(nodeID)
|
||||
if err != nil {
|
||||
errorResponse = models.ErrorResponse{
|
||||
Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
|
||||
}
|
||||
returnErrorResponse(w, r, errorResponse)
|
||||
return
|
||||
}
|
||||
|
@ -285,9 +273,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||
}
|
||||
}
|
||||
if !isAuthorized {
|
||||
errorResponse = models.ErrorResponse{
|
||||
Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
|
||||
}
|
||||
returnErrorResponse(w, r, errorResponse)
|
||||
return
|
||||
} else {
|
||||
|
|
|
@ -2,7 +2,6 @@ package controller
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
|
@ -14,14 +13,30 @@ import (
|
|||
"github.com/gravitl/netmaker/servercfg"
|
||||
)
|
||||
|
||||
const (
|
||||
master_uname = "masteradministrator"
|
||||
unauthorized_msg = "unauthorized"
|
||||
unauthorized_err = models.Error(unauthorized_msg)
|
||||
)
|
||||
|
||||
func securityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
|
||||
/*
|
||||
1. Check master token
|
||||
2. Check if admin
|
||||
3. Check if network admin
|
||||
|
||||
|
||||
*/
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var errorResponse = models.ErrorResponse{
|
||||
Code: http.StatusUnauthorized, Message: "W1R3: It's not you it's me.",
|
||||
Code: http.StatusUnauthorized, Message: unauthorized_msg,
|
||||
}
|
||||
|
||||
var params = mux.Vars(r)
|
||||
bearerToken := r.Header.Get("Authorization")
|
||||
// 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
|
||||
if strings.Contains(r.RequestURI, "/dns") && strings.ToUpper(r.Method) == "GET" && authenticateDNSToken(bearerToken) {
|
||||
// do dns stuff
|
||||
r.Header.Set("user", "nameserver")
|
||||
|
@ -30,19 +45,17 @@ func securityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
|
|||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
networks, username, err := SecurityCheck(reqAdmin, params["networkname"], bearerToken)
|
||||
var networkName = params["networkname"]
|
||||
if len(networkName) == 0 {
|
||||
networkName = params["network"]
|
||||
}
|
||||
networks, username, err := SecurityCheck(reqAdmin, networkName, bearerToken)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "does not exist") {
|
||||
errorResponse.Code = http.StatusNotFound
|
||||
}
|
||||
errorResponse.Message = err.Error()
|
||||
returnErrorResponse(w, r, errorResponse)
|
||||
return
|
||||
}
|
||||
networksJson, err := json.Marshal(&networks)
|
||||
if err != nil {
|
||||
errorResponse.Message = err.Error()
|
||||
returnErrorResponse(w, r, errorResponse)
|
||||
return
|
||||
}
|
||||
|
@ -54,46 +67,33 @@ func securityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
|
|||
|
||||
// SecurityCheck - checks token stuff
|
||||
func SecurityCheck(reqAdmin bool, netname string, token string) ([]string, string, error) {
|
||||
|
||||
var hasBearer = true
|
||||
var tokenSplit = strings.Split(token, " ")
|
||||
var authToken = ""
|
||||
userNetworks := []string{}
|
||||
|
||||
if len(tokenSplit) < 2 {
|
||||
hasBearer = false
|
||||
return userNetworks, "", unauthorized_err
|
||||
} else {
|
||||
authToken = tokenSplit[1]
|
||||
}
|
||||
userNetworks := []string{}
|
||||
//all endpoints here require master so not as complicated
|
||||
isMasterAuthenticated := authenticateMaster(authToken)
|
||||
username := ""
|
||||
if !hasBearer || !isMasterAuthenticated {
|
||||
userName, networks, isadmin, err := logic.VerifyUserToken(authToken)
|
||||
username = userName
|
||||
if err != nil {
|
||||
return nil, username, errors.New("error verifying user token")
|
||||
}
|
||||
if !isadmin && reqAdmin {
|
||||
return nil, username, errors.New("you are unauthorized to access this endpoint")
|
||||
}
|
||||
userNetworks = networks
|
||||
if isadmin {
|
||||
userNetworks = []string{ALL_NETWORK_ACCESS}
|
||||
} else {
|
||||
networkexists, err := functions.NetworkExists(netname)
|
||||
if err != nil && !database.IsEmptyRecord(err) {
|
||||
return nil, "", err
|
||||
}
|
||||
if netname != "" && !networkexists {
|
||||
return nil, "", errors.New("this network does not exist")
|
||||
}
|
||||
}
|
||||
} else if isMasterAuthenticated {
|
||||
userNetworks = []string{ALL_NETWORK_ACCESS}
|
||||
if authenticateMaster(authToken) {
|
||||
return []string{ALL_NETWORK_ACCESS}, master_uname, nil
|
||||
}
|
||||
if len(userNetworks) == 0 {
|
||||
userNetworks = append(userNetworks, NO_NETWORKS_PRESENT)
|
||||
username, networks, isadmin, err := logic.VerifyUserToken(authToken)
|
||||
if err != nil {
|
||||
return nil, username, unauthorized_err
|
||||
}
|
||||
if !isadmin && reqAdmin {
|
||||
return nil, username, unauthorized_err
|
||||
}
|
||||
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) {
|
||||
return nil, username, unauthorized_err
|
||||
}
|
||||
return userNetworks, username, nil
|
||||
}
|
||||
|
@ -103,6 +103,14 @@ func authenticateMaster(tokenString string) bool {
|
|||
return tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != ""
|
||||
}
|
||||
|
||||
func authenticateNetworkUser(network string, userNetworks []string) bool {
|
||||
networkexists, err := functions.NetworkExists(network)
|
||||
if (err != nil && !database.IsEmptyRecord(err)) || !networkexists {
|
||||
return false
|
||||
}
|
||||
return logic.StringSliceContains(userNetworks, network)
|
||||
}
|
||||
|
||||
//Consider a more secure way of setting master key
|
||||
func authenticateDNSToken(tokenString string) bool {
|
||||
tokens := strings.Split(tokenString, " ")
|
||||
|
@ -115,7 +123,7 @@ func authenticateDNSToken(tokenString string) bool {
|
|||
func continueIfUserMatch(next http.Handler) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var errorResponse = models.ErrorResponse{
|
||||
Code: http.StatusUnauthorized, Message: "W1R3: This doesn't look like you.",
|
||||
Code: http.StatusUnauthorized, Message: unauthorized_msg,
|
||||
}
|
||||
var params = mux.Vars(r)
|
||||
var requestedUser = params["username"]
|
||||
|
|
4
main.go
4
main.go
|
@ -86,9 +86,9 @@ func initialize() { // Client Mode Prereq Check
|
|||
logger.Log(0, "no OAuth provider found or not configured, continuing without OAuth")
|
||||
}
|
||||
|
||||
err = serverctl.SetDefaultACLS()
|
||||
err = serverctl.SetDefaults()
|
||||
if err != nil {
|
||||
logger.FatalLog("error setting default acls: ", err.Error())
|
||||
logger.FatalLog("error setting defaults: ", err.Error())
|
||||
}
|
||||
|
||||
if servercfg.IsClientMode() != "off" {
|
||||
|
|
5
models/error.go
Normal file
5
models/error.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package models
|
||||
|
||||
type Error string
|
||||
|
||||
func (e Error) Error() string { return string(e) }
|
|
@ -81,14 +81,24 @@ func SyncServerNetwork(network string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetDefaultACLS - runs through each network to see if ACL's are set. If not, goes through each node in network and adds the default ACL
|
||||
func SetDefaultACLS() error {
|
||||
func SetDefaults() error {
|
||||
if err := setNodeDefaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// setNodeDefaults - runs through each node and set defaults
|
||||
func setNodeDefaults() error {
|
||||
// upgraded systems will not have ACL's set, which is why we need this function
|
||||
nodes, err := logic.GetAllNodes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range nodes {
|
||||
logic.SetNodeDefaults(&nodes[i])
|
||||
logic.UpdateNode(&nodes[i], &nodes[i])
|
||||
currentNodeACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID))
|
||||
if (err != nil && (database.IsEmptyRecord(err) || strings.Contains(err.Error(), "no node ACL present"))) || currentNodeACL == nil {
|
||||
if _, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID), acls.Allowed); err != nil {
|
||||
|
|
Loading…
Add table
Reference in a new issue