main.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. // -build ee
  2. package main
  3. import (
  4. "context"
  5. "crypto/rand"
  6. "encoding/json"
  7. "flag"
  8. "fmt"
  9. "net"
  10. "os"
  11. "os/signal"
  12. "path/filepath"
  13. "runtime/debug"
  14. "sync"
  15. "syscall"
  16. "time"
  17. "github.com/cilium/fake"
  18. "github.com/google/uuid"
  19. "github.com/gravitl/netmaker/config"
  20. controller "github.com/gravitl/netmaker/controllers"
  21. "github.com/gravitl/netmaker/database"
  22. "github.com/gravitl/netmaker/db"
  23. "github.com/gravitl/netmaker/functions"
  24. "github.com/gravitl/netmaker/logger"
  25. "github.com/gravitl/netmaker/logic"
  26. "github.com/gravitl/netmaker/migrate"
  27. "github.com/gravitl/netmaker/models"
  28. "github.com/gravitl/netmaker/mq"
  29. "github.com/gravitl/netmaker/netclient/ncutils"
  30. "github.com/gravitl/netmaker/schema"
  31. "github.com/gravitl/netmaker/servercfg"
  32. "github.com/gravitl/netmaker/serverctl"
  33. _ "go.uber.org/automaxprocs"
  34. "golang.org/x/crypto/nacl/box"
  35. "golang.org/x/exp/slog"
  36. )
  37. var version = "v0.99.0"
  38. // @title NetMaker
  39. // @version 0.99.0
  40. // @description NetMaker API Docs
  41. // @tag.name APIUsage
  42. // @tag.description.markdown
  43. // @tag.name Authentication
  44. // @tag.description.markdown
  45. // @tag.name Pricing
  46. // @tag.description.markdown
  47. // @host api.demo.netmaker.io
  48. // Start DB Connection and start API Request Handler
  49. func main() {
  50. absoluteConfigPath := flag.String("c", "", "absolute path to configuration file")
  51. flag.Parse()
  52. setupConfig(*absoluteConfigPath)
  53. servercfg.SetVersion(version)
  54. fmt.Println(models.RetrieveLogo()) // print the logo
  55. initialize() // initial db and acls
  56. logic.SetAllocatedIpMap()
  57. defer logic.ClearAllocatedIpMap()
  58. setGarbageCollection()
  59. setVerbosity()
  60. if servercfg.DeployedByOperator() && !servercfg.IsPro {
  61. logic.SetFreeTierLimits()
  62. }
  63. defer db.CloseDB()
  64. defer database.CloseDB()
  65. ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, os.Interrupt)
  66. defer stop()
  67. var waitGroup sync.WaitGroup
  68. startControllers(&waitGroup, ctx) // start the api endpoint and mq and stun
  69. startHooks()
  70. <-ctx.Done()
  71. waitGroup.Wait()
  72. }
  73. func setupConfig(absoluteConfigPath string) {
  74. if len(absoluteConfigPath) > 0 {
  75. cfg, err := config.ReadConfig(absoluteConfigPath)
  76. if err != nil {
  77. logger.Log(0, fmt.Sprintf("failed parsing config at: %s", absoluteConfigPath))
  78. return
  79. }
  80. config.Config = cfg
  81. }
  82. }
  83. func startHooks() {
  84. err := logic.TimerCheckpoint()
  85. if err != nil {
  86. logger.Log(1, "Timer error occurred: ", err.Error())
  87. }
  88. logic.EnterpriseCheck()
  89. }
  90. func initialize() { // Client Mode Prereq Check
  91. var err error
  92. if servercfg.GetMasterKey() == "" {
  93. logger.Log(0, "warning: MASTER_KEY not set, this could make account recovery difficult")
  94. }
  95. if servercfg.GetNodeID() == "" {
  96. logger.FatalLog("error: must set NODE_ID, currently blank")
  97. }
  98. // initialize sql schema db.
  99. err = db.InitializeDB(schema.ListModels()...)
  100. if err != nil {
  101. logger.FatalLog("error connecting to database: ", err.Error())
  102. }
  103. logger.Log(0, "database successfully connected")
  104. // initialize kv schema db.
  105. if err = database.InitializeDatabase(); err != nil {
  106. logger.FatalLog("error initializing database: ", err.Error())
  107. }
  108. initializeUUID()
  109. //initialize cache
  110. _, _ = logic.GetNetworks()
  111. _, _ = logic.GetAllNodes()
  112. _, _ = logic.GetAllHosts()
  113. _, _ = logic.GetAllExtClients()
  114. _ = logic.ListAcls()
  115. _, _ = logic.GetAllEnrollmentKeys()
  116. migrate.Run()
  117. logic.SetJWTSecret()
  118. logic.InitialiseRoles()
  119. logic.IntialiseGroups()
  120. err = serverctl.SetDefaults()
  121. if err != nil {
  122. logger.FatalLog("error setting defaults: ", err.Error())
  123. }
  124. if servercfg.IsDNSMode() {
  125. err := functions.SetDNSDir()
  126. if err != nil {
  127. logger.FatalLog(err.Error())
  128. }
  129. }
  130. if servercfg.IsMessageQueueBackend() {
  131. if err = mq.ServerStartNotify(); err != nil {
  132. logger.Log(0, "error occurred when notifying nodes of startup", err.Error())
  133. }
  134. }
  135. go GenerateFakeData()
  136. }
  137. func GenerateFakeData() {
  138. if os.Getenv("GENERATE_FAKE") != "true" {
  139. return
  140. }
  141. var network models.Network
  142. network.NetID = "mock"
  143. network.AddressRange = "10.0.0.0/8"
  144. network.IsIPv4 = "yes"
  145. logic.CreateNetwork(network)
  146. //add new network to allocated ip map
  147. go logic.AddNetworkToAllocatedIpMap(network.NetID)
  148. pub, _, err := box.GenerateKey(rand.Reader)
  149. if err != nil {
  150. logger.FatalLog("error generating traffic keys", err.Error())
  151. }
  152. bytes, err := ncutils.ConvertKeyToBytes(pub)
  153. if err != nil {
  154. logger.FatalLog("error generating traffic keys", err.Error())
  155. }
  156. hosts, _ := logic.GetAllHosts()
  157. for i := len(hosts); i <= 30; i++ {
  158. h := models.Host{
  159. ID: uuid.New(),
  160. Name: fake.App(),
  161. ListenPort: 51821,
  162. HostPass: fake.AlphaNum(8),
  163. Version: version,
  164. OS: models.OS_Types.Linux,
  165. EndpointIP: net.ParseIP(fake.IP(fake.WithIPv4())),
  166. EndpointIPv6: net.ParseIP(fake.IP(fake.WithIPv6())),
  167. TrafficKeyPublic: bytes,
  168. }
  169. logic.CreateHost(&h)
  170. _, _ = logic.UpdateHostNetwork(&h, network.NetID, true)
  171. time.Sleep(time.Millisecond * 600)
  172. }
  173. var network2 models.Network
  174. network2.NetID = "devops"
  175. network2.AddressRange = "100.24.0.0/16"
  176. network2.IsIPv4 = "yes"
  177. logic.CreateNetwork(network2)
  178. //add new network to allocated ip map
  179. go logic.AddNetworkToAllocatedIpMap(network.NetID)
  180. nodes, _ := logic.GetNetworkNodes(network2.NetID)
  181. count := len(nodes)
  182. hosts, _ = logic.GetAllHosts()
  183. for _, hI := range hosts {
  184. _, _ = logic.UpdateHostNetwork(&hI, network2.NetID, true)
  185. if count >= 30 {
  186. break
  187. }
  188. count++
  189. time.Sleep(time.Millisecond * 600)
  190. }
  191. }
  192. func startControllers(wg *sync.WaitGroup, ctx context.Context) {
  193. if servercfg.IsDNSMode() {
  194. err := logic.SetDNS()
  195. if err != nil {
  196. logger.Log(0, "error occurred initializing DNS: ", err.Error())
  197. }
  198. }
  199. //Run Rest Server
  200. if servercfg.IsRestBackend() {
  201. if !servercfg.DisableRemoteIPCheck() && servercfg.GetAPIHost() == "127.0.0.1" {
  202. err := servercfg.SetHost()
  203. if err != nil {
  204. logger.FatalLog("Unable to Set host. Exiting...", err.Error())
  205. }
  206. }
  207. wg.Add(1)
  208. go controller.HandleRESTRequests(wg, ctx)
  209. }
  210. //Run MessageQueue
  211. if servercfg.IsMessageQueueBackend() {
  212. wg.Add(1)
  213. go runMessageQueue(wg, ctx)
  214. }
  215. if !servercfg.IsRestBackend() && !servercfg.IsMessageQueueBackend() {
  216. logger.Log(
  217. 0,
  218. "No Server Mode selected, so nothing is being served! Set Rest mode (REST_BACKEND) or MessageQueue (MESSAGEQUEUE_BACKEND) to 'true'.",
  219. )
  220. }
  221. wg.Add(1)
  222. go logic.StartHookManager(ctx, wg)
  223. }
  224. // Should we be using a context vice a waitgroup????????????
  225. func runMessageQueue(wg *sync.WaitGroup, ctx context.Context) {
  226. defer wg.Done()
  227. brokerHost, _ := servercfg.GetMessageQueueEndpoint()
  228. logger.Log(0, "connecting to mq broker at", brokerHost)
  229. mq.SetupMQTT(true)
  230. if mq.IsConnected() {
  231. logger.Log(0, "connected to MQ Broker")
  232. } else {
  233. logger.FatalLog("error connecting to MQ Broker")
  234. }
  235. defer mq.CloseClient()
  236. go mq.Keepalive(ctx)
  237. go func() {
  238. peerUpdate := make(chan *models.Node, 100)
  239. go logic.ManageZombies(ctx, peerUpdate)
  240. go logic.DeleteExpiredNodes(ctx, peerUpdate)
  241. for nodeUpdate := range peerUpdate {
  242. if nodeUpdate == nil {
  243. continue
  244. }
  245. node := nodeUpdate
  246. node.Action = models.NODE_DELETE
  247. node.PendingDelete = true
  248. if err := mq.NodeUpdate(node); err != nil {
  249. logger.Log(
  250. 0,
  251. "failed to send peer update for deleted node: ",
  252. node.ID.String(),
  253. err.Error(),
  254. )
  255. }
  256. if err := logic.DeleteNode(node, true); err != nil {
  257. slog.Error(
  258. "error deleting expired node",
  259. "nodeid",
  260. node.ID.String(),
  261. "error",
  262. err.Error(),
  263. )
  264. }
  265. go mq.PublishDeletedNodePeerUpdate(node)
  266. }
  267. }()
  268. <-ctx.Done()
  269. logger.Log(0, "Message Queue shutting down")
  270. }
  271. func setVerbosity() {
  272. verbose := int(servercfg.GetVerbosity())
  273. logger.Verbosity = verbose
  274. logLevel := &slog.LevelVar{}
  275. replace := func(groups []string, a slog.Attr) slog.Attr {
  276. if a.Key == slog.SourceKey {
  277. a.Value = slog.StringValue(filepath.Base(a.Value.String()))
  278. }
  279. return a
  280. }
  281. logger := slog.New(
  282. slog.NewJSONHandler(
  283. os.Stderr,
  284. &slog.HandlerOptions{AddSource: true, ReplaceAttr: replace, Level: logLevel},
  285. ),
  286. )
  287. slog.SetDefault(logger)
  288. switch verbose {
  289. case 4:
  290. logLevel.Set(slog.LevelDebug)
  291. case 3:
  292. logLevel.Set(slog.LevelInfo)
  293. case 2:
  294. logLevel.Set(slog.LevelWarn)
  295. default:
  296. logLevel.Set(slog.LevelError)
  297. }
  298. }
  299. func setGarbageCollection() {
  300. _, gcset := os.LookupEnv("GOGC")
  301. if !gcset {
  302. debug.SetGCPercent(ncutils.DEFAULT_GC_PERCENT)
  303. }
  304. }
  305. // initializeUUID - create a UUID record for server if none exists
  306. func initializeUUID() error {
  307. records, err := database.FetchRecords(database.SERVER_UUID_TABLE_NAME)
  308. if err != nil {
  309. if !database.IsEmptyRecord(err) {
  310. return err
  311. }
  312. } else if len(records) > 0 {
  313. return nil
  314. }
  315. // setup encryption keys
  316. var trafficPubKey, trafficPrivKey, errT = box.GenerateKey(rand.Reader) // generate traffic keys
  317. if errT != nil {
  318. return errT
  319. }
  320. tPriv, err := ncutils.ConvertKeyToBytes(trafficPrivKey)
  321. if err != nil {
  322. return err
  323. }
  324. tPub, err := ncutils.ConvertKeyToBytes(trafficPubKey)
  325. if err != nil {
  326. return err
  327. }
  328. telemetry := models.Telemetry{
  329. UUID: uuid.NewString(),
  330. TrafficKeyPriv: tPriv,
  331. TrafficKeyPub: tPub,
  332. }
  333. telJSON, err := json.Marshal(&telemetry)
  334. if err != nil {
  335. return err
  336. }
  337. return database.Insert(database.SERVER_UUID_RECORD_KEY, string(telJSON), database.SERVER_UUID_TABLE_NAME)
  338. }