mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-13 00:24:31 +08:00
* user mgmt models * define user roles * define models for new user mgmt and groups * oauth debug log * initialize user role after db conn * print oauth token in debug log * user roles CRUD apis * user groups CRUD Apis * additional api checks * add additional scopes * add additional scopes url * add additional scopes url * rm additional scopes url * setup middlleware permission checks * integrate permission check into middleware * integrate permission check into middleware * check for headers for subjects * refactor user role models * refactor user groups models * add new user to pending user via RAC login * untracked * allow multiple groups for an user * change json tag * add debug headers * refer network controls form roles, add debug headers * refer network controls form roles, add debug headers * replace auth checks, add network id to role model * nodes handler * migration funcs * invoke sync users migration func * add debug logs * comment middleware * fix get all nodes api * add debug logs * fix middleware error nil check * add new func to get username from jwt * fix jwt parsing * abort on error * allow multiple network roles * allow multiple network roles * add migration func * return err if jwt parsing fails * set global check to true when accessing user apis * set netid for acls api calls * set netid for acls api calls * update role and groups routes * add validation checks * add invite flow apis and magic links * add invited user via oauth signup automatically * create invited user on oauth signup, with groups in the invite * add group validation for user invite * update create user handler with new role mgmt * add validation checks * create user invites tables * add error logging for email invite * fix invite singup url * debug log * get query params from url * get query params from url * add query escape * debug log * debug log * fix user signup via invite api * set admin field for backward compatbility * use new role id for user apis * deprecate use of old admin fields * deprecate usage of old user fields * add user role as service user if empty * setup email sender * delete invite after user singup * add plaform user role * redirect on invite verification link * fix invite redirect * temporary redirect * fix invite redirect * point invite link to frontend * fix query params lookup * add resend support, configure email interface types * fix groups and user creation * validate user groups, add check for metrics api in middleware * add invite url to invite model * migrate rac apis to new user mgmt * handle network nodes * add platform user to default role * fix user role migration * add default on rag creation and cleanup after deletion * fix rac apis * change to invite code param * filter nodes and hosts based on user network access * extend create user group req to accomodate users * filter network based on user access * format oauth error * move user roles and groups * fix get user v1 api * move user mgmt func to pro * add user auth type to user model * fix roles init * remove platform role from group object * list only platform roles * add network roles to invite req * create default groups and roles * fix middleware for global access * create default role * fix nodes filter with global network roles * block selfupdate of groups and network roles * delete netID if net roles are empty * validate user roles nd groups on update * set extclient permission scope when rag vpn access is set * allow deletion of roles and groups * replace _ with - in role naming convention * fix failover middleware mgmt * format oauth templates * fetch route temaplate * return err if user wrong login type * check user groups on rac apis * fix rac apis * fix resp msg * add validation checks for admin invite * return oauth type * format group err msg * fix html tag * clean up default groups * create default rag role * add UI name to roles * remove default net group from user when deleted * reorder migration funcs * fix duplicacy of hosts * check old field for migration * from pro to ce make all secondary users admins * from pro to ce make all secondary users admins * revert: from pro to ce make all secondary users admins * make sure downgrades work * fix pending users approval * fix duplicate hosts * fix duplicate hosts entries * fix cache reference issue * feat: configure FRONTEND_URL during installation * disable user vpn access when network roles are modified * rm vpn acces when roles or groups are deleted * add http to frontend url * revert crypto version * downgrade crytpo version * add platform id check on user invites --------- Co-authored-by: the_aceix <aceixsmartx@gmail.com>
300 lines
8.3 KiB
Go
300 lines
8.3 KiB
Go
package logic
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/gravitl/netmaker/database"
|
|
"github.com/gravitl/netmaker/logger"
|
|
"github.com/gravitl/netmaker/models"
|
|
"github.com/gravitl/netmaker/servercfg"
|
|
)
|
|
|
|
// IsInternetGw - checks if node is acting as internet gw
|
|
func IsInternetGw(node models.Node) bool {
|
|
return node.IsInternetGateway
|
|
}
|
|
|
|
// GetInternetGateways - gets all the nodes that are internet gateways
|
|
func GetInternetGateways() ([]models.Node, error) {
|
|
nodes, err := GetAllNodes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
igs := make([]models.Node, 0)
|
|
for _, node := range nodes {
|
|
if node.IsInternetGateway {
|
|
igs = append(igs, node)
|
|
}
|
|
}
|
|
return igs, nil
|
|
}
|
|
|
|
// GetAllIngresses - gets all the nodes that are ingresses
|
|
func GetAllIngresses() ([]models.Node, error) {
|
|
nodes, err := GetAllNodes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ingresses := make([]models.Node, 0)
|
|
for _, node := range nodes {
|
|
if node.IsIngressGateway {
|
|
ingresses = append(ingresses, node)
|
|
}
|
|
}
|
|
return ingresses, nil
|
|
}
|
|
|
|
// GetAllEgresses - gets all the nodes that are egresses
|
|
func GetAllEgresses() ([]models.Node, error) {
|
|
nodes, err := GetAllNodes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
egresses := make([]models.Node, 0)
|
|
for _, node := range nodes {
|
|
if node.IsEgressGateway {
|
|
egresses = append(egresses, node)
|
|
}
|
|
}
|
|
return egresses, nil
|
|
}
|
|
|
|
// CreateEgressGateway - creates an egress gateway
|
|
func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, error) {
|
|
node, err := GetNodeByID(gateway.NodeID)
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
host, err := GetHost(node.HostID.String())
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
if host.OS != "linux" { // support for other OS to be added
|
|
return models.Node{}, errors.New(host.OS + " is unsupported for egress gateways")
|
|
}
|
|
if host.FirewallInUse == models.FIREWALL_NONE {
|
|
return models.Node{}, errors.New("firewall is not supported for egress gateways. please install iptables or nftables on the device in order to use this feature")
|
|
}
|
|
for i := len(gateway.Ranges) - 1; i >= 0; i-- {
|
|
// check if internet gateway IPv4
|
|
if gateway.Ranges[i] == "0.0.0.0/0" || gateway.Ranges[i] == "::/0" {
|
|
// remove inet range
|
|
gateway.Ranges = append(gateway.Ranges[:i], gateway.Ranges[i+1:]...)
|
|
continue
|
|
}
|
|
normalized, err := NormalizeCIDR(gateway.Ranges[i])
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
gateway.Ranges[i] = normalized
|
|
|
|
}
|
|
if gateway.NatEnabled == "" {
|
|
gateway.NatEnabled = "yes"
|
|
}
|
|
err = ValidateEgressGateway(gateway)
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
if gateway.Ranges == nil {
|
|
gateway.Ranges = make([]string, 0)
|
|
}
|
|
node.IsEgressGateway = true
|
|
node.EgressGatewayRanges = gateway.Ranges
|
|
node.EgressGatewayNatEnabled = models.ParseBool(gateway.NatEnabled)
|
|
node.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway
|
|
node.SetLastModified()
|
|
if err = UpsertNode(&node); err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
return node, nil
|
|
}
|
|
|
|
// ValidateEgressGateway - validates the egress gateway model
|
|
func ValidateEgressGateway(gateway models.EgressGatewayRequest) error {
|
|
return nil
|
|
}
|
|
|
|
// DeleteEgressGateway - deletes egress from node
|
|
func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
|
|
node, err := GetNodeByID(nodeid)
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
node.IsEgressGateway = false
|
|
node.EgressGatewayRanges = []string{}
|
|
node.EgressGatewayRequest = models.EgressGatewayRequest{} // remove preserved request as the egress gateway is gone
|
|
node.SetLastModified()
|
|
if err = UpsertNode(&node); err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
return node, nil
|
|
}
|
|
|
|
// CreateIngressGateway - creates an ingress gateway
|
|
func CreateIngressGateway(netid string, nodeid string, ingress models.IngressRequest) (models.Node, error) {
|
|
|
|
node, err := GetNodeByID(nodeid)
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
if node.IsRelayed {
|
|
return models.Node{}, errors.New("ingress cannot be created on a relayed node")
|
|
}
|
|
host, err := GetHost(node.HostID.String())
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
if host.OS != "linux" {
|
|
return models.Node{}, errors.New("ingress can only be created on linux based node")
|
|
}
|
|
if host.FirewallInUse == models.FIREWALL_NONE {
|
|
return models.Node{}, errors.New("firewall is not supported for ingress gateways")
|
|
}
|
|
|
|
network, err := GetParentNetwork(netid)
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
node.IsIngressGateway = true
|
|
if !servercfg.IsPro {
|
|
node.IsInternetGateway = ingress.IsInternetGateway
|
|
}
|
|
node.IngressGatewayRange = network.AddressRange
|
|
node.IngressGatewayRange6 = network.AddressRange6
|
|
node.IngressDNS = ingress.ExtclientDNS
|
|
if servercfg.IsPro {
|
|
if _, exists := FailOverExists(node.Network); exists {
|
|
ResetFailedOverPeer(&node)
|
|
}
|
|
}
|
|
node.SetLastModified()
|
|
node.Metadata = ingress.Metadata
|
|
if node.Metadata == "" {
|
|
node.Metadata = "This host can be used for remote access"
|
|
}
|
|
err = UpsertNode(&node)
|
|
if err != nil {
|
|
return models.Node{}, err
|
|
}
|
|
// create network role for this gateway
|
|
CreateRole(models.UserRolePermissionTemplate{
|
|
ID: models.GetRAGRoleID(node.Network, host.ID.String()),
|
|
UiName: models.GetRAGRoleName(node.Network, host.Name),
|
|
NetworkID: models.NetworkID(node.Network),
|
|
Default: true,
|
|
NetworkLevelAccess: map[models.RsrcType]map[models.RsrcID]models.RsrcPermissionScope{
|
|
models.RemoteAccessGwRsrc: {
|
|
models.RsrcID(node.ID.String()): models.RsrcPermissionScope{
|
|
Read: true,
|
|
VPNaccess: true,
|
|
},
|
|
},
|
|
models.ExtClientsRsrc: {
|
|
models.AllExtClientsRsrcID: models.RsrcPermissionScope{
|
|
Read: true,
|
|
Create: true,
|
|
Update: true,
|
|
Delete: true,
|
|
SelfOnly: true,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
err = SetNetworkNodesLastModified(netid)
|
|
return node, err
|
|
}
|
|
|
|
// GetIngressGwUsers - lists the users having to access to ingressGW
|
|
func GetIngressGwUsers(node models.Node) (models.IngressGwUsers, error) {
|
|
|
|
gwUsers := models.IngressGwUsers{
|
|
NodeID: node.ID.String(),
|
|
Network: node.Network,
|
|
}
|
|
users, err := GetUsers()
|
|
if err != nil {
|
|
return gwUsers, err
|
|
}
|
|
for _, user := range users {
|
|
if !user.IsAdmin && !user.IsSuperAdmin {
|
|
gwUsers.Users = append(gwUsers.Users, user)
|
|
}
|
|
}
|
|
return gwUsers, nil
|
|
}
|
|
|
|
// DeleteIngressGateway - deletes an ingress gateway
|
|
func DeleteIngressGateway(nodeid string) (models.Node, []models.ExtClient, error) {
|
|
removedClients := []models.ExtClient{}
|
|
node, err := GetNodeByID(nodeid)
|
|
if err != nil {
|
|
return models.Node{}, removedClients, err
|
|
}
|
|
clients, err := GetExtClientsByID(nodeid, node.Network)
|
|
if err != nil && !database.IsEmptyRecord(err) {
|
|
return models.Node{}, removedClients, err
|
|
}
|
|
|
|
removedClients = clients
|
|
|
|
// delete ext clients belonging to ingress gateway
|
|
if err = DeleteGatewayExtClients(node.ID.String(), node.Network); err != nil {
|
|
return models.Node{}, removedClients, err
|
|
}
|
|
logger.Log(3, "deleting ingress gateway")
|
|
node.LastModified = time.Now()
|
|
node.IsIngressGateway = false
|
|
if !servercfg.IsPro {
|
|
node.IsInternetGateway = false
|
|
}
|
|
node.IngressGatewayRange = ""
|
|
node.Metadata = ""
|
|
err = UpsertNode(&node)
|
|
if err != nil {
|
|
return models.Node{}, removedClients, err
|
|
}
|
|
host, err := GetHost(node.HostID.String())
|
|
if err != nil {
|
|
return models.Node{}, removedClients, err
|
|
}
|
|
go DeleteRole(models.GetRAGRoleID(node.Network, host.ID.String()), true)
|
|
err = SetNetworkNodesLastModified(node.Network)
|
|
return node, removedClients, err
|
|
}
|
|
|
|
// DeleteGatewayExtClients - deletes ext clients based on gateway (mac) of ingress node and network
|
|
func DeleteGatewayExtClients(gatewayID string, networkName string) error {
|
|
currentExtClients, err := GetNetworkExtClients(networkName)
|
|
if database.IsEmptyRecord(err) {
|
|
return nil
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, extClient := range currentExtClients {
|
|
if extClient.IngressGatewayID == gatewayID {
|
|
if err = DeleteExtClient(networkName, extClient.ClientID); err != nil {
|
|
logger.Log(1, "failed to remove ext client", extClient.ClientID)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// IsUserAllowedAccessToExtClient - checks if user has permission to access extclient
|
|
func IsUserAllowedAccessToExtClient(username string, client models.ExtClient) bool {
|
|
if username == MasterUser {
|
|
return true
|
|
}
|
|
user, err := GetUser(username)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
if user.UserName != client.OwnerID {
|
|
return false
|
|
}
|
|
return true
|
|
}
|