mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-06 09:22:42 +08:00
adding security fixes
This commit is contained in:
@@ -181,7 +181,7 @@ func nodeauth(next http.Handler) http.HandlerFunc {
|
|||||||
func authorize(nodesAllowed, networkCheck bool, authNetwork string, 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) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var errorResponse = models.ErrorResponse{
|
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)
|
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
|
//check that the request is for a valid network
|
||||||
//if (networkCheck && !networkexists) || err != nil {
|
//if (networkCheck && !networkexists) || err != nil {
|
||||||
if networkCheck && !networkexists {
|
if networkCheck && !networkexists {
|
||||||
errorResponse = models.ErrorResponse{
|
|
||||||
Code: http.StatusNotFound, Message: "W1R3: This network does not exist. ",
|
|
||||||
}
|
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@@ -210,9 +207,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||||||
if len(tokenSplit) > 1 {
|
if len(tokenSplit) > 1 {
|
||||||
authToken = tokenSplit[1]
|
authToken = tokenSplit[1]
|
||||||
} else {
|
} else {
|
||||||
errorResponse = models.ErrorResponse{
|
|
||||||
Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
|
|
||||||
}
|
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -229,9 +223,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||||||
var nodeID = ""
|
var nodeID = ""
|
||||||
username, networks, isadmin, errN := logic.VerifyUserToken(authToken)
|
username, networks, isadmin, errN := logic.VerifyUserToken(authToken)
|
||||||
if errN != nil {
|
if errN != nil {
|
||||||
errorResponse = models.ErrorResponse{
|
|
||||||
Code: http.StatusUnauthorized, Message: "W1R3: Unauthorized, Invalid Token Processed.",
|
|
||||||
}
|
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -264,9 +255,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||||||
} else {
|
} else {
|
||||||
node, err := logic.GetNodeByID(nodeID)
|
node, err := logic.GetNodeByID(nodeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorResponse = models.ErrorResponse{
|
|
||||||
Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
|
|
||||||
}
|
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -285,9 +273,6 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !isAuthorized {
|
if !isAuthorized {
|
||||||
errorResponse = models.ErrorResponse{
|
|
||||||
Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
|
|
||||||
}
|
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
@@ -2,7 +2,6 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -14,14 +13,30 @@ import (
|
|||||||
"github.com/gravitl/netmaker/servercfg"
|
"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 {
|
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) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var errorResponse = models.ErrorResponse{
|
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)
|
var params = mux.Vars(r)
|
||||||
bearerToken := r.Header.Get("Authorization")
|
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) {
|
if strings.Contains(r.RequestURI, "/dns") && strings.ToUpper(r.Method) == "GET" && authenticateDNSToken(bearerToken) {
|
||||||
// do dns stuff
|
// do dns stuff
|
||||||
r.Header.Set("user", "nameserver")
|
r.Header.Set("user", "nameserver")
|
||||||
@@ -30,19 +45,17 @@ func securityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
|
|||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var networkName = params["networkname"]
|
||||||
networks, username, err := SecurityCheck(reqAdmin, params["networkname"], bearerToken)
|
if len(networkName) == 0 {
|
||||||
|
networkName = params["network"]
|
||||||
|
}
|
||||||
|
networks, username, err := SecurityCheck(reqAdmin, networkName, bearerToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "does not exist") {
|
|
||||||
errorResponse.Code = http.StatusNotFound
|
|
||||||
}
|
|
||||||
errorResponse.Message = err.Error()
|
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
networksJson, err := json.Marshal(&networks)
|
networksJson, err := json.Marshal(&networks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorResponse.Message = err.Error()
|
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -54,46 +67,33 @@ func securityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
|
|||||||
|
|
||||||
// SecurityCheck - checks token stuff
|
// SecurityCheck - checks token stuff
|
||||||
func SecurityCheck(reqAdmin bool, netname string, token string) ([]string, string, error) {
|
func SecurityCheck(reqAdmin bool, netname string, token string) ([]string, string, error) {
|
||||||
|
|
||||||
var hasBearer = true
|
|
||||||
var tokenSplit = strings.Split(token, " ")
|
var tokenSplit = strings.Split(token, " ")
|
||||||
var authToken = ""
|
var authToken = ""
|
||||||
|
userNetworks := []string{}
|
||||||
|
|
||||||
if len(tokenSplit) < 2 {
|
if len(tokenSplit) < 2 {
|
||||||
hasBearer = false
|
return userNetworks, "", unauthorized_err
|
||||||
} else {
|
} else {
|
||||||
authToken = tokenSplit[1]
|
authToken = tokenSplit[1]
|
||||||
}
|
}
|
||||||
userNetworks := []string{}
|
|
||||||
//all endpoints here require master so not as complicated
|
//all endpoints here require master so not as complicated
|
||||||
isMasterAuthenticated := authenticateMaster(authToken)
|
if authenticateMaster(authToken) {
|
||||||
username := ""
|
return []string{ALL_NETWORK_ACCESS}, master_uname, nil
|
||||||
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 len(userNetworks) == 0 {
|
username, networks, isadmin, err := logic.VerifyUserToken(authToken)
|
||||||
userNetworks = append(userNetworks, NO_NETWORKS_PRESENT)
|
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
|
return userNetworks, username, nil
|
||||||
}
|
}
|
||||||
@@ -103,6 +103,14 @@ func authenticateMaster(tokenString string) bool {
|
|||||||
return tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != ""
|
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
|
//Consider a more secure way of setting master key
|
||||||
func authenticateDNSToken(tokenString string) bool {
|
func authenticateDNSToken(tokenString string) bool {
|
||||||
tokens := strings.Split(tokenString, " ")
|
tokens := strings.Split(tokenString, " ")
|
||||||
@@ -115,7 +123,7 @@ func authenticateDNSToken(tokenString string) bool {
|
|||||||
func continueIfUserMatch(next http.Handler) http.HandlerFunc {
|
func continueIfUserMatch(next http.Handler) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var errorResponse = models.ErrorResponse{
|
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 params = mux.Vars(r)
|
||||||
var requestedUser = params["username"]
|
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")
|
logger.Log(0, "no OAuth provider found or not configured, continuing without OAuth")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = serverctl.SetDefaultACLS()
|
err = serverctl.SetDefaults()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.FatalLog("error setting default acls: ", err.Error())
|
logger.FatalLog("error setting defaults: ", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if servercfg.IsClientMode() != "off" {
|
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
|
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 SetDefaults() error {
|
||||||
func SetDefaultACLS() 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
|
// upgraded systems will not have ACL's set, which is why we need this function
|
||||||
nodes, err := logic.GetAllNodes()
|
nodes, err := logic.GetAllNodes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for i := range nodes {
|
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))
|
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 != 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 {
|
if _, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID), acls.Allowed); err != nil {
|
||||||
|
Reference in New Issue
Block a user