users.go 13 KB

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