Browse Source

allow multiple network roles

abhishek9686 1 year ago
parent
commit
e326c0fd49
6 changed files with 102 additions and 43 deletions
  1. 38 1
      controllers/node.go
  2. 1 1
      controllers/user.go
  3. 30 20
      logic/security.go
  4. 12 8
      logic/user_mgmt.go
  5. 3 0
      migrate/migrate.go
  6. 18 13
      models/user_mgmt.go

+ 38 - 1
controllers/node.go

@@ -280,7 +280,44 @@ func getNetworkNodes(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 {
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	networkRoles := user.NetworkRoles[models.NetworkID(networkName)]
+	for networkRoleID := range networkRoles {
+		userPermTemplate, err := logic.GetRole(networkRoleID)
+		if err != nil {
+			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+			return
+		}
+		if !userPermTemplate.FullAccess {
+			filteredNodes := []models.Node{}
+			if rsrcPerms, ok := userPermTemplate.NetworkLevelAccess[models.RemoteAccessGwRsrc]; ok {
+				if _, ok := rsrcPerms[models.AllRemoteAccessGwRsrcID]; ok {
+					for _, node := range nodes {
+						if node.IsIngressGateway {
+							filteredNodes = append(filteredNodes, node)
+						}
+					}
+				} else {
+					for gwID, scope := range rsrcPerms {
+						if scope.Read {
+							gwNode, err := logic.GetNodeByID(gwID.String())
+							if err == nil && gwNode.IsIngressGateway {
+								filteredNodes = append(filteredNodes, gwNode)
+							}
+						}
+					}
+				}
+			}
+			nodes = filteredNodes
+		} else {
+			break
+		}
+	}
 	// returns all the nodes in JSON/API format
 	apiNodes := logic.GetAllNodesAPI(nodes[:])
 	logger.Log(2, r.Header.Get("user"), "fetched nodes on network", networkName)

+ 1 - 1
controllers/user.go

@@ -228,7 +228,7 @@ func getRole(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("role is required"), "badrequest"))
 		return
 	}
