network.go 11 KB

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