package controller import ( "encoding/json" "errors" "net/http" "strings" "github.com/gorilla/mux" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/functions" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/servercfg" ) func securityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var errorResponse = models.ErrorResponse{ Code: http.StatusUnauthorized, Message: "W1R3: It's not you it's me.", } var params = mux.Vars(r) bearerToken := r.Header.Get("Authorization") if strings.Contains(r.RequestURI, "/dns") && strings.ToUpper(r.Method) == "GET" && authenticateDNSToken(bearerToken) { // do dns stuff r.Header.Set("user", "nameserver") networks, _ := json.Marshal([]string{ALL_NETWORK_ACCESS}) r.Header.Set("networks", string(networks)) next.ServeHTTP(w, r) return } err, networks, username := SecurityCheck(reqAdmin, params["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 } r.Header.Set("user", username) r.Header.Set("networks", string(networksJson)) next.ServeHTTP(w, r) } } // SecurityCheck - checks token stuff func SecurityCheck(reqAdmin bool, netname string, token string) (error, []string, string) { var hasBearer = true var tokenSplit = strings.Split(token, " ") var authToken = "" if len(tokenSplit) < 2 { hasBearer = false } 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 errors.New("error verifying user token"), nil, username } if !isadmin && reqAdmin { return errors.New("you are unauthorized to access this endpoint"), nil, username } userNetworks = networks if isadmin { userNetworks = []string{ALL_NETWORK_ACCESS} } else { networkexists, err := functions.NetworkExists(netname) if err != nil && !database.IsEmptyRecord(err) { return err, nil, "" } if netname != "" && !networkexists { return errors.New("this network does not exist"), nil, "" } } } else if isMasterAuthenticated { userNetworks = []string{ALL_NETWORK_ACCESS} } if len(userNetworks) == 0 { userNetworks = append(userNetworks, NO_NETWORKS_PRESENT) } return nil, userNetworks, username } // Consider a more secure way of setting master key func authenticateMaster(tokenString string) bool { return tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != "" } //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() } 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.", } var params = mux.Vars(r) var requestedUser = params["username"] if requestedUser != r.Header.Get("user") { returnErrorResponse(w, r, errorResponse) return } next.ServeHTTP(w, r) } }