-	role, err := logic.GetRole(rid)
+	role, err := logic.GetRole(models.UserRole(rid))
 	if err != nil {
 		logic.ReturnErrorResponse(w, r, models.ErrorResponse{
 			Code:    http.StatusInternalServerError,

+ 30 - 20
logic/security.go

@@ -49,27 +49,37 @@ func networkPermissionsCheck(username string, r *http.Request) error {
 	}
 	// check if user has scope for target resource
 	// TODO - differentitate between global scope and network scope apis
-	networkPermissionScope, err := GetRole(user.NetworkRoles[models.NetworkID(netID)].String())
-	if err != nil {
-		return errors.New("access denied")
-	}
-	if networkPermissionScope.FullAccess {
-		return nil
-	}
-	rsrcPermissionScope, ok := networkPermissionScope.NetworkLevelAccess[models.RsrcType(targetRsrc)]
-	if !ok {
-		return fmt.Errorf("access denied to %s rsrc", targetRsrc)
-	}
-	if allRsrcsTypePermissionScope, ok := rsrcPermissionScope[models.RsrcID(fmt.Sprintf("all_%s", targetRsrc))]; ok {
-		return checkPermissionScopeWithReqMethod(allRsrcsTypePermissionScope, r.Method)
+	netRoles := user.NetworkRoles[models.NetworkID(netID)]
+	for netRoleID := range netRoles {
+		networkPermissionScope, err := GetRole(netRoleID)
+		if err != nil {
+			continue
+		}
+		if networkPermissionScope.FullAccess {
+			return nil
+		}
+		rsrcPermissionScope, ok := networkPermissionScope.NetworkLevelAccess[models.RsrcType(targetRsrc)]
+		if !ok {
+			continue
+		}
+		if allRsrcsTypePermissionScope, ok := rsrcPermissionScope[models.RsrcID(fmt.Sprintf("all_%s", targetRsrc))]; ok {
+			err = checkPermissionScopeWithReqMethod(allRsrcsTypePermissionScope, r.Method)
+			if err == nil {
+				return nil
+			}
 
+		}
+		if targetRsrcID == "" {
+			continue
+		}
+		if scope, ok := rsrcPermissionScope[models.RsrcID(targetRsrcID)]; ok {
+			err = checkPermissionScopeWithReqMethod(scope, r.Method)
+			if err == nil {
+				return nil
+			}
+		}
 	}
-	if targetRsrcID == "" {
-		return errors.New("target rsrc is missing")
-	}
-	if scope, ok := rsrcPermissionScope[models.RsrcID(targetRsrcID)]; ok {
-		return checkPermissionScopeWithReqMethod(scope, r.Method)
-	}
+
 	return errors.New("access denied")
 }
 
@@ -78,7 +88,7 @@ func globalPermissionsCheck(username string, r *http.Request) error {
 	if err != nil {
 		return err
 	}
-	userRole, err := GetRole(user.PlatformRoleID.String())
+	userRole, err := GetRole(user.PlatformRoleID)
 	if err != nil {
 		return errors.New("access denied")
 	}

+ 12 - 8
logic/user_mgmt.go

@@ -30,7 +30,7 @@ var ServiceUserPermissionTemplate = models.UserRolePermissionTemplate{
 var NetworkAdminPermissionTemplate = models.UserRolePermissionTemplate{
 	ID:                 models.NetworkAdmin,
 	Default:            true,
-	NetworkID:          "netmaker",
+	NetworkID:          "*",
 	FullAccess:         true,
 	NetworkLevelAccess: make(map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope),
 }
@@ -39,7 +39,7 @@ var NetworkUserPermissionTemplate = models.UserRolePermissionTemplate{
 	ID:                  models.NetworkUser,
 	Default:             true,
 	FullAccess:          false,
-	NetworkID:           "netmaker",
+	NetworkID:           "*",
 	DenyDashboardAccess: false,
 	NetworkLevelAccess: map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope{
 		models.RemoteAccessGwRsrc: {
@@ -63,6 +63,8 @@ func UserRolesInit() {
 	database.Insert(SuperAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
 	d, _ = json.Marshal(AdminPermissionTemplate)
 	database.Insert(AdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
+	d, _ = json.Marshal(ServiceUserPermissionTemplate)
+	database.Insert(ServiceUserPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
 	d, _ = json.Marshal(NetworkAdminPermissionTemplate)
 	database.Insert(NetworkAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
 	d, _ = json.Marshal(NetworkUserPermissionTemplate)
@@ -105,9 +107,9 @@ func CreateRole(r models.UserRolePermissionTemplate) error {
 }
 
 // GetRole - fetches role template by id
-func GetRole(roleID string) (models.UserRolePermissionTemplate, error) {
+func GetRole(roleID models.UserRole) (models.UserRolePermissionTemplate, error) {
 	// check if role already exists
-	data, err := database.FetchRecord(database.USER_PERMISSIONS_TABLE_NAME, roleID)
+	data, err := database.FetchRecord(database.USER_PERMISSIONS_TABLE_NAME, roleID.String())
 	if err != nil {
 		return models.UserRolePermissionTemplate{}, errors.New("role already exists")
 	}
@@ -161,10 +163,12 @@ func DeleteRole(rid models.UserRole) error {
 			err = errors.New("active roles cannot be deleted.switch existing users to a new role before deleting")
 			return err
 		}
-		for _, networkRole := range user.NetworkRoles {
-			if networkRole == rid {
-				err = errors.New("active roles cannot be deleted.switch existing users to a new role before deleting")
-				return err
+		for _, networkRoles := range user.NetworkRoles {
+			for networkRole := range networkRoles {
+				if networkRole == rid {
+					err = errors.New("active roles cannot be deleted.switch existing users to a new role before deleting")
+					return err
+				}
 			}
 		}
 	}

+ 3 - 0
migrate/migrate.go

@@ -327,7 +327,10 @@ func syncUsers() {
 				user.PlatformRoleID = models.ServiceUser
 				logic.UpsertUser(user)
 			}
+			if len(user.RemoteGwIDs) > 0 {
+				// define user roles for network
 
+			}
 		}
 	}
 }

+ 18 - 13
models/user_mgmt.go

@@ -16,6 +16,10 @@ func (r RsrcType) String() string {
 	return string(r)
 }
 
+func (rid RsrcID) String() string {
+	return string(rid)
+}
+
 const (
 	HostRsrc           RsrcType = "hosts"
 	RelayRsrc          RsrcType = "relays"
@@ -65,10 +69,11 @@ func (g UserGroupID) String() string {
 }
 
 type RsrcPermissionScope struct {
-	Create bool `json:"create"`
-	Read   bool `json:"read"`
-	Update bool `json:"update"`
-	Delete bool `json:"delete"`
+	Create    bool `json:"create"`
+	Read      bool `json:"read"`
+	Update    bool `json:"update"`
+	Delete    bool `json:"delete"`
+	VPNaccess bool `json:"vpn_access"`
 }
 
 type UserRolePermissionTemplate struct {
@@ -89,15 +94,15 @@ type UserGroup struct {
 
 // User struct - struct for Users
 type User struct {
-	UserName       string                   `json:"username" bson:"username" validate:"min=3,max=40,in_charset|email"`
-	Password       string                   `json:"password" bson:"password" validate:"required,min=5"`
-	IsAdmin        bool                     `json:"isadmin" bson:"isadmin"`
-	IsSuperAdmin   bool                     `json:"issuperadmin"`
-	RemoteGwIDs    map[string]struct{}      `json:"remote_gw_ids"`
-	UserGroups     map[UserGroupID]struct{} `json:"user_group_ids"`
-	PlatformRoleID UserRole                 `json:"platform_role_id"`
-	NetworkRoles   map[NetworkID]UserRole   `json:"network_roles"`
-	LastLoginTime  time.Time                `json:"last_login_time"`
+	UserName       string                              `json:"username" bson:"username" validate:"min=3,max=40,in_charset|email"`
+	Password       string                              `json:"password" bson:"password" validate:"required,min=5"`
+	IsAdmin        bool                                `json:"isadmin" bson:"isadmin"`
+	IsSuperAdmin   bool                                `json:"issuperadmin"`
+	RemoteGwIDs    map[string]struct{}                 `json:"remote_gw_ids"`
+	UserGroups     map[UserGroupID]struct{}            `json:"user_group_ids"`
+	PlatformRoleID UserRole                            `json:"platform_role_id"`
+	NetworkRoles   map[NetworkID]map[UserRole]struct{} `json:"network_roles"`
+	LastLoginTime  time.Time                           `json:"last_login_time"`
 }
 
 // ReturnUser - return user struct