Bläddra i källkod

NM-57: Graphs API Forbidden for Platform User (#3577)

* fix(go): permissions for network graph;

* fix(go): allow platform user to get network graph;

* feat(go): allow read only access to host resource to network users.

* feat(go): remove specific check for hosts resource.
Vishal Dalwadi 1 månad sedan
förälder
incheckning
996410fc61

+ 5 - 0
controllers/middleware.go

@@ -60,6 +60,11 @@ func userMiddleWare(handler http.Handler) http.Handler {
 		if strings.Contains(route, "networks") {
 			r.Header.Set("TARGET_RSRC", models.NetworkRsrc.String())
 		}
+		// check 'graph' after 'networks', otherwise the
+		// header will be overwritten.
+		if strings.Contains(route, "graph") {
+			r.Header.Set("TARGET_RSRC", models.HostRsrc.String())
+		}
 		if strings.Contains(route, "acls") {
 			r.Header.Set("TARGET_RSRC", models.AclRsrc.String())
 		}

+ 32 - 0
logic/user_mgmt.go

@@ -136,6 +136,38 @@ func ListPlatformRoles() ([]models.UserRolePermissionTemplate, error) {
 	return userRoles, nil
 }
 
+func GetAllRsrcIDForRsrc(rsrc models.RsrcType) models.RsrcID {
+	switch rsrc {
+	case models.HostRsrc:
+		return models.AllHostRsrcID
+	case models.RelayRsrc:
+		return models.AllRelayRsrcID
+	case models.RemoteAccessGwRsrc:
+		return models.AllRemoteAccessGwRsrcID
+	case models.ExtClientsRsrc:
+		return models.AllExtClientsRsrcID
+	case models.InetGwRsrc:
+		return models.AllInetGwRsrcID
+	case models.EgressGwRsrc:
+		return models.AllEgressGwRsrcID
+	case models.NetworkRsrc:
+		return models.AllNetworkRsrcID
+	case models.EnrollmentKeysRsrc:
+		return models.AllEnrollmentKeysRsrcID
+	case models.UserRsrc:
+		return models.AllUserRsrcID
+	case models.DnsRsrc:
+		return models.AllDnsRsrcID
+	case models.FailOverRsrc:
+		return models.AllFailOverRsrcID
+	case models.AclRsrc:
+		return models.AllAclsRsrcID
+	case models.TagRsrc:
+		return models.AllTagsRsrcID
+	}
+	return ""
+}
+
 func userRolesInit() {
 	d, _ := json.Marshal(SuperAdminPermissionTemplate)
 	database.Insert(SuperAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)

+ 0 - 19
pro/controllers/metrics.go

@@ -20,7 +20,6 @@ func MetricHandlers(r *mux.Router) {
 	r.HandleFunc("/api/metrics/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkNodesMetrics))).Methods(http.MethodGet)
 	r.HandleFunc("/api/metrics", logic.SecurityCheck(true, http.HandlerFunc(getAllMetrics))).Methods(http.MethodGet)
 	r.HandleFunc("/api/metrics-ext/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkExtMetrics))).Methods(http.MethodGet)
-	r.HandleFunc("/api/v1/graph/{network}", logic.SecurityCheck(true, http.HandlerFunc(graph))).Methods(http.MethodGet)
 }
 
 // get the metrics of a given node
@@ -166,21 +165,3 @@ func getAllMetrics(w http.ResponseWriter, r *http.Request) {
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(networkMetrics)
 }
-
-func graph(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "application/json")
-
-	var params = mux.Vars(r)
-	network := params["network"]
-	networkNodes, err := logic.GetNetworkNodes(network)
-	if err != nil {
-		logger.Log(1, r.Header.Get("user"), "failed to get network nodes", err.Error())
-		return
-	}
-	networkNodes = logic.AddStaticNodestoList(networkNodes)
-	// return all the nodes in JSON/API format
-	apiNodes := logic.GetAllNodesAPIWithLocation(networkNodes[:])
-	logic.SortApiNodes(apiNodes[:])
-	w.WriteHeader(http.StatusOK)
-	json.NewEncoder(w).Encode(apiNodes)
-}

+ 31 - 0
pro/controllers/networks.go

@@ -0,0 +1,31 @@
+package controllers
+
+import (
+	"encoding/json"
+	"github.com/gorilla/mux"
+	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/logic"
+	"net/http"
+)
+
+func NetworkHandlers(r *mux.Router) {
+	r.HandleFunc("/api/v1/networks/{network}/graph", logic.SecurityCheck(true, http.HandlerFunc(getNetworkGraph))).Methods(http.MethodGet)
+}
+
+func getNetworkGraph(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+
+	var params = mux.Vars(r)
+	network := params["network"]
+	networkNodes, err := logic.GetNetworkNodes(network)
+	if err != nil {
+		logger.Log(1, r.Header.Get("user"), "failed to get network nodes", err.Error())
+		return
+	}
+	networkNodes = logic.AddStaticNodestoList(networkNodes)
+	// return all the nodes in JSON/API format
+	apiNodes := logic.GetAllNodesAPIWithLocation(networkNodes[:])
+	logic.SortApiNodes(apiNodes[:])
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(apiNodes)
+}

+ 1 - 0
pro/initialize.go

@@ -35,6 +35,7 @@ func InitPro() {
 		proControllers.RacHandlers,
 		proControllers.EventHandlers,
 		proControllers.TagHandlers,
+		proControllers.NetworkHandlers,
 	)
 	controller.ListRoles = proControllers.ListRoles
 	logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {

+ 1 - 12
pro/logic/security.go

@@ -115,13 +115,10 @@ func checkNetworkAccessPermissions(netRoleID models.UserRoleID, username, reqSco
 		return nil
 	}
 	rsrcPermissionScope, ok := networkPermissionScope.NetworkLevelAccess[models.RsrcType(targetRsrc)]
-	if targetRsrc == models.HostRsrc.String() && !ok {
-		rsrcPermissionScope, ok = networkPermissionScope.NetworkLevelAccess[models.RemoteAccessGwRsrc]
-	}
 	if !ok {
 		return errors.New("access denied")
 	}
-	if allRsrcsTypePermissionScope, ok := rsrcPermissionScope[models.RsrcID(fmt.Sprintf("all_%s", targetRsrc))]; ok {
+	if allRsrcsTypePermissionScope, ok := rsrcPermissionScope[logic.GetAllRsrcIDForRsrc(models.RsrcType(targetRsrc))]; ok {
 		// handle extclient apis here
 		if models.RsrcType(targetRsrc) == models.ExtClientsRsrc && allRsrcsTypePermissionScope.SelfOnly && targetRsrcID != "" {
 			extclient, err := logic.GetExtClient(targetRsrcID, netID)
@@ -138,14 +135,6 @@ func checkNetworkAccessPermissions(netRoleID models.UserRoleID, username, reqSco
 		}
 
 	}
-	if targetRsrc == models.HostRsrc.String() {
-		if allRsrcsTypePermissionScope, ok := rsrcPermissionScope[models.RsrcID(fmt.Sprintf("all_%s", models.RemoteAccessGwRsrc))]; ok {
-			err = checkPermissionScopeWithReqMethod(allRsrcsTypePermissionScope, reqScope)
-			if err == nil {
-				return nil
-			}
-		}
-	}
 	if targetRsrcID == "" {
 		return errors.New("target rsrc id is empty")
 	}

+ 10 - 1
pro/logic/user_mgmt.go

@@ -53,6 +53,11 @@ var NetworkUserAllPermissionTemplate = models.UserRolePermissionTemplate{
 	FullAccess: false,
 	NetworkID:  models.AllNetworks,
 	NetworkLevelAccess: map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope{
+		models.HostRsrc: {
+			models.AllHostRsrcID: models.RsrcPermissionScope{
+				Read: true,
+			},
+		},
 		models.RemoteAccessGwRsrc: {
 			models.AllRemoteAccessGwRsrcID: models.RsrcPermissionScope{
 				Read:      true,
@@ -114,7 +119,6 @@ func UserRolesInit() {
 	database.Insert(NetworkAdminAllPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
 	d, _ = json.Marshal(NetworkUserAllPermissionTemplate)
 	database.Insert(NetworkUserAllPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
-
 }
 
 func UserGroupsInit() {
@@ -170,6 +174,11 @@ func CreateDefaultNetworkRolesAndGroups(netID models.NetworkID) {
 		NetworkID:           netID,
 		DenyDashboardAccess: false,
 		NetworkLevelAccess: map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope{
+			models.HostRsrc: {
+				models.AllHostRsrcID: models.RsrcPermissionScope{
+					Read: true,
+				},
+			},
 			models.RemoteAccessGwRsrc: {
 				models.AllRemoteAccessGwRsrcID: models.RsrcPermissionScope{
 					Read:      true,