ext_client.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "strconv"
  9. "strings"
  10. "github.com/gorilla/mux"
  11. "github.com/gravitl/netmaker/database"
  12. "github.com/gravitl/netmaker/logger"
  13. "github.com/gravitl/netmaker/logic"
  14. "github.com/gravitl/netmaker/models"
  15. "github.com/gravitl/netmaker/mq"
  16. "github.com/skip2/go-qrcode"
  17. "golang.org/x/exp/slog"
  18. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  19. )
  20. func extClientHandlers(r *mux.Router) {
  21. r.HandleFunc("/api/extclients", logic.SecurityCheck(true, http.HandlerFunc(getAllExtClients))).Methods(http.MethodGet)
  22. r.HandleFunc("/api/extclients/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkExtClients))).Methods(http.MethodGet)
  23. r.HandleFunc("/api/extclients/{network}/{clientid}", logic.SecurityCheck(false, http.HandlerFunc(getExtClient))).Methods(http.MethodGet)
  24. r.HandleFunc("/api/extclients/{network}/{clientid}/{type}", logic.SecurityCheck(false, http.HandlerFunc(getExtClientConf))).Methods(http.MethodGet)
  25. r.HandleFunc("/api/extclients/{network}/{clientid}", logic.SecurityCheck(false, http.HandlerFunc(updateExtClient))).Methods(http.MethodPut)
  26. r.HandleFunc("/api/extclients/{network}/{clientid}", logic.SecurityCheck(false, http.HandlerFunc(deleteExtClient))).Methods(http.MethodDelete)
  27. r.HandleFunc("/api/extclients/{network}/{nodeid}", logic.SecurityCheck(false, checkFreeTierLimits(limitChoiceMachines, http.HandlerFunc(createExtClient)))).Methods(http.MethodPost)
  28. }
  29. func checkIngressExists(nodeID string) bool {
  30. node, err := logic.GetNodeByID(nodeID)
  31. if err != nil {
  32. return false
  33. }
  34. return node.IsIngressGateway
  35. }
  36. // swagger:route GET /api/extclients/{network} ext_client getNetworkExtClients
  37. //
  38. // Get all extclients associated with network.
  39. // Gets all extclients associated with network, including pending extclients.
  40. //
  41. // Schemes: https
  42. //
  43. // Security:
  44. // oauth
  45. //
  46. // Responses:
  47. // 200: extClientSliceResponse
  48. func getNetworkExtClients(w http.ResponseWriter, r *http.Request) {
  49. w.Header().Set("Content-Type", "application/json")
  50. var extclients []models.ExtClient
  51. var params = mux.Vars(r)
  52. network := params["network"]
  53. extclients, err := logic.GetNetworkExtClients(network)
  54. if err != nil {
  55. logger.Log(0, r.Header.Get("user"),
  56. fmt.Sprintf("failed to get ext clients for network [%s]: %v", network, err))
  57. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  58. return
  59. }
  60. //Returns all the extclients in JSON format
  61. w.WriteHeader(http.StatusOK)
  62. json.NewEncoder(w).Encode(extclients)
  63. }
  64. // swagger:route GET /api/extclients ext_client getAllExtClients
  65. //
  66. // A separate function to get all extclients, not just extclients for a particular network.
  67. //
  68. // Schemes: https
  69. //
  70. // Security:
  71. // oauth
  72. //
  73. // Responses:
  74. // 200: extClientSliceResponse
  75. //
  76. // Not quite sure if this is necessary. Probably necessary based on front end but may
  77. // want to review after iteration 1 if it's being used or not
  78. func getAllExtClients(w http.ResponseWriter, r *http.Request) {
  79. w.Header().Set("Content-Type", "application/json")
  80. clients, err := logic.GetAllExtClients()
  81. if err != nil && !database.IsEmptyRecord(err) {
  82. logger.Log(0, "failed to get all extclients: ", err.Error())
  83. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  84. return
  85. }
  86. //Return all the extclients in JSON format
  87. logic.SortExtClient(clients[:])
  88. w.WriteHeader(http.StatusOK)
  89. json.NewEncoder(w).Encode(clients)
  90. }
  91. // swagger:route GET /api/extclients/{network}/{clientid} ext_client getExtClient
  92. //
  93. // Get an individual extclient.
  94. //
  95. // Schemes: https
  96. //
  97. // Security:
  98. // oauth
  99. //
  100. // Responses:
  101. // 200: extClientResponse
  102. func getExtClient(w http.ResponseWriter, r *http.Request) {
  103. // set header.
  104. w.Header().Set("Content-Type", "application/json")
  105. var params = mux.Vars(r)
  106. clientid := params["clientid"]
  107. network := params["network"]
  108. client, err := logic.GetExtClient(clientid, network)
  109. if err != nil {
  110. logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to get extclient for [%s] on network [%s]: %v",
  111. clientid, network, err))
  112. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  113. return
  114. }
  115. if !logic.IsUserAllowedAccessToExtClient(r.Header.Get("user"), client) {
  116. // check if user has access to extclient
  117. slog.Error("failed to get extclient", "network", network, "clientID",
  118. clientid, "error", errors.New("access is denied"))
  119. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("access is denied"), "forbidden"))
  120. return
  121. }
  122. w.WriteHeader(http.StatusOK)
  123. json.NewEncoder(w).Encode(client)
  124. }
  125. // swagger:route GET /api/extclients/{network}/{clientid}/{type} ext_client getExtClientConf
  126. //
  127. // Get an individual extclient.
  128. //
  129. // Schemes: https
  130. //
  131. // Security:
  132. // oauth
  133. //
  134. // Responses:
  135. // 200: extClientResponse
  136. func getExtClientConf(w http.ResponseWriter, r *http.Request) {
  137. // set header.
  138. w.Header().Set("Content-Type", "application/json")
  139. var params = mux.Vars(r)
  140. clientid := params["clientid"]
  141. networkid := params["network"]
  142. client, err := logic.GetExtClient(clientid, networkid)
  143. if err != nil {
  144. logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to get extclient for [%s] on network [%s]: %v",
  145. clientid, networkid, err))
  146. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  147. return
  148. }
  149. if !logic.IsUserAllowedAccessToExtClient(r.Header.Get("user"), client) {
  150. slog.Error("failed to get extclient", "network", networkid, "clientID",
  151. clientid, "error", errors.New("access is denied"))
  152. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("access is denied"), "forbidden"))
  153. return
  154. }
  155. gwnode, err := logic.GetNodeByID(client.IngressGatewayID)
  156. if err != nil {
  157. logger.Log(0, r.Header.Get("user"),
  158. fmt.Sprintf("failed to get ingress gateway node [%s] info: %v", client.IngressGatewayID, err))
  159. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  160. return
  161. }
  162. host, err := logic.GetHost(gwnode.HostID.String())
  163. if err != nil {
  164. logger.Log(0, r.Header.Get("user"),
  165. fmt.Sprintf("failed to get host for ingress gateway node [%s] info: %v", client.IngressGatewayID, err))
  166. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  167. return
  168. }
  169. network, err := logic.GetParentNetwork(client.Network)
  170. if err != nil {
  171. logger.Log(1, r.Header.Get("user"), "Could not retrieve Ingress Gateway Network", client.Network)
  172. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  173. return
  174. }
  175. addrString := client.Address
  176. if addrString != "" {
  177. addrString += "/32"
  178. }
  179. if client.Address6 != "" {
  180. if addrString != "" {
  181. addrString += ","
  182. }
  183. addrString += client.Address6 + "/128"
  184. }
  185. keepalive := ""
  186. if network.DefaultKeepalive != 0 {
  187. keepalive = "PersistentKeepalive = " + strconv.Itoa(int(network.DefaultKeepalive))
  188. }
  189. gwendpoint := ""
  190. if host.EndpointIP.To4() == nil {
  191. gwendpoint = fmt.Sprintf("[%s]:%d", host.EndpointIP.String(), host.ListenPort)
  192. } else {
  193. gwendpoint = fmt.Sprintf("%s:%d", host.EndpointIP.String(), host.ListenPort)
  194. }
  195. defaultDNS := ""
  196. if client.DNS != "" {
  197. defaultDNS = "DNS = " + client.DNS
  198. } else if gwnode.IngressDNS != "" {
  199. defaultDNS = "DNS = " + gwnode.IngressDNS
  200. }
  201. defaultMTU := 1420
  202. if host.MTU != 0 {
  203. defaultMTU = host.MTU
  204. }
  205. config := fmt.Sprintf(`[Interface]
  206. Address = %s
  207. PrivateKey = %s
  208. MTU = %d
  209. %s
  210. [Peer]
  211. PublicKey = %s
  212. AllowedIPs = %s
  213. Endpoint = %s
  214. %s
  215. `, addrString,
  216. client.PrivateKey,
  217. defaultMTU,
  218. defaultDNS,
  219. host.PublicKey,
  220. strings.Join(logic.GetExtclientAllowedIPs(client), ","),
  221. gwendpoint,
  222. keepalive)
  223. if params["type"] == "qr" {
  224. bytes, err := qrcode.Encode(config, qrcode.Medium, 220)
  225. if err != nil {
  226. logger.Log(1, r.Header.Get("user"), "failed to encode qr code: ", err.Error())
  227. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  228. return
  229. }
  230. w.Header().Set("Content-Type", "image/png")
  231. w.WriteHeader(http.StatusOK)
  232. _, err = w.Write(bytes)
  233. if err != nil {
  234. logger.Log(1, r.Header.Get("user"), "response writer error (qr) ", err.Error())
  235. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  236. return
  237. }
  238. return
  239. }
  240. if params["type"] == "file" {
  241. name := client.ClientID + ".conf"
  242. w.Header().Set("Content-Type", "application/config")
  243. w.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"")
  244. w.WriteHeader(http.StatusOK)
  245. _, err := fmt.Fprint(w, config)
  246. if err != nil {
  247. logger.Log(1, r.Header.Get("user"), "response writer error (file) ", err.Error())
  248. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  249. }
  250. return
  251. }
  252. logger.Log(2, r.Header.Get("user"), "retrieved ext client config")
  253. w.WriteHeader(http.StatusOK)
  254. json.NewEncoder(w).Encode(client)
  255. }
  256. // swagger:route POST /api/extclients/{network}/{nodeid} ext_client createExtClient
  257. //
  258. // Create an individual extclient. Must have valid key and be unique.
  259. //
  260. // Schemes: https
  261. //
  262. // Security:
  263. // oauth
  264. // Responses:
  265. // 200: okResponse
  266. func createExtClient(w http.ResponseWriter, r *http.Request) {
  267. w.Header().Set("Content-Type", "application/json")
  268. var params = mux.Vars(r)
  269. nodeid := params["nodeid"]
  270. ingressExists := checkIngressExists(nodeid)
  271. if !ingressExists {
  272. err := errors.New("ingress does not exist")
  273. slog.Error("failed to create extclient", "user", r.Header.Get("user"), "error", err)
  274. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  275. return
  276. }
  277. var customExtClient models.CustomExtClient
  278. if err := json.NewDecoder(r.Body).Decode(&customExtClient); err != nil {
  279. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  280. return
  281. }
  282. if err := validateCustomExtClient(&customExtClient, true); err != nil {
  283. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  284. return
  285. }
  286. node, err := logic.GetNodeByID(nodeid)
  287. if err != nil {
  288. logger.Log(0, r.Header.Get("user"),
  289. fmt.Sprintf("failed to get ingress gateway node [%s] info: %v", nodeid, err))
  290. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  291. return
  292. }
  293. var userName string
  294. if r.Header.Get("ismaster") == "yes" {
  295. userName = logic.MasterUser
  296. } else {
  297. caller, err := logic.GetUser(r.Header.Get("user"))
  298. if err != nil {
  299. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  300. return
  301. }
  302. userName = caller.UserName
  303. if !caller.IsAdmin && !caller.IsSuperAdmin {
  304. if _, ok := caller.RemoteGwIDs[nodeid]; !ok {
  305. err = errors.New("permission denied")
  306. slog.Error("failed to create extclient", "error", err)
  307. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  308. return
  309. }
  310. // check if user has a config already for remote access client
  311. extclients, err := logic.GetNetworkExtClients(node.Network)
  312. if err != nil {
  313. slog.Error("failed to get extclients", "error", err)
  314. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  315. return
  316. }
  317. for _, extclient := range extclients {
  318. if extclient.RemoteAccessClientID != "" &&
  319. extclient.RemoteAccessClientID == customExtClient.RemoteAccessClientID && nodeid == extclient.IngressGatewayID {
  320. // extclient on the gw already exists for the remote access client
  321. err = errors.New("remote client config already exists on the gateway")
  322. slog.Error("failed to create extclient", "user", userName, "error", err)
  323. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  324. return
  325. }
  326. }
  327. }
  328. }
  329. extclient := logic.UpdateExtClient(&models.ExtClient{}, &customExtClient)
  330. extclient.OwnerID = userName
  331. extclient.RemoteAccessClientID = customExtClient.RemoteAccessClientID
  332. extclient.IngressGatewayID = nodeid
  333. // set extclient dns to ingressdns if extclient dns is not explicitly set
  334. if (extclient.DNS == "") && (node.IngressDNS != "") {
  335. extclient.DNS = node.IngressDNS
  336. }
  337. extclient.Network = node.Network
  338. host, err := logic.GetHost(node.HostID.String())
  339. if err != nil {
  340. logger.Log(0, r.Header.Get("user"),
  341. fmt.Sprintf("failed to get ingress gateway host for node [%s] info: %v", nodeid, err))
  342. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  343. return
  344. }
  345. listenPort := logic.GetPeerListenPort(host)
  346. extclient.IngressGatewayEndpoint = fmt.Sprintf("%s:%d", host.EndpointIP.String(), listenPort)
  347. extclient.Enabled = true
  348. parentNetwork, err := logic.GetNetwork(node.Network)
  349. if err == nil { // check if parent network default ACL is enabled (yes) or not (no)
  350. extclient.Enabled = parentNetwork.DefaultACL == "yes"
  351. }
  352. if err := logic.SetClientDefaultACLs(&extclient); err != nil {
  353. slog.Error("failed to set default acls for extclient", "user", r.Header.Get("user"), "network", node.Network, "error", err)
  354. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  355. return
  356. }
  357. if err = logic.CreateExtClient(&extclient); err != nil {
  358. slog.Error("failed to create extclient", "user", r.Header.Get("user"), "network", node.Network, "error", err)
  359. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  360. return
  361. }
  362. slog.Info("created extclient", "user", r.Header.Get("user"), "network", node.Network, "clientid", extclient.ClientID)
  363. w.WriteHeader(http.StatusOK)
  364. go func() {
  365. if err := mq.PublishPeerUpdate(); err != nil {
  366. logger.Log(1, "error setting ext peers on "+nodeid+": "+err.Error())
  367. }
  368. if err := mq.PublishExtClientDNS(&extclient); err != nil {
  369. logger.Log(1, "error publishing extclient dns", err.Error())
  370. }
  371. }()
  372. }
  373. // swagger:route PUT /api/extclients/{network}/{clientid} ext_client updateExtClient
  374. //
  375. // Update an individual extclient.
  376. //
  377. // Schemes: https
  378. //
  379. // Security:
  380. // oauth
  381. //
  382. // Responses:
  383. // 200: extClientResponse
  384. func updateExtClient(w http.ResponseWriter, r *http.Request) {
  385. w.Header().Set("Content-Type", "application/json")
  386. var params = mux.Vars(r)
  387. var update models.CustomExtClient
  388. //var oldExtClient models.ExtClient
  389. var sendPeerUpdate bool
  390. err := json.NewDecoder(r.Body).Decode(&update)
  391. if err != nil {
  392. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  393. err.Error())
  394. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  395. return
  396. }
  397. clientid := params["clientid"]
  398. network := params["network"]
  399. oldExtClient, err := logic.GetExtClientByName(clientid)
  400. if err != nil {
  401. slog.Error("failed to retrieve extclient", "user", r.Header.Get("user"), "id", clientid, "error", err)
  402. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  403. return
  404. }
  405. if !logic.IsUserAllowedAccessToExtClient(r.Header.Get("user"), oldExtClient) {
  406. // check if user has access to extclient
  407. slog.Error("failed to get extclient", "network", network, "clientID",
  408. clientid, "error", errors.New("access is denied"))
  409. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("access is denied"), "forbidden"))
  410. return
  411. }
  412. if oldExtClient.ClientID == update.ClientID {
  413. if err := validateCustomExtClient(&update, false); err != nil {
  414. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  415. return
  416. }
  417. } else {
  418. if err := validateCustomExtClient(&update, true); err != nil {
  419. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  420. return
  421. }
  422. }
  423. var changedID = update.ClientID != oldExtClient.ClientID
  424. if len(update.DeniedACLs) != len(oldExtClient.DeniedACLs) {
  425. sendPeerUpdate = true
  426. logic.SetClientACLs(&oldExtClient, update.DeniedACLs)
  427. }
  428. if !logic.IsSlicesEqual(update.ExtraAllowedIPs, oldExtClient.ExtraAllowedIPs) {
  429. sendPeerUpdate = true
  430. }
  431. if update.Enabled != oldExtClient.Enabled {
  432. sendPeerUpdate = true
  433. }
  434. newclient := logic.UpdateExtClient(&oldExtClient, &update)
  435. if err := logic.DeleteExtClient(oldExtClient.Network, oldExtClient.ClientID); err != nil {
  436. slog.Error("failed to delete ext client", "user", r.Header.Get("user"), "id", oldExtClient.ClientID, "network", oldExtClient.Network, "error", err)
  437. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  438. return
  439. }
  440. if err := logic.SaveExtClient(&newclient); err != nil {
  441. slog.Error("failed to save ext client", "user", r.Header.Get("user"), "id", newclient.ClientID, "network", newclient.Network, "error", err)
  442. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  443. return
  444. }
  445. logger.Log(0, r.Header.Get("user"), "updated ext client", update.ClientID)
  446. if sendPeerUpdate { // need to send a peer update to the ingress node as enablement of one of it's clients has changed
  447. if ingressNode, err := logic.GetNodeByID(newclient.IngressGatewayID); err == nil {
  448. if err = mq.PublishPeerUpdate(); err != nil {
  449. logger.Log(1, "error setting ext peers on", ingressNode.ID.String(), ":", err.Error())
  450. }
  451. }
  452. }
  453. w.WriteHeader(http.StatusOK)
  454. json.NewEncoder(w).Encode(newclient)
  455. if changedID {
  456. go func() {
  457. if err := mq.PublishExtClientDNSUpdate(oldExtClient, newclient, oldExtClient.Network); err != nil {
  458. logger.Log(1, "error pubishing dns update for extcient update", err.Error())
  459. }
  460. }()
  461. }
  462. }
  463. // swagger:route DELETE /api/extclients/{network}/{clientid} ext_client deleteExtClient
  464. //
  465. // Delete an individual extclient.
  466. //
  467. // Schemes: https
  468. //
  469. // Security:
  470. // oauth
  471. //
  472. // Responses:
  473. // 200: successResponse
  474. func deleteExtClient(w http.ResponseWriter, r *http.Request) {
  475. // Set header
  476. w.Header().Set("Content-Type", "application/json")
  477. // get params
  478. var params = mux.Vars(r)
  479. clientid := params["clientid"]
  480. network := params["network"]
  481. extclient, err := logic.GetExtClient(clientid, network)
  482. if err != nil {
  483. err = errors.New("Could not delete extclient " + params["clientid"])
  484. logger.Log(0, r.Header.Get("user"),
  485. fmt.Sprintf("failed to get extclient [%s],network [%s]: %v", clientid, network, err))
  486. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  487. return
  488. }
  489. if !logic.IsUserAllowedAccessToExtClient(r.Header.Get("user"), extclient) {
  490. slog.Error("user not allowed to delete", "network", network, "clientID",
  491. clientid, "error", errors.New("access is denied"))
  492. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("access is denied"), "forbidden"))
  493. return
  494. }
  495. ingressnode, err := logic.GetNodeByID(extclient.IngressGatewayID)
  496. if err != nil {
  497. logger.Log(0, r.Header.Get("user"),
  498. fmt.Sprintf("failed to get ingress gateway node [%s] info: %v", extclient.IngressGatewayID, err))
  499. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  500. return
  501. }
  502. err = logic.DeleteExtClient(params["network"], params["clientid"])
  503. if err != nil {
  504. logger.Log(0, r.Header.Get("user"),
  505. fmt.Sprintf("failed to delete extclient [%s],network [%s]: %v", clientid, network, err))
  506. err = errors.New("Could not delete extclient " + params["clientid"])
  507. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  508. return
  509. }
  510. go func() {
  511. if err := mq.PublishDeletedClientPeerUpdate(&extclient); err != nil {
  512. logger.Log(1, "error setting ext peers on "+ingressnode.ID.String()+": "+err.Error())
  513. }
  514. if err = mq.PublishDeleteExtClientDNS(&extclient); err != nil {
  515. logger.Log(1, "error publishing dns update for extclient deletion", err.Error())
  516. }
  517. }()
  518. logger.Log(0, r.Header.Get("user"),
  519. "Deleted extclient client", params["clientid"], "from network", params["network"])
  520. logic.ReturnSuccessResponse(w, r, params["clientid"]+" deleted.")
  521. }
  522. // validateCustomExtClient Validates the extclient object
  523. func validateCustomExtClient(customExtClient *models.CustomExtClient, checkID bool) error {
  524. //validate clientid
  525. if customExtClient.ClientID != "" {
  526. if err := isValid(customExtClient.ClientID, checkID); err != nil {
  527. return fmt.Errorf("client validatation: %v", err)
  528. }
  529. }
  530. //extclient.ClientID = customExtClient.ClientID
  531. if len(customExtClient.PublicKey) > 0 {
  532. if _, err := wgtypes.ParseKey(customExtClient.PublicKey); err != nil {
  533. return errInvalidExtClientPubKey
  534. }
  535. //extclient.PublicKey = customExtClient.PublicKey
  536. }
  537. //validate extra ips
  538. if len(customExtClient.ExtraAllowedIPs) > 0 {
  539. for _, ip := range customExtClient.ExtraAllowedIPs {
  540. if _, _, err := net.ParseCIDR(ip); err != nil {
  541. return errInvalidExtClientExtraIP
  542. }
  543. }
  544. //extclient.ExtraAllowedIPs = customExtClient.ExtraAllowedIPs
  545. }
  546. //validate DNS
  547. if customExtClient.DNS != "" {
  548. if ip := net.ParseIP(customExtClient.DNS); ip == nil {
  549. return errInvalidExtClientDNS
  550. }
  551. //extclient.DNS = customExtClient.DNS
  552. }
  553. return nil
  554. }
  555. // isValid Checks if the clientid is valid
  556. func isValid(clientid string, checkID bool) error {
  557. if !validName(clientid) {
  558. return errInvalidExtClientID
  559. }
  560. if checkID {
  561. extclients, err := logic.GetAllExtClients()
  562. if err != nil {
  563. return fmt.Errorf("extclients isValid: %v", err)
  564. }
  565. for _, extclient := range extclients {
  566. if clientid == extclient.ClientID {
  567. return errDuplicateExtClientName
  568. }
  569. }
  570. }
  571. return nil
  572. }