node.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. package controller
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "strings"
  7. "github.com/gorilla/mux"
  8. "github.com/gravitl/netmaker/database"
  9. "github.com/gravitl/netmaker/logger"
  10. "github.com/gravitl/netmaker/logic"
  11. "github.com/gravitl/netmaker/models"
  12. "github.com/gravitl/netmaker/mq"
  13. "github.com/gravitl/netmaker/servercfg"
  14. "golang.org/x/crypto/bcrypt"
  15. "golang.org/x/exp/slog"
  16. )
  17. var hostIDHeader = "host-id"
  18. func nodeHandlers(r *mux.Router) {
  19. r.HandleFunc("/api/nodes", Authorize(false, false, "user", http.HandlerFunc(getAllNodes))).
  20. Methods(http.MethodGet)
  21. r.HandleFunc("/api/nodes/{network}", Authorize(false, true, "network", http.HandlerFunc(getNetworkNodes))).
  22. Methods(http.MethodGet)
  23. r.HandleFunc("/api/nodes/{network}/{nodeid}", Authorize(true, true, "node", http.HandlerFunc(getNode))).
  24. Methods(http.MethodGet)
  25. r.HandleFunc("/api/nodes/{network}/{nodeid}", logic.SecurityCheck(true, http.HandlerFunc(updateNode))).
  26. Methods(http.MethodPut)
  27. r.HandleFunc("/api/nodes/{network}/{nodeid}", Authorize(true, true, "node", http.HandlerFunc(deleteNode))).
  28. Methods(http.MethodDelete)
  29. r.HandleFunc("/api/nodes/{network}/{nodeid}/creategateway", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceEgress, http.HandlerFunc(createEgressGateway)))).
  30. Methods(http.MethodPost)
  31. r.HandleFunc("/api/nodes/{network}/{nodeid}/deletegateway", logic.SecurityCheck(true, http.HandlerFunc(deleteEgressGateway))).
  32. Methods(http.MethodDelete)
  33. r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceIngress, http.HandlerFunc(createIngressGateway)))).
  34. Methods(http.MethodPost)
  35. r.HandleFunc("/api/nodes/{network}/{nodeid}/deleteingress", logic.SecurityCheck(true, http.HandlerFunc(deleteIngressGateway))).
  36. Methods(http.MethodDelete)
  37. r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods(http.MethodPost)
  38. r.HandleFunc("/api/v1/nodes/migrate", migrate).Methods(http.MethodPost)
  39. }
  40. func authenticate(response http.ResponseWriter, request *http.Request) {
  41. var authRequest models.AuthParams
  42. var result models.Node
  43. var errorResponse = models.ErrorResponse{
  44. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  45. }
  46. decoder := json.NewDecoder(request.Body)
  47. decoderErr := decoder.Decode(&authRequest)
  48. defer request.Body.Close()
  49. if decoderErr != nil {
  50. errorResponse.Code = http.StatusBadRequest
  51. errorResponse.Message = decoderErr.Error()
  52. logger.Log(0, request.Header.Get("user"), "error decoding request body: ",
  53. decoderErr.Error())
  54. logic.ReturnErrorResponse(response, request, errorResponse)
  55. return
  56. }
  57. errorResponse.Code = http.StatusBadRequest
  58. if authRequest.ID == "" {
  59. errorResponse.Message = "W1R3: ID can't be empty"
  60. logger.Log(0, request.Header.Get("user"), errorResponse.Message)
  61. logic.ReturnErrorResponse(response, request, errorResponse)
  62. return
  63. } else if authRequest.Password == "" {
  64. errorResponse.Message = "W1R3: Password can't be empty"
  65. logger.Log(0, request.Header.Get("user"), errorResponse.Message)
  66. logic.ReturnErrorResponse(response, request, errorResponse)
  67. return
  68. }
  69. var err error
  70. result, err = logic.GetNodeByID(authRequest.ID)
  71. if err != nil {
  72. result, err = logic.GetDeletedNodeByID(authRequest.ID)
  73. if err != nil {
  74. errorResponse.Code = http.StatusBadRequest
  75. errorResponse.Message = err.Error()
  76. logger.Log(0, request.Header.Get("user"),
  77. fmt.Sprintf("failed to get node info [%s]: %v", authRequest.ID, err))
  78. logic.ReturnErrorResponse(response, request, errorResponse)
  79. return
  80. }
  81. }
  82. host, err := logic.GetHost(result.HostID.String())
  83. if err != nil {
  84. errorResponse.Code = http.StatusBadRequest
  85. errorResponse.Message = err.Error()
  86. logger.Log(0, request.Header.Get("user"),
  87. "error retrieving host: ", result.HostID.String(), err.Error())
  88. logic.ReturnErrorResponse(response, request, errorResponse)
  89. return
  90. }
  91. err = bcrypt.CompareHashAndPassword([]byte(host.HostPass), []byte(authRequest.Password))
  92. if err != nil {
  93. errorResponse.Code = http.StatusBadRequest
  94. errorResponse.Message = err.Error()
  95. logger.Log(0, request.Header.Get("user"),
  96. "error validating user password: ", err.Error())
  97. logic.ReturnErrorResponse(response, request, errorResponse)
  98. return
  99. }
  100. tokenString, err := logic.CreateJWT(authRequest.ID, authRequest.MacAddress, result.Network)
  101. if tokenString == "" {
  102. errorResponse.Code = http.StatusBadRequest
  103. errorResponse.Message = "Could not create Token"
  104. logger.Log(0, request.Header.Get("user"),
  105. fmt.Sprintf("%s: %v", errorResponse.Message, err))
  106. logic.ReturnErrorResponse(response, request, errorResponse)
  107. return
  108. }
  109. var successResponse = models.SuccessResponse{
  110. Code: http.StatusOK,
  111. Message: "W1R3: Device " + authRequest.ID + " Authorized",
  112. Response: models.SuccessfulLoginResponse{
  113. AuthToken: tokenString,
  114. ID: authRequest.ID,
  115. },
  116. }
  117. successJSONResponse, jsonError := json.Marshal(successResponse)
  118. if jsonError != nil {
  119. errorResponse.Code = http.StatusBadRequest
  120. errorResponse.Message = err.Error()
  121. logger.Log(0, request.Header.Get("user"),
  122. "error marshalling resp: ", err.Error())
  123. logic.ReturnErrorResponse(response, request, errorResponse)
  124. return
  125. }
  126. response.WriteHeader(http.StatusOK)
  127. response.Header().Set("Content-Type", "application/json")
  128. response.Write(successJSONResponse)
  129. }
  130. // The middleware for most requests to the API
  131. // They all pass through here first
  132. // This will validate the JWT (or check for master token)
  133. // This will also check against the authNetwork and make sure the node should be accessing that endpoint,
  134. // even if it's technically ok
  135. // This is kind of a poor man's RBAC. There's probably a better/smarter way.
  136. // TODO: Consider better RBAC implementations
  137. func Authorize(
  138. hostAllowed, networkCheck bool,
  139. authNetwork string,
  140. next http.Handler,
  141. ) http.HandlerFunc {
  142. return func(w http.ResponseWriter, r *http.Request) {
  143. var errorResponse = models.ErrorResponse{
  144. Code: http.StatusForbidden, Message: logic.Forbidden_Msg,
  145. }
  146. var params = mux.Vars(r)
  147. networkexists, _ := logic.NetworkExists(params["network"])
  148. //check that the request is for a valid network
  149. //if (networkCheck && !networkexists) || err != nil {
  150. if networkCheck && !networkexists {
  151. logic.ReturnErrorResponse(w, r, errorResponse)
  152. return
  153. } else {
  154. w.Header().Set("Content-Type", "application/json")
  155. //get the auth token
  156. bearerToken := r.Header.Get("Authorization")
  157. var tokenSplit = strings.Split(bearerToken, " ")
  158. //I put this in in case the user doesn't put in a token at all (in which case it's empty)
  159. //There's probably a smarter way of handling this.
  160. var authToken = "928rt238tghgwe@TY@$Y@#WQAEGB2FC#@HG#@$Hddd"
  161. if len(tokenSplit) > 1 {
  162. authToken = tokenSplit[1]
  163. } else {
  164. logic.ReturnErrorResponse(w, r, errorResponse)
  165. return
  166. }
  167. // check if host instead of user
  168. if hostAllowed {
  169. // TODO --- should ensure that node is only operating on itself
  170. if hostID, _, _, err := logic.VerifyHostToken(authToken); err == nil {
  171. r.Header.Set(hostIDHeader, hostID)
  172. // this indicates request is from a node
  173. // used for failover - if a getNode comes from node, this will trigger a metrics wipe
  174. next.ServeHTTP(w, r)
  175. return
  176. }
  177. }
  178. var isAuthorized = false
  179. var nodeID = ""
  180. username, issuperadmin, isadmin, errN := logic.VerifyUserToken(authToken)
  181. if errN != nil {
  182. logic.ReturnErrorResponse(w, r, logic.FormatError(errN, logic.Unauthorized_Msg))
  183. return
  184. }
  185. isnetadmin := issuperadmin || isadmin
  186. if issuperadmin || isadmin {
  187. nodeID = "mastermac"
  188. isAuthorized = true
  189. r.Header.Set("ismasterkey", "yes")
  190. }
  191. //The mastermac (login with masterkey from config) can do everything!! May be dangerous.
  192. if nodeID == "mastermac" {
  193. isAuthorized = true
  194. r.Header.Set("ismasterkey", "yes")
  195. //for everyone else, there's poor man's RBAC. The "cases" are defined in the routes in the handlers
  196. //So each route defines which access network should be allowed to access it
  197. } else {
  198. switch authNetwork {
  199. case "all":
  200. isAuthorized = true
  201. case "nodes":
  202. isAuthorized = (nodeID != "") || isnetadmin
  203. case "network":
  204. if isnetadmin {
  205. isAuthorized = true
  206. } else {
  207. node, err := logic.GetNodeByID(nodeID)
  208. if err != nil {
  209. logic.ReturnErrorResponse(w, r, errorResponse)
  210. return
  211. }
  212. isAuthorized = (node.Network == params["network"])
  213. }
  214. case "node":
  215. if isnetadmin {
  216. isAuthorized = true
  217. } else {
  218. isAuthorized = (nodeID == params["netid"])
  219. }
  220. case "host":
  221. case "user":
  222. isAuthorized = true
  223. default:
  224. isAuthorized = false
  225. }
  226. }
  227. if !isAuthorized {
  228. logic.ReturnErrorResponse(w, r, errorResponse)
  229. return
  230. } else {
  231. //If authorized, this function passes along it's request and output to the appropriate route function.
  232. if username == "" {
  233. username = "(user not found)"
  234. }
  235. r.Header.Set("user", username)
  236. next.ServeHTTP(w, r)
  237. }
  238. }
  239. }
  240. }
  241. // @Summary Gets all nodes associated with network including pending nodes
  242. // @Router /api/nodes/adm/{network} [get]
  243. // @Securitydefinitions.oauth2.application OAuth2Application
  244. // @Tags Nodes
  245. // @Success 200 {array} models.Node
  246. // @Failure 500 {object} models.ErrorResponse
  247. func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
  248. w.Header().Set("Content-Type", "application/json")
  249. var params = mux.Vars(r)
  250. networkName := params["network"]
  251. nodes, err := logic.GetNetworkNodes(networkName)
  252. if err != nil {
  253. logger.Log(0, r.Header.Get("user"),
  254. fmt.Sprintf("error fetching nodes on network %s: %v", networkName, err))
  255. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  256. return
  257. }
  258. // returns all the nodes in JSON/API format
  259. apiNodes := logic.GetAllNodesAPI(nodes[:])
  260. logger.Log(2, r.Header.Get("user"), "fetched nodes on network", networkName)
  261. w.WriteHeader(http.StatusOK)
  262. json.NewEncoder(w).Encode(apiNodes)
  263. }
  264. // @Summary Get all nodes across all networks
  265. // @Router /api/nodes [get]
  266. // @Tags Nodes
  267. // @Securitydefinitions.oauth2.application OAuth2Application
  268. // @Success 200 {array} models.ApiNode
  269. // @Failure 500 {object} models.ErrorResponse
  270. // Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
  271. func getAllNodes(w http.ResponseWriter, r *http.Request) {
  272. w.Header().Set("Content-Type", "application/json")
  273. user, err := logic.GetUser(r.Header.Get("user"))
  274. if err != nil && r.Header.Get("ismasterkey") != "yes" {
  275. logger.Log(0, r.Header.Get("user"),
  276. "error fetching user info: ", err.Error())
  277. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  278. return
  279. }
  280. var nodes []models.Node
  281. if user.IsAdmin || r.Header.Get("ismasterkey") == "yes" {
  282. nodes, err = logic.GetAllNodes()
  283. if err != nil {
  284. logger.Log(0, "error fetching all nodes info: ", err.Error())
  285. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  286. return
  287. }
  288. }
  289. // return all the nodes in JSON/API format
  290. apiNodes := logic.GetAllNodesAPI(nodes[:])
  291. logger.Log(3, r.Header.Get("user"), "fetched all nodes they have access to")
  292. logic.SortApiNodes(apiNodes[:])
  293. w.WriteHeader(http.StatusOK)
  294. json.NewEncoder(w).Encode(apiNodes)
  295. }
  296. // @Summary Get an individual node
  297. // @Router /api/nodes/{network}/{nodeid} [get]
  298. // @Tags Nodes
  299. // @Security oauth2
  300. // @Success 200 {object} models.NodeGet
  301. // @Failure 500 {object} models.ErrorResponse
  302. func getNode(w http.ResponseWriter, r *http.Request) {
  303. // set header.
  304. w.Header().Set("Content-Type", "application/json")
  305. var params = mux.Vars(r)
  306. nodeid := params["nodeid"]
  307. node, err := logic.ValidateParams(nodeid, params["network"])
  308. if err != nil {
  309. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  310. return
  311. }
  312. host, err := logic.GetHost(node.HostID.String())
  313. if err != nil {
  314. logger.Log(0, r.Header.Get("user"),
  315. fmt.Sprintf("error fetching host for node [ %s ] info: %v", nodeid, err))
  316. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  317. return
  318. }
  319. allNodes, err := logic.GetAllNodes()
  320. if err != nil {
  321. logger.Log(
  322. 0,
  323. r.Header.Get("user"),
  324. fmt.Sprintf(
  325. "error fetching wg peers config for host [ %s ]: %v",
  326. host.ID.String(),
  327. err,
  328. ),
  329. )
  330. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  331. return
  332. }
  333. hostPeerUpdate, err := logic.GetPeerUpdateForHost(node.Network, host, allNodes, nil, nil)
  334. if err != nil && !database.IsEmptyRecord(err) {
  335. logger.Log(
  336. 0,
  337. r.Header.Get("user"),
  338. fmt.Sprintf(
  339. "error fetching wg peers config for host [ %s ]: %v",
  340. host.ID.String(),
  341. err,
  342. ),
  343. )
  344. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  345. return
  346. }
  347. server := servercfg.GetServerInfo()
  348. response := models.NodeGet{
  349. Node: node,
  350. Host: *host,
  351. HostPeers: hostPeerUpdate.Peers,
  352. Peers: hostPeerUpdate.NodePeers,
  353. ServerConfig: server,
  354. PeerIDs: hostPeerUpdate.PeerIDs,
  355. }
  356. logger.Log(2, r.Header.Get("user"), "fetched node", params["nodeid"])
  357. w.WriteHeader(http.StatusOK)
  358. json.NewEncoder(w).Encode(response)
  359. }
  360. // == EGRESS ==
  361. // @Summary Create an egress gateway
  362. // @Router /api/nodes/{network}/{nodeid}/creategateway [post]
  363. // @Tags Nodes
  364. // @Security oauth2
  365. // @Success 200 {object} models.ApiNode
  366. // @Failure 500 {object} models.ErrorResponse
  367. func createEgressGateway(w http.ResponseWriter, r *http.Request) {
  368. var gateway models.EgressGatewayRequest
  369. var params = mux.Vars(r)
  370. node, err := logic.ValidateParams(params["nodeid"], params["network"])
  371. if err != nil {
  372. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  373. return
  374. }
  375. w.Header().Set("Content-Type", "application/json")
  376. if err := json.NewDecoder(r.Body).Decode(&gateway); err != nil {
  377. logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error())
  378. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  379. return
  380. }
  381. gateway.NetID = params["network"]
  382. gateway.NodeID = params["nodeid"]
  383. err = logic.ValidateEgressRange(gateway)
  384. if err != nil {
  385. logger.Log(0, r.Header.Get("user"), "error validating egress range: ", err.Error())
  386. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  387. return
  388. }
  389. node, err = logic.CreateEgressGateway(gateway)
  390. if err != nil {
  391. logger.Log(0, r.Header.Get("user"),
  392. fmt.Sprintf("failed to create egress gateway on node [%s] on network [%s]: %v",
  393. gateway.NodeID, gateway.NetID, err))
  394. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  395. return
  396. }
  397. apiNode := node.ConvertToAPINode()
  398. logger.Log(
  399. 1,
  400. r.Header.Get("user"),
  401. "created egress gateway on node",
  402. gateway.NodeID,
  403. "on network",
  404. gateway.NetID,
  405. )
  406. w.WriteHeader(http.StatusOK)
  407. json.NewEncoder(w).Encode(apiNode)
  408. go func() {
  409. if err := mq.NodeUpdate(&node); err != nil {
  410. slog.Error("error publishing node update to node", "node", node.ID, "error", err)
  411. }
  412. mq.PublishPeerUpdate(false)
  413. }()
  414. }
  415. // @Summary Delete an egress gateway
  416. // @Router /api/nodes/{network}/{nodeid}/deletegateway [delete]
  417. // @Tags Nodes
  418. // @Security oauth2
  419. // @Success 200 {object} models.ApiNode
  420. // @Failure 500 {object} models.ErrorResponse
  421. func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
  422. w.Header().Set("Content-Type", "application/json")
  423. var params = mux.Vars(r)
  424. nodeid := params["nodeid"]
  425. netid := params["network"]
  426. node, err := logic.ValidateParams(nodeid, netid)
  427. if err != nil {
  428. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  429. return
  430. }
  431. node, err = logic.DeleteEgressGateway(netid, nodeid)
  432. if err != nil {
  433. logger.Log(0, r.Header.Get("user"),
  434. fmt.Sprintf("failed to delete egress gateway on node [%s] on network [%s]: %v",
  435. nodeid, netid, err))
  436. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  437. return
  438. }
  439. apiNode := node.ConvertToAPINode()
  440. logger.Log(
  441. 1,
  442. r.Header.Get("user"),
  443. "deleted egress gateway on node",
  444. nodeid,
  445. "on network",
  446. netid,
  447. )
  448. w.WriteHeader(http.StatusOK)
  449. json.NewEncoder(w).Encode(apiNode)
  450. go func() {
  451. if err := mq.NodeUpdate(&node); err != nil {
  452. slog.Error("error publishing node update to node", "node", node.ID, "error", err)
  453. }
  454. mq.PublishPeerUpdate(false)
  455. }()
  456. }
  457. // == INGRESS ==
  458. // @Summary Create an remote access gateway
  459. // @Router /api/nodes/{network}/{nodeid}/createingress [post]
  460. // @Tags Nodes
  461. // @Security oauth2
  462. // @Success 200 {object} models.ApiNode
  463. // @Failure 500 {object} models.ErrorResponse
  464. func createIngressGateway(w http.ResponseWriter, r *http.Request) {
  465. var params = mux.Vars(r)
  466. w.Header().Set("Content-Type", "application/json")
  467. nodeid := params["nodeid"]
  468. netid := params["network"]
  469. node, err := logic.ValidateParams(nodeid, netid)
  470. if err != nil {
  471. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  472. return
  473. }
  474. var request models.IngressRequest
  475. json.NewDecoder(r.Body).Decode(&request)
  476. node, err = logic.CreateIngressGateway(netid, nodeid, request)
  477. if err != nil {
  478. logger.Log(0, r.Header.Get("user"),
  479. fmt.Sprintf("failed to create ingress gateway on node [%s] on network [%s]: %v",
  480. nodeid, netid, err))
  481. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  482. return
  483. }
  484. apiNode := node.ConvertToAPINode()
  485. logger.Log(
  486. 1,
  487. r.Header.Get("user"),
  488. "created ingress gateway on node",
  489. nodeid,
  490. "on network",
  491. netid,
  492. )
  493. w.WriteHeader(http.StatusOK)
  494. json.NewEncoder(w).Encode(apiNode)
  495. go func() {
  496. if err := mq.NodeUpdate(&node); err != nil {
  497. slog.Error("error publishing node update to node", "node", node.ID, "error", err)
  498. }
  499. }()
  500. }
  501. // @Summary Delete an remote access gateway
  502. // @Router /api/nodes/{network}/{nodeid}/deleteingress [delete]
  503. // @Tags Nodes
  504. // @Security oauth2
  505. // @Success 200 {object} models.ApiNode
  506. // @Failure 500 {object} models.ErrorResponse
  507. func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
  508. w.Header().Set("Content-Type", "application/json")
  509. var params = mux.Vars(r)
  510. nodeid := params["nodeid"]
  511. netid := params["network"]
  512. node, err := logic.ValidateParams(nodeid, netid)
  513. if err != nil {
  514. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  515. return
  516. }
  517. node, removedClients, err := logic.DeleteIngressGateway(nodeid)
  518. if err != nil {
  519. logger.Log(0, r.Header.Get("user"),
  520. fmt.Sprintf("failed to delete ingress gateway on node [%s] on network [%s]: %v",
  521. nodeid, netid, err))
  522. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  523. return
  524. }
  525. if servercfg.IsPro {
  526. go func() {
  527. users, err := logic.GetUsersDB()
  528. if err == nil {
  529. for _, user := range users {
  530. if _, ok := user.RemoteGwIDs[nodeid]; ok {
  531. delete(user.RemoteGwIDs, nodeid)
  532. err = logic.UpsertUser(user)
  533. if err != nil {
  534. slog.Error("failed to get user", "user", user.UserName, "error", err)
  535. }
  536. }
  537. }
  538. } else {
  539. slog.Error("failed to get users", "error", err)
  540. }
  541. }()
  542. }
  543. apiNode := node.ConvertToAPINode()
  544. logger.Log(1, r.Header.Get("user"), "deleted ingress gateway", nodeid)
  545. w.WriteHeader(http.StatusOK)
  546. json.NewEncoder(w).Encode(apiNode)
  547. if len(removedClients) > 0 {
  548. host, err := logic.GetHost(node.HostID.String())
  549. if err == nil {
  550. allNodes, err := logic.GetAllNodes()
  551. if err != nil {
  552. return
  553. }
  554. go func() {
  555. if err := mq.PublishSingleHostPeerUpdate(host, allNodes, nil, removedClients[:], false, nil); err != nil {
  556. slog.Error("publishSingleHostUpdate", "host", host.Name, "error", err)
  557. }
  558. if err := mq.NodeUpdate(&node); err != nil {
  559. slog.Error(
  560. "error publishing node update to node",
  561. "node",
  562. node.ID,
  563. "error",
  564. err,
  565. )
  566. }
  567. if servercfg.IsDNSMode() {
  568. logic.SetDNS()
  569. }
  570. }()
  571. }
  572. }
  573. }
  574. // @Summary Update an individual node
  575. // @Router /api/nodes/{network}/{nodeid} [put]
  576. // @Tags Nodes
  577. // @Security oauth2
  578. // @Success 200 {object} models.ApiNode
  579. // @Failure 500 {object} models.ErrorResponse
  580. func updateNode(w http.ResponseWriter, r *http.Request) {
  581. w.Header().Set("Content-Type", "application/json")
  582. var params = mux.Vars(r)
  583. //start here
  584. nodeid := params["nodeid"]
  585. currentNode, err := logic.ValidateParams(nodeid, params["network"])
  586. if err != nil {
  587. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  588. return
  589. }
  590. var newData models.ApiNode
  591. // we decode our body request params
  592. err = json.NewDecoder(r.Body).Decode(&newData)
  593. if err != nil {
  594. logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error())
  595. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  596. return
  597. }
  598. if !servercfg.IsPro {
  599. newData.AdditionalRagIps = []string{}
  600. }
  601. newNode := newData.ConvertToServerNode(&currentNode)
  602. if newNode == nil {
  603. logic.ReturnErrorResponse(
  604. w,
  605. r,
  606. logic.FormatError(fmt.Errorf("error converting node"), "badrequest"),
  607. )
  608. return
  609. }
  610. if newNode.IsInternetGateway != currentNode.IsInternetGateway {
  611. if newNode.IsInternetGateway {
  612. logic.SetInternetGw(newNode, models.InetNodeReq{})
  613. } else {
  614. logic.UnsetInternetGw(newNode)
  615. }
  616. }
  617. relayUpdate := logic.RelayUpdates(&currentNode, newNode)
  618. if relayUpdate && newNode.IsRelay {
  619. err = logic.ValidateRelay(models.RelayRequest{
  620. NodeID: newNode.ID.String(),
  621. NetID: newNode.Network,
  622. RelayedNodes: newNode.RelayedNodes,
  623. }, true)
  624. if err != nil {
  625. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  626. return
  627. }
  628. }
  629. _, err = logic.GetHost(newNode.HostID.String())
  630. if err != nil {
  631. logger.Log(0, r.Header.Get("user"),
  632. fmt.Sprintf("failed to get host for node [ %s ] info: %v", nodeid, err))
  633. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  634. return
  635. }
  636. ifaceDelta := logic.IfaceDelta(&currentNode, newNode)
  637. aclUpdate := currentNode.DefaultACL != newNode.DefaultACL
  638. err = logic.UpdateNode(&currentNode, newNode)
  639. if err != nil {
  640. logger.Log(0, r.Header.Get("user"),
  641. fmt.Sprintf("failed to update node info [ %s ] info: %v", nodeid, err))
  642. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  643. return
  644. }
  645. if relayUpdate {
  646. logic.UpdateRelayed(&currentNode, newNode)
  647. }
  648. apiNode := newNode.ConvertToAPINode()
  649. logger.Log(
  650. 1,
  651. r.Header.Get("user"),
  652. "updated node",
  653. currentNode.ID.String(),
  654. "on network",
  655. currentNode.Network,
  656. )
  657. w.WriteHeader(http.StatusOK)
  658. json.NewEncoder(w).Encode(apiNode)
  659. go func(aclUpdate, relayupdate bool, newNode *models.Node) {
  660. if err := mq.NodeUpdate(newNode); err != nil {
  661. slog.Error("error publishing node update to node", "node", newNode.ID, "error", err)
  662. }
  663. if aclUpdate || relayupdate || ifaceDelta {
  664. if err := mq.PublishPeerUpdate(false); err != nil {
  665. logger.Log(0, "error during node ACL update for node", newNode.ID.String())
  666. }
  667. }
  668. if servercfg.IsDNSMode() {
  669. logic.SetDNS()
  670. }
  671. }(aclUpdate, relayUpdate, newNode)
  672. }
  673. // @Summary Delete an individual node
  674. // @Router /api/nodes/{network}/{nodeid} [delete]
  675. // @Tags Nodes
  676. // @Security oauth2
  677. // @Success 200 {string} string "Node deleted."
  678. // @Failure 500 {object} models.ErrorResponse
  679. func deleteNode(w http.ResponseWriter, r *http.Request) {
  680. // Set header
  681. w.Header().Set("Content-Type", "application/json")
  682. // get params
  683. var params = mux.Vars(r)
  684. var nodeid = params["nodeid"]
  685. node, err := logic.ValidateParams(nodeid, params["network"])
  686. if err != nil {
  687. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  688. return
  689. }
  690. forceDelete := r.URL.Query().Get("force") == "true"
  691. fromNode := r.Header.Get("requestfrom") == "node"
  692. var gwClients []models.ExtClient
  693. if node.IsIngressGateway {
  694. gwClients = logic.GetGwExtclients(node.ID.String(), node.Network)
  695. }
  696. purge := forceDelete || fromNode
  697. if err := logic.DeleteNode(&node, purge); err != nil {
  698. logic.ReturnErrorResponse(
  699. w,
  700. r,
  701. logic.FormatError(fmt.Errorf("failed to delete node"), "internal"),
  702. )
  703. return
  704. }
  705. logic.ReturnSuccessResponse(w, r, nodeid+" deleted.")
  706. logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"])
  707. go mq.PublishMqUpdatesForDeletedNode(node, !fromNode, gwClients)
  708. }