| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681 |
- package logic
- import (
- "encoding/json"
- "errors"
- "fmt"
- "time"
- "github.com/gravitl/netmaker/database"
- "github.com/gravitl/netmaker/logic"
- "github.com/gravitl/netmaker/models"
- "github.com/gravitl/netmaker/mq"
- "github.com/gravitl/netmaker/servercfg"
- "golang.org/x/exp/slog"
- )
- var ServiceUserPermissionTemplate = models.UserRolePermissionTemplate{
- ID: models.ServiceUser,
- UiName: "Network User",
- Default: true,
- FullAccess: false,
- DenyDashboardAccess: true,
- }
- var PlatformUserUserPermissionTemplate = models.UserRolePermissionTemplate{
- ID: models.PlatformUser,
- UiName: "Network Admin",
- Default: true,
- FullAccess: false,
- }
- func UserRolesInit() {
- d, _ := json.Marshal(logic.SuperAdminPermissionTemplate)
- database.Insert(logic.SuperAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
- d, _ = json.Marshal(logic.AdminPermissionTemplate)
- database.Insert(logic.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(PlatformUserUserPermissionTemplate)
- database.Insert(PlatformUserUserPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
- }
- func ValidateCreateRoleReq(userRole *models.UserRolePermissionTemplate) error {
- // check if role exists with this id
- _, err := logic.GetRole(userRole.ID)
- if err == nil {
- return fmt.Errorf("role with id `%s` exists already", userRole.ID.String())
- }
- if len(userRole.NetworkLevelAccess) > 0 {
- for rsrcType := range userRole.NetworkLevelAccess {
- if _, ok := models.RsrcTypeMap[rsrcType]; !ok {
- return errors.New("invalid rsrc type " + rsrcType.String())
- }
- if rsrcType == models.RemoteAccessGwRsrc {
- userRsrcPermissions := userRole.NetworkLevelAccess[models.RemoteAccessGwRsrc]
- var vpnAccess bool
- for _, scope := range userRsrcPermissions {
- if scope.VPNaccess {
- vpnAccess = true
- break
- }
- }
- if vpnAccess {
- userRole.NetworkLevelAccess[models.ExtClientsRsrc] = map[models.RsrcID]models.RsrcPermissionScope{
- models.AllExtClientsRsrcID: {
- Read: true,
- Create: true,
- Update: true,
- Delete: true,
- SelfOnly: true,
- },
- }
- }
- }
- }
- }
- return nil
- }
- func ValidateUpdateRoleReq(userRole *models.UserRolePermissionTemplate) error {
- roleInDB, err := logic.GetRole(userRole.ID)
- if err != nil {
- return err
- }
- if roleInDB.Default {
- return errors.New("cannot update default role")
- }
- if len(userRole.NetworkLevelAccess) > 0 {
- for rsrcType := range userRole.NetworkLevelAccess {
- if _, ok := models.RsrcTypeMap[rsrcType]; !ok {
- return errors.New("invalid rsrc type " + rsrcType.String())
- }
- if rsrcType == models.RemoteAccessGwRsrc {
- userRsrcPermissions := userRole.NetworkLevelAccess[models.RemoteAccessGwRsrc]
- var vpnAccess bool
- for _, scope := range userRsrcPermissions {
- if scope.VPNaccess {
- vpnAccess = true
- break
- }
- }
- if vpnAccess {
- userRole.NetworkLevelAccess[models.ExtClientsRsrc] = map[models.RsrcID]models.RsrcPermissionScope{
- models.AllExtClientsRsrcID: {
- Read: true,
- Create: true,
- Update: true,
- Delete: true,
- SelfOnly: true,
- },
- }
- }
- }
- }
- }
- return nil
- }
- // CreateRole - inserts new role into DB
- func CreateRole(r models.UserRolePermissionTemplate) error {
- // check if role already exists
- if r.ID.String() == "" {
- return errors.New("role id cannot be empty")
- }
- _, err := database.FetchRecord(database.USER_PERMISSIONS_TABLE_NAME, r.ID.String())
- if err == nil {
- return errors.New("role already exists")
- }
- d, err := json.Marshal(r)
- if err != nil {
- return err
- }
- return database.Insert(r.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
- }
- // UpdateRole - updates role template
- func UpdateRole(r models.UserRolePermissionTemplate) error {
- if r.ID.String() == "" {
- return errors.New("role id cannot be empty")
- }
- _, err := database.FetchRecord(database.USER_PERMISSIONS_TABLE_NAME, r.ID.String())
- if err != nil {
- return err
- }
- d, err := json.Marshal(r)
- if err != nil {
- return err
- }
- return database.Insert(r.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)
- }
- // DeleteRole - deletes user role
- func DeleteRole(rid models.UserRoleID, force bool) error {
- if rid.String() == "" {
- return errors.New("role id cannot be empty")
- }
- users, err := logic.GetUsersDB()
- if err != nil {
- return err
- }
- role, err := logic.GetRole(rid)
- if err != nil {
- return err
- }
- for _, user := range users {
- for userG := range user.UserGroups {
- _, err := GetUserGroup(userG)
- if err == nil {
- }
- }
- if user.PlatformRoleID == rid {
- err = errors.New("active roles cannot be deleted.switch existing users to a new role before deleting")
- return err
- }
- }
- return database.DeleteRecord(database.USER_PERMISSIONS_TABLE_NAME, role.ID.String())
- }
- func ValidateCreateGroupReq(g models.UserGroup) error {
- // check if network roles are valid
- for _, roleMap := range g.NetworkRoles {
- for roleID := range roleMap {
- _, err := logic.GetRole(roleID)
- if err != nil {
- return fmt.Errorf("invalid network role %s", roleID)
- }
- }
- }
- return nil
- }
- func ValidateUpdateGroupReq(g models.UserGroup) error {
- for networkID := range g.NetworkRoles {
- userRolesMap := g.NetworkRoles[networkID]
- for roleID := range userRolesMap {
- _, err := logic.GetRole(roleID)
- if err != nil {
- err = fmt.Errorf("invalid network role")
- return err
- }
- }
- }
- return nil
- }
- // CreateUserGroup - creates new user group
- func CreateUserGroup(g models.UserGroup) error {
- // check if role already exists
- if g.ID == "" {
- return errors.New("group id cannot be empty")
- }
- _, err := database.FetchRecord(database.USER_GROUPS_TABLE_NAME, g.ID.String())
- if err == nil {
- return errors.New("group already exists")
- }
- d, err := json.Marshal(g)
- if err != nil {
- return err
- }
- return database.Insert(g.ID.String(), string(d), database.USER_GROUPS_TABLE_NAME)
- }
- // GetUserGroup - fetches user group
- func GetUserGroup(gid models.UserGroupID) (models.UserGroup, error) {
- d, err := database.FetchRecord(database.USER_GROUPS_TABLE_NAME, gid.String())
- if err != nil {
- return models.UserGroup{}, err
- }
- var ug models.UserGroup
- err = json.Unmarshal([]byte(d), &ug)
- if err != nil {
- return ug, err
- }
- return ug, nil
- }
- // ListUserGroups - lists user groups
- func ListUserGroups() ([]models.UserGroup, error) {
- data, err := database.FetchRecords(database.USER_GROUPS_TABLE_NAME)
- if err != nil && !database.IsEmptyRecord(err) {
- return []models.UserGroup{}, err
- }
- userGroups := []models.UserGroup{}
- for _, dataI := range data {
- userGroup := models.UserGroup{}
- err := json.Unmarshal([]byte(dataI), &userGroup)
- if err != nil {
- continue
- }
- userGroups = append(userGroups, userGroup)
- }
- return userGroups, nil
- }
- // UpdateUserGroup - updates new user group
- func UpdateUserGroup(g models.UserGroup) error {
- // check if group exists
- if g.ID == "" {
- return errors.New("group id cannot be empty")
- }
- _, err := database.FetchRecord(database.USER_GROUPS_TABLE_NAME, g.ID.String())
- if err != nil {
- return err
- }
- d, err := json.Marshal(g)
- if err != nil {
- return err
- }
- return database.Insert(g.ID.String(), string(d), database.USER_GROUPS_TABLE_NAME)
- }
- // DeleteUserGroup - deletes user group
- func DeleteUserGroup(gid models.UserGroupID) error {
- users, err := logic.GetUsersDB()
- if err != nil {
- return err
- }
- for _, user := range users {
- delete(user.UserGroups, gid)
- logic.UpsertUser(user)
- }
- return database.DeleteRecord(database.USER_GROUPS_TABLE_NAME, gid.String())
- }
- func HasNetworkRsrcScope(permissionTemplate models.UserRolePermissionTemplate, netid string, rsrcType models.RsrcType, rsrcID models.RsrcID, op string) bool {
- if permissionTemplate.FullAccess {
- return true
- }
- rsrcScope, ok := permissionTemplate.NetworkLevelAccess[rsrcType]
- if !ok {
- return false
- }
- _, ok = rsrcScope[rsrcID]
- return ok
- }
- func GetUserRAGNodesV1(user models.User) (gws map[string]models.Node) {
- gws = make(map[string]models.Node)
- nodes, err := logic.GetAllNodes()
- if err != nil {
- return
- }
- if user.IsAdmin || user.IsSuperAdmin {
- for _, node := range nodes {
- if node.IsIngressGateway {
- gws[node.ID.String()] = node
- }
- }
- }
- tagNodesMap := logic.GetTagMapWithNodes()
- accessPolices := logic.ListUserPolicies(user)
- for _, policyI := range accessPolices {
- if !policyI.Enabled {
- continue
- }
- for _, dstI := range policyI.Dst {
- if dstI.Value == "*" {
- networkNodes := logic.GetNetworkNodesMemory(nodes, policyI.NetworkID.String())
- for _, node := range networkNodes {
- if node.IsIngressGateway {
- gws[node.ID.String()] = node
- }
- }
- }
- if nodes, ok := tagNodesMap[models.TagID(dstI.Value)]; ok {
- for _, node := range nodes {
- if node.IsIngressGateway {
- gws[node.ID.String()] = node
- }
- }
- }
- }
- }
- return
- }
- func GetFilteredNodesByUserAccess(user models.User, nodes []models.Node) (filteredNodes []models.Node) {
- nodesMap := make(map[string]struct{})
- allNetworkRoles := make(map[models.UserRoleID]struct{})
- defer func() {
- filteredNodes = logic.AddStaticNodestoList(filteredNodes)
- }()
- if len(user.UserGroups) > 0 {
- for userGID := range user.UserGroups {
- userG, err := GetUserGroup(userGID)
- if err == nil {
- if len(userG.NetworkRoles) > 0 {
- if _, ok := userG.NetworkRoles[models.AllNetworks]; ok {
- filteredNodes = nodes
- return
- }
- for _, netRoles := range userG.NetworkRoles {
- for netRoleI := range netRoles {
- allNetworkRoles[netRoleI] = struct{}{}
- }
- }
- }
- }
- }
- }
- for networkRoleID := range allNetworkRoles {
- userPermTemplate, err := logic.GetRole(networkRoleID)
- if err != nil {
- continue
- }
- // TODO: MIGRATE
- networkNodes := logic.GetNetworkNodesMemory(nodes, "netmaker")
- if userPermTemplate.FullAccess {
- for _, node := range networkNodes {
- if _, ok := nodesMap[node.ID.String()]; ok {
- continue
- }
- nodesMap[node.ID.String()] = struct{}{}
- filteredNodes = append(filteredNodes, node)
- }
- 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 := logic.GetNodeByID(gwID.String())
- if err == nil && gwNode.IsIngressGateway {
- nodesMap[gwNode.ID.String()] = struct{}{}
- filteredNodes = append(filteredNodes, gwNode)
- }
- }
- }
- }
- }
- }
- return
- }
- func FilterNetworksByRole(allnetworks []models.Network, user models.User) []models.Network {
- platformRole, err := logic.GetRole(user.PlatformRoleID)
- if err != nil {
- return []models.Network{}
- }
- if !platformRole.FullAccess {
- allNetworkRoles := make(map[models.NetworkID]struct{})
- if len(user.UserGroups) > 0 {
- for userGID := range user.UserGroups {
- userG, err := GetUserGroup(userGID)
- if err == nil {
- if len(userG.NetworkRoles) > 0 {
- for netID := range userG.NetworkRoles {
- if netID == models.AllNetworks {
- return allnetworks
- }
- allNetworkRoles[netID] = struct{}{}
- }
- }
- }
- }
- }
- filteredNetworks := []models.Network{}
- for _, networkI := range allnetworks {
- if _, ok := allNetworkRoles[models.NetworkID(networkI.NetID)]; ok {
- filteredNetworks = append(filteredNetworks, networkI)
- }
- }
- allnetworks = filteredNetworks
- }
- return allnetworks
- }
- func IsGroupsValid(groups map[models.UserGroupID]struct{}) error {
- for groupID := range groups {
- _, err := GetUserGroup(groupID)
- if err != nil {
- return fmt.Errorf("user group `%s` not found", groupID)
- }
- }
- return nil
- }
- func IsGroupValid(groupID models.UserGroupID) error {
- _, err := GetUserGroup(groupID)
- if err != nil {
- return fmt.Errorf("user group `%s` not found", groupID)
- }
- return nil
- }
- func IsNetworkRolesValid(networkRoles map[models.NetworkID]map[models.UserRoleID]struct{}) error {
- for netID, netRoles := range networkRoles {
- if netID != models.AllNetworks {
- _, err := logic.GetNetwork(netID.String())
- if err != nil {
- return fmt.Errorf("failed to fetch network %s ", netID)
- }
- }
- for netRoleID := range netRoles {
- _, err := logic.GetRole(netRoleID)
- if err != nil {
- return fmt.Errorf("failed to fetch role %s ", netRoleID)
- }
- }
- }
- return nil
- }
- // PrepareOauthUserFromInvite - init oauth user before create
- func PrepareOauthUserFromInvite(in models.UserInvite) (models.User, error) {
- var newPass, fetchErr = logic.FetchPassValue("")
- if fetchErr != nil {
- return models.User{}, fetchErr
- }
- user := models.User{
- UserName: in.Email,
- Password: newPass,
- }
- user.UserGroups = in.UserGroups
- user.PlatformRoleID = models.UserRoleID(in.PlatformRoleID)
- if user.PlatformRoleID == "" {
- user.PlatformRoleID = models.ServiceUser
- }
- return user, nil
- }
- func UpdatesUserGwAccessOnGrpUpdates(currNetworkRoles, changeNetworkRoles map[models.NetworkID]map[models.UserRoleID]struct{}) {
- networkChangeMap := make(map[models.NetworkID]map[models.UserRoleID]struct{})
- for netID, networkUserRoles := range currNetworkRoles {
- if _, ok := changeNetworkRoles[netID]; !ok {
- for netRoleID := range networkUserRoles {
- if _, ok := networkChangeMap[netID]; !ok {
- networkChangeMap[netID] = make(map[models.UserRoleID]struct{})
- }
- networkChangeMap[netID][netRoleID] = struct{}{}
- }
- } else {
- for netRoleID := range networkUserRoles {
- if _, ok := changeNetworkRoles[netID][netRoleID]; !ok {
- if _, ok := networkChangeMap[netID]; !ok {
- networkChangeMap[netID] = make(map[models.UserRoleID]struct{})
- }
- networkChangeMap[netID][netRoleID] = struct{}{}
- }
- }
- }
- }
- extclients, err := logic.GetAllExtClients()
- if err != nil {
- slog.Error("failed to fetch extclients", "error", err)
- return
- }
- userMap, err := logic.GetUserMap()
- if err != nil {
- return
- }
- for _, extclient := range extclients {
- if _, ok := networkChangeMap[models.NetworkID(extclient.Network)]; ok {
- if user, ok := userMap[extclient.OwnerID]; ok {
- if user.PlatformRoleID != models.ServiceUser {
- continue
- }
- err = logic.DeleteExtClientAndCleanup(extclient)
- if err != nil {
- slog.Error("failed to delete extclient",
- "id", extclient.ClientID, "owner", user.UserName, "error", err)
- } else {
- if err := mq.PublishDeletedClientPeerUpdate(&extclient); err != nil {
- slog.Error("error setting ext peers: " + err.Error())
- }
- }
- }
- }
- }
- if servercfg.IsDNSMode() {
- logic.SetDNS()
- }
- }
- func CreateDefaultUserPolicies(netID models.NetworkID) {
- if netID.String() == "" {
- return
- }
- // if !logic.IsAclExists(models.AclID(fmt.Sprintf("%s.%s", netID, models.NetworkAdmin))) {
- // defaultUserAcl := models.Acl{
- // ID: models.AclID(fmt.Sprintf("%s.%s", netID, models.NetworkAdmin)),
- // Name: models.NetworkAdmin.String(),
- // Default: true,
- // NetworkID: netID,
- // RuleType: models.UserPolicy,
- // Src: []models.AclPolicyTag{
- // {
- // ID: models.UserRoleAclID,
- // Value: fmt.Sprintf("%s-%s", netID, models.NetworkAdmin),
- // }},
- // Dst: []models.AclPolicyTag{
- // {
- // ID: models.DeviceAclID,
- // Value: fmt.Sprintf("%s.%s", netID, models.RemoteAccessTagName),
- // },
- // },
- // AllowedDirection: models.TrafficDirectionUni,
- // Enabled: true,
- // CreatedBy: "auto",
- // CreatedAt: time.Now().UTC(),
- // }
- // logic.InsertAcl(defaultUserAcl)
- // }
- // if !logic.IsAclExists(models.AclID(fmt.Sprintf("%s.%s", netID, models.NetworkUser))) {
- // defaultUserAcl := models.Acl{
- // ID: models.AclID(fmt.Sprintf("%s.%s", netID, models.NetworkUser)),
- // Name: models.NetworkUser.String(),
- // Default: true,
- // NetworkID: netID,
- // RuleType: models.UserPolicy,
- // Src: []models.AclPolicyTag{
- // {
- // ID: models.UserRoleAclID,
- // Value: fmt.Sprintf("%s-%s", netID, models.NetworkUser),
- // }},
- // Dst: []models.AclPolicyTag{
- // {
- // ID: models.DeviceAclID,
- // Value: fmt.Sprintf("%s.%s", netID, models.RemoteAccessTagName),
- // }},
- // AllowedDirection: models.TrafficDirectionUni,
- // Enabled: true,
- // CreatedBy: "auto",
- // CreatedAt: time.Now().UTC(),
- // }
- // logic.InsertAcl(defaultUserAcl)
- // }
- if !logic.IsAclExists(models.AclID(fmt.Sprintf("%s.%s-grp", netID, models.NetworkAdmin))) {
- defaultUserAcl := models.Acl{
- ID: models.AclID(fmt.Sprintf("%s.%s-grp", netID, models.NetworkAdmin)),
- Name: fmt.Sprintf("%s-grp", models.NetworkAdmin),
- Default: true,
- NetworkID: netID,
- RuleType: models.UserPolicy,
- Src: []models.AclPolicyTag{
- {
- ID: models.UserGroupAclID,
- Value: fmt.Sprintf("%s-%s-grp", netID, models.NetworkAdmin),
- }},
- Dst: []models.AclPolicyTag{
- {
- ID: models.DeviceAclID,
- Value: fmt.Sprintf("%s.%s", netID, models.RemoteAccessTagName),
- }},
- AllowedDirection: models.TrafficDirectionUni,
- Enabled: true,
- CreatedBy: "auto",
- CreatedAt: time.Now().UTC(),
- }
- logic.InsertAcl(defaultUserAcl)
- }
- if !logic.IsAclExists(models.AclID(fmt.Sprintf("%s.%s-grp", netID, models.NetworkUser))) {
- defaultUserAcl := models.Acl{
- ID: models.AclID(fmt.Sprintf("%s.%s-grp", netID, models.NetworkUser)),
- Name: fmt.Sprintf("%s-grp", models.NetworkUser),
- Default: true,
- NetworkID: netID,
- RuleType: models.UserPolicy,
- Src: []models.AclPolicyTag{
- {
- ID: models.UserGroupAclID,
- Value: fmt.Sprintf("%s-%s-grp", netID, models.NetworkUser),
- }},
- Dst: []models.AclPolicyTag{
- {
- ID: models.DeviceAclID,
- Value: fmt.Sprintf("%s.%s", netID, models.RemoteAccessTagName),
- }},
- AllowedDirection: models.TrafficDirectionUni,
- Enabled: true,
- CreatedBy: "auto",
- CreatedAt: time.Now().UTC(),
- }
- logic.InsertAcl(defaultUserAcl)
- }
- }
|