mirror of
https://github.com/gravitl/netmaker.git
synced 2025-11-01 12:42:42 +08:00
resolve merge conflicts
This commit is contained in:
@@ -17,6 +17,17 @@ var extClientConfigCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var extClientHAConfigCmd = &cobra.Command{
|
||||||
|
Use: "auto_config [NETWORK NAME]",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Short: "Get an External Client Configuration",
|
||||||
|
Long: `Get an External Client Configuration`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println(functions.GetExtClientHAConfig(args[0]))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(extClientConfigCmd)
|
rootCmd.AddCommand(extClientConfigCmd)
|
||||||
|
rootCmd.AddCommand(extClientHAConfigCmd)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ func GetExtClientConfig(networkName, clientID string) string {
|
|||||||
return get(fmt.Sprintf("/api/extclients/%s/%s/file", networkName, clientID))
|
return get(fmt.Sprintf("/api/extclients/%s/%s/file", networkName, clientID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetExtClientConfig - auto fetch a client config
|
||||||
|
func GetExtClientHAConfig(networkName string) string {
|
||||||
|
return get(fmt.Sprintf("/api/v1/client_conf/%s", networkName))
|
||||||
|
}
|
||||||
|
|
||||||
// CreateExtClient - create an external client
|
// CreateExtClient - create an external client
|
||||||
func CreateExtClient(networkName, nodeID string, extClient models.CustomExtClient) {
|
func CreateExtClient(networkName, nodeID string, extClient models.CustomExtClient) {
|
||||||
request[any](http.MethodPost, fmt.Sprintf("/api/extclients/%s/%s", networkName, nodeID), extClient)
|
request[any](http.MethodPost, fmt.Sprintf("/api/extclients/%s/%s", networkName, nodeID), extClient)
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ func extClientHandlers(r *mux.Router) {
|
|||||||
Methods(http.MethodDelete)
|
Methods(http.MethodDelete)
|
||||||
r.HandleFunc("/api/extclients/{network}/{nodeid}", logic.SecurityCheck(false, checkFreeTierLimits(limitChoiceMachines, http.HandlerFunc(createExtClient)))).
|
r.HandleFunc("/api/extclients/{network}/{nodeid}", logic.SecurityCheck(false, checkFreeTierLimits(limitChoiceMachines, http.HandlerFunc(createExtClient)))).
|
||||||
Methods(http.MethodPost)
|
Methods(http.MethodPost)
|
||||||
|
r.HandleFunc("/api/v1/client_conf/{network}", logic.SecurityCheck(false, http.HandlerFunc(getExtClientHAConf))).Methods(http.MethodGet)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkIngressExists(nodeID string) bool {
|
func checkIngressExists(nodeID string) bool {
|
||||||
@@ -387,6 +388,251 @@ Endpoint = %s
|
|||||||
json.NewEncoder(w).Encode(client)
|
json.NewEncoder(w).Encode(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary Get an individual remote access client
|
||||||
|
// @Router /api/extclients/{network}/{clientid}/{type} [get]
|
||||||
|
// @Tags Remote Access Client
|
||||||
|
// @Security oauth2
|
||||||
|
// @Success 200 {object} models.ExtClient
|
||||||
|
// @Failure 500 {object} models.ErrorResponse
|
||||||
|
// @Failure 403 {object} models.ErrorResponse
|
||||||
|
func getExtClientHAConf(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
networkid := params["network"]
|
||||||
|
network, err := logic.GetParentNetwork(networkid)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(
|
||||||
|
1,
|
||||||
|
r.Header.Get("user"),
|
||||||
|
"Could not retrieve Ingress Gateway Network",
|
||||||
|
networkid,
|
||||||
|
)
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// fetch client based on availability
|
||||||
|
nodes, _ := logic.GetNetworkNodes(networkid)
|
||||||
|
defaultPolicy, _ := logic.GetDefaultPolicy(models.NetworkID(networkid), models.DevicePolicy)
|
||||||
|
var targetGwID string
|
||||||
|
var connectionCnt int = -1
|
||||||
|
for _, nodeI := range nodes {
|
||||||
|
if nodeI.IsGw {
|
||||||
|
// check health status
|
||||||
|
logic.GetNodeStatus(&nodeI, defaultPolicy.Enabled)
|
||||||
|
if nodeI.Status != models.OnlineSt {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Get Total connections on the gw
|
||||||
|
clients := logic.GetGwExtclients(nodeI.ID.String(), networkid)
|
||||||
|
|
||||||
|
if connectionCnt == -1 || len(clients) < connectionCnt {
|
||||||
|
connectionCnt = len(clients)
|
||||||
|
targetGwID = nodeI.ID.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gwnode, err := logic.GetNodeByID(targetGwID)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(
|
||||||
|
0,
|
||||||
|
r.Header.Get("user"),
|
||||||
|
fmt.Sprintf(
|
||||||
|
"failed to get ingress gateway node [%s] info: %v",
|
||||||
|
gwnode.ID,
|
||||||
|
err,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
host, err := logic.GetHost(gwnode.HostID.String())
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(0, r.Header.Get("user"),
|
||||||
|
fmt.Sprintf("failed to get ingress gateway host for node [%s] info: %v", gwnode.ID, err))
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var userName string
|
||||||
|
if r.Header.Get("ismaster") == "yes" {
|
||||||
|
userName = logic.MasterUser
|
||||||
|
} else {
|
||||||
|
caller, err := logic.GetUser(r.Header.Get("user"))
|
||||||
|
if err != nil {
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userName = caller.UserName
|
||||||
|
}
|
||||||
|
// create client
|
||||||
|
var extclient models.ExtClient
|
||||||
|
extclient.OwnerID = userName
|
||||||
|
extclient.IngressGatewayID = targetGwID
|
||||||
|
extclient.Network = networkid
|
||||||
|
extclient.Tags = make(map[models.TagID]struct{})
|
||||||
|
// extclient.Tags[models.TagID(fmt.Sprintf("%s.%s", extclient.Network,
|
||||||
|
// models.RemoteAccessTagName))] = struct{}{}
|
||||||
|
// set extclient dns to ingressdns if extclient dns is not explicitly set
|
||||||
|
if (extclient.DNS == "") && (gwnode.IngressDNS != "") {
|
||||||
|
extclient.DNS = gwnode.IngressDNS
|
||||||
|
}
|
||||||
|
|
||||||
|
listenPort := logic.GetPeerListenPort(host)
|
||||||
|
extclient.IngressGatewayEndpoint = fmt.Sprintf("%s:%d", host.EndpointIP.String(), listenPort)
|
||||||
|
extclient.Enabled = true
|
||||||
|
|
||||||
|
if err = logic.CreateExtClient(&extclient); err != nil {
|
||||||
|
slog.Error(
|
||||||
|
"failed to create extclient",
|
||||||
|
"user",
|
||||||
|
r.Header.Get("user"),
|
||||||
|
"network",
|
||||||
|
networkid,
|
||||||
|
"error",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
client, err := logic.GetExtClient(extclient.ClientID, networkid)
|
||||||
|
if err != nil {
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addrString := client.Address
|
||||||
|
if addrString != "" {
|
||||||
|
addrString += "/32"
|
||||||
|
}
|
||||||
|
if client.Address6 != "" {
|
||||||
|
if addrString != "" {
|
||||||
|
addrString += ","
|
||||||
|
}
|
||||||
|
addrString += client.Address6 + "/128"
|
||||||
|
}
|
||||||
|
|
||||||
|
keepalive := ""
|
||||||
|
if network.DefaultKeepalive != 0 {
|
||||||
|
keepalive = "PersistentKeepalive = " + strconv.Itoa(int(network.DefaultKeepalive))
|
||||||
|
}
|
||||||
|
if gwnode.IngressPersistentKeepalive != 0 {
|
||||||
|
keepalive = "PersistentKeepalive = " + strconv.Itoa(int(gwnode.IngressPersistentKeepalive))
|
||||||
|
}
|
||||||
|
var newAllowedIPs string
|
||||||
|
if logic.IsInternetGw(gwnode) || gwnode.InternetGwID != "" {
|
||||||
|
egressrange := "0.0.0.0/0"
|
||||||
|
if gwnode.Address6.IP != nil && client.Address6 != "" {
|
||||||
|
egressrange += "," + "::/0"
|
||||||
|
}
|
||||||
|
newAllowedIPs = egressrange
|
||||||
|
} else {
|
||||||
|
newAllowedIPs = network.AddressRange
|
||||||
|
if newAllowedIPs != "" && network.AddressRange6 != "" {
|
||||||
|
newAllowedIPs += ","
|
||||||
|
}
|
||||||
|
if network.AddressRange6 != "" {
|
||||||
|
newAllowedIPs += network.AddressRange6
|
||||||
|
}
|
||||||
|
if egressGatewayRanges, err := logic.GetEgressRangesOnNetwork(&client); err == nil {
|
||||||
|
for _, egressGatewayRange := range egressGatewayRanges {
|
||||||
|
newAllowedIPs += "," + egressGatewayRange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gwendpoint := ""
|
||||||
|
if host.EndpointIP.To4() == nil {
|
||||||
|
gwendpoint = fmt.Sprintf("[%s]:%d", host.EndpointIPv6.String(), host.ListenPort)
|
||||||
|
} else {
|
||||||
|
gwendpoint = fmt.Sprintf("%s:%d", host.EndpointIP.String(), host.ListenPort)
|
||||||
|
}
|
||||||
|
defaultDNS := ""
|
||||||
|
if client.DNS != "" {
|
||||||
|
defaultDNS = "DNS = " + client.DNS
|
||||||
|
} else if gwnode.IngressDNS != "" {
|
||||||
|
defaultDNS = "DNS = " + gwnode.IngressDNS
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultMTU := 1420
|
||||||
|
if host.MTU != 0 {
|
||||||
|
defaultMTU = host.MTU
|
||||||
|
}
|
||||||
|
if gwnode.IngressMTU != 0 {
|
||||||
|
defaultMTU = int(gwnode.IngressMTU)
|
||||||
|
}
|
||||||
|
|
||||||
|
postUp := strings.Builder{}
|
||||||
|
if client.PostUp != "" && params["type"] != "qr" {
|
||||||
|
for _, loc := range strings.Split(client.PostUp, "\n") {
|
||||||
|
postUp.WriteString(fmt.Sprintf("PostUp = %s\n", loc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
postDown := strings.Builder{}
|
||||||
|
if client.PostDown != "" && params["type"] != "qr" {
|
||||||
|
for _, loc := range strings.Split(client.PostDown, "\n") {
|
||||||
|
postDown.WriteString(fmt.Sprintf("PostDown = %s\n", loc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config := fmt.Sprintf(`[Interface]
|
||||||
|
Address = %s
|
||||||
|
PrivateKey = %s
|
||||||
|
MTU = %d
|
||||||
|
%s
|
||||||
|
%s
|
||||||
|
%s
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = %s
|
||||||
|
AllowedIPs = %s
|
||||||
|
Endpoint = %s
|
||||||
|
%s
|
||||||
|
|
||||||
|
`, addrString,
|
||||||
|
client.PrivateKey,
|
||||||
|
defaultMTU,
|
||||||
|
defaultDNS,
|
||||||
|
postUp.String(),
|
||||||
|
postDown.String(),
|
||||||
|
host.PublicKey,
|
||||||
|
newAllowedIPs,
|
||||||
|
gwendpoint,
|
||||||
|
keepalive,
|
||||||
|
)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := logic.SetClientDefaultACLs(&extclient); err != nil {
|
||||||
|
slog.Error(
|
||||||
|
"failed to set default acls for extclient",
|
||||||
|
"user",
|
||||||
|
r.Header.Get("user"),
|
||||||
|
"network",
|
||||||
|
networkid,
|
||||||
|
"error",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := mq.PublishPeerUpdate(false); err != nil {
|
||||||
|
logger.Log(1, "error publishing peer update ", err.Error())
|
||||||
|
}
|
||||||
|
if servercfg.IsDNSMode() {
|
||||||
|
logic.SetDNS()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
name := client.ClientID + ".conf"
|
||||||
|
w.Header().Set("Content-Type", "application/config")
|
||||||
|
w.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, err = fmt.Fprint(w, config)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(1, r.Header.Get("user"), "response writer error (file) ", err.Error())
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @Summary Create an individual remote access client
|
// @Summary Create an individual remote access client
|
||||||
// @Router /api/extclients/{network}/{nodeid} [post]
|
// @Router /api/extclients/{network}/{nodeid} [post]
|
||||||
// @Tags Remote Access Client
|
// @Tags Remote Access Client
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
|
|||||||
logic.CreateDefaultNetworkRolesAndGroups(models.NetworkID(network.NetID))
|
logic.CreateDefaultNetworkRolesAndGroups(models.NetworkID(network.NetID))
|
||||||
logic.CreateDefaultAclNetworkPolicies(models.NetworkID(network.NetID))
|
logic.CreateDefaultAclNetworkPolicies(models.NetworkID(network.NetID))
|
||||||
logic.CreateDefaultTags(models.NetworkID(network.NetID))
|
logic.CreateDefaultTags(models.NetworkID(network.NetID))
|
||||||
//add new network to allocated ip map
|
|
||||||
go logic.AddNetworkToAllocatedIpMap(network.NetID)
|
go logic.AddNetworkToAllocatedIpMap(network.NetID)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -640,6 +640,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
netNew := netOld
|
netNew := netOld
|
||||||
|
netNew.NameServers = payload.NameServers
|
||||||
netNew.DefaultACL = payload.DefaultACL
|
netNew.DefaultACL = payload.DefaultACL
|
||||||
_, _, _, err = logic.UpdateNetwork(&netOld, &netNew)
|
_, _, _, err = logic.UpdateNetwork(&netOld, &netNew)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -647,7 +648,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
|
|||||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
go mq.PublishPeerUpdate(false)
|
||||||
slog.Info("updated network", "network", payload.NetID, "user", r.Header.Get("user"))
|
slog.Info("updated network", "network", payload.NetID, "user", r.Header.Get("user"))
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(payload)
|
json.NewEncoder(w).Encode(payload)
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ var linuxHost models.Host
|
|||||||
func TestCreateEgressGateway(t *testing.T) {
|
func TestCreateEgressGateway(t *testing.T) {
|
||||||
var gateway models.EgressGatewayRequest
|
var gateway models.EgressGatewayRequest
|
||||||
gateway.Ranges = []string{"10.100.100.0/24"}
|
gateway.Ranges = []string{"10.100.100.0/24"}
|
||||||
|
gateway.RangesWithMetric = append(gateway.RangesWithMetric, models.EgressRangeMetric{
|
||||||
|
Network: "10.100.100.0/24",
|
||||||
|
RouteMetric: 256,
|
||||||
|
})
|
||||||
gateway.NetID = "skynet"
|
gateway.NetID = "skynet"
|
||||||
deleteAllNetworks()
|
deleteAllNetworks()
|
||||||
createNet()
|
createNet()
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import (
|
|||||||
var (
|
var (
|
||||||
aclCacheMutex = &sync.RWMutex{}
|
aclCacheMutex = &sync.RWMutex{}
|
||||||
aclCacheMap = make(map[string]models.Acl)
|
aclCacheMap = make(map[string]models.Acl)
|
||||||
aclTagsMutex = &sync.RWMutex{}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func MigrateAclPolicies() {
|
func MigrateAclPolicies() {
|
||||||
@@ -620,10 +619,22 @@ func IsPeerAllowed(node, peer models.Node, checkDefaultPolicy bool) bool {
|
|||||||
} else {
|
} else {
|
||||||
peerId = peer.ID.String()
|
peerId = peer.ID.String()
|
||||||
}
|
}
|
||||||
aclTagsMutex.RLock()
|
|
||||||
peerTags := maps.Clone(peer.Tags)
|
var nodeTags, peerTags map[models.TagID]struct{}
|
||||||
nodeTags := maps.Clone(node.Tags)
|
if node.Mutex != nil {
|
||||||
aclTagsMutex.RUnlock()
|
node.Mutex.Lock()
|
||||||
|
nodeTags = maps.Clone(node.Tags)
|
||||||
|
node.Mutex.Unlock()
|
||||||
|
} else {
|
||||||
|
nodeTags = node.Tags
|
||||||
|
}
|
||||||
|
if peer.Mutex != nil {
|
||||||
|
peer.Mutex.Lock()
|
||||||
|
peerTags = maps.Clone(peer.Tags)
|
||||||
|
peer.Mutex.Unlock()
|
||||||
|
} else {
|
||||||
|
peerTags = peer.Tags
|
||||||
|
}
|
||||||
nodeTags[models.TagID(nodeId)] = struct{}{}
|
nodeTags[models.TagID(nodeId)] = struct{}{}
|
||||||
peerTags[models.TagID(peerId)] = struct{}{}
|
peerTags[models.TagID(peerId)] = struct{}{}
|
||||||
if checkDefaultPolicy {
|
if checkDefaultPolicy {
|
||||||
@@ -854,10 +865,21 @@ func IsNodeAllowedToCommunicateV1(node, peer models.Node, checkDefaultPolicy boo
|
|||||||
peerId = peer.ID.String()
|
peerId = peer.ID.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
aclTagsMutex.RLock()
|
var nodeTags, peerTags map[models.TagID]struct{}
|
||||||
peerTags := maps.Clone(peer.Tags)
|
if node.Mutex != nil {
|
||||||
nodeTags := maps.Clone(node.Tags)
|
node.Mutex.Lock()
|
||||||
aclTagsMutex.RUnlock()
|
nodeTags = maps.Clone(node.Tags)
|
||||||
|
node.Mutex.Unlock()
|
||||||
|
} else {
|
||||||
|
nodeTags = node.Tags
|
||||||
|
}
|
||||||
|
if peer.Mutex != nil {
|
||||||
|
peer.Mutex.Lock()
|
||||||
|
peerTags = maps.Clone(peer.Tags)
|
||||||
|
peer.Mutex.Unlock()
|
||||||
|
} else {
|
||||||
|
peerTags = peer.Tags
|
||||||
|
}
|
||||||
nodeTags[models.TagID(nodeId)] = struct{}{}
|
nodeTags[models.TagID(nodeId)] = struct{}{}
|
||||||
peerTags[models.TagID(peerId)] = struct{}{}
|
peerTags[models.TagID(peerId)] = struct{}{}
|
||||||
if checkDefaultPolicy {
|
if checkDefaultPolicy {
|
||||||
@@ -996,10 +1018,21 @@ func IsNodeAllowedToCommunicate(node, peer models.Node, checkDefaultPolicy bool)
|
|||||||
peerId = peer.ID.String()
|
peerId = peer.ID.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
aclTagsMutex.RLock()
|
var nodeTags, peerTags map[models.TagID]struct{}
|
||||||
peerTags := maps.Clone(peer.Tags)
|
if node.Mutex != nil {
|
||||||
nodeTags := maps.Clone(node.Tags)
|
node.Mutex.Lock()
|
||||||
aclTagsMutex.RUnlock()
|
nodeTags = maps.Clone(node.Tags)
|
||||||
|
node.Mutex.Unlock()
|
||||||
|
} else {
|
||||||
|
nodeTags = node.Tags
|
||||||
|
}
|
||||||
|
if peer.Mutex != nil {
|
||||||
|
peer.Mutex.Lock()
|
||||||
|
peerTags = maps.Clone(peer.Tags)
|
||||||
|
peer.Mutex.Unlock()
|
||||||
|
} else {
|
||||||
|
peerTags = peer.Tags
|
||||||
|
}
|
||||||
nodeTags[models.TagID(nodeId)] = struct{}{}
|
nodeTags[models.TagID(nodeId)] = struct{}{}
|
||||||
peerTags[models.TagID(peerId)] = struct{}{}
|
peerTags[models.TagID(peerId)] = struct{}{}
|
||||||
if checkDefaultPolicy {
|
if checkDefaultPolicy {
|
||||||
@@ -1222,13 +1255,20 @@ func getUserAclRulesForNode(targetnode *models.Node,
|
|||||||
userGrpMap := GetUserGrpMap()
|
userGrpMap := GetUserGrpMap()
|
||||||
allowedUsers := make(map[string][]models.Acl)
|
allowedUsers := make(map[string][]models.Acl)
|
||||||
acls := listUserPolicies(models.NetworkID(targetnode.Network))
|
acls := listUserPolicies(models.NetworkID(targetnode.Network))
|
||||||
|
var targetNodeTags = make(map[models.TagID]struct{})
|
||||||
|
if targetnode.Mutex != nil {
|
||||||
|
targetnode.Mutex.Lock()
|
||||||
|
targetNodeTags = maps.Clone(targetnode.Tags)
|
||||||
|
targetnode.Mutex.Unlock()
|
||||||
|
} else {
|
||||||
|
targetNodeTags = maps.Clone(targetnode.Tags)
|
||||||
|
}
|
||||||
for _, acl := range acls {
|
for _, acl := range acls {
|
||||||
if !acl.Enabled {
|
if !acl.Enabled {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dstTags := convAclTagToValueMap(acl.Dst)
|
dstTags := convAclTagToValueMap(acl.Dst)
|
||||||
for nodeTag := range targetnode.Tags {
|
for nodeTag := range targetNodeTags {
|
||||||
if _, ok := dstTags[nodeTag.String()]; !ok {
|
if _, ok := dstTags[nodeTag.String()]; !ok {
|
||||||
if _, ok = dstTags[targetnode.ID.String()]; !ok {
|
if _, ok = dstTags[targetnode.ID.String()]; !ok {
|
||||||
continue
|
continue
|
||||||
@@ -1338,7 +1378,15 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|||||||
}
|
}
|
||||||
|
|
||||||
acls := listDevicePolicies(models.NetworkID(targetnode.Network))
|
acls := listDevicePolicies(models.NetworkID(targetnode.Network))
|
||||||
targetnode.Tags["*"] = struct{}{}
|
var targetNodeTags = make(map[models.TagID]struct{})
|
||||||
|
if targetnode.Mutex != nil {
|
||||||
|
targetnode.Mutex.Lock()
|
||||||
|
targetNodeTags = maps.Clone(targetnode.Tags)
|
||||||
|
targetnode.Mutex.Unlock()
|
||||||
|
} else {
|
||||||
|
targetNodeTags = maps.Clone(targetnode.Tags)
|
||||||
|
}
|
||||||
|
targetNodeTags["*"] = struct{}{}
|
||||||
|
|
||||||
for _, acl := range acls {
|
for _, acl := range acls {
|
||||||
if !acl.Enabled {
|
if !acl.Enabled {
|
||||||
@@ -1355,7 +1403,7 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|||||||
Direction: acl.AllowedDirection,
|
Direction: acl.AllowedDirection,
|
||||||
Allowed: true,
|
Allowed: true,
|
||||||
}
|
}
|
||||||
for nodeTag := range targetnode.Tags {
|
for nodeTag := range targetNodeTags {
|
||||||
if acl.AllowedDirection == models.TrafficDirectionBi {
|
if acl.AllowedDirection == models.TrafficDirectionBi {
|
||||||
var existsInSrcTag bool
|
var existsInSrcTag bool
|
||||||
var existsInDstTag bool
|
var existsInDstTag bool
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ var (
|
|||||||
func getAllExtClientsFromCache() (extClients []models.ExtClient) {
|
func getAllExtClientsFromCache() (extClients []models.ExtClient) {
|
||||||
extClientCacheMutex.RLock()
|
extClientCacheMutex.RLock()
|
||||||
for _, extclient := range extClientCacheMap {
|
for _, extclient := range extClientCacheMap {
|
||||||
|
if extclient.Mutex == nil {
|
||||||
|
extclient.Mutex = &sync.Mutex{}
|
||||||
|
}
|
||||||
extClients = append(extClients, extclient)
|
extClients = append(extClients, extclient)
|
||||||
}
|
}
|
||||||
extClientCacheMutex.RUnlock()
|
extClientCacheMutex.RUnlock()
|
||||||
@@ -43,12 +46,18 @@ func deleteExtClientFromCache(key string) {
|
|||||||
func getExtClientFromCache(key string) (extclient models.ExtClient, ok bool) {
|
func getExtClientFromCache(key string) (extclient models.ExtClient, ok bool) {
|
||||||
extClientCacheMutex.RLock()
|
extClientCacheMutex.RLock()
|
||||||
extclient, ok = extClientCacheMap[key]
|
extclient, ok = extClientCacheMap[key]
|
||||||
|
if extclient.Mutex == nil {
|
||||||
|
extclient.Mutex = &sync.Mutex{}
|
||||||
|
}
|
||||||
extClientCacheMutex.RUnlock()
|
extClientCacheMutex.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeExtClientInCache(key string, extclient models.ExtClient) {
|
func storeExtClientInCache(key string, extclient models.ExtClient) {
|
||||||
extClientCacheMutex.Lock()
|
extClientCacheMutex.Lock()
|
||||||
|
if extclient.Mutex == nil {
|
||||||
|
extclient.Mutex = &sync.Mutex{}
|
||||||
|
}
|
||||||
extClientCacheMap[key] = extclient
|
extClientCacheMap[key] = extclient
|
||||||
extClientCacheMutex.Unlock()
|
extClientCacheMutex.Unlock()
|
||||||
}
|
}
|
||||||
@@ -96,14 +105,14 @@ func DeleteExtClient(network string, clientid string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//recycle ip address
|
if servercfg.CacheEnabled() {
|
||||||
|
// recycle ip address
|
||||||
if extClient.Address != "" {
|
if extClient.Address != "" {
|
||||||
RemoveIpFromAllocatedIpMap(network, extClient.Address)
|
RemoveIpFromAllocatedIpMap(network, extClient.Address)
|
||||||
}
|
}
|
||||||
if extClient.Address6 != "" {
|
if extClient.Address6 != "" {
|
||||||
RemoveIpFromAllocatedIpMap(network, extClient.Address6)
|
RemoveIpFromAllocatedIpMap(network, extClient.Address6)
|
||||||
}
|
}
|
||||||
if servercfg.CacheEnabled() {
|
|
||||||
deleteExtClientFromCache(key)
|
deleteExtClientFromCache(key)
|
||||||
}
|
}
|
||||||
go RemoveNodeFromAclPolicy(extClient.ConvertToStaticNode())
|
go RemoveNodeFromAclPolicy(extClient.ConvertToStaticNode())
|
||||||
@@ -334,7 +343,6 @@ func SaveExtClient(extclient *models.ExtClient) error {
|
|||||||
}
|
}
|
||||||
if servercfg.CacheEnabled() {
|
if servercfg.CacheEnabled() {
|
||||||
storeExtClientInCache(key, *extclient)
|
storeExtClientInCache(key, *extclient)
|
||||||
}
|
|
||||||
if _, ok := allocatedIpMap[extclient.Network]; ok {
|
if _, ok := allocatedIpMap[extclient.Network]; ok {
|
||||||
if extclient.Address != "" {
|
if extclient.Address != "" {
|
||||||
AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address))
|
AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address))
|
||||||
@@ -343,6 +351,8 @@ func SaveExtClient(extclient *models.ExtClient) error {
|
|||||||
AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address6))
|
AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address6))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return SetNetworkNodesLastModified(extclient.Network)
|
return SetNetworkNodesLastModified(extclient.Network)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package logic
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
@@ -77,6 +79,14 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
|
|||||||
if host.FirewallInUse == models.FIREWALL_NONE {
|
if host.FirewallInUse == models.FIREWALL_NONE {
|
||||||
return models.Node{}, errors.New("please install iptables or nftables on the device")
|
return models.Node{}, errors.New("please install iptables or nftables on the device")
|
||||||
}
|
}
|
||||||
|
if len(gateway.RangesWithMetric) == 0 && len(gateway.Ranges) > 0 {
|
||||||
|
for _, rangeI := range gateway.Ranges {
|
||||||
|
gateway.RangesWithMetric = append(gateway.RangesWithMetric, models.EgressRangeMetric{
|
||||||
|
Network: rangeI,
|
||||||
|
RouteMetric: 256,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
for i := len(gateway.Ranges) - 1; i >= 0; i-- {
|
for i := len(gateway.Ranges) - 1; i >= 0; i-- {
|
||||||
// check if internet gateway IPv4
|
// check if internet gateway IPv4
|
||||||
if gateway.Ranges[i] == "0.0.0.0/0" || gateway.Ranges[i] == "::/0" {
|
if gateway.Ranges[i] == "0.0.0.0/0" || gateway.Ranges[i] == "::/0" {
|
||||||
@@ -91,6 +101,28 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
|
|||||||
gateway.Ranges[i] = normalized
|
gateway.Ranges[i] = normalized
|
||||||
|
|
||||||
}
|
}
|
||||||
|
rangesWithMetric := []string{}
|
||||||
|
for i := len(gateway.RangesWithMetric) - 1; i >= 0; i-- {
|
||||||
|
if gateway.RangesWithMetric[i].Network == "0.0.0.0/0" || gateway.RangesWithMetric[i].Network == "::/0" {
|
||||||
|
// remove inet range
|
||||||
|
gateway.RangesWithMetric = append(gateway.RangesWithMetric[:i], gateway.RangesWithMetric[i+1:]...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
normalized, err := NormalizeCIDR(gateway.RangesWithMetric[i].Network)
|
||||||
|
if err != nil {
|
||||||
|
return models.Node{}, err
|
||||||
|
}
|
||||||
|
gateway.RangesWithMetric[i].Network = normalized
|
||||||
|
rangesWithMetric = append(rangesWithMetric, gateway.RangesWithMetric[i].Network)
|
||||||
|
if gateway.RangesWithMetric[i].RouteMetric <= 0 || gateway.RangesWithMetric[i].RouteMetric > 999 {
|
||||||
|
gateway.RangesWithMetric[i].RouteMetric = 256
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(gateway.Ranges)
|
||||||
|
sort.Strings(rangesWithMetric)
|
||||||
|
if !slices.Equal(gateway.Ranges, rangesWithMetric) {
|
||||||
|
return models.Node{}, errors.New("invalid ranges")
|
||||||
|
}
|
||||||
if gateway.NatEnabled == "" {
|
if gateway.NatEnabled == "" {
|
||||||
gateway.NatEnabled = "yes"
|
gateway.NatEnabled = "yes"
|
||||||
}
|
}
|
||||||
@@ -104,6 +136,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
|
|||||||
node.IsEgressGateway = true
|
node.IsEgressGateway = true
|
||||||
node.EgressGatewayRanges = gateway.Ranges
|
node.EgressGatewayRanges = gateway.Ranges
|
||||||
node.EgressGatewayNatEnabled = models.ParseBool(gateway.NatEnabled)
|
node.EgressGatewayNatEnabled = models.ParseBool(gateway.NatEnabled)
|
||||||
|
|
||||||
node.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway
|
node.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway
|
||||||
node.SetLastModified()
|
node.SetLastModified()
|
||||||
if err = UpsertNode(&node); err != nil {
|
if err = UpsertNode(&node); err != nil {
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ var (
|
|||||||
|
|
||||||
// SetAllocatedIpMap - set allocated ip map for networks
|
// SetAllocatedIpMap - set allocated ip map for networks
|
||||||
func SetAllocatedIpMap() error {
|
func SetAllocatedIpMap() error {
|
||||||
|
if !servercfg.CacheEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
logger.Log(0, "start setting up allocated ip map")
|
logger.Log(0, "start setting up allocated ip map")
|
||||||
if allocatedIpMap == nil {
|
if allocatedIpMap == nil {
|
||||||
allocatedIpMap = map[string]map[string]net.IP{}
|
allocatedIpMap = map[string]map[string]net.IP{}
|
||||||
@@ -84,16 +87,25 @@ func SetAllocatedIpMap() error {
|
|||||||
|
|
||||||
// ClearAllocatedIpMap - set allocatedIpMap to nil
|
// ClearAllocatedIpMap - set allocatedIpMap to nil
|
||||||
func ClearAllocatedIpMap() {
|
func ClearAllocatedIpMap() {
|
||||||
|
if !servercfg.CacheEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
allocatedIpMap = nil
|
allocatedIpMap = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddIpToAllocatedIpMap(networkName string, ip net.IP) {
|
func AddIpToAllocatedIpMap(networkName string, ip net.IP) {
|
||||||
|
if !servercfg.CacheEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
networkCacheMutex.Lock()
|
networkCacheMutex.Lock()
|
||||||
allocatedIpMap[networkName][ip.String()] = ip
|
allocatedIpMap[networkName][ip.String()] = ip
|
||||||
networkCacheMutex.Unlock()
|
networkCacheMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveIpFromAllocatedIpMap(networkName string, ip string) {
|
func RemoveIpFromAllocatedIpMap(networkName string, ip string) {
|
||||||
|
if !servercfg.CacheEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
networkCacheMutex.Lock()
|
networkCacheMutex.Lock()
|
||||||
delete(allocatedIpMap[networkName], ip)
|
delete(allocatedIpMap[networkName], ip)
|
||||||
networkCacheMutex.Unlock()
|
networkCacheMutex.Unlock()
|
||||||
@@ -101,6 +113,10 @@ func RemoveIpFromAllocatedIpMap(networkName string, ip string) {
|
|||||||
|
|
||||||
// AddNetworkToAllocatedIpMap - add network to allocated ip map when network is added
|
// AddNetworkToAllocatedIpMap - add network to allocated ip map when network is added
|
||||||
func AddNetworkToAllocatedIpMap(networkName string) {
|
func AddNetworkToAllocatedIpMap(networkName string) {
|
||||||
|
//add new network to allocated ip map
|
||||||
|
if !servercfg.CacheEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
networkCacheMutex.Lock()
|
networkCacheMutex.Lock()
|
||||||
allocatedIpMap[networkName] = make(map[string]net.IP)
|
allocatedIpMap[networkName] = make(map[string]net.IP)
|
||||||
networkCacheMutex.Unlock()
|
networkCacheMutex.Unlock()
|
||||||
@@ -108,6 +124,9 @@ func AddNetworkToAllocatedIpMap(networkName string) {
|
|||||||
|
|
||||||
// RemoveNetworkFromAllocatedIpMap - remove network from allocated ip map when network is deleted
|
// RemoveNetworkFromAllocatedIpMap - remove network from allocated ip map when network is deleted
|
||||||
func RemoveNetworkFromAllocatedIpMap(networkName string) {
|
func RemoveNetworkFromAllocatedIpMap(networkName string) {
|
||||||
|
if !servercfg.CacheEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
networkCacheMutex.Lock()
|
networkCacheMutex.Lock()
|
||||||
delete(allocatedIpMap, networkName)
|
delete(allocatedIpMap, networkName)
|
||||||
networkCacheMutex.Unlock()
|
networkCacheMutex.Unlock()
|
||||||
@@ -354,7 +373,7 @@ func GetNetworkSettings(networkname string) (models.Network, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UniqueAddress - get a unique ipv4 address
|
// UniqueAddress - get a unique ipv4 address
|
||||||
func UniqueAddress(networkName string, reverse bool) (net.IP, error) {
|
func UniqueAddressCache(networkName string, reverse bool) (net.IP, error) {
|
||||||
add := net.IP{}
|
add := net.IP{}
|
||||||
var network models.Network
|
var network models.Network
|
||||||
network, err := GetParentNetwork(networkName)
|
network, err := GetParentNetwork(networkName)
|
||||||
@@ -396,6 +415,49 @@ func UniqueAddress(networkName string, reverse bool) (net.IP, error) {
|
|||||||
return add, errors.New("ERROR: No unique addresses available. Check network subnet")
|
return add, errors.New("ERROR: No unique addresses available. Check network subnet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UniqueAddress - get a unique ipv4 address
|
||||||
|
func UniqueAddressDB(networkName string, reverse bool) (net.IP, error) {
|
||||||
|
add := net.IP{}
|
||||||
|
var network models.Network
|
||||||
|
network, err := GetParentNetwork(networkName)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(0, "UniqueAddressServer encountered an error")
|
||||||
|
return add, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if network.IsIPv4 == "no" {
|
||||||
|
return add, fmt.Errorf("IPv4 not active on network " + networkName)
|
||||||
|
}
|
||||||
|
//ensure AddressRange is valid
|
||||||
|
if _, _, err := net.ParseCIDR(network.AddressRange); err != nil {
|
||||||
|
logger.Log(0, "UniqueAddress encountered an error")
|
||||||
|
return add, err
|
||||||
|
}
|
||||||
|
net4 := iplib.Net4FromStr(network.AddressRange)
|
||||||
|
newAddrs := net4.FirstAddress()
|
||||||
|
|
||||||
|
if reverse {
|
||||||
|
newAddrs = net4.LastAddress()
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, false) &&
|
||||||
|
IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, false) {
|
||||||
|
return newAddrs, nil
|
||||||
|
}
|
||||||
|
if reverse {
|
||||||
|
newAddrs, err = net4.PreviousIP(newAddrs)
|
||||||
|
} else {
|
||||||
|
newAddrs, err = net4.NextIP(newAddrs)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return add, errors.New("ERROR: No unique addresses available. Check network subnet")
|
||||||
|
}
|
||||||
|
|
||||||
// IsIPUnique - checks if an IP is unique
|
// IsIPUnique - checks if an IP is unique
|
||||||
func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {
|
func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {
|
||||||
|
|
||||||
@@ -439,9 +501,67 @@ func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {
|
|||||||
|
|
||||||
return isunique
|
return isunique
|
||||||
}
|
}
|
||||||
|
func UniqueAddress(networkName string, reverse bool) (net.IP, error) {
|
||||||
|
if servercfg.CacheEnabled() {
|
||||||
|
return UniqueAddressCache(networkName, reverse)
|
||||||
|
}
|
||||||
|
return UniqueAddressDB(networkName, reverse)
|
||||||
|
}
|
||||||
|
|
||||||
// UniqueAddress6 - see if ipv6 address is unique
|
|
||||||
func UniqueAddress6(networkName string, reverse bool) (net.IP, error) {
|
func UniqueAddress6(networkName string, reverse bool) (net.IP, error) {
|
||||||
|
if servercfg.CacheEnabled() {
|
||||||
|
return UniqueAddress6Cache(networkName, reverse)
|
||||||
|
}
|
||||||
|
return UniqueAddress6DB(networkName, reverse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UniqueAddress6DB - see if ipv6 address is unique
|
||||||
|
func UniqueAddress6DB(networkName string, reverse bool) (net.IP, error) {
|
||||||
|
add := net.IP{}
|
||||||
|
var network models.Network
|
||||||
|
network, err := GetParentNetwork(networkName)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Network Not Found")
|
||||||
|
return add, err
|
||||||
|
}
|
||||||
|
if network.IsIPv6 == "no" {
|
||||||
|
return add, fmt.Errorf("IPv6 not active on network " + networkName)
|
||||||
|
}
|
||||||
|
|
||||||
|
//ensure AddressRange is valid
|
||||||
|
if _, _, err := net.ParseCIDR(network.AddressRange6); err != nil {
|
||||||
|
return add, err
|
||||||
|
}
|
||||||
|
net6 := iplib.Net6FromStr(network.AddressRange6)
|
||||||
|
|
||||||
|
newAddrs, err := net6.NextIP(net6.FirstAddress())
|
||||||
|
if reverse {
|
||||||
|
newAddrs, err = net6.PreviousIP(net6.LastAddress())
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return add, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, true) &&
|
||||||
|
IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, true) {
|
||||||
|
return newAddrs, nil
|
||||||
|
}
|
||||||
|
if reverse {
|
||||||
|
newAddrs, err = net6.PreviousIP(newAddrs)
|
||||||
|
} else {
|
||||||
|
newAddrs, err = net6.NextIP(newAddrs)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return add, errors.New("ERROR: No unique IPv6 addresses available. Check network subnet")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UniqueAddress6Cache - see if ipv6 address is unique using cache
|
||||||
|
func UniqueAddress6Cache(networkName string, reverse bool) (net.IP, error) {
|
||||||
add := net.IP{}
|
add := net.IP{}
|
||||||
var network models.Network
|
var network models.Network
|
||||||
network, err := GetParentNetwork(networkName)
|
network, err := GetParentNetwork(networkName)
|
||||||
|
|||||||
@@ -35,12 +35,20 @@ var (
|
|||||||
func getNodeFromCache(nodeID string) (node models.Node, ok bool) {
|
func getNodeFromCache(nodeID string) (node models.Node, ok bool) {
|
||||||
nodeCacheMutex.RLock()
|
nodeCacheMutex.RLock()
|
||||||
node, ok = nodesCacheMap[nodeID]
|
node, ok = nodesCacheMap[nodeID]
|
||||||
|
if node.Mutex == nil {
|
||||||
|
node.Mutex = &sync.Mutex{}
|
||||||
|
}
|
||||||
nodeCacheMutex.RUnlock()
|
nodeCacheMutex.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func getNodesFromCache() (nodes []models.Node) {
|
func getNodesFromCache() (nodes []models.Node) {
|
||||||
nodeCacheMutex.RLock()
|
nodeCacheMutex.RLock()
|
||||||
nodes = slices.Collect(maps.Values(nodesCacheMap))
|
for _, node := range nodesCacheMap {
|
||||||
|
if node.Mutex == nil {
|
||||||
|
node.Mutex = &sync.Mutex{}
|
||||||
|
}
|
||||||
|
nodes = append(nodes, node)
|
||||||
|
}
|
||||||
nodeCacheMutex.RUnlock()
|
nodeCacheMutex.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -357,12 +365,15 @@ func DeleteNodeByID(node *models.Node) error {
|
|||||||
logger.Log(1, "unable to remove metrics from DB for node", node.ID.String(), err.Error())
|
logger.Log(1, "unable to remove metrics from DB for node", node.ID.String(), err.Error())
|
||||||
}
|
}
|
||||||
//recycle ip address
|
//recycle ip address
|
||||||
|
if servercfg.CacheEnabled() {
|
||||||
if node.Address.IP != nil {
|
if node.Address.IP != nil {
|
||||||
RemoveIpFromAllocatedIpMap(node.Network, node.Address.IP.String())
|
RemoveIpFromAllocatedIpMap(node.Network, node.Address.IP.String())
|
||||||
}
|
}
|
||||||
if node.Address6.IP != nil {
|
if node.Address6.IP != nil {
|
||||||
RemoveIpFromAllocatedIpMap(node.Network, node.Address6.IP.String())
|
RemoveIpFromAllocatedIpMap(node.Network, node.Address6.IP.String())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,6 +435,9 @@ func GetAllNodes() ([]models.Node, error) {
|
|||||||
}
|
}
|
||||||
// add node to our array
|
// add node to our array
|
||||||
nodes = append(nodes, node)
|
nodes = append(nodes, node)
|
||||||
|
if node.Mutex == nil {
|
||||||
|
node.Mutex = &sync.Mutex{}
|
||||||
|
}
|
||||||
nodesMap[node.ID.String()] = node
|
nodesMap[node.ID.String()] = node
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,7 +713,6 @@ func createNode(node *models.Node) error {
|
|||||||
if servercfg.CacheEnabled() {
|
if servercfg.CacheEnabled() {
|
||||||
storeNodeInCache(*node)
|
storeNodeInCache(*node)
|
||||||
storeNodeInNetworkCache(*node, node.Network)
|
storeNodeInNetworkCache(*node, node.Network)
|
||||||
}
|
|
||||||
if _, ok := allocatedIpMap[node.Network]; ok {
|
if _, ok := allocatedIpMap[node.Network]; ok {
|
||||||
if node.Address.IP != nil {
|
if node.Address.IP != nil {
|
||||||
AddIpToAllocatedIpMap(node.Network, node.Address.IP)
|
AddIpToAllocatedIpMap(node.Network, node.Address.IP)
|
||||||
@@ -708,6 +721,8 @@ func createNode(node *models.Node) error {
|
|||||||
AddIpToAllocatedIpMap(node.Network, node.Address6.IP)
|
AddIpToAllocatedIpMap(node.Network, node.Address6.IP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), defaultACLVal)
|
_, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), defaultACLVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(1, "failed to create node ACL for node,", node.ID.String(), "err:", err.Error())
|
logger.Log(1, "failed to create node ACL for node,", node.ID.String(), "err:", err.Error())
|
||||||
@@ -753,16 +768,14 @@ func ValidateParams(nodeid, netid string) (models.Node, error) {
|
|||||||
func ValidateNodeIp(currentNode *models.Node, newNode *models.ApiNode) error {
|
func ValidateNodeIp(currentNode *models.Node, newNode *models.ApiNode) error {
|
||||||
|
|
||||||
if currentNode.Address.IP != nil && currentNode.Address.String() != newNode.Address {
|
if currentNode.Address.IP != nil && currentNode.Address.String() != newNode.Address {
|
||||||
newIp, _, _ := net.ParseCIDR(newNode.Address)
|
if !IsIPUnique(newNode.Network, newNode.Address, database.NODES_TABLE_NAME, false) ||
|
||||||
ipAllocated := allocatedIpMap[currentNode.Network]
|
!IsIPUnique(newNode.Network, newNode.Address, database.EXT_CLIENT_TABLE_NAME, false) {
|
||||||
if _, ok := ipAllocated[newIp.String()]; ok {
|
|
||||||
return errors.New("ip specified is already allocated: " + newNode.Address)
|
return errors.New("ip specified is already allocated: " + newNode.Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if currentNode.Address6.IP != nil && currentNode.Address6.String() != newNode.Address6 {
|
if currentNode.Address6.IP != nil && currentNode.Address6.String() != newNode.Address6 {
|
||||||
newIp, _, _ := net.ParseCIDR(newNode.Address6)
|
if !IsIPUnique(newNode.Network, newNode.Address6, database.NODES_TABLE_NAME, false) ||
|
||||||
ipAllocated := allocatedIpMap[currentNode.Network]
|
!IsIPUnique(newNode.Network, newNode.Address6, database.EXT_CLIENT_TABLE_NAME, false) {
|
||||||
if _, ok := ipAllocated[newIp.String()]; ok {
|
|
||||||
return errors.New("ip specified is already allocated: " + newNode.Address6)
|
return errors.New("ip specified is already allocated: " + newNode.Address6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -825,9 +838,16 @@ func GetTagMapWithNodes() (tagNodesMap map[models.TagID][]models.Node) {
|
|||||||
if nodeI.Tags == nil {
|
if nodeI.Tags == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if nodeI.Mutex != nil {
|
||||||
|
nodeI.Mutex.Lock()
|
||||||
|
}
|
||||||
for nodeTagID := range nodeI.Tags {
|
for nodeTagID := range nodeI.Tags {
|
||||||
tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
|
tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
|
||||||
}
|
}
|
||||||
|
if nodeI.Mutex != nil {
|
||||||
|
nodeI.Mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -842,9 +862,15 @@ func GetTagMapWithNodesByNetwork(netID models.NetworkID, withStaticNodes bool) (
|
|||||||
if nodeI.Tags == nil {
|
if nodeI.Tags == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if nodeI.Mutex != nil {
|
||||||
|
nodeI.Mutex.Lock()
|
||||||
|
}
|
||||||
for nodeTagID := range nodeI.Tags {
|
for nodeTagID := range nodeI.Tags {
|
||||||
tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
|
tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
|
||||||
}
|
}
|
||||||
|
if nodeI.Mutex != nil {
|
||||||
|
nodeI.Mutex.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tagNodesMap["*"] = nodes
|
tagNodesMap["*"] = nodes
|
||||||
if !withStaticNodes {
|
if !withStaticNodes {
|
||||||
@@ -873,17 +899,16 @@ func AddTagMapWithStaticNodes(netID models.NetworkID,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for tagID := range extclient.Tags {
|
if extclient.Mutex != nil {
|
||||||
tagNodesMap[tagID] = append(tagNodesMap[tagID], models.Node{
|
extclient.Mutex.Lock()
|
||||||
IsStatic: true,
|
}
|
||||||
StaticNode: extclient,
|
for tagID := range extclient.Tags {
|
||||||
})
|
tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
|
||||||
tagNodesMap["*"] = append(tagNodesMap["*"], models.Node{
|
tagNodesMap["*"] = append(tagNodesMap["*"], extclient.ConvertToStaticNode())
|
||||||
IsStatic: true,
|
}
|
||||||
StaticNode: extclient,
|
if extclient.Mutex != nil {
|
||||||
})
|
extclient.Mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return tagNodesMap
|
return tagNodesMap
|
||||||
}
|
}
|
||||||
@@ -904,11 +929,14 @@ func AddTagMapWithStaticNodesWithUsers(netID models.NetworkID,
|
|||||||
if extclient.Tags == nil {
|
if extclient.Tags == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if extclient.Mutex != nil {
|
||||||
|
extclient.Mutex.Lock()
|
||||||
|
}
|
||||||
for tagID := range extclient.Tags {
|
for tagID := range extclient.Tags {
|
||||||
tagNodesMap[tagID] = append(tagNodesMap[tagID], models.Node{
|
tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
|
||||||
IsStatic: true,
|
}
|
||||||
StaticNode: extclient,
|
if extclient.Mutex != nil {
|
||||||
})
|
extclient.Mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -926,9 +954,15 @@ func GetNodesWithTag(tagID models.TagID) map[string]models.Node {
|
|||||||
if nodeI.Tags == nil {
|
if nodeI.Tags == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if nodeI.Mutex != nil {
|
||||||
|
nodeI.Mutex.Lock()
|
||||||
|
}
|
||||||
if _, ok := nodeI.Tags[tagID]; ok {
|
if _, ok := nodeI.Tags[tagID]; ok {
|
||||||
nMap[nodeI.ID.String()] = nodeI
|
nMap[nodeI.ID.String()] = nodeI
|
||||||
}
|
}
|
||||||
|
if nodeI.Mutex != nil {
|
||||||
|
nodeI.Mutex.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return AddStaticNodesWithTag(tag, nMap)
|
return AddStaticNodesWithTag(tag, nMap)
|
||||||
}
|
}
|
||||||
@@ -942,13 +976,15 @@ func AddStaticNodesWithTag(tag models.Tag, nMap map[string]models.Node) map[stri
|
|||||||
if extclient.RemoteAccessClientID != "" {
|
if extclient.RemoteAccessClientID != "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if extclient.Mutex != nil {
|
||||||
|
extclient.Mutex.Lock()
|
||||||
|
}
|
||||||
if _, ok := extclient.Tags[tag.ID]; ok {
|
if _, ok := extclient.Tags[tag.ID]; ok {
|
||||||
nMap[extclient.ClientID] = models.Node{
|
nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
|
||||||
IsStatic: true,
|
|
||||||
StaticNode: extclient,
|
|
||||||
}
|
}
|
||||||
|
if extclient.Mutex != nil {
|
||||||
|
extclient.Mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return nMap
|
return nMap
|
||||||
}
|
}
|
||||||
@@ -964,10 +1000,7 @@ func GetStaticNodeWithTag(tagID models.TagID) map[string]models.Node {
|
|||||||
return nMap
|
return nMap
|
||||||
}
|
}
|
||||||
for _, extclient := range extclients {
|
for _, extclient := range extclients {
|
||||||
nMap[extclient.ClientID] = models.Node{
|
nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
|
||||||
IsStatic: true,
|
|
||||||
StaticNode: extclient,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nMap
|
return nMap
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,7 +269,11 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
networkSettings, err := GetNetwork(node.Network)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hostPeerUpdate.NameServers = append(hostPeerUpdate.NameServers, networkSettings.NameServers...)
|
||||||
currentPeers := GetNetworkNodesMemory(allNodes, node.Network)
|
currentPeers := GetNetworkNodesMemory(allNodes, node.Network)
|
||||||
for _, peer := range currentPeers {
|
for _, peer := range currentPeers {
|
||||||
peer := peer
|
peer := peer
|
||||||
@@ -296,6 +300,7 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
|
|||||||
NodeAddr: node.Address,
|
NodeAddr: node.Address,
|
||||||
NodeAddr6: node.Address6,
|
NodeAddr6: node.Address6,
|
||||||
EgressRanges: peer.EgressGatewayRanges,
|
EgressRanges: peer.EgressGatewayRanges,
|
||||||
|
EgressRangesWithMetric: peer.EgressGatewayRequest.RangesWithMetric,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if peer.IsIngressGateway {
|
if peer.IsIngressGateway {
|
||||||
|
|||||||
@@ -225,6 +225,16 @@ func updateNodes() {
|
|||||||
node.EgressGatewayRanges = egressRanges
|
node.EgressGatewayRanges = egressRanges
|
||||||
logic.UpsertNode(&node)
|
logic.UpsertNode(&node)
|
||||||
}
|
}
|
||||||
|
if len(node.EgressGatewayRequest.Ranges) > 0 && len(node.EgressGatewayRequest.RangesWithMetric) == 0 {
|
||||||
|
for _, egressRangeI := range node.EgressGatewayRequest.Ranges {
|
||||||
|
node.EgressGatewayRequest.RangesWithMetric = append(node.EgressGatewayRequest.RangesWithMetric, models.EgressRangeMetric{
|
||||||
|
Network: egressRangeI,
|
||||||
|
RouteMetric: 256,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
logic.UpsertNode(&node)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ type ApiNode struct {
|
|||||||
IsIngressGateway bool `json:"isingressgateway"`
|
IsIngressGateway bool `json:"isingressgateway"`
|
||||||
EgressGatewayRanges []string `json:"egressgatewayranges"`
|
EgressGatewayRanges []string `json:"egressgatewayranges"`
|
||||||
EgressGatewayNatEnabled bool `json:"egressgatewaynatenabled"`
|
EgressGatewayNatEnabled bool `json:"egressgatewaynatenabled"`
|
||||||
|
EgressGatewayRangesWithMetric []EgressRangeMetric `json:"egressgatewayranges_with_metric"`
|
||||||
DNSOn bool `json:"dnson"`
|
DNSOn bool `json:"dnson"`
|
||||||
IngressDns string `json:"ingressdns"`
|
IngressDns string `json:"ingressdns"`
|
||||||
IngressPersistentKeepalive int32 `json:"ingresspersistentkeepalive"`
|
IngressPersistentKeepalive int32 `json:"ingresspersistentkeepalive"`
|
||||||
@@ -189,6 +190,7 @@ func (nm *Node) ConvertToAPINode() *ApiNode {
|
|||||||
apiNode.IsEgressGateway = nm.IsEgressGateway
|
apiNode.IsEgressGateway = nm.IsEgressGateway
|
||||||
apiNode.IsIngressGateway = nm.IsIngressGateway
|
apiNode.IsIngressGateway = nm.IsIngressGateway
|
||||||
apiNode.EgressGatewayRanges = nm.EgressGatewayRanges
|
apiNode.EgressGatewayRanges = nm.EgressGatewayRanges
|
||||||
|
apiNode.EgressGatewayRangesWithMetric = nm.EgressGatewayRequest.RangesWithMetric
|
||||||
apiNode.EgressGatewayNatEnabled = nm.EgressGatewayNatEnabled
|
apiNode.EgressGatewayNatEnabled = nm.EgressGatewayNatEnabled
|
||||||
apiNode.DNSOn = nm.DNSOn
|
apiNode.DNSOn = nm.DNSOn
|
||||||
apiNode.IngressDns = nm.IngressDNS
|
apiNode.IngressDns = nm.IngressDNS
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
// ExtClient - struct for external clients
|
// ExtClient - struct for external clients
|
||||||
type ExtClient struct {
|
type ExtClient struct {
|
||||||
ClientID string `json:"clientid" bson:"clientid"`
|
ClientID string `json:"clientid" bson:"clientid"`
|
||||||
@@ -25,6 +27,7 @@ type ExtClient struct {
|
|||||||
DeviceName string `json:"device_name"`
|
DeviceName string `json:"device_name"`
|
||||||
PublicEndpoint string `json:"public_endpoint"`
|
PublicEndpoint string `json:"public_endpoint"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
|
Mutex *sync.Mutex `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomExtClient - struct for CustomExtClient params
|
// CustomExtClient - struct for CustomExtClient params
|
||||||
@@ -57,5 +60,6 @@ func (ext *ExtClient) ConvertToStaticNode() Node {
|
|||||||
Tags: ext.Tags,
|
Tags: ext.Tags,
|
||||||
IsStatic: true,
|
IsStatic: true,
|
||||||
StaticNode: *ext,
|
StaticNode: *ext,
|
||||||
|
Mutex: ext.Mutex,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type HostPeerUpdate struct {
|
|||||||
EgressRoutes []EgressNetworkRoutes `json:"egress_network_routes"`
|
EgressRoutes []EgressNetworkRoutes `json:"egress_network_routes"`
|
||||||
FwUpdate FwUpdate `json:"fw_update"`
|
FwUpdate FwUpdate `json:"fw_update"`
|
||||||
ReplacePeers bool `json:"replace_peers"`
|
ReplacePeers bool `json:"replace_peers"`
|
||||||
|
NameServers []string `json:"name_servers"`
|
||||||
ServerConfig
|
ServerConfig
|
||||||
OldPeerUpdateFields
|
OldPeerUpdateFields
|
||||||
}
|
}
|
||||||
@@ -74,6 +75,7 @@ type EgressNetworkRoutes struct {
|
|||||||
NodeAddr net.IPNet `json:"node_addr"`
|
NodeAddr net.IPNet `json:"node_addr"`
|
||||||
NodeAddr6 net.IPNet `json:"node_addr6"`
|
NodeAddr6 net.IPNet `json:"node_addr6"`
|
||||||
EgressRanges []string `json:"egress_ranges"`
|
EgressRanges []string `json:"egress_ranges"`
|
||||||
|
EgressRangesWithMetric []EgressRangeMetric `json:"egress_ranges_metric"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PeerRouteInfo - struct for peer info for an ext. client
|
// PeerRouteInfo - struct for peer info for an ext. client
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type Network struct {
|
|||||||
DefaultUDPHolePunch string `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"checkyesorno"`
|
DefaultUDPHolePunch string `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"checkyesorno"`
|
||||||
DefaultMTU int32 `json:"defaultmtu" bson:"defaultmtu"`
|
DefaultMTU int32 `json:"defaultmtu" bson:"defaultmtu"`
|
||||||
DefaultACL string `json:"defaultacl" bson:"defaultacl" yaml:"defaultacl" validate:"checkyesorno"`
|
DefaultACL string `json:"defaultacl" bson:"defaultacl" yaml:"defaultacl" validate:"checkyesorno"`
|
||||||
|
NameServers []string `json:"dns_nameservers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveData - sensitive fields of a network that should be kept the same
|
// SaveData - sensitive fields of a network that should be kept the same
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@@ -119,6 +120,7 @@ type Node struct {
|
|||||||
IsUserNode bool `json:"is_user_node"`
|
IsUserNode bool `json:"is_user_node"`
|
||||||
StaticNode ExtClient `json:"static_node"`
|
StaticNode ExtClient `json:"static_node"`
|
||||||
Status NodeStatus `json:"node_status"`
|
Status NodeStatus `json:"node_status"`
|
||||||
|
Mutex *sync.Mutex `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LegacyNode - legacy struct for node model
|
// LegacyNode - legacy struct for node model
|
||||||
|
|||||||
@@ -151,12 +151,18 @@ type ExtPeersResponse struct {
|
|||||||
KeepAlive int32 `json:"persistentkeepalive" bson:"persistentkeepalive"`
|
KeepAlive int32 `json:"persistentkeepalive" bson:"persistentkeepalive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EgressRangeMetric struct {
|
||||||
|
Network string `json:"network"`
|
||||||
|
RouteMetric uint32 `json:"route_metric"` // preffered range 1-999
|
||||||
|
}
|
||||||
|
|
||||||
// EgressGatewayRequest - egress gateway request
|
// EgressGatewayRequest - egress gateway request
|
||||||
type EgressGatewayRequest struct {
|
type EgressGatewayRequest struct {
|
||||||
NodeID string `json:"nodeid" bson:"nodeid"`
|
NodeID string `json:"nodeid" bson:"nodeid"`
|
||||||
NetID string `json:"netid" bson:"netid"`
|
NetID string `json:"netid" bson:"netid"`
|
||||||
NatEnabled string `json:"natenabled" bson:"natenabled"`
|
NatEnabled string `json:"natenabled" bson:"natenabled"`
|
||||||
Ranges []string `json:"ranges" bson:"ranges"`
|
Ranges []string `json:"ranges" bson:"ranges"`
|
||||||
|
RangesWithMetric []EgressRangeMetric `json:"ranges_with_metric"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RelayRequest - relay request struct
|
// RelayRequest - relay request struct
|
||||||
|
|||||||
@@ -245,6 +245,12 @@ func getUserEmailFromClaims(token string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
claims, _ := accessToken.Claims.(jwt.MapClaims)
|
claims, _ := accessToken.Claims.(jwt.MapClaims)
|
||||||
|
if claims == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if claims["email"] == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
return claims["email"].(string)
|
return claims["email"].(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,10 @@ func getAzureUserInfo(state string, code string) (*OAuthUser, error) {
|
|||||||
if userInfo.Email == "" {
|
if userInfo.Email == "" {
|
||||||
userInfo.Email = getUserEmailFromClaims(token.AccessToken)
|
userInfo.Email = getUserEmailFromClaims(token.AccessToken)
|
||||||
}
|
}
|
||||||
|
if userInfo.Email == "" && userInfo.UserPrincipalName != "" {
|
||||||
|
userInfo.Email = userInfo.UserPrincipalName
|
||||||
|
|
||||||
|
}
|
||||||
if userInfo.Email == "" {
|
if userInfo.Email == "" {
|
||||||
err = errors.New("failed to fetch user email from SSO state")
|
err = errors.New("failed to fetch user email from SSO state")
|
||||||
return userInfo, err
|
return userInfo, err
|
||||||
|
|||||||
@@ -1108,6 +1108,9 @@ func getUserRemoteAccessGwsV1(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gws := userGws[node.Network]
|
gws := userGws[node.Network]
|
||||||
|
if extClient.DNS == "" {
|
||||||
|
extClient.DNS = node.IngressDNS
|
||||||
|
}
|
||||||
extClient.AllowedIPs = logic.GetExtclientAllowedIPs(extClient)
|
extClient.AllowedIPs = logic.GetExtclientAllowedIPs(extClient)
|
||||||
gws = append(gws, models.UserRemoteGws{
|
gws = append(gws, models.UserRemoteGws{
|
||||||
GwID: node.ID.String(),
|
GwID: node.ID.String(),
|
||||||
|
|||||||
@@ -55,6 +55,6 @@ func GetClient() (e EmailSender) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func IsValid(email string) bool {
|
func IsValid(email string) bool {
|
||||||
emailRegex := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`)
|
emailRegex := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}$`)
|
||||||
return emailRegex.MatchString(email)
|
return emailRegex.MatchString(email)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user