mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-07 13:44:17 +08:00
* feat: api access tokens
* revoke all user tokens
* redefine access token api routes, add auto egress option to enrollment keys
* add server settings apis, add db table for settigs
* handle server settings updates
* switch to using settings from DB
* fix sever settings migration
* revet force migration for settings
* fix server settings database write
* egress model
* fix revoked tokens to be unauthorized
* update egress model
* remove unused functions
* convert access token to sql schema
* switch access token to sql schema
* fix merge conflicts
* fix server settings types
* bypass basic auth setting for super admin
* add TODO comment
* setup api handlers for egress revamp
* use single DB, fix update nat boolean field
* extend validaiton checks for egress ranges
* add migration to convert to new egress model
* fix panic interface conversion
* publish peer update on settings update
* revoke token generated by an user
* add user token creation restriction by user role
* add forbidden check for access token creation
* revoke user token when group or role is changed
* add default group to admin users on update
* chore(go): import style changes from migration branch;
1. Singular file names for table schema.
2. No table name method.
3. Use .Model instead of .Table.
4. No unnecessary tagging.
* remove nat check on egress gateway request
* Revert "remove nat check on egress gateway request"
This reverts commit 0aff12a189
.
* remove nat check on egress gateway request
* feat(go): add db middleware;
* feat(go): restore method;
* feat(go): add user access token schema;
* add inet gw status to egress model
* fetch node ids in the tag, add inet gw info clients
* add inet gw info to node from egress list
* add migration logic internet gws
* create default acl policies
* add egress info
* add egress TODO
* add egress TODO
* fix user auth api:
* add reference id to acl policy
* add egress response from DB
* publish peer update on egress changes
* re initalise oauth and email config
* set verbosity
* normalise cidr on egress req
* add egress id to acl group
* change acls to use egress id
* resolve merge conflicts
* fix egress reference errors
* move egress model to schema
* add api context to DB
* sync auto update settings with hosts
* sync auto update settings with hosts
* check acl for egress node
* check for egress policy in the acl dst groups
* fix acl rules for egress policies with new models
* add status to egress model
* fix inet node func
* mask secret and convert jwt duration to minutes
* enable egress policies on creation
* convert jwt duration to minutes
* add relevant ranges to inet egress
* skip non active egress routes
* resolve merge conflicts
* fix static check
* update gorm tag for primary key on egress model
* create user policies for egress resources
* resolve merge conflicts
* get egress info on failover apis, add egress src validation for inet gws
* add additional validation checks on egress req
* add additional validation checks on egress req
* skip all resources for inet policy
* delete associated egress acl policies
* fix failover of inetclient
* avoid setting inet client asd inet gw
* fix all resource egress policy
* fix inet gw egress rule
* check for node egress on relay req
* fix egress acl rules comms
* add new field for egress info on node
* check acl policy in failover ctx
* avoid default host to be set as inet client
* fix relayed egress node
* add valid error messaging for egress validate func
* return if inet default host
* jump port detection to 51821
* check host ports on pull
* check user access gws via acls
* add validation check for default host and failover for inet clients
* add error messaging for acl policy check
* fix inet gw status
* ignore failover req for peer using inet gw
* check for allowed egress ranges for a peer
* add egress routes to static nodes by access
* avoid setting failvoer as inet client
* fix egress error messaging
* fix extclients egress comms
* fix inet gw acting as inet client
* return formatted error on update acl validation
* add default route for static nodes on inetclient
* check relay node acting as inetclient
* move inet node info to separate field, fix all resouces policy
* remove debug logs
---------
Co-authored-by: Vishal Dalwadi <dalwadivishal26@gmail.com>
248 lines
6.8 KiB
Go
248 lines
6.8 KiB
Go
package logic
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/gravitl/netmaker/logger"
|
|
"github.com/gravitl/netmaker/logic/acls/nodeacls"
|
|
"github.com/gravitl/netmaker/models"
|
|
)
|
|
|
|
// GetRelays - gets all the nodes that are relays
|
|
func GetRelays() ([]models.Node, error) {
|
|
nodes, err := GetAllNodes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
relays := make([]models.Node, 0)
|
|
for _, node := range nodes {
|
|
if node.IsRelay {
|
|
relays = append(relays, node)
|
|
}
|
|
}
|
|
return relays, nil
|
|
}
|
|
|
|
// CreateRelay - creates a relay
|
|
func CreateRelay(relay models.RelayRequest) ([]models.Node, models.Node, error) {
|
|
var returnnodes []models.Node
|
|
|
|
node, err := GetNodeByID(relay.NodeID)
|
|
if err != nil {
|
|
return returnnodes, models.Node{}, err
|
|
}
|
|
host, err := GetHost(node.HostID.String())
|
|
if err != nil {
|
|
return returnnodes, models.Node{}, err
|
|
}
|
|
if host.OS != "linux" {
|
|
return returnnodes, models.Node{}, fmt.Errorf("only linux machines can be gateway nodes")
|
|
}
|
|
err = ValidateRelay(relay, false)
|
|
if err != nil {
|
|
return returnnodes, models.Node{}, err
|
|
}
|
|
node.IsRelay = true
|
|
node.IsGw = true
|
|
node.RelayedNodes = relay.RelayedNodes
|
|
node.SetLastModified()
|
|
err = UpsertNode(&node)
|
|
if err != nil {
|
|
return returnnodes, node, err
|
|
}
|
|
returnnodes = SetRelayedNodes(true, relay.NodeID, relay.RelayedNodes)
|
|
return returnnodes, node, nil
|
|
}
|
|
|
|
// SetRelayedNodes- sets and saves node as relayed
|
|
func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.Node {
|
|
var returnnodes []models.Node
|
|
for _, id := range relayed {
|
|
node, err := GetNodeByID(id)
|
|
if err != nil {
|
|
logger.Log(0, "setRelayedNodes.GetNodebyID", err.Error())
|
|
continue
|
|
}
|
|
node.IsRelayed = setRelayed
|
|
if setRelayed {
|
|
node.RelayedBy = relay
|
|
} else {
|
|
node.RelayedBy = ""
|
|
}
|
|
node.SetLastModified()
|
|
if err := UpsertNode(&node); err != nil {
|
|
logger.Log(0, "setRelayedNodes.Insert", err.Error())
|
|
continue
|
|
}
|
|
returnnodes = append(returnnodes, node)
|
|
}
|
|
return returnnodes
|
|
}
|
|
|
|
// func GetRelayedNodes(relayNode *models.Node) (models.Node, error) {
|
|
// var returnnodes []models.Node
|
|
// networkNodes, err := GetNetworkNodes(relayNode.Network)
|
|
// if err != nil {
|
|
// return returnnodes, err
|
|
// }
|
|
// for _, node := range networkNodes {
|
|
// for _, addr := range relayNode.RelayAddrs {
|
|
// if addr == node.Address.IP.String() || addr == node.Address6.IP.String() {
|
|
// returnnodes = append(returnnodes, node)
|
|
// }
|
|
// }
|
|
// }
|
|
// return returnnodes, nil
|
|
// }
|
|
|
|
// ValidateRelay - checks if relay is valid
|
|
func ValidateRelay(relay models.RelayRequest, update bool) error {
|
|
var err error
|
|
|
|
node, err := GetNodeByID(relay.NodeID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !update && node.IsRelay {
|
|
return errors.New("node is already acting as a relay")
|
|
}
|
|
for _, relayedNodeID := range relay.RelayedNodes {
|
|
relayedNode, err := GetNodeByID(relayedNodeID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
GetNodeEgressInfo(&relayedNode)
|
|
if relayedNode.IsIngressGateway {
|
|
return errors.New("cannot relay an ingress gateway (" + relayedNodeID + ")")
|
|
}
|
|
if relayedNode.EgressDetails.IsInternetGateway {
|
|
return errors.New("cannot relay an internet gateway (" + relayedNodeID + ")")
|
|
}
|
|
if relayedNode.EgressDetails.InternetGwID != "" && relayedNode.EgressDetails.InternetGwID != relay.NodeID {
|
|
return errors.New("cannot relay an internet client (" + relayedNodeID + ")")
|
|
}
|
|
if relayedNode.IsFailOver {
|
|
return errors.New("cannot relay a failOver (" + relayedNodeID + ")")
|
|
}
|
|
if relayedNode.FailedOverBy != uuid.Nil {
|
|
ResetFailedOverPeer(&relayedNode)
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
// UpdateRelayNodes - updates relay nodes
|
|
func updateRelayNodes(relay string, oldNodes []string, newNodes []string) []models.Node {
|
|
_ = SetRelayedNodes(false, relay, oldNodes)
|
|
return SetRelayedNodes(true, relay, newNodes)
|
|
}
|
|
|
|
func RelayUpdates(currentNode, newNode *models.Node) bool {
|
|
relayUpdates := false
|
|
if newNode.IsRelay {
|
|
if len(newNode.RelayedNodes) != len(currentNode.RelayedNodes) {
|
|
relayUpdates = true
|
|
} else {
|
|
for i, node := range newNode.RelayedNodes {
|
|
if node != currentNode.RelayedNodes[i] {
|
|
relayUpdates = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return relayUpdates
|
|
}
|
|
|
|
// UpdateRelayed - updates a relay's relayed nodes, and sends updates to the relayed nodes over MQ
|
|
func UpdateRelayed(currentNode, newNode *models.Node) {
|
|
updatenodes := updateRelayNodes(currentNode.ID.String(), currentNode.RelayedNodes, newNode.RelayedNodes)
|
|
if len(updatenodes) > 0 {
|
|
for _, relayedNode := range updatenodes {
|
|
node := relayedNode
|
|
ResetFailedOverPeer(&node)
|
|
}
|
|
}
|
|
}
|
|
|
|
// DeleteRelay - deletes a relay
|
|
func DeleteRelay(network, nodeid string) ([]models.Node, models.Node, error) {
|
|
var returnnodes []models.Node
|
|
node, err := GetNodeByID(nodeid)
|
|
if err != nil {
|
|
return returnnodes, models.Node{}, err
|
|
}
|
|
returnnodes = SetRelayedNodes(false, nodeid, node.RelayedNodes)
|
|
node.IsRelay = false
|
|
node.RelayedNodes = []string{}
|
|
node.SetLastModified()
|
|
if err = UpsertNode(&node); err != nil {
|
|
return returnnodes, models.Node{}, err
|
|
}
|
|
return returnnodes, node, nil
|
|
}
|
|
|
|
func RelayedAllowedIPs(peer, node *models.Node) []net.IPNet {
|
|
var allowedIPs = []net.IPNet{}
|
|
for _, relayedNodeID := range peer.RelayedNodes {
|
|
if node.ID.String() == relayedNodeID {
|
|
continue
|
|
}
|
|
relayedNode, err := GetNodeByID(relayedNodeID)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
GetNodeEgressInfo(&relayedNode)
|
|
allowed := getRelayedAddresses(relayedNodeID)
|
|
if relayedNode.EgressDetails.IsEgressGateway {
|
|
allowed = append(allowed, GetEgressIPs(&relayedNode)...)
|
|
}
|
|
allowedIPs = append(allowedIPs, allowed...)
|
|
}
|
|
return allowedIPs
|
|
}
|
|
|
|
// GetAllowedIpsForRelayed - returns the peerConfig for a node relayed by relay
|
|
func GetAllowedIpsForRelayed(relayed, relay *models.Node) (allowedIPs []net.IPNet) {
|
|
if relayed.RelayedBy != relay.ID.String() {
|
|
logger.Log(0, "RelayedByRelay called with invalid parameters")
|
|
return
|
|
}
|
|
if relay.EgressDetails.InternetGwID != "" {
|
|
return GetAllowedIpForInetNodeClient(relayed, relay)
|
|
}
|
|
peers, err := GetNetworkNodes(relay.Network)
|
|
if err != nil {
|
|
logger.Log(0, "error getting network clients", err.Error())
|
|
return
|
|
}
|
|
for _, peer := range peers {
|
|
if peer.ID == relayed.ID || peer.ID == relay.ID {
|
|
continue
|
|
}
|
|
if nodeacls.AreNodesAllowed(nodeacls.NetworkID(relayed.Network), nodeacls.NodeID(relayed.ID.String()), nodeacls.NodeID(peer.ID.String())) {
|
|
allowedIPs = append(allowedIPs, GetAllowedIPs(relayed, &peer, nil)...)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func getRelayedAddresses(id string) []net.IPNet {
|
|
addrs := []net.IPNet{}
|
|
node, err := GetNodeByID(id)
|
|
if err != nil {
|
|
logger.Log(0, "getRelayedAddresses: "+err.Error())
|
|
return addrs
|
|
}
|
|
if node.Address.IP != nil {
|
|
node.Address.Mask = net.CIDRMask(32, 32)
|
|
addrs = append(addrs, node.Address)
|
|
}
|
|
if node.Address6.IP != nil {
|
|
node.Address6.Mask = net.CIDRMask(128, 128)
|
|
addrs = append(addrs, node.Address6)
|
|
}
|
|
return addrs
|
|
}
|