瀏覽代碼

filter nodes and hosts based on user network access

abhishek9686 1 年之前
父節點
當前提交
16874d4992
共有 10 個文件被更改,包括 197 次插入48 次删除
  1. 40 3
      controllers/hosts.go
  2. 2 0
      controllers/middleware.go
  3. 2 1
      controllers/network.go
  4. 12 0
      controllers/node.go
  5. 5 4
      controllers/user.go
  6. 2 2
      logic/auth.go
  7. 52 0
      logic/nodes.go
  8. 4 0
      logic/security.go
  9. 67 36
      logic/user_mgmt.go
  10. 11 2
      pro/auth/google.go

+ 40 - 3
controllers/hosts.go

@@ -64,12 +64,49 @@ func upgradeHost(w http.ResponseWriter, r *http.Request) {
 //			Responses:
 //				200: apiHostSliceResponse
 func getHosts(w http.ResponseWriter, r *http.Request) {
-	currentHosts, err := logic.GetAllHosts()
+
+	currentHosts := []models.Host{}
+	username := r.Header.Get("user")
+	user, err := logic.GetUser(username)
+	if err != nil {
+		return
+	}
+	userPlatformRole, err := logic.GetRole(user.PlatformRoleID)
 	if err != nil {
-		logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
-		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
+
+	if !userPlatformRole.FullAccess {
+		nodes, err := logic.GetAllNodes()
+		if err != nil {
+			logger.Log(0, "error fetching all nodes info: ", err.Error())
+			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+			return
+		}
+		filteredNodes := logic.GetFilteredNodesByUserAccess(*user, nodes)
+		if len(filteredNodes) > 0 {
+			currentHostsMap, err := logic.GetHostsMap()
+			if err != nil {
+				logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
+				logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+				return
+			}
+			for _, node := range filteredNodes {
+				if host, ok := currentHostsMap[node.HostID.String()]; ok {
+					currentHosts = append(currentHosts, host)
+				}
+			}
+
+		}
+	} else {
+		currentHosts, err = logic.GetAllHosts()
+		if err != nil {
+			logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
+			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+			return
+		}
+	}
+
 	apiHosts := logic.GetAllHostsAPI(currentHosts[:])
 	logger.Log(2, r.Header.Get("user"), "fetched all hosts")
 	logic.SortApiHosts(apiHosts[:])

+ 2 - 0
controllers/middleware.go

@@ -5,6 +5,7 @@ import (
 	"strings"
 
 	"github.com/gorilla/mux"
+	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/models"
 )
 
@@ -78,6 +79,7 @@ func userMiddleWare(handler http.Handler) http.Handler {
 			r.Header.Get("TARGET_RSRC") == models.UserRsrc.String()) {
 			r.Header.Set("IS_GLOBAL_ACCESS", "yes")
 		}
+		logger.Log(0, "URL ------> ", r.URL.String())
 		handler.ServeHTTP(w, r)
 	})
 }

+ 2 - 1
controllers/network.go

@@ -392,7 +392,7 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, errtype))
 		return
 	}
-
+	go logic.DeleteNetworkRoles(network)
 	logger.Log(1, r.Header.Get("user"), "deleted network", network)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode("success")
