users.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. package controllers
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "github.com/gorilla/mux"
  8. "github.com/gravitl/netmaker/logger"
  9. "github.com/gravitl/netmaker/logic"
  10. "github.com/gravitl/netmaker/models"
  11. "github.com/gravitl/netmaker/mq"
  12. "github.com/gravitl/netmaker/pro/auth"
  13. "github.com/gravitl/netmaker/servercfg"
  14. "golang.org/x/exp/slog"
  15. )
  16. func UserHandlers(r *mux.Router) {
  17. r.HandleFunc("/api/users/{username}/remote_access_gw/{remote_access_gateway_id}", logic.SecurityCheck(true, http.HandlerFunc(attachUserToRemoteAccessGw))).Methods(http.MethodPost)
  18. r.HandleFunc("/api/users/{username}/remote_access_gw/{remote_access_gateway_id}", logic.SecurityCheck(true, http.HandlerFunc(removeUserFromRemoteAccessGW))).Methods(http.MethodDelete)
  19. r.HandleFunc("/api/users/{username}/remote_access_gw", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUserRemoteAccessGws)))).Methods(http.MethodGet)
  20. r.HandleFunc("/api/users/ingress/{ingress_id}", logic.SecurityCheck(true, http.HandlerFunc(ingressGatewayUsers))).Methods(http.MethodGet)
  21. r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods(http.MethodGet)
  22. r.HandleFunc("/api/oauth/callback", auth.HandleAuthCallback).Methods(http.MethodGet)
  23. r.HandleFunc("/api/oauth/headless", auth.HandleHeadlessSSO)
  24. r.HandleFunc("/api/oauth/register/{regKey}", auth.RegisterHostSSO).Methods(http.MethodGet)
  25. }
  26. // swagger:route POST /api/users/{username}/remote_access_gw user attachUserToRemoteAccessGateway
  27. //
  28. // Attach User to a remote access gateway.
  29. //
  30. // Schemes: https
  31. //
  32. // Security:
  33. // oauth
  34. //
  35. // Responses:
  36. // 200: userBodyResponse
  37. func attachUserToRemoteAccessGw(w http.ResponseWriter, r *http.Request) {
  38. // set header.
  39. w.Header().Set("Content-Type", "application/json")
  40. var params = mux.Vars(r)
  41. username := params["username"]
  42. remoteGwID := params["remote_access_gateway_id"]
  43. if username == "" || remoteGwID == "" {
  44. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("required params `username` and `remote_access_gateway_id`"), "badrequest"))
  45. return
  46. }
  47. user, err := logic.GetUser(username)
  48. if err != nil {
  49. slog.Error("failed to fetch user: ", "username", username, "error", err.Error())
  50. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to fetch user %s, error: %v", username, err), "badrequest"))
  51. return
  52. }
  53. if user.IsAdmin || user.IsSuperAdmin {
  54. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("superadmins/admins have access to all gateways"), "badrequest"))
  55. return
  56. }
  57. node, err := logic.GetNodeByID(remoteGwID)
  58. if err != nil {
  59. slog.Error("failed to fetch gateway node", "nodeID", remoteGwID, "error", err)
  60. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to fetch remote access gateway node, error: %v", err), "badrequest"))
  61. return
  62. }
  63. if !node.IsIngressGateway {
  64. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("node is not a remote access gateway"), "badrequest"))
  65. return
  66. }
  67. if user.RemoteGwIDs == nil {
  68. user.RemoteGwIDs = make(map[string]struct{})
  69. }
  70. user.RemoteGwIDs[node.ID.String()] = struct{}{}
  71. err = logic.UpsertUser(*user)
  72. if err != nil {
  73. slog.Error("failed to update user's gateways", "user", username, "error", err)
  74. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to fetch remote access gateway node,error: %v", err), "badrequest"))
  75. return
  76. }
  77. json.NewEncoder(w).Encode(logic.ToReturnUser(*user))
  78. }
  79. // swagger:route DELETE /api/users/{username}/remote_access_gw user removeUserFromRemoteAccessGW
  80. //
  81. // Delete User from a remote access gateway.
  82. //
  83. // Schemes: https
  84. //
  85. // Security:
  86. // oauth
  87. //
  88. // Responses:
  89. // 200: userBodyResponse
  90. func removeUserFromRemoteAccessGW(w http.ResponseWriter, r *http.Request) {
  91. // set header.
  92. w.Header().Set("Content-Type", "application/json")
  93. var params = mux.Vars(r)
  94. username := params["username"]
  95. remoteGwID := params["remote_access_gateway_id"]
  96. if username == "" || remoteGwID == "" {
  97. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("required params `username` and `remote_access_gateway_id`"), "badrequest"))
  98. return
  99. }
  100. user, err := logic.GetUser(username)
  101. if err != nil {
  102. logger.Log(0, username, "failed to fetch user: ", err.Error())
  103. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to fetch user %s, error: %v", username, err), "badrequest"))
  104. return
  105. }
  106. delete(user.RemoteGwIDs, remoteGwID)
  107. go func(user models.User, remoteGwID string) {
  108. extclients, err := logic.GetAllExtClients()
  109. if err != nil {
  110. slog.Error("failed to fetch extclients", "error", err)
  111. return
  112. }
  113. for _, extclient := range extclients {
  114. if extclient.OwnerID == user.UserName && remoteGwID == extclient.IngressGatewayID {
  115. err = logic.DeleteExtClientAndCleanup(extclient)
  116. if err != nil {
  117. slog.Error("failed to delete extclient",
  118. "id", extclient.ClientID, "owner", user.UserName, "error", err)
  119. } else {
  120. if err := mq.PublishDeletedClientPeerUpdate(&extclient); err != nil {
  121. slog.Error("error setting ext peers: " + err.Error())
  122. }
  123. }
  124. }
  125. }
  126. if servercfg.IsDNSMode() {
  127. logic.SetDNS()
  128. }
  129. }(*user, remoteGwID)
  130. err = logic.UpsertUser(*user)
  131. if err != nil {
  132. slog.Error("failed to update user gateways", "user", username, "error", err)
  133. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("failed to fetch remote access gaetway node "+err.Error()), "badrequest"))
  134. return
  135. }
  136. json.NewEncoder(w).Encode(logic.ToReturnUser(*user))
  137. }
  138. // swagger:route GET "/api/users/{username}/remote_access_gw" nodes getUserRemoteAccessGws
  139. //
  140. // Get an individual node.
  141. //
  142. // Schemes: https
  143. //
  144. // Security:
  145. // oauth
  146. //
  147. // Responses:
  148. // 200: nodeResponse
  149. func getUserRemoteAccessGws(w http.ResponseWriter, r *http.Request) {
  150. // set header.
  151. w.Header().Set("Content-Type", "application/json")
  152. var params = mux.Vars(r)
  153. username := params["username"]
  154. if username == "" {
  155. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("required params username"), "badrequest"))
  156. return
  157. }
  158. remoteAccessClientID := r.URL.Query().Get("remote_access_clientid")
  159. var req models.UserRemoteGwsReq
  160. if remoteAccessClientID == "" {
  161. err := json.NewDecoder(r.Body).Decode(&req)
  162. if err != nil {
  163. slog.Error("error decoding request body: ", "error", err)
  164. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  165. return
  166. }
  167. }
  168. reqFromMobile := r.URL.Query().Get("from_mobile") == "true"
  169. if req.RemoteAccessClientID == "" && remoteAccessClientID == "" {
  170. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("remote access client id cannot be empty"), "badrequest"))
  171. return
  172. }
  173. if req.RemoteAccessClientID == "" {
  174. req.RemoteAccessClientID = remoteAccessClientID
  175. }
  176. userGws := make(map[string][]models.UserRemoteGws)
  177. user, err := logic.GetUser(username)
  178. if err != nil {
  179. logger.Log(0, username, "failed to fetch user: ", err.Error())
  180. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to fetch user %s, error: %v", username, err), "badrequest"))
  181. return
  182. }
  183. allextClients, err := logic.GetAllExtClients()
  184. if err != nil {
  185. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  186. return
  187. }
  188. processedAdminNodeIds := make(map[string]struct{})
  189. for _, extClient := range allextClients {
  190. if extClient.RemoteAccessClientID == req.RemoteAccessClientID && extClient.OwnerID == username {
  191. node, err := logic.GetNodeByID(extClient.IngressGatewayID)
  192. if err != nil {
  193. continue
  194. }
  195. if node.PendingDelete {
  196. continue
  197. }
  198. if !node.IsIngressGateway {
  199. continue
  200. }
  201. host, err := logic.GetHost(node.HostID.String())
  202. if err != nil {
  203. continue
  204. }
  205. network, err := logic.GetNetwork(node.Network)
  206. if err != nil {
  207. slog.Error("failed to get node network", "error", err)
  208. }
  209. if _, ok := user.RemoteGwIDs[node.ID.String()]; (!user.IsAdmin && !user.IsSuperAdmin) && ok {
  210. gws := userGws[node.Network]
  211. extClient.AllowedIPs = logic.GetExtclientAllowedIPs(extClient)
  212. gws = append(gws, models.UserRemoteGws{
  213. GwID: node.ID.String(),
  214. GWName: host.Name,
  215. Network: node.Network,
  216. GwClient: extClient,
  217. Connected: true,
  218. IsInternetGateway: node.IsInternetGateway,
  219. GwPeerPublicKey: host.PublicKey.String(),
  220. GwListenPort: logic.GetPeerListenPort(host),
  221. Metadata: node.Metadata,
  222. AllowedEndpoints: getAllowedRagEndpoints(&node, host),
  223. NetworkAddresses: []string{network.AddressRange, network.AddressRange6},
  224. })
  225. userGws[node.Network] = gws
  226. delete(user.RemoteGwIDs, node.ID.String())
  227. } else {
  228. gws := userGws[node.Network]
  229. extClient.AllowedIPs = logic.GetExtclientAllowedIPs(extClient)
  230. gws = append(gws, models.UserRemoteGws{
  231. GwID: node.ID.String(),
  232. GWName: host.Name,
  233. Network: node.Network,
  234. GwClient: extClient,
  235. Connected: true,
  236. IsInternetGateway: node.IsInternetGateway,
  237. GwPeerPublicKey: host.PublicKey.String(),
  238. GwListenPort: logic.GetPeerListenPort(host),
  239. Metadata: node.Metadata,
  240. AllowedEndpoints: getAllowedRagEndpoints(&node, host),
  241. NetworkAddresses: []string{network.AddressRange, network.AddressRange6},
  242. })
  243. userGws[node.Network] = gws
  244. processedAdminNodeIds[node.ID.String()] = struct{}{}
  245. }
  246. }
  247. }
  248. // add remaining gw nodes to resp
  249. if !user.IsAdmin && !user.IsSuperAdmin {
  250. for gwID := range user.RemoteGwIDs {
  251. node, err := logic.GetNodeByID(gwID)
  252. if err != nil {
  253. continue
  254. }
  255. if !node.IsIngressGateway {
  256. continue
  257. }
  258. if node.PendingDelete {
  259. continue
  260. }
  261. host, err := logic.GetHost(node.HostID.String())
  262. if err != nil {
  263. continue
  264. }
  265. network, err := logic.GetNetwork(node.Network)
  266. if err != nil {
  267. slog.Error("failed to get node network", "error", err)
  268. }
  269. gws := userGws[node.Network]
  270. gws = append(gws, models.UserRemoteGws{
  271. GwID: node.ID.String(),
  272. GWName: host.Name,
  273. Network: node.Network,
  274. IsInternetGateway: node.IsInternetGateway,
  275. GwPeerPublicKey: host.PublicKey.String(),
  276. GwListenPort: logic.GetPeerListenPort(host),
  277. Metadata: node.Metadata,
  278. AllowedEndpoints: getAllowedRagEndpoints(&node, host),
  279. NetworkAddresses: []string{network.AddressRange, network.AddressRange6},
  280. })
  281. userGws[node.Network] = gws
  282. }
  283. } else {
  284. allNodes, err := logic.GetAllNodes()
  285. if err != nil {
  286. slog.Error("failed to fetch all nodes", "error", err)
  287. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  288. return
  289. }
  290. for _, node := range allNodes {
  291. _, ok := processedAdminNodeIds[node.ID.String()]
  292. if node.IsIngressGateway && !node.PendingDelete && !ok {
  293. host, err := logic.GetHost(node.HostID.String())
  294. if err != nil {
  295. slog.Error("failed to fetch host", "error", err)
  296. continue
  297. }
  298. network, err := logic.GetNetwork(node.Network)
  299. if err != nil {
  300. slog.Error("failed to get node network", "error", err)
  301. }
  302. gws := userGws[node.Network]
  303. gws = append(gws, models.UserRemoteGws{
  304. GwID: node.ID.String(),
  305. GWName: host.Name,
  306. Network: node.Network,
  307. IsInternetGateway: node.IsInternetGateway,
  308. GwPeerPublicKey: host.PublicKey.String(),
  309. GwListenPort: logic.GetPeerListenPort(host),
  310. Metadata: node.Metadata,
  311. AllowedEndpoints: getAllowedRagEndpoints(&node, host),
  312. NetworkAddresses: []string{network.AddressRange, network.AddressRange6},
  313. })
  314. userGws[node.Network] = gws
  315. }
  316. }
  317. }
  318. if reqFromMobile {
  319. // send resp in array format
  320. userGwsArr := []models.UserRemoteGws{}
  321. for _, userGwI := range userGws {
  322. userGwsArr = append(userGwsArr, userGwI...)
  323. }
  324. logic.ReturnSuccessResponseWithJson(w, r, userGwsArr, "fetched gateways for user"+username)
  325. return
  326. }
  327. slog.Debug("returned user gws", "user", username, "gws", userGws)
  328. w.WriteHeader(http.StatusOK)
  329. json.NewEncoder(w).Encode(userGws)
  330. }
  331. // swagger:route GET /api/nodes/{network}/{nodeid}/ingress/users users ingressGatewayUsers
  332. //
  333. // Lists all the users attached to an ingress gateway.
  334. //
  335. // Schemes: https
  336. //
  337. // Security:
  338. // oauth
  339. //
  340. // Responses:
  341. // 200: nodeResponse
  342. func ingressGatewayUsers(w http.ResponseWriter, r *http.Request) {
  343. w.Header().Set("Content-Type", "application/json")
  344. var params = mux.Vars(r)
  345. ingressID := params["ingress_id"]
  346. node, err := logic.GetNodeByID(ingressID)
  347. if err != nil {
  348. slog.Error("failed to get ingress node", "error", err)
  349. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  350. return
  351. }
  352. gwUsers, err := logic.GetIngressGwUsers(node)
  353. if err != nil {
  354. slog.Error("failed to get users on ingress gateway", "nodeid", ingressID, "network", node.Network, "user", r.Header.Get("user"),
  355. "error", err)
  356. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  357. return
  358. }
  359. w.WriteHeader(http.StatusOK)
  360. json.NewEncoder(w).Encode(gwUsers)
  361. }
  362. func getAllowedRagEndpoints(ragNode *models.Node, ragHost *models.Host) []string {
  363. endpoints := []string{}
  364. if len(ragHost.EndpointIP) > 0 {
  365. endpoints = append(endpoints, ragHost.EndpointIP.String())
  366. }
  367. if len(ragHost.EndpointIPv6) > 0 {
  368. endpoints = append(endpoints, ragHost.EndpointIPv6.String())
  369. }
  370. if servercfg.IsPro {
  371. for _, ip := range ragNode.AdditionalRagIps {
  372. endpoints = append(endpoints, ip.String())
  373. }
  374. }
  375. return endpoints
  376. }