network.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "strings"
  9. "github.com/google/uuid"
  10. "github.com/gorilla/mux"
  11. "golang.org/x/exp/slog"
  12. "github.com/gravitl/netmaker/database"
  13. "github.com/gravitl/netmaker/logger"
  14. "github.com/gravitl/netmaker/logic"
  15. "github.com/gravitl/netmaker/logic/acls"
  16. "github.com/gravitl/netmaker/logic/acls/nodeacls"
  17. "github.com/gravitl/netmaker/models"
  18. "github.com/gravitl/netmaker/mq"
  19. "github.com/gravitl/netmaker/servercfg"
  20. )
  21. func networkHandlers(r *mux.Router) {
  22. r.HandleFunc("/api/networks", logic.SecurityCheck(true, http.HandlerFunc(getNetworks))).
  23. Methods(http.MethodGet)
  24. r.HandleFunc("/api/v1/networks/stats", logic.SecurityCheck(true, http.HandlerFunc(getNetworksStats))).
  25. Methods(http.MethodGet)
  26. r.HandleFunc("/api/networks", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceNetworks, http.HandlerFunc(createNetwork)))).
  27. Methods(http.MethodPost)
  28. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(getNetwork))).
  29. Methods(http.MethodGet)
  30. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(deleteNetwork))).
  31. Methods(http.MethodDelete)
  32. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(updateNetwork))).
  33. Methods(http.MethodPut)
  34. // ACLs
  35. r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkACL))).
  36. Methods(http.MethodPut)
  37. r.HandleFunc("/api/networks/{networkname}/acls/v2", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkACLv2))).
  38. Methods(http.MethodPut)
  39. r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(getNetworkACL))).
  40. Methods(http.MethodGet)
  41. r.HandleFunc("/api/networks/{networkname}/egress_routes", logic.SecurityCheck(true, http.HandlerFunc(getNetworkEgressRoutes)))
  42. r.HandleFunc("/api/networks/{networkname}/old_acl_status", logic.SecurityCheck(true, http.HandlerFunc(OldNetworkACLStatus))).
  43. Methods(http.MethodGet)
  44. }
  45. // @Summary Lists all networks
  46. // @Router /api/networks [get]
  47. // @Tags Networks
  48. // @Security oauth
  49. // @Produce json
  50. // @Success 200 {object} models.Network
  51. // @Failure 500 {object} models.ErrorResponse
  52. func getNetworks(w http.ResponseWriter, r *http.Request) {
  53. var err error
  54. allnetworks, err := logic.GetNetworks()
  55. if err != nil && !database.IsEmptyRecord(err) {
  56. slog.Error("failed to fetch networks", "error", err.Error())
  57. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  58. return
  59. }
  60. if r.Header.Get("ismaster") != "yes" {
  61. username := r.Header.Get("user")
  62. user, err := logic.GetUser(username)
  63. if err != nil {
  64. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  65. return
  66. }
  67. allnetworks = logic.FilterNetworksByRole(allnetworks, *user)
  68. }
  69. logger.Log(2, r.Header.Get("user"), "fetched networks.")
  70. logic.SortNetworks(allnetworks[:])
  71. w.WriteHeader(http.StatusOK)
  72. json.NewEncoder(w).Encode(allnetworks)
  73. }
  74. // @Summary Lists all networks with stats
  75. // @Router /api/v1/networks/stats [get]
  76. // @Tags Networks
  77. // @Security oauth
  78. // @Produce json
  79. // @Success 200 {object} models.SuccessResponse
  80. // @Failure 500 {object} models.ErrorResponse
  81. func getNetworksStats(w http.ResponseWriter, r *http.Request) {
  82. var err error
  83. allnetworks, err := logic.GetNetworks()
  84. if err != nil && !database.IsEmptyRecord(err) {
  85. slog.Error("failed to fetch networks", "error", err.Error())
  86. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  87. return
  88. }
  89. if r.Header.Get("ismaster") != "yes" {
  90. username := r.Header.Get("user")
  91. user, err := logic.GetUser(username)
  92. if err != nil {
  93. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  94. return
  95. }
  96. allnetworks = logic.FilterNetworksByRole(allnetworks, *user)
  97. }
  98. allNodes, err := logic.GetAllNodes()
  99. if err != nil {
  100. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  101. return
  102. }
  103. netstats := []models.NetworkStatResp{}
  104. logic.SortNetworks(allnetworks[:])
  105. for _, network := range allnetworks {
  106. netstats = append(netstats, models.NetworkStatResp{
  107. Network: network,
  108. Hosts: len(logic.GetNetworkNodesMemory(allNodes, network.NetID)),
  109. })
  110. }
  111. logger.Log(2, r.Header.Get("user"), "fetched networks.")
  112. logic.ReturnSuccessResponseWithJson(w, r, netstats, "fetched networks with stats")
  113. }
  114. // @Summary Get a network
  115. // @Router /api/networks/{networkname} [get]
  116. // @Tags Networks
  117. // @Security oauth
  118. // @Param networkname path string true "Network name"
  119. // @Produce json
  120. // @Success 200 {object} models.Network
  121. // @Failure 500 {object} models.ErrorResponse
  122. func getNetwork(w http.ResponseWriter, r *http.Request) {
  123. // set header.
  124. w.Header().Set("Content-Type", "application/json")
  125. var params = mux.Vars(r)
  126. netname := params["networkname"]
  127. network, err := logic.GetNetwork(netname)
  128. if err != nil {
  129. logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to fetch network [%s] info: %v",
  130. netname, err))
  131. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  132. return
  133. }
  134. logger.Log(2, r.Header.Get("user"), "fetched network", netname)
  135. w.WriteHeader(http.StatusOK)
  136. json.NewEncoder(w).Encode(network)
  137. }
  138. // @Summary Update a network ACL (Access Control List)
  139. // @Router /api/networks/{networkname}/acls [put]
  140. // @Tags Networks
  141. // @Security oauth
  142. // @Param networkname path string true "Network name"
  143. // @Param body body acls.ACLContainer true "ACL container"
  144. // @Produce json
  145. // @Success 200 {object} acls.ACLContainer
  146. // @Failure 400 {object} models.ErrorResponse
  147. // @Failure 500 {object} models.ErrorResponse
  148. func updateNetworkACL(w http.ResponseWriter, r *http.Request) {
  149. w.Header().Set("Content-Type", "application/json")
  150. var params = mux.Vars(r)
  151. netname := params["networkname"]
  152. var networkACLChange acls.ACLContainer
  153. networkACLChange, err := networkACLChange.Get(acls.ContainerID(netname))
  154. if err != nil {
  155. logger.Log(0, r.Header.Get("user"),
  156. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  157. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  158. return
  159. }
  160. err = json.NewDecoder(r.Body).Decode(&networkACLChange)
  161. if err != nil {
  162. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  163. err.Error())
  164. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  165. return
  166. }
  167. newNetACL, err := networkACLChange.Save(acls.ContainerID(netname))
  168. if err != nil {
  169. logger.Log(0, r.Header.Get("user"),
  170. fmt.Sprintf("failed to update ACLs for network [%s]: %v", netname, err))
  171. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  172. return
  173. }
  174. logger.Log(1, r.Header.Get("user"), "updated ACLs for network", netname)
  175. // send peer updates
  176. go func() {
  177. if err = mq.PublishPeerUpdate(false); err != nil {
  178. logger.Log(0, "failed to publish peer update after ACL update on network:", netname)
  179. }
  180. }()
  181. w.WriteHeader(http.StatusOK)
  182. json.NewEncoder(w).Encode(newNetACL)
  183. }
  184. // @Summary Update a network ACL (Access Control List)
  185. // @Router /api/networks/{networkname}/acls/v2 [put]
  186. // @Tags Networks
  187. // @Security oauth
  188. // @Param networkname path string true "Network name"
  189. // @Param body body acls.ACLContainer true "ACL container"
  190. // @Produce json
  191. // @Success 200 {object} acls.ACLContainer
  192. // @Failure 400 {object} models.ErrorResponse
  193. // @Failure 500 {object} models.ErrorResponse
  194. func updateNetworkACLv2(w http.ResponseWriter, r *http.Request) {
  195. w.Header().Set("Content-Type", "application/json")
  196. var params = mux.Vars(r)
  197. netname := params["networkname"]
  198. var networkACLChange acls.ACLContainer
  199. networkACLChange, err := networkACLChange.Get(acls.ContainerID(netname))
  200. if err != nil {
  201. logger.Log(0, r.Header.Get("user"),
  202. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  203. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  204. return
  205. }
  206. err = json.NewDecoder(r.Body).Decode(&networkACLChange)
  207. if err != nil {
  208. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  209. err.Error())
  210. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  211. return
  212. }
  213. // clone req body to use as return data successful update
  214. retData := make(acls.ACLContainer)
  215. data, err := json.Marshal(networkACLChange)
  216. if err != nil {
  217. slog.Error("failed to marshal networkACLChange whiles cloning", "error", err.Error())
  218. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  219. return
  220. }
  221. err = json.Unmarshal(data, &retData)
  222. if err != nil {
  223. slog.Error("failed to unmarshal networkACLChange whiles cloning", "error", err.Error())
  224. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  225. return
  226. }
  227. allNodes, err := logic.GetAllNodes()
  228. if err != nil {
  229. slog.Error("failed to fetch all nodes", "error", err.Error())
  230. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  231. return
  232. }
  233. networkNodes := make([]models.Node, 0)
  234. for _, node := range allNodes {
  235. if node.Network == netname {
  236. networkNodes = append(networkNodes, node)
  237. }
  238. }
  239. networkNodesIdMap := make(map[string]models.Node)
  240. for _, node := range networkNodes {
  241. networkNodesIdMap[node.ID.String()] = node
  242. }
  243. networkClients, err := logic.GetNetworkExtClients(netname)
  244. if err != nil {
  245. slog.Error("failed to fetch network clients", "error", err.Error())
  246. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  247. return
  248. }
  249. networkClientsMap := make(map[string]models.ExtClient)
  250. for _, client := range networkClients {
  251. networkClientsMap[client.ClientID] = client
  252. }
  253. // keep track of ingress gateways to disconnect from their clients
  254. // this is required because PublishPeerUpdate only somehow does not stop communication
  255. // between blocked clients and their ingress
  256. assocClientsToDisconnectPerHost := make(map[uuid.UUID][]models.ExtClient)
  257. // update client acls and then, remove client acls from req data to pass to existing functions
  258. for id, acl := range networkACLChange {
  259. // for node acls
  260. if _, ok := networkNodesIdMap[string(id)]; ok {
  261. nodeId := string(id)
  262. // check acl update, then remove client entries
  263. for id2 := range acl {
  264. if _, ok := networkNodesIdMap[string(id2)]; !ok {
  265. // update client acl
  266. clientId := string(id2)
  267. if client, ok := networkClientsMap[clientId]; ok {
  268. if client.DeniedACLs == nil {
  269. client.DeniedACLs = make(map[string]struct{})
  270. }
  271. if acl[acls.AclID(clientId)] == acls.NotAllowed {
  272. client.DeniedACLs[nodeId] = struct{}{}
  273. } else {
  274. delete(client.DeniedACLs, string(nodeId))
  275. }
  276. networkClientsMap[clientId] = client
  277. }
  278. }
  279. }
  280. } else {
  281. // for client acls
  282. clientId := string(id)
  283. for id2 := range acl {
  284. if _, ok := networkNodesIdMap[string(id2)]; !ok {
  285. // update client acl
  286. clientId2 := string(id2)
  287. if client, ok := networkClientsMap[clientId]; ok {
  288. if client.DeniedACLs == nil {
  289. client.DeniedACLs = make(map[string]struct{})
  290. }
  291. {
  292. // TODO: review this when client-to-client acls are supported
  293. // if acl[acls.AclID(clientId2)] == acls.NotAllowed {
  294. // client.DeniedACLs[clientId2] = struct{}{}
  295. // } else {
  296. // delete(client.DeniedACLs, clientId2)
  297. // }
  298. delete(client.DeniedACLs, clientId2)
  299. }
  300. networkClientsMap[clientId] = client
  301. }
  302. } else {
  303. nodeId2 := string(id2)
  304. if networkClientsMap[clientId].IngressGatewayID == nodeId2 && acl[acls.AclID(nodeId2)] == acls.NotAllowed {
  305. assocClientsToDisconnectPerHost[networkNodesIdMap[nodeId2].HostID] = append(assocClientsToDisconnectPerHost[networkNodesIdMap[nodeId2].HostID], networkClientsMap[clientId])
  306. }
  307. }
  308. }
  309. }
  310. }
  311. // update each client in db for pro servers
  312. if servercfg.IsPro {
  313. for _, client := range networkClientsMap {
  314. client := client
  315. err := logic.DeleteExtClient(client.Network, client.ClientID, true)
  316. if err != nil {
  317. slog.Error(
  318. "failed to delete client during update",
  319. "client",
  320. client.ClientID,
  321. "error",
  322. err.Error(),
  323. )
  324. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  325. return
  326. }
  327. err = logic.SaveExtClient(&client)
  328. if err != nil {
  329. slog.Error(
  330. "failed to save client during update",
  331. "client",
  332. client.ClientID,
  333. "error",
  334. err.Error(),
  335. )
  336. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  337. return
  338. }
  339. }
  340. }
  341. _, err = networkACLChange.Save(acls.ContainerID(netname))
  342. if err != nil {
  343. logger.Log(0, r.Header.Get("user"),
  344. fmt.Sprintf("failed to update ACLs for network [%s]: %v", netname, err))
  345. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  346. return
  347. }
  348. logger.Log(1, r.Header.Get("user"), "updated ACLs for network", netname)
  349. // send peer updates
  350. go func() {
  351. if err = mq.PublishPeerUpdate(false); err != nil {
  352. logger.Log(0, "failed to publish peer update after ACL update on network:", netname)
  353. }
  354. // update ingress gateways of associated clients
  355. hosts, err := logic.GetAllHosts()
  356. if err != nil {
  357. slog.Error(
  358. "failed to fetch hosts after network ACL update. skipping publish extclients ACL",
  359. "network",
  360. netname,
  361. )
  362. return
  363. }
  364. hostsMap := make(map[uuid.UUID]models.Host)
  365. for _, host := range hosts {
  366. hostsMap[host.ID] = host
  367. }
  368. for hostId, clients := range assocClientsToDisconnectPerHost {
  369. if host, ok := hostsMap[hostId]; ok {
  370. if err = mq.PublishSingleHostPeerUpdate(&host, allNodes, nil, clients, false, nil); err != nil {
  371. slog.Error("failed to publish peer update to ingress after ACL update on network", "network", netname, "host", hostId)
  372. }
  373. }
  374. }
  375. }()
  376. w.WriteHeader(http.StatusOK)
  377. json.NewEncoder(w).Encode(networkACLChange)
  378. }
  379. // @Summary Get a network ACL (Access Control List)
  380. // @Router /api/networks/{networkname}/acls [get]
  381. // @Tags Networks
  382. // @Security oauth
  383. // @Param networkname path string true "Network name"
  384. // @Produce json
  385. // @Success 200 {object} acls.ACLContainer
  386. // @Failure 500 {object} models.ErrorResponse
  387. func getNetworkACL(w http.ResponseWriter, r *http.Request) {
  388. w.Header().Set("Content-Type", "application/json")
  389. var params = mux.Vars(r)
  390. netname := params["networkname"]
  391. var networkACL acls.ACLContainer
  392. networkACL, err := networkACL.Get(acls.ContainerID(netname))
  393. if err != nil {
  394. if database.IsEmptyRecord(err) {
  395. networkACL = acls.ACLContainer{}
  396. w.WriteHeader(http.StatusOK)
  397. json.NewEncoder(w).Encode(networkACL)
  398. return
  399. }
  400. logger.Log(0, r.Header.Get("user"),
  401. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  402. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  403. return
  404. }
  405. logger.Log(2, r.Header.Get("user"), "fetched acl for network", netname)
  406. w.WriteHeader(http.StatusOK)
  407. json.NewEncoder(w).Encode(networkACL)
  408. }
  409. // @Summary Check a Old ACL Status (Access Control List)
  410. // @Router /api/networks/{networkname}/old_acl_status [get]
  411. // @Tags Networks
  412. // @Security oauth
  413. // @Param networkname path string true "Network name"
  414. // @Produce json
  415. // @Success 200 {object} acls.ACLContainer
  416. // @Failure 500 {object} models.ErrorResponse
  417. func OldNetworkACLStatus(w http.ResponseWriter, r *http.Request) {
  418. w.Header().Set("Content-Type", "application/json")
  419. var params = mux.Vars(r)
  420. netname := params["networkname"]
  421. var networkACL acls.ACLContainer
  422. networkACL, err := nodeacls.FetchAllACLs(nodeacls.NetworkID(netname))
  423. if err != nil {
  424. logic.ReturnSuccessResponse(w, r, "false")
  425. return
  426. }
  427. disableOldAcls := true
  428. for _, aclNode := range networkACL {
  429. for _, allowed := range aclNode {
  430. if allowed != acls.Allowed {
  431. disableOldAcls = false
  432. break
  433. }
  434. }
  435. }
  436. msg := "true"
  437. if disableOldAcls {
  438. msg = "false"
  439. }
  440. logic.ReturnSuccessResponse(w, r, msg)
  441. }
  442. // @Summary Get a network Egress routes
  443. // @Router /api/networks/{networkname}/egress_routes [get]
  444. // @Tags Networks
  445. // @Security oauth
  446. // @Param networkname path string true "Network name"
  447. // @Produce json
  448. // @Success 200 {object} models.SuccessResponse
  449. // @Failure 500 {object} models.ErrorResponse
  450. func getNetworkEgressRoutes(w http.ResponseWriter, r *http.Request) {
  451. var params = mux.Vars(r)
  452. netname := params["networkname"]
  453. // check if network exists
  454. _, err := logic.GetNetwork(netname)
  455. if err != nil {
  456. logger.Log(0, r.Header.Get("user"),
  457. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  458. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  459. return
  460. }
  461. nodeEgressRoutes, _, err := logic.GetEgressRanges(models.NetworkID(netname))
  462. if err != nil {
  463. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  464. return
  465. }
  466. logic.ReturnSuccessResponseWithJson(w, r, nodeEgressRoutes, "fetched network egress routes")
  467. }
  468. // @Summary Delete a network
  469. // @Router /api/networks/{networkname} [delete]
  470. // @Tags Networks
  471. // @Security oauth
  472. // @Param networkname path string true "Network name"
  473. // @Param force query bool false "Force Delete"
  474. // @Produce json
  475. // @Success 200 {object} models.SuccessResponse
  476. // @Failure 400 {object} models.ErrorResponse
  477. // @Failure 403 {object} models.ErrorResponse
  478. func deleteNetwork(w http.ResponseWriter, r *http.Request) {
  479. // Set header
  480. w.Header().Set("Content-Type", "application/json")
  481. force := r.URL.Query().Get("force") == "true"
  482. var params = mux.Vars(r)
  483. network := params["networkname"]
  484. doneCh := make(chan struct{}, 1)
  485. networkNodes, err := logic.GetNetworkNodes(network)
  486. if err != nil {
  487. logger.Log(0, r.Header.Get("user"),
  488. fmt.Sprintf("failed to get network nodes [%s]: %v", network, err))
  489. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  490. return
  491. }
  492. err = logic.DeleteNetwork(network, force, doneCh)
  493. if err != nil {
  494. errtype := logic.BadReq
  495. if strings.Contains(err.Error(), "Node check failed") {
  496. errtype = logic.Forbidden
  497. }
  498. logger.Log(0, r.Header.Get("user"),
  499. fmt.Sprintf("failed to delete network [%s]: %v", network, err))
  500. logic.ReturnErrorResponse(w, r, logic.FormatError(err, errtype))
  501. return
  502. }
  503. go logic.UnlinkNetworkAndTagsFromEnrollmentKeys(network, true)
  504. go logic.DeleteNetworkRoles(network)
  505. go logic.DeleteAllNetworkTags(models.NetworkID(network))
  506. go logic.DeleteNetworkPolicies(models.NetworkID(network))
  507. //delete network from allocated ip map
  508. go logic.RemoveNetworkFromAllocatedIpMap(network)
  509. go func() {
  510. <-doneCh
  511. mq.PublishPeerUpdate(true)
  512. // send node update to clean up locally
  513. for _, node := range networkNodes {
  514. node := node
  515. node.PendingDelete = true
  516. node.Action = models.NODE_DELETE
  517. if err := mq.NodeUpdate(&node); err != nil {
  518. slog.Error("error publishing node update to node", "node", node.ID, "error", err)
  519. }
  520. }
  521. if servercfg.IsDNSMode() {
  522. logic.SetDNS()
  523. }
  524. }()
  525. logic.LogEvent(&models.Event{
  526. Action: models.Delete,
  527. Source: models.Subject{
  528. ID: r.Header.Get("user"),
  529. Name: r.Header.Get("user"),
  530. Type: models.UserSub,
  531. },
  532. TriggeredBy: r.Header.Get("user"),
  533. Target: models.Subject{
  534. ID: network,
  535. Name: network,
  536. Type: models.NetworkSub,
  537. },
  538. Origin: models.Dashboard,
  539. Diff: models.Diff{
  540. Old: network,
  541. New: nil,
  542. },
  543. })
  544. logger.Log(1, r.Header.Get("user"), "deleted network", network)
  545. w.WriteHeader(http.StatusOK)
  546. json.NewEncoder(w).Encode("success")
  547. }
  548. // @Summary Create a network
  549. // @Router /api/networks [post]
  550. // @Tags Networks
  551. // @Security oauth
  552. // @Param body body models.Network true "Network details"
  553. // @Produce json
  554. // @Success 200 {object} models.Network
  555. // @Failure 400 {object} models.ErrorResponse
  556. func createNetwork(w http.ResponseWriter, r *http.Request) {
  557. w.Header().Set("Content-Type", "application/json")
  558. var network models.Network
  559. // we decode our body request params
  560. err := json.NewDecoder(r.Body).Decode(&network)
  561. if err != nil {
  562. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  563. err.Error())
  564. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  565. return
  566. }
  567. featureFlags := logic.GetFeatureFlags()
  568. if !featureFlags.EnableDeviceApproval {
  569. network.AutoJoin = "true"
  570. }
  571. if len(network.NetID) > 32 {
  572. err := errors.New("network name shouldn't exceed 32 characters")
  573. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  574. err.Error())
  575. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  576. return
  577. }
  578. if network.AddressRange == "" && network.AddressRange6 == "" {
  579. err := errors.New("IPv4 or IPv6 CIDR required")
  580. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  581. err.Error())
  582. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  583. return
  584. }
  585. // validate address ranges: must be private
  586. if network.AddressRange != "" {
  587. _, cidr, err := net.ParseCIDR(network.AddressRange)
  588. if err != nil {
  589. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  590. err.Error())
  591. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  592. return
  593. } else {
  594. ones, bits := cidr.Mask.Size()
  595. if bits-ones <= 1 {
  596. err = fmt.Errorf("cannot create network with /31 or /32 cidr")
  597. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  598. err.Error())
  599. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  600. return
  601. }
  602. }
  603. }
  604. if network.AddressRange6 != "" {
  605. _, cidr, err := net.ParseCIDR(network.AddressRange6)
  606. if err != nil {
  607. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  608. err.Error())
  609. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  610. return
  611. } else {
  612. ones, bits := cidr.Mask.Size()
  613. if bits-ones <= 1 {
  614. err = fmt.Errorf("cannot create network with /127 or /128 cidr")
  615. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  616. err.Error())
  617. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  618. return
  619. }
  620. }
  621. }
  622. network, err = logic.CreateNetwork(network)
  623. if err != nil {
  624. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  625. err.Error())
  626. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  627. return
  628. }
  629. logic.CreateDefaultNetworkRolesAndGroups(models.NetworkID(network.NetID))
  630. logic.CreateDefaultAclNetworkPolicies(models.NetworkID(network.NetID))
  631. logic.CreateDefaultTags(models.NetworkID(network.NetID))
  632. logic.AddNetworkToAllocatedIpMap(network.NetID)
  633. go func() {
  634. defaultHosts := logic.GetDefaultHosts()
  635. for i := range defaultHosts {
  636. currHost := &defaultHosts[i]
  637. newNode, err := logic.UpdateHostNetwork(currHost, network.NetID, true)
  638. if err != nil {
  639. logger.Log(
  640. 0,
  641. r.Header.Get("user"),
  642. "failed to add host to network:",
  643. currHost.ID.String(),
  644. network.NetID,
  645. err.Error(),
  646. )
  647. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  648. return
  649. }
  650. logger.Log(1, "added new node", newNode.ID.String(), "to host", currHost.Name)
  651. if len(currHost.Nodes) == 1 {
  652. if err = mq.HostUpdate(&models.HostUpdate{
  653. Action: models.RequestPull,
  654. Host: *currHost,
  655. Node: *newNode,
  656. }); err != nil {
  657. logger.Log(
  658. 0,
  659. r.Header.Get("user"),
  660. "failed to add host to network:",
  661. currHost.ID.String(),
  662. network.NetID,
  663. err.Error(),
  664. )
  665. }
  666. } else {
  667. if err = mq.HostUpdate(&models.HostUpdate{
  668. Action: models.JoinHostToNetwork,
  669. Host: *currHost,
  670. Node: *newNode,
  671. }); err != nil {
  672. logger.Log(
  673. 0,
  674. r.Header.Get("user"),
  675. "failed to add host to network:",
  676. currHost.ID.String(),
  677. network.NetID,
  678. err.Error(),
  679. )
  680. }
  681. }
  682. // make host failover
  683. logic.CreateFailOver(*newNode)
  684. // make host remote access gateway
  685. logic.CreateIngressGateway(network.NetID, newNode.ID.String(), models.IngressRequest{})
  686. logic.CreateRelay(models.RelayRequest{
  687. NodeID: newNode.ID.String(),
  688. NetID: network.NetID,
  689. })
  690. }
  691. // send peer updates
  692. if err = mq.PublishPeerUpdate(false); err != nil {
  693. logger.Log(1, "failed to publish peer update for default hosts after network is added")
  694. }
  695. }()
  696. logic.LogEvent(&models.Event{
  697. Action: models.Create,
  698. Source: models.Subject{
  699. ID: r.Header.Get("user"),
  700. Name: r.Header.Get("user"),
  701. Type: models.UserSub,
  702. },
  703. TriggeredBy: r.Header.Get("user"),
  704. Target: models.Subject{
  705. ID: network.NetID,
  706. Name: network.NetID,
  707. Type: models.NetworkSub,
  708. Info: network,
  709. },
  710. Origin: models.Dashboard,
  711. })
  712. logger.Log(1, r.Header.Get("user"), "created network", network.NetID)
  713. w.WriteHeader(http.StatusOK)
  714. json.NewEncoder(w).Encode(network)
  715. }
  716. // @Summary Update network settings
  717. // @Router /api/networks/{networkname} [put]
  718. // @Tags Networks
  719. // @Security oauth
  720. // @Param networkname path string true "Network name"
  721. // @Param body body models.Network true "Network details"
  722. // @Produce json
  723. // @Success 200 {object} models.Network
  724. // @Failure 400 {object} models.ErrorResponse
  725. func updateNetwork(w http.ResponseWriter, r *http.Request) {
  726. w.Header().Set("Content-Type", "application/json")
  727. var payload models.Network
  728. // we decode our body request params
  729. err := json.NewDecoder(r.Body).Decode(&payload)
  730. if err != nil {
  731. slog.Info("error decoding request body", "user", r.Header.Get("user"), "err", err)
  732. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  733. return
  734. }
  735. netOld, err := logic.GetNetwork(payload.NetID)
  736. if err != nil {
  737. slog.Info("error fetching network", "user", r.Header.Get("user"), "err", err)
  738. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  739. return
  740. }
  741. err = logic.UpdateNetwork(&netOld, &payload)
  742. if err != nil {
  743. slog.Info("failed to update network", "user", r.Header.Get("user"), "err", err)
  744. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  745. return
  746. }
  747. go mq.PublishPeerUpdate(false)
  748. slog.Info("updated network", "network", payload.NetID, "user", r.Header.Get("user"))
  749. w.WriteHeader(http.StatusOK)
  750. json.NewEncoder(w).Encode(payload)
  751. }