users.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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/pro/auth"
  12. "github.com/gravitl/netmaker/mq"
  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. if _, ok := user.RemoteGwIDs[node.ID.String()]; (!user.IsAdmin && !user.IsSuperAdmin) && ok {
  206. gws := userGws[node.Network]
  207. extClient.AllowedIPs = logic.GetExtclientAllowedIPs(extClient)
  208. gws = append(gws, models.UserRemoteGws{
  209. GwID: node.ID.String(),
  210. GWName: host.Name,
  211. Network: node.Network,
  212. GwClient: extClient,
  213. Connected: true,
  214. IsInternetGateway: node.IsInternetGateway,
  215. GwPeerPublicKey: host.PublicKey.String(),
  216. Metadata: node.Metadata,
  217. })
  218. userGws[node.Network] = gws
  219. delete(user.RemoteGwIDs, node.ID.String())
  220. } else {
  221. gws := userGws[node.Network]
  222. extClient.AllowedIPs = logic.GetExtclientAllowedIPs(extClient)
  223. gws = append(gws, models.UserRemoteGws{
  224. GwID: node.ID.String(),
  225. GWName: host.Name,
  226. Network: node.Network,
  227. GwClient: extClient,
  228. Connected: true,
  229. IsInternetGateway: node.IsInternetGateway,
  230. GwPeerPublicKey: host.PublicKey.String(),
  231. Metadata: node.Metadata,
  232. })
  233. userGws[node.Network] = gws
  234. processedAdminNodeIds[node.ID.String()] = struct{}{}
  235. }
  236. }
  237. }
  238. // add remaining gw nodes to resp
  239. if !user.IsAdmin && !user.IsSuperAdmin {
  240. for gwID := range user.RemoteGwIDs {
  241. node, err := logic.GetNodeByID(gwID)
  242. if err != nil {
  243. continue
  244. }
  245. if !node.IsIngressGateway {
  246. continue
  247. }
  248. if node.PendingDelete {
  249. continue
  250. }
  251. host, err := logic.GetHost(node.HostID.String())
  252. if err != nil {
  253. continue
  254. }
  255. gws := userGws[node.Network]
  256. gws = append(gws, models.UserRemoteGws{
  257. GwID: node.ID.String(),
  258. GWName: host.Name,
  259. Network: node.Network,
  260. IsInternetGateway: node.IsInternetGateway,
  261. GwPeerPublicKey: host.PublicKey.String(),
  262. Metadata: node.Metadata,
  263. })
  264. userGws[node.Network] = gws
  265. }
  266. } else {
  267. allNodes, err := logic.GetAllNodes()
  268. if err != nil {
  269. slog.Error("failed to fetch all nodes", "error", err)
  270. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  271. return
  272. }
  273. for _, node := range allNodes {
  274. _, ok := processedAdminNodeIds[node.ID.String()]
  275. if node.IsIngressGateway && !node.PendingDelete && !ok {
  276. host, err := logic.GetHost(node.HostID.String())
  277. if err != nil {
  278. slog.Error("failed to fetch host", "error", err)
  279. continue
  280. }
  281. gws := userGws[node.Network]
  282. gws = append(gws, models.UserRemoteGws{
  283. GwID: node.ID.String(),
  284. GWName: host.Name,
  285. Network: node.Network,
  286. IsInternetGateway: node.IsInternetGateway,
  287. GwPeerPublicKey: host.PublicKey.String(),
  288. Metadata: node.Metadata,
  289. })
  290. userGws[node.Network] = gws
  291. }
  292. }
  293. }
  294. if reqFromMobile {
  295. // send resp in array format
  296. userGwsArr := []models.UserRemoteGws{}
  297. for _, userGwI := range userGws {
  298. userGwsArr = append(userGwsArr, userGwI...)
  299. }
  300. logic.ReturnSuccessResponseWithJson(w, r, userGwsArr, "fetched gateways for user"+username)
  301. return
  302. }
  303. slog.Debug("returned user gws", "user", username, "gws", userGws)
  304. w.WriteHeader(http.StatusOK)
  305. json.NewEncoder(w).Encode(userGws)
  306. }
  307. // swagger:route GET /api/nodes/{network}/{nodeid}/ingress/users users ingressGatewayUsers
  308. //
  309. // Lists all the users attached to an ingress gateway.
  310. //
  311. // Schemes: https
  312. //
  313. // Security:
  314. // oauth
  315. //
  316. // Responses:
  317. // 200: nodeResponse
  318. func ingressGatewayUsers(w http.ResponseWriter, r *http.Request) {
  319. w.Header().Set("Content-Type", "application/json")
  320. var params = mux.Vars(r)
  321. ingressID := params["ingress_id"]
  322. node, err := logic.GetNodeByID(ingressID)
  323. if err != nil {
  324. slog.Error("failed to get ingress node", "error", err)
  325. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  326. return
  327. }
  328. gwUsers, err := logic.GetIngressGwUsers(node)
  329. if err != nil {
  330. slog.Error("failed to get users on ingress gateway", "nodeid", ingressID, "network", node.Network, "user", r.Header.Get("user"),
  331. "error", err)
  332. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  333. return
  334. }
  335. w.WriteHeader(http.StatusOK)
  336. json.NewEncoder(w).Encode(gwUsers)
  337. }