@@ -467,6 +467,7 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
+	logic.CreateDefaultNetworkRoles(network.NetID)
 	go func() {
 		defaultHosts := logic.GetDefaultHosts()
 		for i := range defaultHosts {

+ 12 - 0
controllers/node.go

@@ -365,6 +365,18 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
+	username := r.Header.Get("user")
+	user, err := logic.GetUser(username)
+	if err != nil {
+		return
+	}
+	userPlatformRole, err := logic.GetRole(user.PlatformRoleID)
+	if err != nil {
+		return
+	}
+	if !userPlatformRole.FullAccess {
+		nodes = logic.GetFilteredNodesByUserAccess(*user, nodes)
+	}
 
 	// return all the nodes in JSON/API format
 	apiNodes := logic.GetAllNodesAPI(nodes[:])

+ 5 - 4
controllers/user.go

@@ -1124,6 +1124,7 @@ func userInviteSignUp(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 		user.PlatformRoleID = userG.PlatformRole
+		user.UserGroups = make(map[models.UserGroupID]struct{})
 		user.UserGroups[inviteGroupID] = struct{}{}
 	}
 	if user.PlatformRoleID == "" {
@@ -1138,6 +1139,7 @@ func userInviteSignUp(w http.ResponseWriter, r *http.Request) {
 	// delete invite
 	logic.DeleteUserInvite(email)
 	logic.DeletePendingUser(email)
+	w.Header().Set("Access-Control-Allow-Origin", "*")
 	logic.ReturnSuccessResponse(w, r, "created user successfully "+email)
 }
 
@@ -1273,11 +1275,10 @@ func listUserInvites(w http.ResponseWriter, r *http.Request) {
 //			Responses:
 //				200: ReturnSuccessResponse
 func deleteUserInvite(w http.ResponseWriter, r *http.Request) {
-	var params = mux.Vars(r)
-	username := params["invitee_email"]
-	err := logic.DeleteUserInvite(username)
+	email, _ := url.QueryUnescape(r.URL.Query().Get("invitee_email"))
+	err := logic.DeleteUserInvite(email)
 	if err != nil {
-		logger.Log(0, "failed to delete user invite: ", username, err.Error())
+		logger.Log(0, "failed to delete user invite: ", email, err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}

+ 2 - 2
logic/auth.go

@@ -119,8 +119,8 @@ func CreateUser(user *models.User) error {
 	if len(user.UserGroups) == 0 {
 		user.UserGroups = make(map[models.UserGroupID]struct{})
 	}
-	tokenString, _ := CreateUserJWT(user.UserName, user.PlatformRoleID)
-	if tokenString == "" {
+	_, err = CreateUserJWT(user.UserName, user.PlatformRoleID)
+	if err != nil {
 		logger.Log(0, "failed to generate token", err.Error())
 		return err
 	}

+ 52 - 0
logic/nodes.go

@@ -674,3 +674,55 @@ func GetAllFailOvers() ([]models.Node, error) {
 	}
 	return igs, nil
 }
+
+func GetFilteredNodesByUserAccess(user models.User, nodes []models.Node) (filteredNodes []models.Node) {
+
+	nodesMap := make(map[string]struct{})
+	allNetworkRoles := []models.UserRole{}
+	for _, netRoles := range user.NetworkRoles {
+		for netRoleI := range netRoles {
+			allNetworkRoles = append(allNetworkRoles, netRoleI)
+		}
+	}
+	for _, networkRoleID := range allNetworkRoles {
+		userPermTemplate, err := GetRole(networkRoleID)
+		if err != nil {
+			return
+		}
+		networkNodes := GetNetworkNodesMemory(nodes, userPermTemplate.NetworkID)
+		if userPermTemplate.FullAccess {
+			for _, node := range networkNodes {
+				nodesMap[node.ID.String()] = struct{}{}
+			}
+			filteredNodes = append(filteredNodes, networkNodes...)
+			continue
+		}
+		if rsrcPerms, ok := userPermTemplate.NetworkLevelAccess[models.RemoteAccessGwRsrc]; ok {
+			if _, ok := rsrcPerms[models.AllRemoteAccessGwRsrcID]; ok {
+				for _, node := range networkNodes {
+					if _, ok := nodesMap[node.ID.String()]; ok {
+						continue
+					}
+					if node.IsIngressGateway {
+						nodesMap[node.ID.String()] = struct{}{}
+						filteredNodes = append(filteredNodes, node)
+					}
+				}
+			} else {
+				for gwID, scope := range rsrcPerms {
+					if _, ok := nodesMap[gwID.String()]; ok {
+						continue
+					}
+					if scope.Read {
+						gwNode, err := GetNodeByID(gwID.String())
+						if err == nil && gwNode.IsIngressGateway {
+							filteredNodes = append(filteredNodes, gwNode)
+						}
+					}
+				}
+			}
+		}
+
+	}
+	return
+}

+ 4 - 0
logic/security.go

@@ -165,6 +165,9 @@ func globalPermissionsCheck(username string, r *http.Request) error {
 	if targetRsrc == models.MetricRsrc.String() {
 		return nil
 	}
+	if targetRsrc == models.HostRsrc.String() && r.Method == http.MethodGet && targetRsrcID == "" {
+		return nil
+	}
 	if targetRsrc == models.UserRsrc.String() && username == targetRsrcID && (r.Method != http.MethodDelete) {
 		return nil
 	}
@@ -229,6 +232,7 @@ func SecurityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
 		w.Header().Set("TARGET_RSRC_ID", r.Header.Get("TARGET_RSRC_ID"))
 		w.Header().Set("RSRC_TYPE", r.Header.Get("RSRC_TYPE"))
 		w.Header().Set("IS_GLOBAL_ACCESS", r.Header.Get("IS_GLOBAL_ACCESS"))
+		w.Header().Set("Access-Control-Allow-Origin", "*")
 		if err != nil {
 			w.Header().Set("ACCESS_PERM", err.Error())
 			ReturnErrorResponse(w, r, FormatError(err, "forbidden"))

+ 67 - 36
logic/user_mgmt.go

@@ -36,39 +36,6 @@ var PlatformUserUserPermissionTemplate = models.UserRolePermissionTemplate{
 	FullAccess: false,
 }
 
-var NetworkAdminPermissionTemplate = models.UserRolePermissionTemplate{
-	ID:                 models.NetworkAdmin,
-	Default:            true,
-	NetworkID:          "netmaker",
-	FullAccess:         true,
-	NetworkLevelAccess: make(map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope),
-}
-
-var NetworkUserPermissionTemplate = models.UserRolePermissionTemplate{
-	ID:                  models.NetworkUser,
-	Default:             true,
-	FullAccess:          false,
-	NetworkID:           "netmaker",
-	DenyDashboardAccess: false,
-	NetworkLevelAccess: map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope{
-		models.RemoteAccessGwRsrc: {
-			models.AllRemoteAccessGwRsrcID: models.RsrcPermissionScope{
-				Read:      true,
-				VPNaccess: true,
-			},
-		},
-		models.ExtClientsRsrc: {
-			models.AllExtClientsRsrcID: models.RsrcPermissionScope{
-				Read:     true,
-				Create:   true,
-				Update:   true,
-				Delete:   true,
-				SelfOnly: true,
-			},
-		},
-	},
-}
-
 func UserRolesInit() {
 	d, _ := json.Marshal(SuperAdminPermissionTemplate)
 	database.Insert(SuperAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
@@ -78,12 +45,76 @@ func UserRolesInit() {
 	database.Insert(ServiceUserPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
 	d, _ = json.Marshal(PlatformUserUserPermissionTemplate)
 	database.Insert(PlatformUserUserPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
-	d, _ = json.Marshal(NetworkAdminPermissionTemplate)
+
+}
+
+func CreateDefaultNetworkRoles(netID string) {
+	var NetworkAdminPermissionTemplate = models.UserRolePermissionTemplate{
+		ID:                 models.UserRole(fmt.Sprintf("%s_%s", netID, models.NetworkAdmin)),
+		Default:            false,
+		NetworkID:          netID,
+		FullAccess:         true,
+		NetworkLevelAccess: make(map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope),
+	}
+
+	var NetworkUserPermissionTemplate = models.UserRolePermissionTemplate{
+		ID:                  models.UserRole(fmt.Sprintf("%s_%s", netID, models.NetworkUser)),
+		Default:             false,
+		FullAccess:          false,
+		NetworkID:           netID,
+		DenyDashboardAccess: false,
+		NetworkLevelAccess: map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope{
+			models.RemoteAccessGwRsrc: {
+				models.AllRemoteAccessGwRsrcID: models.RsrcPermissionScope{
+					Read:      true,
+					VPNaccess: true,
+				},
+			},
+			models.ExtClientsRsrc: {
+				models.AllExtClientsRsrcID: models.RsrcPermissionScope{
+					Read:     true,
+					Create:   true,
+					Update:   true,
+					Delete:   true,
+					SelfOnly: true,
+				},
+			},
+		},
+	}
+	d, _ := json.Marshal(NetworkAdminPermissionTemplate)
 	database.Insert(NetworkAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
 	d, _ = json.Marshal(NetworkUserPermissionTemplate)
 	database.Insert(NetworkUserPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
 }
 
+func DeleteNetworkRoles(netID string) {
+	users, err := GetUsersDB()
+	if err != nil {
+		return
+	}
+	for _, user := range users {
+		if _, ok := user.NetworkRoles[models.NetworkID(netID)]; ok {
+			delete(user.NetworkRoles, models.NetworkID(netID))
+			UpsertUser(user)
+		}
+
+	}
+	userGs, _ := ListUserGroups()
+	for _, userGI := range userGs {
+		if _, ok := userGI.NetworkRoles[models.NetworkID(netID)]; ok {
+			delete(userGI.NetworkRoles, models.NetworkID(netID))
+			UpdateUserGroup(userGI)
+		}
+	}
+
+	roles, _ := ListRoles()
+	for _, role := range roles {
+		if role.NetworkID == netID {
+			DeleteRole(role.ID)
+		}
+	}
+}
+
 // ListRoles - lists user roles permission templates
 func ListRoles() ([]models.UserRolePermissionTemplate, error) {
 	data, err := database.FetchRecords(database.USER_PERMISSIONS_TABLE_NAME)
@@ -274,12 +305,12 @@ func ValidateUpdateGroupReq(g models.UserGroup) error {
 	for networkID := range g.NetworkRoles {
 		userRolesMap := g.NetworkRoles[networkID]
 		for roleID := range userRolesMap {
-			_, err := GetRole(roleID)
+			netRole, err := GetRole(roleID)
 			if err != nil {
 				err = fmt.Errorf("invalid network role")
 				return err
 			}
-			if role.NetworkID == "" {
+			if netRole.NetworkID == "" {
 				return errors.New("platform role cannot be used as network role")
 			}
 		}

+ 11 - 2
pro/auth/google.go

@@ -46,7 +46,7 @@ func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
 		handleOauthNotConfigured(w)
 		return
 	}
-
+	logger.Log(0, "Setting OAuth State ", oauth_state_string)
 	if err := logic.SetState(oauth_state_string); err != nil {
 		handleOauthNotConfigured(w)
 		return
@@ -59,7 +59,7 @@ func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
 func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
 
 	var rState, rCode = getStateAndCode(r)
-
+	logger.Log(0, "Fetched OAuth State ", rState)
 	var content, err = getGoogleUserInfo(rState, rCode)
 	if err != nil {
 		logger.Log(1, "error when getting user info from google:", err.Error())
@@ -70,26 +70,31 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
 		handleOauthNotConfigured(w)
 		return
 	}
+	logger.Log(0, "CALLBACK ----> 1")
 	if !isEmailAllowed(content.Email) {
 		handleOauthUserNotAllowedToSignUp(w)
 		return
 	}
+	logger.Log(0, "CALLBACK ----> 2")
 	var inviteExists bool
 	// check if invite exists for User
 	in, err := logic.GetUserInvite(content.Email)
 	if err == nil {
 		inviteExists = true
 	}
+	logger.Log(0, fmt.Sprintf("CALLBACK ----> 3  %v", inviteExists))
 	// check if user approval is already pending
 	if !inviteExists && logic.IsPendingUser(content.Email) {
 		handleOauthUserSignUpApprovalPending(w)
 		return
 	}
+	logger.Log(0, "CALLBACK ----> 4")
 	_, err = logic.GetUser(content.Email)
 	if err != nil {
 		if database.IsEmptyRecord(err) { // user must not exist, so try to make one
 			if inviteExists {
 				// create user
+				logger.Log(0, "CALLBACK ----> 4.0")
 				var newPass, fetchErr = auth.FetchPassValue("")
 				if fetchErr != nil {
 					logic.ReturnErrorResponse(w, r, logic.FormatError(fetchErr, "internal"))
@@ -99,6 +104,7 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
 					UserName: content.Email,
 					Password: newPass,
 				}
+				logger.Log(0, "CALLBACK ----> 4.1")
 				for _, inviteGroupID := range in.Groups {
 					userG, err := logic.GetUserGroup(inviteGroupID)
 					if err != nil {
@@ -106,8 +112,10 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
 						return
 					}
 					user.PlatformRoleID = userG.PlatformRole
+					user.UserGroups = make(map[models.UserGroupID]struct{})
 					user.UserGroups[inviteGroupID] = struct{}{}
 				}
+				logger.Log(0, "CALLBACK ----> 5")
 				if user.PlatformRoleID == "" {
 					user.PlatformRoleID = models.ServiceUser
 				}
@@ -134,6 +142,7 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 	}
+	logger.Log(0, "CALLBACK ----> 6")
 	user, err := logic.GetUser(content.Email)
 	if err != nil {
 		logger.Log(0, "error fetching user: ", err.Error())