|
@@ -0,0 +1,143 @@
|
|
|
+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"
|
|
|
+)
|
|
|
+
|
|
|
+//Security check DNS is middleware for every DNS function and just checks to make sure that its the master or dns token calling
|
|
|
+//Only admin should have access to all these network-level actions
|
|
|
+//DNS token should have access to only read functions
|
|
|
+func securityCheck(reqAdmin bool, allowDNSToken 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 allowDNSToken && authenticateDNSToken(bearerToken) {
|
|
|
+ r.Header.Set("user", "nameserver")
|
|
|
+ networks, _ := json.Marshal([]string{ALL_NETWORK_ACCESS})
|
|
|
+ r.Header.Set("networks", string(networks))
|
|
|
+ next.ServeHTTP(w, r)
|
|
|
+ } else {
|
|
|
+ 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)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+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")
|
|
|
+ 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()
|
|
|
+}
|
|
|
+
|
|
|
+//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()
|
|
|
+}
|