network.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "strings"
  9. "github.com/gorilla/mux"
  10. "golang.org/x/exp/slog"
  11. "github.com/gravitl/netmaker/database"
  12. "github.com/gravitl/netmaker/logger"
  13. "github.com/gravitl/netmaker/logic"
  14. "github.com/gravitl/netmaker/logic/acls"
  15. "github.com/gravitl/netmaker/models"
  16. "github.com/gravitl/netmaker/mq"
  17. )
  18. func networkHandlers(r *mux.Router) {
  19. r.HandleFunc("/api/networks", logic.SecurityCheck(true, http.HandlerFunc(getNetworks))).Methods(http.MethodGet)
  20. r.HandleFunc("/api/networks", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceNetworks, http.HandlerFunc(createNetwork)))).Methods(http.MethodPost)
  21. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(getNetwork))).Methods(http.MethodGet)
  22. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(deleteNetwork))).Methods(http.MethodDelete)
  23. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(updateNetwork))).Methods(http.MethodPut)
  24. // ACLs
  25. r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkACL))).Methods(http.MethodPut)
  26. r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(getNetworkACL))).Methods(http.MethodGet)
  27. }
  28. // swagger:route GET /api/networks networks getNetworks
  29. //
  30. // Lists all networks.
  31. //
  32. // Schemes: https
  33. //
  34. // Security:
  35. // oauth
  36. //
  37. // Responses:
  38. // 200: getNetworksSliceResponse
  39. func getNetworks(w http.ResponseWriter, r *http.Request) {
  40. var err error
  41. allnetworks, err := logic.GetNetworks()
  42. if err != nil && !database.IsEmptyRecord(err) {
  43. slog.Error("failed to fetch networks", "error", err.Error())
  44. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  45. return
  46. }
  47. logger.Log(2, r.Header.Get("user"), "fetched networks.")
  48. logic.SortNetworks(allnetworks[:])
  49. w.WriteHeader(http.StatusOK)
  50. json.NewEncoder(w).Encode(allnetworks)
  51. }
  52. // swagger:route GET /api/networks/{networkname} networks getNetwork
  53. //
  54. // Get a network.
  55. //
  56. // Schemes: https
  57. //
  58. // Security:
  59. // oauth
  60. //
  61. // Responses:
  62. // 200: networkBodyResponse
  63. func getNetwork(w http.ResponseWriter, r *http.Request) {
  64. // set header.
  65. w.Header().Set("Content-Type", "application/json")
  66. var params = mux.Vars(r)
  67. netname := params["networkname"]
  68. network, err := logic.GetNetwork(netname)
  69. if err != nil {
  70. logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to fetch network [%s] info: %v",
  71. netname, err))
  72. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  73. return
  74. }
  75. logger.Log(2, r.Header.Get("user"), "fetched network", netname)
  76. w.WriteHeader(http.StatusOK)
  77. json.NewEncoder(w).Encode(network)
  78. }
  79. // swagger:route PUT /api/networks/{networkname}/acls networks updateNetworkACL
  80. //
  81. // Update a network ACL (Access Control List).
  82. //
  83. // Schemes: https
  84. //
  85. // Security:
  86. // oauth
  87. //
  88. // Responses:
  89. // 200: aclContainerResponse
  90. func updateNetworkACL(w http.ResponseWriter, r *http.Request) {
  91. w.Header().Set("Content-Type", "application/json")
  92. var params = mux.Vars(r)
  93. netname := params["networkname"]
  94. var networkACLChange acls.ACLContainer
  95. networkACLChange, err := networkACLChange.Get(acls.ContainerID(netname))
  96. if err != nil {
  97. logger.Log(0, r.Header.Get("user"),
  98. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  99. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  100. return
  101. }
  102. err = json.NewDecoder(r.Body).Decode(&networkACLChange)
  103. if err != nil {
  104. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  105. err.Error())
  106. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  107. return
  108. }
  109. newNetACL, err := networkACLChange.Save(acls.ContainerID(netname))
  110. if err != nil {
  111. logger.Log(0, r.Header.Get("user"),
  112. fmt.Sprintf("failed to update ACLs for network [%s]: %v", netname, err))
  113. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  114. return
  115. }
  116. logger.Log(1, r.Header.Get("user"), "updated ACLs for network", netname)
  117. // send peer updates
  118. go func() {
  119. if err = mq.PublishPeerUpdate(false); err != nil {
  120. logger.Log(0, "failed to publish peer update after ACL update on", netname)
  121. }
  122. }()
  123. w.WriteHeader(http.StatusOK)
  124. json.NewEncoder(w).Encode(newNetACL)
  125. }
  126. // swagger:route GET /api/networks/{networkname}/acls networks getNetworkACL
  127. //
  128. // Get a network ACL (Access Control List).
  129. //
  130. // Schemes: https
  131. //
  132. // Security:
  133. // oauth
  134. //
  135. // Responses:
  136. // 200: aclContainerResponse
  137. func getNetworkACL(w http.ResponseWriter, r *http.Request) {
  138. w.Header().Set("Content-Type", "application/json")
  139. var params = mux.Vars(r)
  140. netname := params["networkname"]
  141. var networkACL acls.ACLContainer
  142. networkACL, err := networkACL.Get(acls.ContainerID(netname))
  143. if err != nil {
  144. if database.IsEmptyRecord(err) {
  145. networkACL = acls.ACLContainer{}
  146. w.WriteHeader(http.StatusOK)
  147. json.NewEncoder(w).Encode(networkACL)
  148. return
  149. }
  150. logger.Log(0, r.Header.Get("user"),
  151. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  152. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  153. return
  154. }
  155. logger.Log(2, r.Header.Get("user"), "fetched acl for network", netname)
  156. w.WriteHeader(http.StatusOK)
  157. json.NewEncoder(w).Encode(networkACL)
  158. }
  159. // swagger:route DELETE /api/networks/{networkname} networks deleteNetwork
  160. //
  161. // Delete a network. Will not delete if there are any nodes that belong to the network.
  162. //
  163. // Schemes: https
  164. //
  165. // Security:
  166. // oauth
  167. //
  168. // Responses:
  169. // 200: successResponse
  170. func deleteNetwork(w http.ResponseWriter, r *http.Request) {
  171. // Set header
  172. w.Header().Set("Content-Type", "application/json")
  173. var params = mux.Vars(r)
  174. network := params["networkname"]
  175. err := logic.DeleteNetwork(network)
  176. if err != nil {
  177. errtype := "badrequest"
  178. if strings.Contains(err.Error(), "Node check failed") {
  179. errtype = "forbidden"
  180. }
  181. logger.Log(0, r.Header.Get("user"),
  182. fmt.Sprintf("failed to delete network [%s]: %v", network, err))
  183. logic.ReturnErrorResponse(w, r, logic.FormatError(err, errtype))
  184. return
  185. }
  186. logger.Log(1, r.Header.Get("user"), "deleted network", network)
  187. w.WriteHeader(http.StatusOK)
  188. json.NewEncoder(w).Encode("success")
  189. }
  190. // swagger:route POST /api/networks networks createNetwork
  191. //
  192. // Create a network.
  193. //
  194. // Schemes: https
  195. //
  196. // Security:
  197. // oauth
  198. //
  199. // Responses:
  200. // 200: networkBodyResponse
  201. func createNetwork(w http.ResponseWriter, r *http.Request) {
  202. w.Header().Set("Content-Type", "application/json")
  203. var network models.Network
  204. // we decode our body request params
  205. err := json.NewDecoder(r.Body).Decode(&network)
  206. if err != nil {
  207. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  208. err.Error())
  209. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  210. return
  211. }
  212. if len(network.NetID) > 32 {
  213. err := errors.New("network name shouldn't exceed 32 characters")
  214. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  215. err.Error())
  216. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  217. return
  218. }
  219. if network.AddressRange == "" && network.AddressRange6 == "" {
  220. err := errors.New("IPv4 or IPv6 CIDR required")
  221. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  222. err.Error())
  223. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  224. return
  225. }
  226. // validate address ranges: must be private
  227. if network.AddressRange != "" {
  228. _, ipNet, err := net.ParseCIDR(network.AddressRange)
  229. if err != nil {
  230. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  231. err.Error())
  232. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  233. return
  234. }
  235. if !ipNet.IP.IsPrivate() {
  236. err := errors.New("address range must be private")
  237. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  238. err.Error())
  239. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  240. return
  241. }
  242. }
  243. if network.AddressRange6 != "" {
  244. _, ipNet, err := net.ParseCIDR(network.AddressRange6)
  245. if err != nil {
  246. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  247. err.Error())
  248. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  249. return
  250. }
  251. if !ipNet.IP.IsPrivate() {
  252. err := errors.New("address range must be private")
  253. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  254. err.Error())
  255. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  256. return
  257. }
  258. }
  259. network, err = logic.CreateNetwork(network)
  260. if err != nil {
  261. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  262. err.Error())
  263. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  264. return
  265. }
  266. go func() {
  267. defaultHosts := logic.GetDefaultHosts()
  268. for i := range defaultHosts {
  269. currHost := &defaultHosts[i]
  270. newNode, err := logic.UpdateHostNetwork(currHost, network.NetID, true)
  271. if err != nil {
  272. logger.Log(0, r.Header.Get("user"), "failed to add host to network:", currHost.ID.String(), network.NetID, err.Error())
  273. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  274. return
  275. }
  276. logger.Log(1, "added new node", newNode.ID.String(), "to host", currHost.Name)
  277. if err = mq.HostUpdate(&models.HostUpdate{
  278. Action: models.JoinHostToNetwork,
  279. Host: *currHost,
  280. Node: *newNode,
  281. }); err != nil {
  282. logger.Log(0, r.Header.Get("user"), "failed to add host to network:", currHost.ID.String(), network.NetID, err.Error())
  283. }
  284. // make host failover
  285. logic.CreateFailOver(*newNode)
  286. // make host remote access gateway
  287. logic.CreateIngressGateway(network.NetID, newNode.ID.String(), models.IngressRequest{})
  288. }
  289. }()
  290. logger.Log(1, r.Header.Get("user"), "created network", network.NetID)
  291. w.WriteHeader(http.StatusOK)
  292. json.NewEncoder(w).Encode(network)
  293. }
  294. // swagger:route PUT /api/networks/{networkname} networks updateNetwork
  295. //
  296. // Update pro settings for a network.
  297. //
  298. // Schemes: https
  299. //
  300. // Security:
  301. // oauth
  302. //
  303. // Responses:
  304. // 200: networkBodyResponse
  305. func updateNetwork(w http.ResponseWriter, r *http.Request) {
  306. w.Header().Set("Content-Type", "application/json")
  307. var payload models.Network
  308. // we decode our body request params
  309. err := json.NewDecoder(r.Body).Decode(&payload)
  310. if err != nil {
  311. slog.Info("error decoding request body", "user", r.Header.Get("user"), "err", err)
  312. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  313. return
  314. }
  315. netOld1, err := logic.GetNetwork(payload.NetID)
  316. if err != nil {
  317. slog.Info("error fetching network", "user", r.Header.Get("user"), "err", err)
  318. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  319. return
  320. }
  321. // partial update
  322. netOld2 := netOld1
  323. _, _, _, err = logic.UpdateNetwork(&netOld1, &netOld2)
  324. if err != nil {
  325. slog.Info("failed to update network", "user", r.Header.Get("user"), "err", err)
  326. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  327. return
  328. }
  329. slog.Info("updated network", "network", payload.NetID, "user", r.Header.Get("user"))
  330. w.WriteHeader(http.StatusOK)
  331. json.NewEncoder(w).Encode(payload)
  332. }