mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-13 12:34:30 +08:00
Merge branch 'develop' of https://github.com/gravitl/netmaker into NET-390-scale-latest
This commit is contained in:
@@ -83,6 +83,11 @@ type ServerConfig struct {
|
|||||||
TurnUserName string `yaml:"turn_username"`
|
TurnUserName string `yaml:"turn_username"`
|
||||||
TurnPassword string `yaml:"turn_password"`
|
TurnPassword string `yaml:"turn_password"`
|
||||||
UseTurn bool `yaml:"use_turn"`
|
UseTurn bool `yaml:"use_turn"`
|
||||||
|
UsersLimit int `yaml:"user_limit"`
|
||||||
|
ClientsLimit int `yaml:"client_limit"`
|
||||||
|
NetworksLimit int `yaml:"network_limit"`
|
||||||
|
HostsLimit int `yaml:"host_limit"`
|
||||||
|
DeployedByOperator bool `yaml:"deployed_by_operator"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProxyMode - default proxy mode for server
|
// ProxyMode - default proxy mode for server
|
||||||
|
@@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/logic"
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// limit consts
|
// limit consts
|
||||||
@@ -23,20 +22,13 @@ func checkFreeTierLimits(limit_choice int, next http.Handler) http.HandlerFunc {
|
|||||||
Code: http.StatusForbidden, Message: "free tier limits exceeded on networks",
|
Code: http.StatusForbidden, Message: "free tier limits exceeded on networks",
|
||||||
}
|
}
|
||||||
|
|
||||||
if logic.Free_Tier && servercfg.Is_EE { // check that free tier limits not exceeded
|
if logic.Free_Tier { // check that free tier limits not exceeded
|
||||||
if limit_choice == networks_l {
|
if limit_choice == networks_l {
|
||||||
currentNetworks, err := logic.GetNetworks()
|
currentNetworks, err := logic.GetNetworks()
|
||||||
if (err != nil && !database.IsEmptyRecord(err)) || len(currentNetworks) >= logic.Networks_Limit {
|
if (err != nil && !database.IsEmptyRecord(err)) || len(currentNetworks) >= logic.Networks_Limit {
|
||||||
logic.ReturnErrorResponse(w, r, errorResponse)
|
logic.ReturnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if limit_choice == node_l {
|
|
||||||
nodes, err := logic.GetAllNodes()
|
|
||||||
if (err != nil && !database.IsEmptyRecord(err)) || len(nodes) >= logic.Node_Limit {
|
|
||||||
errorResponse.Message = "free tier limits exceeded on nodes"
|
|
||||||
logic.ReturnErrorResponse(w, r, errorResponse)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if limit_choice == users_l {
|
} else if limit_choice == users_l {
|
||||||
users, err := logic.GetUsers()
|
users, err := logic.GetUsers()
|
||||||
if (err != nil && !database.IsEmptyRecord(err)) || len(users) >= logic.Users_Limit {
|
if (err != nil && !database.IsEmptyRecord(err)) || len(users) >= logic.Users_Limit {
|
||||||
|
@@ -22,6 +22,38 @@ func serverHandlers(r *mux.Router) {
|
|||||||
r.HandleFunc("/api/server/getconfig", allowUsers(http.HandlerFunc(getConfig))).Methods(http.MethodGet)
|
r.HandleFunc("/api/server/getconfig", allowUsers(http.HandlerFunc(getConfig))).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/api/server/getserverinfo", Authorize(true, false, "node", http.HandlerFunc(getServerInfo))).Methods(http.MethodGet)
|
r.HandleFunc("/api/server/getserverinfo", Authorize(true, false, "node", http.HandlerFunc(getServerInfo))).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/api/server/status", http.HandlerFunc(getStatus)).Methods(http.MethodGet)
|
r.HandleFunc("/api/server/status", http.HandlerFunc(getStatus)).Methods(http.MethodGet)
|
||||||
|
r.HandleFunc("/api/server/usage", Authorize(true, false, "user", http.HandlerFunc(getUsage))).Methods(http.MethodGet)
|
||||||
|
}
|
||||||
|
func getUsage(w http.ResponseWriter, r *http.Request) {
|
||||||
|
type usage struct {
|
||||||
|
Hosts int `json:"hosts"`
|
||||||
|
Clients int `json:"clients"`
|
||||||
|
Networks int `json:"networks"`
|
||||||
|
Users int `json:"users"`
|
||||||
|
}
|
||||||
|
var serverUsage usage
|
||||||
|
hosts, err := logic.GetAllHosts()
|
||||||
|
if err == nil {
|
||||||
|
serverUsage.Hosts = len(hosts)
|
||||||
|
}
|
||||||
|
clients, err := logic.GetAllExtClients()
|
||||||
|
if err == nil {
|
||||||
|
serverUsage.Clients = len(clients)
|
||||||
|
}
|
||||||
|
users, err := logic.GetUsers()
|
||||||
|
if err == nil {
|
||||||
|
serverUsage.Users = len(users)
|
||||||
|
}
|
||||||
|
networks, err := logic.GetNetworks()
|
||||||
|
if err == nil {
|
||||||
|
serverUsage.Networks = len(networks)
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(models.SuccessResponse{
|
||||||
|
Code: http.StatusOK,
|
||||||
|
Response: serverUsage,
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// swagger:route GET /api/server/status server getStatus
|
// swagger:route GET /api/server/status server getStatus
|
||||||
@@ -41,6 +73,12 @@ func getStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
type status struct {
|
type status struct {
|
||||||
DB bool `json:"db_connected"`
|
DB bool `json:"db_connected"`
|
||||||
Broker bool `json:"broker_connected"`
|
Broker bool `json:"broker_connected"`
|
||||||
|
Usage struct {
|
||||||
|
Hosts int `json:"hosts"`
|
||||||
|
Clients int `json:"clients"`
|
||||||
|
Networks int `json:"networks"`
|
||||||
|
Users int `json:"users"`
|
||||||
|
} `json:"usage"`
|
||||||
}
|
}
|
||||||
|
|
||||||
currentServerStatus := status{
|
currentServerStatus := status{
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package ee_controllers
|
package ee_controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -87,6 +88,15 @@ func deleteRelay(w http.ResponseWriter, r *http.Request) {
|
|||||||
logger.Log(1, "relayed node update ", relayedNode.ID.String(), "on network", relayedNode.Network, ": ", err.Error())
|
logger.Log(1, "relayed node update ", relayedNode.ID.String(), "on network", relayedNode.Network, ": ", err.Error())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
h, err := logic.GetHost(relayedNode.HostID.String())
|
||||||
|
if err == nil {
|
||||||
|
if h.OS == models.OS_Types.IoT {
|
||||||
|
node.IsRelay = true // for iot update to recognise that it has to delete relay peer
|
||||||
|
if err = mq.PublishSingleHostPeerUpdate(context.Background(), h, &node, nil); err != nil {
|
||||||
|
logger.Log(1, "failed to publish peer update to host", h.ID.String(), ": ", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mq.PublishPeerUpdate()
|
mq.PublishPeerUpdate()
|
||||||
}()
|
}()
|
||||||
|
@@ -16,6 +16,7 @@ import (
|
|||||||
// InitEE - Initialize EE Logic
|
// InitEE - Initialize EE Logic
|
||||||
func InitEE() {
|
func InitEE() {
|
||||||
setIsEnterprise()
|
setIsEnterprise()
|
||||||
|
servercfg.Is_EE = true
|
||||||
models.SetLogo(retrieveEELogo())
|
models.SetLogo(retrieveEELogo())
|
||||||
controller.HttpHandlers = append(
|
controller.HttpHandlers = append(
|
||||||
controller.HttpHandlers,
|
controller.HttpHandlers,
|
||||||
@@ -27,13 +28,8 @@ func InitEE() {
|
|||||||
logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {
|
logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {
|
||||||
// == License Handling ==
|
// == License Handling ==
|
||||||
ValidateLicense()
|
ValidateLicense()
|
||||||
if Limits.FreeTier {
|
|
||||||
logger.Log(0, "proceeding with Free Tier license")
|
|
||||||
logic.SetFreeTierForTelemetry(true)
|
|
||||||
} else {
|
|
||||||
logger.Log(0, "proceeding with Paid Tier license")
|
logger.Log(0, "proceeding with Paid Tier license")
|
||||||
logic.SetFreeTierForTelemetry(false)
|
logic.SetFreeTierForTelemetry(false)
|
||||||
}
|
|
||||||
// == End License Handling ==
|
// == End License Handling ==
|
||||||
AddLicenseHooks()
|
AddLicenseHooks()
|
||||||
resetFailover()
|
resetFailover()
|
||||||
@@ -46,17 +42,6 @@ func InitEE() {
|
|||||||
logic.AllowClientNodeAccess = eelogic.RemoveDeniedNodeFromClient
|
logic.AllowClientNodeAccess = eelogic.RemoveDeniedNodeFromClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func setControllerLimits() {
|
|
||||||
logic.Node_Limit = Limits.Nodes
|
|
||||||
logic.Users_Limit = Limits.Users
|
|
||||||
logic.Clients_Limit = Limits.Clients
|
|
||||||
logic.Free_Tier = Limits.FreeTier
|
|
||||||
servercfg.Is_EE = true
|
|
||||||
if logic.Free_Tier {
|
|
||||||
logic.Networks_Limit = 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func resetFailover() {
|
func resetFailover() {
|
||||||
nets, err := logic.GetNetworks()
|
nets, err := logic.GetNetworks()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@@ -9,12 +9,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
"github.com/gravitl/netmaker/logic"
|
"github.com/gravitl/netmaker/logic"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
"golang.org/x/crypto/nacl/box"
|
"golang.org/x/crypto/nacl/box"
|
||||||
@@ -31,8 +32,14 @@ type apiServerConf struct {
|
|||||||
|
|
||||||
// AddLicenseHooks - adds the validation and cache clear hooks
|
// AddLicenseHooks - adds the validation and cache clear hooks
|
||||||
func AddLicenseHooks() {
|
func AddLicenseHooks() {
|
||||||
logic.AddHook(ValidateLicense)
|
logic.HookManagerCh <- models.HookDetails{
|
||||||
logic.AddHook(ClearLicenseCache)
|
Hook: ValidateLicense,
|
||||||
|
Interval: time.Hour,
|
||||||
|
}
|
||||||
|
logic.HookManagerCh <- models.HookDetails{
|
||||||
|
Hook: ClearLicenseCache,
|
||||||
|
Interval: time.Hour,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateLicense - the initial license check for netmaker server
|
// ValidateLicense - the initial license check for netmaker server
|
||||||
@@ -58,7 +65,7 @@ func ValidateLicense() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
licenseSecret := LicenseSecret{
|
licenseSecret := LicenseSecret{
|
||||||
UserID: netmakerAccountID,
|
AssociatedID: netmakerAccountID,
|
||||||
Limits: getCurrentServerLimit(),
|
Limits: getCurrentServerLimit(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,17 +99,6 @@ func ValidateLicense() error {
|
|||||||
logger.FatalLog0(errValidation.Error())
|
logger.FatalLog0(errValidation.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
Limits.Networks = math.MaxInt
|
|
||||||
Limits.FreeTier = license.FreeTier == "yes"
|
|
||||||
Limits.Clients = license.LimitClients
|
|
||||||
Limits.Nodes = license.LimitNodes
|
|
||||||
Limits.Servers = license.LimitServers
|
|
||||||
Limits.Users = license.LimitUsers
|
|
||||||
if Limits.FreeTier {
|
|
||||||
Limits.Networks = 3
|
|
||||||
}
|
|
||||||
setControllerLimits()
|
|
||||||
|
|
||||||
logger.Log(0, "License validation succeeded!")
|
logger.Log(0, "License validation succeeded!")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -167,6 +163,7 @@ func validateLicenseKey(encryptedData []byte, publicKey *[32]byte) ([]byte, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg := ValidateLicenseRequest{
|
msg := ValidateLicenseRequest{
|
||||||
|
LicenseKey: servercfg.GetLicenseKey(),
|
||||||
NmServerPubKey: base64encode(publicKeyBytes),
|
NmServerPubKey: base64encode(publicKeyBytes),
|
||||||
EncryptedPart: base64encode(encryptedData),
|
EncryptedPart: base64encode(encryptedData),
|
||||||
}
|
}
|
||||||
@@ -180,9 +177,6 @@ func validateLicenseKey(encryptedData []byte, publicKey *[32]byte) ([]byte, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
reqParams := req.URL.Query()
|
|
||||||
reqParams.Add("licensevalue", servercfg.GetLicenseKey())
|
|
||||||
req.URL.RawQuery = reqParams.Encode()
|
|
||||||
req.Header.Add("Content-Type", "application/json")
|
req.Header.Add("Content-Type", "application/json")
|
||||||
req.Header.Add("Accept", "application/json")
|
req.Header.Add("Accept", "application/json")
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
44
ee/types.go
44
ee/types.go
@@ -3,7 +3,7 @@ package ee
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
api_endpoint = "https://api.controller.netmaker.io/api/v1/license/validate"
|
api_endpoint = "https://api.accounts.netmaker.io/api/v1/license/validate"
|
||||||
license_cache_key = "license_response_cache"
|
license_cache_key = "license_response_cache"
|
||||||
license_validation_err_msg = "invalid license"
|
license_validation_err_msg = "invalid license"
|
||||||
server_id_key = "nm-server-id"
|
server_id_key = "nm-server-id"
|
||||||
@@ -11,38 +11,17 @@ const (
|
|||||||
|
|
||||||
var errValidation = fmt.Errorf(license_validation_err_msg)
|
var errValidation = fmt.Errorf(license_validation_err_msg)
|
||||||
|
|
||||||
// Limits - limits to be referenced throughout server
|
|
||||||
var Limits = GlobalLimits{
|
|
||||||
Servers: 0,
|
|
||||||
Users: 0,
|
|
||||||
Nodes: 0,
|
|
||||||
Clients: 0,
|
|
||||||
Networks: 0,
|
|
||||||
FreeTier: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalLimits - struct for holding global limits on this netmaker server in memory
|
|
||||||
type GlobalLimits struct {
|
|
||||||
Servers int
|
|
||||||
Users int
|
|
||||||
Nodes int
|
|
||||||
Clients int
|
|
||||||
FreeTier bool
|
|
||||||
Networks int
|
|
||||||
}
|
|
||||||
|
|
||||||
// LicenseKey - the license key struct representation with associated data
|
// LicenseKey - the license key struct representation with associated data
|
||||||
type LicenseKey struct {
|
type LicenseKey struct {
|
||||||
LicenseValue string `json:"license_value"` // actual (public) key and the unique value for the key
|
LicenseValue string `json:"license_value"` // actual (public) key and the unique value for the key
|
||||||
Expiration int64 `json:"expiration"`
|
Expiration int64 `json:"expiration"`
|
||||||
LimitServers int `json:"limit_servers"`
|
LimitServers int `json:"limit_servers"`
|
||||||
LimitUsers int `json:"limit_users"`
|
LimitUsers int `json:"limit_users"`
|
||||||
LimitNodes int `json:"limit_nodes"`
|
LimitHosts int `json:"limit_hosts"`
|
||||||
|
LimitNetworks int `json:"limit_networks"`
|
||||||
LimitClients int `json:"limit_clients"`
|
LimitClients int `json:"limit_clients"`
|
||||||
Metadata string `json:"metadata"`
|
Metadata string `json:"metadata"`
|
||||||
SubscriptionID string `json:"subscription_id"` // for a paid subscription (non-free-tier license)
|
IsActive bool `json:"is_active"` // yes if active
|
||||||
FreeTier string `json:"free_tier"` // yes if free tier
|
|
||||||
IsActive string `json:"is_active"` // yes if active
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidatedLicense - the validated license struct
|
// ValidatedLicense - the validated license struct
|
||||||
@@ -53,28 +32,31 @@ type ValidatedLicense struct {
|
|||||||
|
|
||||||
// LicenseSecret - the encrypted struct for sending user-id
|
// LicenseSecret - the encrypted struct for sending user-id
|
||||||
type LicenseSecret struct {
|
type LicenseSecret struct {
|
||||||
UserID string `json:"user_id" binding:"required"` // UUID for user foreign key to User table
|
AssociatedID string `json:"associated_id" binding:"required"` // UUID for user foreign key to User table
|
||||||
Limits LicenseLimits `json:"limits" binding:"required"`
|
Limits LicenseLimits `json:"limits" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LicenseLimits - struct license limits
|
// LicenseLimits - struct license limits
|
||||||
type LicenseLimits struct {
|
type LicenseLimits struct {
|
||||||
Servers int `json:"servers" binding:"required"`
|
Servers int `json:"servers"`
|
||||||
Users int `json:"users" binding:"required"`
|
Users int `json:"users"`
|
||||||
Nodes int `json:"nodes" binding:"required"`
|
Hosts int `json:"hosts"`
|
||||||
Clients int `json:"clients" binding:"required"`
|
Clients int `json:"clients"`
|
||||||
|
Networks int `json:"networks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LicenseLimits.SetDefaults - sets the default values for limits
|
// LicenseLimits.SetDefaults - sets the default values for limits
|
||||||
func (l *LicenseLimits) SetDefaults() {
|
func (l *LicenseLimits) SetDefaults() {
|
||||||
l.Clients = 0
|
l.Clients = 0
|
||||||
l.Servers = 1
|
l.Servers = 1
|
||||||
l.Nodes = 0
|
l.Hosts = 0
|
||||||
l.Users = 1
|
l.Users = 1
|
||||||
|
l.Networks = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateLicenseRequest - used for request to validate license endpoint
|
// ValidateLicenseRequest - used for request to validate license endpoint
|
||||||
type ValidateLicenseRequest struct {
|
type ValidateLicenseRequest struct {
|
||||||
|
LicenseKey string `json:"license_key" binding:"required"`
|
||||||
NmServerPubKey string `json:"nm_server_pub_key" binding:"required"` // Netmaker server public key used to send data back to Netmaker for the Netmaker server to decrypt (eg output from validating license)
|
NmServerPubKey string `json:"nm_server_pub_key" binding:"required"` // Netmaker server public key used to send data back to Netmaker for the Netmaker server to decrypt (eg output from validating license)
|
||||||
EncryptedPart string `json:"secret" binding:"required"`
|
EncryptedPart string `json:"secret" binding:"required"`
|
||||||
}
|
}
|
||||||
|
@@ -30,12 +30,11 @@ func base64decode(input string) []byte {
|
|||||||
|
|
||||||
return bytes
|
return bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCurrentServerLimit() (limits LicenseLimits) {
|
func getCurrentServerLimit() (limits LicenseLimits) {
|
||||||
limits.SetDefaults()
|
limits.SetDefaults()
|
||||||
nodes, err := logic.GetAllNodes()
|
hosts, err := logic.GetAllHosts()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
limits.Nodes = len(nodes)
|
limits.Hosts = len(hosts)
|
||||||
}
|
}
|
||||||
clients, err := logic.GetAllExtClients()
|
clients, err := logic.GetAllExtClients()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -45,5 +44,9 @@ func getCurrentServerLimit() (limits LicenseLimits) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
limits.Users = len(users)
|
limits.Users = len(users)
|
||||||
}
|
}
|
||||||
|
networks, err := logic.GetNetworks()
|
||||||
|
if err == nil {
|
||||||
|
limits.Networks = len(networks)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -159,7 +159,14 @@ func GetHost(hostid string) (*models.Host, error) {
|
|||||||
|
|
||||||
// CreateHost - creates a host if not exist
|
// CreateHost - creates a host if not exist
|
||||||
func CreateHost(h *models.Host) error {
|
func CreateHost(h *models.Host) error {
|
||||||
_, err := GetHost(h.ID.String())
|
hosts, err := GetAllHosts()
|
||||||
|
if err != nil && !database.IsEmptyRecord(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(hosts) >= Hosts_Limit {
|
||||||
|
return errors.New("free tier limits exceeded on hosts")
|
||||||
|
}
|
||||||
|
_, err = GetHost(h.ID.String())
|
||||||
if (err != nil && !database.IsEmptyRecord(err)) || (err == nil) {
|
if (err != nil && !database.IsEmptyRecord(err)) || (err == nil) {
|
||||||
return ErrHostExists
|
return ErrHostExists
|
||||||
}
|
}
|
||||||
|
@@ -131,6 +131,61 @@ func GetPeerUpdateForHost(ctx context.Context, network string, host *models.Host
|
|||||||
if !node.Connected || node.PendingDelete || node.Action == models.NODE_DELETE {
|
if !node.Connected || node.PendingDelete || node.Action == models.NODE_DELETE {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if host.OS == models.OS_Types.IoT {
|
||||||
|
hostPeerUpdate.NodeAddrs = append(hostPeerUpdate.NodeAddrs, node.PrimaryAddressIPNet())
|
||||||
|
if node.IsRelayed {
|
||||||
|
relayNode, err := GetNodeByID(node.RelayedBy)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
relayHost, err := GetHost(relayNode.HostID.String())
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
relayPeer := wgtypes.PeerConfig{
|
||||||
|
PublicKey: relayHost.PublicKey,
|
||||||
|
PersistentKeepaliveInterval: &relayNode.PersistentKeepalive,
|
||||||
|
ReplaceAllowedIPs: true,
|
||||||
|
AllowedIPs: GetAllowedIPs(&node, &relayNode, nil),
|
||||||
|
}
|
||||||
|
uselocal := false
|
||||||
|
if host.EndpointIP.String() == relayHost.EndpointIP.String() {
|
||||||
|
// peer is on same network
|
||||||
|
// set to localaddress
|
||||||
|
uselocal = true
|
||||||
|
if node.LocalAddress.IP == nil {
|
||||||
|
// use public endpint
|
||||||
|
uselocal = false
|
||||||
|
}
|
||||||
|
if node.LocalAddress.String() == relayNode.LocalAddress.String() {
|
||||||
|
uselocal = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
relayPeer.Endpoint = &net.UDPAddr{
|
||||||
|
IP: relayHost.EndpointIP,
|
||||||
|
Port: getPeerWgListenPort(relayHost),
|
||||||
|
}
|
||||||
|
|
||||||
|
if uselocal {
|
||||||
|
relayPeer.Endpoint.IP = relayNode.LocalAddress.IP
|
||||||
|
relayPeer.Endpoint.Port = relayHost.ListenPort
|
||||||
|
}
|
||||||
|
|
||||||
|
hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, relayPeer)
|
||||||
|
} else if deletedNode != nil && deletedNode.IsRelay {
|
||||||
|
relayHost, err := GetHost(deletedNode.HostID.String())
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
relayPeer := wgtypes.PeerConfig{
|
||||||
|
PublicKey: relayHost.PublicKey,
|
||||||
|
Remove: true,
|
||||||
|
}
|
||||||
|
hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, relayPeer)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
currentPeers := GetNetworkNodesMemory(allNodes, node.Network)
|
currentPeers := GetNetworkNodesMemory(allNodes, node.Network)
|
||||||
var nodePeerMap map[string]models.PeerRouteInfo
|
var nodePeerMap map[string]models.PeerRouteInfo
|
||||||
if node.IsIngressGateway || node.IsEgressGateway {
|
if node.IsIngressGateway || node.IsEgressGateway {
|
||||||
|
@@ -4,17 +4,18 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Node_Limit - dummy var for community
|
|
||||||
Node_Limit = 1000000000
|
|
||||||
// Networks_Limit - dummy var for community
|
// Networks_Limit - dummy var for community
|
||||||
Networks_Limit = 1000000000
|
Networks_Limit = 1000000000
|
||||||
// Users_Limit - dummy var for community
|
// Users_Limit - dummy var for community
|
||||||
Users_Limit = 1000000000
|
Users_Limit = 1000000000
|
||||||
// Clients_Limit - dummy var for community
|
// Clients_Limit - dummy var for community
|
||||||
Clients_Limit = 1000000000
|
Clients_Limit = 1000000000
|
||||||
|
// Hosts_Limit - dummy var for community
|
||||||
|
Hosts_Limit = 1000000000
|
||||||
// Free_Tier - specifies if free tier
|
// Free_Tier - specifies if free tier
|
||||||
Free_Tier = false
|
Free_Tier = false
|
||||||
)
|
)
|
||||||
@@ -85,3 +86,11 @@ func StoreJWTSecret(privateKey string) error {
|
|||||||
}
|
}
|
||||||
return database.Insert("nm-jwt-secret", string(data), database.SERVERCONF_TABLE_NAME)
|
return database.Insert("nm-jwt-secret", string(data), database.SERVERCONF_TABLE_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetFreeTierLimits() {
|
||||||
|
Free_Tier = true
|
||||||
|
Users_Limit = servercfg.GetUserLimit()
|
||||||
|
Clients_Limit = servercfg.GetClientLimit()
|
||||||
|
Networks_Limit = servercfg.GetNetworkLimit()
|
||||||
|
Hosts_Limit = servercfg.GetHostLimit()
|
||||||
|
}
|
||||||
|
@@ -60,6 +60,7 @@ func sendTelemetry() error {
|
|||||||
Event: "daily checkin",
|
Event: "daily checkin",
|
||||||
Properties: posthog.NewProperties().
|
Properties: posthog.NewProperties().
|
||||||
Set("nodes", d.Nodes).
|
Set("nodes", d.Nodes).
|
||||||
|
Set("hosts", d.Hosts).
|
||||||
Set("servers", d.Servers).
|
Set("servers", d.Servers).
|
||||||
Set("non-server nodes", d.Count.NonServer).
|
Set("non-server nodes", d.Count.NonServer).
|
||||||
Set("extclients", d.ExtClients).
|
Set("extclients", d.ExtClients).
|
||||||
@@ -84,6 +85,7 @@ func fetchTelemetryData() (telemetryData, error) {
|
|||||||
data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME)
|
data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME)
|
||||||
data.Users = getDBLength(database.USERS_TABLE_NAME)
|
data.Users = getDBLength(database.USERS_TABLE_NAME)
|
||||||
data.Networks = getDBLength(database.NETWORKS_TABLE_NAME)
|
data.Networks = getDBLength(database.NETWORKS_TABLE_NAME)
|
||||||
|
data.Hosts = getDBLength(database.HOSTS_TABLE_NAME)
|
||||||
data.Version = servercfg.GetVersion()
|
data.Version = servercfg.GetVersion()
|
||||||
data.Servers = getServerCount()
|
data.Servers = getServerCount()
|
||||||
nodes, err := GetAllNodes()
|
nodes, err := GetAllNodes()
|
||||||
@@ -167,6 +169,7 @@ func getDBLength(dbname string) int {
|
|||||||
// telemetryData - What data to send to posthog
|
// telemetryData - What data to send to posthog
|
||||||
type telemetryData struct {
|
type telemetryData struct {
|
||||||
Nodes int
|
Nodes int
|
||||||
|
Hosts int
|
||||||
ExtClients int
|
ExtClients int
|
||||||
Users int
|
Users int
|
||||||
Count clientCount
|
Count clientCount
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
package logic
|
package logic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// == Constants ==
|
// == Constants ==
|
||||||
@@ -12,6 +15,9 @@ import (
|
|||||||
// How long to wait before sending telemetry to server (24 hours)
|
// How long to wait before sending telemetry to server (24 hours)
|
||||||
const timer_hours_between_runs = 24
|
const timer_hours_between_runs = 24
|
||||||
|
|
||||||
|
// HookManagerCh - channel to add any new hooks
|
||||||
|
var HookManagerCh = make(chan models.HookDetails, 2)
|
||||||
|
|
||||||
// == Public ==
|
// == Public ==
|
||||||
|
|
||||||
// TimerCheckpoint - Checks if 24 hours has passed since telemetry was last sent. If so, sends telemetry data to posthog
|
// TimerCheckpoint - Checks if 24 hours has passed since telemetry was last sent. If so, sends telemetry data to posthog
|
||||||
@@ -40,6 +46,36 @@ func AddHook(ifaceToAdd interface{}) {
|
|||||||
timeHooks = append(timeHooks, ifaceToAdd)
|
timeHooks = append(timeHooks, ifaceToAdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartHookManager - listens on `HookManagerCh` to run any hook
|
||||||
|
func StartHookManager(ctx context.Context, wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
logger.Log(0, "## Stopping Hook Manager")
|
||||||
|
return
|
||||||
|
case newhook := <-HookManagerCh:
|
||||||
|
wg.Add(1)
|
||||||
|
go addHookWithInterval(ctx, wg, newhook.Hook, newhook.Interval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addHookWithInterval(ctx context.Context, wg *sync.WaitGroup, hook func() error, interval time.Duration) {
|
||||||
|
defer wg.Done()
|
||||||
|
ticker := time.NewTicker(interval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
hook()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// == private ==
|
// == private ==
|
||||||
|
|
||||||
// timeHooks - functions to run once a day, functions must take no parameters
|
// timeHooks - functions to run once a day, functions must take no parameters
|
||||||
|
7
main.go
7
main.go
@@ -42,6 +42,9 @@ func main() {
|
|||||||
initialize() // initial db and acls
|
initialize() // initial db and acls
|
||||||
setGarbageCollection()
|
setGarbageCollection()
|
||||||
setVerbosity()
|
setVerbosity()
|
||||||
|
if servercfg.DeployedByOperator() && !servercfg.Is_EE {
|
||||||
|
logic.SetFreeTierLimits()
|
||||||
|
}
|
||||||
defer database.CloseDB()
|
defer database.CloseDB()
|
||||||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, os.Interrupt)
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, os.Interrupt)
|
||||||
defer stop()
|
defer stop()
|
||||||
@@ -89,7 +92,6 @@ func initialize() { // Client Mode Prereq Check
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(1, "Timer error occurred: ", err.Error())
|
logger.Log(1, "Timer error occurred: ", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
logic.EnterpriseCheck()
|
logic.EnterpriseCheck()
|
||||||
|
|
||||||
var authProvider = auth.InitializeAuthProvider()
|
var authProvider = auth.InitializeAuthProvider()
|
||||||
@@ -150,6 +152,9 @@ func startControllers(wg *sync.WaitGroup, ctx context.Context) {
|
|||||||
// starts the stun server
|
// starts the stun server
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go stunserver.Start(wg, ctx)
|
go stunserver.Start(wg, ctx)
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go logic.StartHookManager(ctx, wg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should we be using a context vice a waitgroup????????????
|
// Should we be using a context vice a waitgroup????????????
|
||||||
|
@@ -34,6 +34,7 @@ type ApiHost struct {
|
|||||||
RelayedBy string `json:"relayed_by" bson:"relayed_by" yaml:"relayed_by"`
|
RelayedBy string `json:"relayed_by" bson:"relayed_by" yaml:"relayed_by"`
|
||||||
IsRelay bool `json:"isrelay" bson:"isrelay" yaml:"isrelay"`
|
IsRelay bool `json:"isrelay" bson:"isrelay" yaml:"isrelay"`
|
||||||
RelayedHosts []string `json:"relay_hosts" bson:"relay_hosts" yaml:"relay_hosts"`
|
RelayedHosts []string `json:"relay_hosts" bson:"relay_hosts" yaml:"relay_hosts"`
|
||||||
|
NatType string `json:"nat_type" yaml:"nat_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host.ConvertNMHostToAPI - converts a Netmaker host to an API editable host
|
// Host.ConvertNMHostToAPI - converts a Netmaker host to an API editable host
|
||||||
@@ -67,6 +68,7 @@ func (h *Host) ConvertNMHostToAPI() *ApiHost {
|
|||||||
a.Verbosity = h.Verbosity
|
a.Verbosity = h.Verbosity
|
||||||
a.Version = h.Version
|
a.Version = h.Version
|
||||||
a.IsDefault = h.IsDefault
|
a.IsDefault = h.IsDefault
|
||||||
|
a.NatType = h.NatType
|
||||||
return &a
|
return &a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ import (
|
|||||||
// HostPeerUpdate - struct for host peer updates
|
// HostPeerUpdate - struct for host peer updates
|
||||||
type HostPeerUpdate struct {
|
type HostPeerUpdate struct {
|
||||||
Host Host `json:"host" bson:"host" yaml:"host"`
|
Host Host `json:"host" bson:"host" yaml:"host"`
|
||||||
|
NodeAddrs []net.IPNet `json:"nodes_addrs" yaml:"nodes_addrs"`
|
||||||
Server string `json:"server" bson:"server" yaml:"server"`
|
Server string `json:"server" bson:"server" yaml:"server"`
|
||||||
ServerVersion string `json:"serverversion" bson:"serverversion" yaml:"serverversion"`
|
ServerVersion string `json:"serverversion" bson:"serverversion" yaml:"serverversion"`
|
||||||
ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"`
|
ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"`
|
||||||
|
@@ -181,6 +181,14 @@ func isLess(ipA string, ipB string) bool {
|
|||||||
return bytes.Compare(ipNetA, ipNetB) < 0
|
return bytes.Compare(ipNetA, ipNetB) < 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Node.PrimaryAddress - return ipv4 address if present, else return ipv6
|
||||||
|
func (node *Node) PrimaryAddressIPNet() net.IPNet {
|
||||||
|
if node.Address.IP != nil {
|
||||||
|
return node.Address
|
||||||
|
}
|
||||||
|
return node.Address6
|
||||||
|
}
|
||||||
|
|
||||||
// Node.PrimaryAddress - return ipv4 address if present, else return ipv6
|
// Node.PrimaryAddress - return ipv4 address if present, else return ipv6
|
||||||
func (node *Node) PrimaryAddress() string {
|
func (node *Node) PrimaryAddress() string {
|
||||||
if node.Address.IP != nil {
|
if node.Address.IP != nil {
|
||||||
|
@@ -2,6 +2,7 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
jwt "github.com/golang-jwt/jwt/v4"
|
jwt "github.com/golang-jwt/jwt/v4"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
@@ -274,3 +275,18 @@ type StunServer struct {
|
|||||||
Domain string `json:"domain" yaml:"domain"`
|
Domain string `json:"domain" yaml:"domain"`
|
||||||
Port int `json:"port" yaml:"port"`
|
Port int `json:"port" yaml:"port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HookDetails - struct to hold hook info
|
||||||
|
type HookDetails struct {
|
||||||
|
Hook func() error
|
||||||
|
Interval time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// LicenseLimits - struct license limits
|
||||||
|
type LicenseLimits struct {
|
||||||
|
Servers int `json:"servers"`
|
||||||
|
Users int `json:"users"`
|
||||||
|
Hosts int `json:"hosts"`
|
||||||
|
Clients int `json:"clients"`
|
||||||
|
Networks int `json:"networks"`
|
||||||
|
}
|
||||||
|
@@ -6,11 +6,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const already_exists = "ALREADY_EXISTS"
|
||||||
|
|
||||||
type (
|
type (
|
||||||
emqxUser struct {
|
emqxUser struct {
|
||||||
UserID string `json:"user_id"`
|
UserID string `json:"user_id"`
|
||||||
@@ -99,8 +102,10 @@ func CreateEmqxUser(username, password string, admin bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(string(msg), already_exists) {
|
||||||
return fmt.Errorf("error creating EMQX user %v", string(msg))
|
return fmt.Errorf("error creating EMQX user %v", string(msg))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -100,6 +100,7 @@ func PublishSingleHostPeerUpdate(ctx context.Context, host *models.Host, allNode
|
|||||||
if len(peerUpdate.Peers) == 0 { // no peers to send
|
if len(peerUpdate.Peers) == 0 { // no peers to send
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if host.OS != models.OS_Types.IoT {
|
||||||
proxyUpdate, err := logic.GetProxyUpdateForHost(ctx, host)
|
proxyUpdate, err := logic.GetProxyUpdateForHost(ctx, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -112,6 +113,7 @@ func PublishSingleHostPeerUpdate(ctx context.Context, host *models.Host, allNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
peerUpdate.ProxyUpdate = proxyUpdate
|
peerUpdate.ProxyUpdate = proxyUpdate
|
||||||
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(&peerUpdate)
|
data, err := json.Marshal(&peerUpdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/config"
|
"github.com/gravitl/netmaker/config"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -741,6 +742,58 @@ func IsProxyEnabled() bool {
|
|||||||
return enabled
|
return enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNetworkLimit - fetches free tier limits on users
|
||||||
|
func GetUserLimit() int {
|
||||||
|
var userslimit int
|
||||||
|
if os.Getenv("USERS_LIMIT") != "" {
|
||||||
|
userslimit, _ = strconv.Atoi(os.Getenv("USERS_LIMIT"))
|
||||||
|
} else {
|
||||||
|
userslimit = config.Config.Server.UsersLimit
|
||||||
|
}
|
||||||
|
return userslimit
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkLimit - fetches free tier limits on networks
|
||||||
|
func GetNetworkLimit() int {
|
||||||
|
var networkslimit int
|
||||||
|
if os.Getenv("NETWORKS_LIMIT") != "" {
|
||||||
|
networkslimit, _ = strconv.Atoi(os.Getenv("NETWORKS_LIMIT"))
|
||||||
|
} else {
|
||||||
|
networkslimit = config.Config.Server.NetworksLimit
|
||||||
|
}
|
||||||
|
return networkslimit
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetClientLimit - fetches free tier limits on ext. clients
|
||||||
|
func GetClientLimit() int {
|
||||||
|
var clientsLimit int
|
||||||
|
if os.Getenv("CLIENTS_LIMIT") != "" {
|
||||||
|
clientsLimit, _ = strconv.Atoi(os.Getenv("CLIENTS_LIMIT"))
|
||||||
|
} else {
|
||||||
|
clientsLimit = config.Config.Server.ClientsLimit
|
||||||
|
}
|
||||||
|
return clientsLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHostLimit - fetches free tier limits on hosts
|
||||||
|
func GetHostLimit() int {
|
||||||
|
var hostsLimit int
|
||||||
|
if os.Getenv("HOSTS_LIMIT") != "" {
|
||||||
|
hostsLimit, _ = strconv.Atoi(os.Getenv("HOSTS_LIMIT"))
|
||||||
|
} else {
|
||||||
|
hostsLimit = config.Config.Server.HostsLimit
|
||||||
|
}
|
||||||
|
return hostsLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeployedByOperator - returns true if the instance is deployed by netmaker operator
|
||||||
|
func DeployedByOperator() bool {
|
||||||
|
if os.Getenv("DEPLOYED_BY_OPERATOR") != "" {
|
||||||
|
return os.Getenv("DEPLOYED_BY_OPERATOR") == "true"
|
||||||
|
}
|
||||||
|
return config.Config.Server.DeployedByOperator
|
||||||
|
}
|
||||||
|
|
||||||
// GetDefaultProxyMode - default proxy mode for a server
|
// GetDefaultProxyMode - default proxy mode for a server
|
||||||
func GetDefaultProxyMode() config.ProxyMode {
|
func GetDefaultProxyMode() config.ProxyMode {
|
||||||
var (
|
var (
|
||||||
|
Reference in New Issue
Block a user