user.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "github.com/gorilla/mux"
  8. "github.com/gorilla/websocket"
  9. "github.com/gravitl/netmaker/auth"
  10. "github.com/gravitl/netmaker/logger"
  11. "github.com/gravitl/netmaker/logic"
  12. "github.com/gravitl/netmaker/models"
  13. "github.com/gravitl/netmaker/servercfg"
  14. "golang.org/x/exp/slog"
  15. )
  16. var (
  17. upgrader = websocket.Upgrader{}
  18. )
  19. func userHandlers(r *mux.Router) {
  20. r.HandleFunc("/api/users/adm/hassuperadmin", hasSuperAdmin).Methods(http.MethodGet)
  21. r.HandleFunc("/api/users/adm/createsuperadmin", createSuperAdmin).Methods(http.MethodPost)
  22. r.HandleFunc("/api/users/adm/transfersuperadmin/{username}", logic.SecurityCheck(true, http.HandlerFunc(transferSuperAdmin))).Methods(http.MethodPost)
  23. r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods(http.MethodPost)
  24. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(updateUser))).Methods(http.MethodPut)
  25. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceUsers, http.HandlerFunc(createUser)))).Methods(http.MethodPost)
  26. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(deleteUser))).Methods(http.MethodDelete)
  27. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUser)))).Methods(http.MethodGet)
  28. r.HandleFunc("/api/users", logic.SecurityCheck(true, http.HandlerFunc(getUsers))).Methods(http.MethodGet)
  29. r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods(http.MethodGet)
  30. r.HandleFunc("/api/oauth/callback", auth.HandleAuthCallback).Methods(http.MethodGet)
  31. r.HandleFunc("/api/oauth/headless", auth.HandleHeadlessSSO)
  32. r.HandleFunc("/api/oauth/register/{regKey}", auth.RegisterHostSSO).Methods(http.MethodGet)
  33. }
  34. // swagger:route POST /api/users/adm/authenticate user authenticateUser
  35. //
  36. // Node authenticates using its password and retrieves a JWT for authorization.
  37. //
  38. // Schemes: https
  39. //
  40. // Security:
  41. // oauth
  42. //
  43. // Responses:
  44. // 200: successResponse
  45. func authenticateUser(response http.ResponseWriter, request *http.Request) {
  46. // Auth request consists of Mac Address and Password (from node that is authorizing
  47. // in case of Master, auth is ignored and mac is set to "mastermac"
  48. var authRequest models.UserAuthParams
  49. var errorResponse = models.ErrorResponse{
  50. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  51. }
  52. if !servercfg.IsBasicAuthEnabled() {
  53. logic.ReturnErrorResponse(response, request, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  54. return
  55. }
  56. decoder := json.NewDecoder(request.Body)
  57. decoderErr := decoder.Decode(&authRequest)
  58. defer request.Body.Close()
  59. if decoderErr != nil {
  60. logger.Log(0, "error decoding request body: ",
  61. decoderErr.Error())
  62. logic.ReturnErrorResponse(response, request, errorResponse)
  63. return
  64. }
  65. username := authRequest.UserName
  66. jwt, err := logic.VerifyAuthRequest(authRequest)
  67. if err != nil {
  68. logger.Log(0, username, "user validation failed: ",
  69. err.Error())
  70. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "badrequest"))
  71. return
  72. }
  73. if jwt == "" {
  74. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  75. logger.Log(0, username, "jwt token is empty")
  76. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("no token returned"), "internal"))
  77. return
  78. }
  79. var successResponse = models.SuccessResponse{
  80. Code: http.StatusOK,
  81. Message: "W1R3: Device " + username + " Authorized",
  82. Response: models.SuccessfulUserLoginResponse{
  83. AuthToken: jwt,
  84. UserName: username,
  85. },
  86. }
  87. // Send back the JWT
  88. successJSONResponse, jsonError := json.Marshal(successResponse)
  89. if jsonError != nil {
  90. logger.Log(0, username,
  91. "error marshalling resp: ", err.Error())
  92. logic.ReturnErrorResponse(response, request, errorResponse)
  93. return
  94. }
  95. logger.Log(2, username, "was authenticated")
  96. response.Header().Set("Content-Type", "application/json")
  97. response.Write(successJSONResponse)
  98. }
  99. // swagger:route GET /api/users/adm/hassuperadmin user hasSuperAdmin
  100. //
  101. // Checks whether the server has an admin.
  102. //
  103. // Schemes: https
  104. //
  105. // Security:
  106. // oauth
  107. //
  108. // Responses:
  109. // 200: successResponse
  110. func hasSuperAdmin(w http.ResponseWriter, r *http.Request) {
  111. w.Header().Set("Content-Type", "application/json")
  112. hasSuperAdmin, err := logic.HasSuperAdmin()
  113. if err != nil {
  114. logger.Log(0, "failed to check for admin: ", err.Error())
  115. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  116. return
  117. }
  118. json.NewEncoder(w).Encode(hasSuperAdmin)
  119. }
  120. // swagger:route GET /api/users/{username} user getUser
  121. //
  122. // Get an individual user.
  123. //
  124. // Schemes: https
  125. //
  126. // Security:
  127. // oauth
  128. //
  129. // Responses:
  130. // 200: userBodyResponse
  131. func getUser(w http.ResponseWriter, r *http.Request) {
  132. // set header.
  133. w.Header().Set("Content-Type", "application/json")
  134. var params = mux.Vars(r)
  135. usernameFetched := params["username"]
  136. user, err := logic.GetReturnUser(usernameFetched)
  137. if err != nil {
  138. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  139. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  140. return
  141. }
  142. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  143. json.NewEncoder(w).Encode(user)
  144. }
  145. // swagger:route GET /api/users user getUsers
  146. //
  147. // Get all users.
  148. //
  149. // Schemes: https
  150. //
  151. // Security:
  152. // oauth
  153. //
  154. // Responses:
  155. // 200: userBodyResponse
  156. func getUsers(w http.ResponseWriter, r *http.Request) {
  157. // set header.
  158. w.Header().Set("Content-Type", "application/json")
  159. users, err := logic.GetUsers()
  160. if err != nil {
  161. logger.Log(0, "failed to fetch users: ", err.Error())
  162. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  163. return
  164. }
  165. logic.SortUsers(users[:])
  166. logger.Log(2, r.Header.Get("user"), "fetched users")
  167. json.NewEncoder(w).Encode(users)
  168. }
  169. // swagger:route POST /api/users/adm/createsuperadmin user createAdmin
  170. //
  171. // Make a user an admin.
  172. //
  173. // Schemes: https
  174. //
  175. // Security:
  176. // oauth
  177. //
  178. // Responses:
  179. // 200: userBodyResponse
  180. func createSuperAdmin(w http.ResponseWriter, r *http.Request) {
  181. w.Header().Set("Content-Type", "application/json")
  182. var u models.User
  183. err := json.NewDecoder(r.Body).Decode(&u)
  184. if err != nil {
  185. slog.Error("error decoding request body", "error", err.Error())
  186. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  187. return
  188. }
  189. if !servercfg.IsBasicAuthEnabled() {
  190. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  191. return
  192. }
  193. err = logic.CreateSuperAdmin(&u)
  194. if err != nil {
  195. slog.Error("failed to create admin", "error", err.Error())
  196. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  197. return
  198. }
  199. logger.Log(1, u.UserName, "was made a super admin")
  200. json.NewEncoder(w).Encode(logic.ToReturnUser(u))
  201. }
  202. // swagger:route POST /api/users/adm/transfersuperadmin user transferSuperAdmin
  203. //
  204. // Transfers superadmin role to an admin user.
  205. //
  206. // Schemes: https
  207. //
  208. // Security:
  209. // oauth
  210. //
  211. // Responses:
  212. // 200: userBodyResponse
  213. func transferSuperAdmin(w http.ResponseWriter, r *http.Request) {
  214. w.Header().Set("Content-Type", "application/json")
  215. caller, err := logic.GetUser(r.Header.Get("user"))
  216. if err != nil {
  217. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  218. }
  219. if !caller.IsSuperAdmin {
  220. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only superadmin can assign the superadmin role to another user"), "forbidden"))
  221. return
  222. }
  223. var params = mux.Vars(r)
  224. username := params["username"]
  225. u, err := logic.GetUser(username)
  226. if err != nil {
  227. slog.Error("error getting user", "user", u.UserName, "error", err.Error())
  228. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  229. return
  230. }
  231. if !u.IsAdmin {
  232. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only admins can be promoted to superadmin role"), "forbidden"))
  233. return
  234. }
  235. if !servercfg.IsBasicAuthEnabled() {
  236. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  237. return
  238. }
  239. u.IsSuperAdmin = true
  240. u.IsAdmin = false
  241. err = logic.UpsertUser(*u)
  242. if err != nil {
  243. slog.Error("error updating user to superadmin: ", "user", u.UserName, "error", err.Error())
  244. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  245. return
  246. }
  247. caller.IsSuperAdmin = false
  248. caller.IsAdmin = true
  249. err = logic.UpsertUser(*caller)
  250. if err != nil {
  251. slog.Error("error demoting user to admin: ", "user", caller.UserName, "error", err.Error())
  252. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  253. return
  254. }
  255. slog.Info("user was made a super admin", "user", u.UserName)
  256. json.NewEncoder(w).Encode(logic.ToReturnUser(*u))
  257. }
  258. // swagger:route POST /api/users/{username} user createUser
  259. //
  260. // Create a user.
  261. //
  262. // Schemes: https
  263. //
  264. // Security:
  265. // oauth
  266. //
  267. // Responses:
  268. // 200: userBodyResponse
  269. func createUser(w http.ResponseWriter, r *http.Request) {
  270. w.Header().Set("Content-Type", "application/json")
  271. caller, err := logic.GetUser(r.Header.Get("user"))
  272. if err != nil {
  273. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  274. }
  275. var user models.User
  276. err = json.NewDecoder(r.Body).Decode(&user)
  277. if err != nil {
  278. logger.Log(0, user.UserName, "error decoding request body: ",
  279. err.Error())
  280. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  281. return
  282. }
  283. if !caller.IsSuperAdmin && user.IsAdmin {
  284. err = errors.New("only superadmin can create admin users")
  285. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  286. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  287. return
  288. }
  289. if user.IsSuperAdmin {
  290. err = errors.New("additional superadmins cannot be created")
  291. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  292. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  293. return
  294. }
  295. err = logic.CreateUser(&user)
  296. if err != nil {
  297. slog.Error("error creating new user: ", "user", user.UserName, "error", err.Error())
  298. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  299. return
  300. }
  301. slog.Info("user was created", "username", user.UserName)
  302. json.NewEncoder(w).Encode(logic.ToReturnUser(user))
  303. }
  304. // swagger:route PUT /api/users/{username} user updateUser
  305. //
  306. // Update a user.
  307. //
  308. // Schemes: https
  309. //
  310. // Security:
  311. // oauth
  312. //
  313. // Responses:
  314. // 200: userBodyResponse
  315. func updateUser(w http.ResponseWriter, r *http.Request) {
  316. w.Header().Set("Content-Type", "application/json")
  317. var params = mux.Vars(r)
  318. // start here
  319. var caller *models.User
  320. var err error
  321. var ismaster bool
  322. if r.Header.Get("user") == logic.MasterUser {
  323. ismaster = true
  324. } else {
  325. caller, err = logic.GetUser(r.Header.Get("user"))
  326. if err != nil {
  327. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  328. }
  329. }
  330. username := params["username"]
  331. user, err := logic.GetUser(username)
  332. if err != nil {
  333. logger.Log(0, username,
  334. "failed to update user info: ", err.Error())
  335. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  336. return
  337. }
  338. var userchange models.User
  339. // we decode our body request params
  340. err = json.NewDecoder(r.Body).Decode(&userchange)
  341. if err != nil {
  342. slog.Error("failed to decode body", "error ", err.Error())
  343. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  344. return
  345. }
  346. if user.UserName != userchange.UserName {
  347. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user in param and request body not matching"), "badrequest"))
  348. return
  349. }
  350. selfUpdate := false
  351. if !ismaster && caller.UserName == user.UserName {
  352. selfUpdate = true
  353. }
  354. if !ismaster && !selfUpdate {
  355. if caller.IsAdmin && user.IsSuperAdmin {
  356. slog.Error("non-superadmin user", "caller", caller.UserName, "attempted to update superadmin user", username)
  357. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  358. return
  359. }
  360. if !caller.IsAdmin && !caller.IsSuperAdmin {
  361. slog.Error("operation not allowed", "caller", caller.UserName, "attempted to update user", username)
  362. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  363. return
  364. }
  365. if caller.IsAdmin && user.IsAdmin {
  366. slog.Error("admin user cannot update another admin", "caller", caller.UserName, "attempted to update admin user", username)
  367. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("admin user cannot update another admin"), "forbidden"))
  368. return
  369. }
  370. if caller.IsAdmin && userchange.IsAdmin {
  371. err = errors.New("admin user cannot update role of an another user to admin")
  372. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  373. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  374. return
  375. }
  376. }
  377. if !ismaster && selfUpdate {
  378. if user.IsAdmin != userchange.IsAdmin || user.IsSuperAdmin != userchange.IsSuperAdmin {
  379. slog.Error("user cannot change his own role", "caller", caller.UserName, "attempted to update user role", username)
  380. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user not allowed to self assign role"), "forbidden"))
  381. return
  382. }
  383. }
  384. if ismaster {
  385. if !user.IsSuperAdmin && userchange.IsSuperAdmin {
  386. slog.Error("operation not allowed", "caller", logic.MasterUser, "attempted to update user role to superadmin", username)
  387. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("attempted to update user role to superadmin"), "forbidden"))
  388. return
  389. }
  390. }
  391. if auth.IsOauthUser(user) == nil {
  392. err := fmt.Errorf("cannot update user info for oauth user %s", username)
  393. logger.Log(0, err.Error())
  394. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  395. return
  396. }
  397. user, err = logic.UpdateUser(&userchange, user)
  398. if err != nil {
  399. logger.Log(0, username,
  400. "failed to update user info: ", err.Error())
  401. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  402. return
  403. }
  404. logger.Log(1, username, "was updated")
  405. json.NewEncoder(w).Encode(logic.ToReturnUser(*user))
  406. }
  407. // swagger:route DELETE /api/users/{username} user deleteUser
  408. //
  409. // Delete a user.
  410. //
  411. // Schemes: https
  412. //
  413. // Security:
  414. // oauth
  415. //
  416. // Responses:
  417. // 200: userBodyResponse
  418. func deleteUser(w http.ResponseWriter, r *http.Request) {
  419. // Set header
  420. w.Header().Set("Content-Type", "application/json")
  421. // get params
  422. var params = mux.Vars(r)
  423. caller, err := logic.GetUser(r.Header.Get("user"))
  424. if err != nil {
  425. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  426. }
  427. username := params["username"]
  428. user, err := logic.GetUser(username)
  429. if err != nil {
  430. logger.Log(0, username,
  431. "failed to update user info: ", err.Error())
  432. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  433. return
  434. }
  435. if user.IsSuperAdmin {
  436. slog.Error(
  437. "failed to delete user: ", "user", username, "error", "superadmin cannot be deleted")
  438. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  439. return
  440. }
  441. if !caller.IsSuperAdmin {
  442. if caller.IsAdmin && user.IsAdmin {
  443. slog.Error(
  444. "failed to delete user: ", "user", username, "error", "admin cannot delete another admin user")
  445. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  446. return
  447. }
  448. }
  449. success, err := logic.DeleteUser(username)
  450. if err != nil {
  451. logger.Log(0, username,
  452. "failed to delete user: ", err.Error())
  453. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  454. return
  455. } else if !success {
  456. err := errors.New("delete unsuccessful")
  457. logger.Log(0, username, err.Error())
  458. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  459. return
  460. }
  461. logger.Log(1, username, "was deleted")
  462. json.NewEncoder(w).Encode(params["username"] + " deleted.")
  463. }
  464. // Called when vpn client dials in to start the auth flow and first stage is to get register URL itself
  465. func socketHandler(w http.ResponseWriter, r *http.Request) {
  466. // Upgrade our raw HTTP connection to a websocket based one
  467. conn, err := upgrader.Upgrade(w, r, nil)
  468. if err != nil {
  469. logger.Log(0, "error during connection upgrade for node sign-in:", err.Error())
  470. return
  471. }
  472. if conn == nil {
  473. logger.Log(0, "failed to establish web-socket connection during node sign-in")
  474. return
  475. }
  476. // Start handling the session
  477. go auth.SessionHandler(conn)
  478. }