auth.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. package logic
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "time"
  8. "github.com/go-playground/validator/v10"
  9. "golang.org/x/crypto/bcrypt"
  10. "github.com/gravitl/netmaker/database"
  11. "github.com/gravitl/netmaker/logger"
  12. "github.com/gravitl/netmaker/logic/pro"
  13. "github.com/gravitl/netmaker/models"
  14. "github.com/gravitl/netmaker/models/promodels"
  15. "github.com/gravitl/netmaker/servercfg"
  16. )
  17. const auth_key = "netmaker_auth"
  18. // HasAdmin - checks if server has an admin
  19. func HasAdmin() (bool, error) {
  20. collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
  21. if err != nil {
  22. if database.IsEmptyRecord(err) {
  23. return false, nil
  24. } else {
  25. return true, err
  26. }
  27. }
  28. for _, value := range collection { // filter for isadmin true
  29. var user models.User
  30. err = json.Unmarshal([]byte(value), &user)
  31. if err != nil {
  32. continue
  33. }
  34. if user.IsAdmin {
  35. return true, nil
  36. }
  37. }
  38. return false, err
  39. }
  40. // GetReturnUser - gets a user
  41. func GetReturnUser(username string) (models.ReturnUser, error) {
  42. var user models.ReturnUser
  43. record, err := database.FetchRecord(database.USERS_TABLE_NAME, username)
  44. if err != nil {
  45. return user, err
  46. }
  47. if err = json.Unmarshal([]byte(record), &user); err != nil {
  48. return models.ReturnUser{}, err
  49. }
  50. return user, err
  51. }
  52. // GetUsers - gets users
  53. func GetUsers() ([]models.ReturnUser, error) {
  54. var users []models.ReturnUser
  55. collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
  56. if err != nil {
  57. return users, err
  58. }
  59. for _, value := range collection {
  60. var user models.ReturnUser
  61. err = json.Unmarshal([]byte(value), &user)
  62. if err != nil {
  63. continue // get users
  64. }
  65. users = append(users, user)
  66. }
  67. return users, err
  68. }
  69. // CreateUser - creates a user
  70. func CreateUser(user *models.User) error {
  71. // check if user exists
  72. if _, err := GetUser(user.UserName); err == nil {
  73. return errors.New("user exists")
  74. }
  75. var err = ValidateUser(user)
  76. if err != nil {
  77. return err
  78. }
  79. // encrypt that password so we never see it again
  80. hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 5)
  81. if err != nil {
  82. return err
  83. }
  84. // set password to encrypted password
  85. user.Password = string(hash)
  86. tokenString, _ := CreateProUserJWT(user.UserName, user.Networks, user.Groups, user.IsAdmin)
  87. if tokenString == "" {
  88. // logic.ReturnErrorResponse(w, r, errorResponse)
  89. return err
  90. }
  91. SetUserDefaults(user)
  92. // connect db
  93. data, err := json.Marshal(user)
  94. if err != nil {
  95. return err
  96. }
  97. err = database.Insert(user.UserName, string(data), database.USERS_TABLE_NAME)
  98. if err != nil {
  99. return err
  100. }
  101. // == PRO == Add user to every network as network user ==
  102. currentNets, err := GetNetworks()
  103. if err != nil {
  104. currentNets = []models.Network{}
  105. }
  106. for i := range currentNets {
  107. newUser := promodels.NetworkUser{
  108. ID: promodels.NetworkUserID(user.UserName),
  109. Clients: []string{},
  110. Nodes: []string{},
  111. }
  112. pro.AddProNetDefaults(&currentNets[i])
  113. if pro.IsUserAllowed(&currentNets[i], user.UserName, user.Groups) {
  114. newUser.AccessLevel = currentNets[i].ProSettings.DefaultAccessLevel
  115. newUser.ClientLimit = currentNets[i].ProSettings.DefaultUserClientLimit
  116. newUser.NodeLimit = currentNets[i].ProSettings.DefaultUserNodeLimit
  117. } else {
  118. newUser.AccessLevel = pro.NO_ACCESS
  119. newUser.ClientLimit = 0
  120. newUser.NodeLimit = 0
  121. }
  122. // legacy
  123. if StringSliceContains(user.Networks, currentNets[i].NetID) {
  124. if !servercfg.Is_EE {
  125. newUser.AccessLevel = pro.NET_ADMIN
  126. }
  127. }
  128. userErr := pro.CreateNetworkUser(&currentNets[i], &newUser)
  129. if userErr != nil {
  130. logger.Log(0, "failed to add network user data on network", currentNets[i].NetID, "for user", user.UserName)
  131. }
  132. }
  133. // == END PRO ==
  134. return nil
  135. }
  136. // CreateAdmin - creates an admin user
  137. func CreateAdmin(admin *models.User) error {
  138. hasadmin, err := HasAdmin()
  139. if err != nil {
  140. return err
  141. }
  142. if hasadmin {
  143. return errors.New("admin user already exists")
  144. }
  145. admin.IsAdmin = true
  146. return CreateUser(admin)
  147. }
  148. // VerifyAuthRequest - verifies an auth request
  149. func VerifyAuthRequest(authRequest models.UserAuthParams) (string, error) {
  150. var result models.User
  151. if authRequest.UserName == "" {
  152. return "", errors.New("username can't be empty")
  153. } else if authRequest.Password == "" {
  154. return "", errors.New("password can't be empty")
  155. }
  156. // Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API until approved).
  157. record, err := database.FetchRecord(database.USERS_TABLE_NAME, authRequest.UserName)
  158. if err != nil {
  159. return "", errors.New("error retrieving user from db: " + err.Error())
  160. }
  161. if err = json.Unmarshal([]byte(record), &result); err != nil {
  162. return "", errors.New("error unmarshalling user json: " + err.Error())
  163. }
  164. // compare password from request to stored password in database
  165. // might be able to have a common hash (certificates?) and compare those so that a password isn't passed in in plain text...
  166. // TODO: Consider a way of hashing the password client side before sending, or using certificates
  167. if err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(authRequest.Password)); err != nil {
  168. return "", errors.New("incorrect credentials")
  169. }
  170. // Create a new JWT for the node
  171. tokenString, _ := CreateProUserJWT(authRequest.UserName, result.Networks, result.Groups, result.IsAdmin)
  172. return tokenString, nil
  173. }
  174. // UpdateUserNetworks - updates the networks of a given user
  175. func UpdateUserNetworks(newNetworks, newGroups []string, isadmin bool, currentUser *models.ReturnUser) error {
  176. // check if user exists
  177. returnedUser, err := GetUser(currentUser.UserName)
  178. if err != nil {
  179. return err
  180. } else if returnedUser.IsAdmin {
  181. return fmt.Errorf("can not make changes to an admin user, attempted to change %s", returnedUser.UserName)
  182. }
  183. if isadmin {
  184. currentUser.IsAdmin = true
  185. currentUser.Networks = nil
  186. } else {
  187. // == PRO ==
  188. currentUser.Groups = newGroups
  189. for _, n := range newNetworks {
  190. if !StringSliceContains(currentUser.Networks, n) {
  191. // make net admin of any network not previously assigned
  192. pro.MakeNetAdmin(n, currentUser.UserName)
  193. }
  194. }
  195. // Compare networks, find networks not in previous
  196. for _, n := range currentUser.Networks {
  197. if !StringSliceContains(newNetworks, n) {
  198. // if user was removed from a network, re-assign access to net default level
  199. if network, err := GetNetwork(n); err == nil {
  200. if network.ProSettings != nil {
  201. ok := pro.AssignAccessLvl(n, currentUser.UserName, network.ProSettings.DefaultAccessLevel)
  202. if ok {
  203. logger.Log(0, "changed", currentUser.UserName, "access level on network", network.NetID, "to", fmt.Sprintf("%d", network.ProSettings.DefaultAccessLevel))
  204. }
  205. }
  206. }
  207. }
  208. }
  209. if err := AdjustGroupPermissions(currentUser); err != nil {
  210. logger.Log(0, "failed to update user", currentUser.UserName, "after group update", err.Error())
  211. }
  212. // == END PRO ==
  213. currentUser.Networks = newNetworks
  214. }
  215. userChange := models.User{
  216. UserName: currentUser.UserName,
  217. Networks: currentUser.Networks,
  218. IsAdmin: currentUser.IsAdmin,
  219. Password: "",
  220. Groups: currentUser.Groups,
  221. }
  222. _, err = UpdateUser(&userChange, returnedUser)
  223. return err
  224. }
  225. // UpdateUser - updates a given user
  226. func UpdateUser(userchange, user *models.User) (*models.User, error) {
  227. // check if user exists
  228. if _, err := GetUser(user.UserName); err != nil {
  229. return &models.User{}, err
  230. }
  231. queryUser := user.UserName
  232. if !isOauthUser(user) && userchange.UserName != "" { // cannot update username for an oAuth user
  233. user.UserName = userchange.UserName
  234. }
  235. if len(userchange.Networks) > 0 {
  236. user.Networks = userchange.Networks
  237. }
  238. if len(userchange.Groups) > 0 {
  239. user.Groups = userchange.Groups
  240. }
  241. if !isOauthUser(user) && userchange.Password != "" { // cannot update password for an oAuth User
  242. // encrypt that password so we never see it again
  243. hash, err := bcrypt.GenerateFromPassword([]byte(userchange.Password), 5)
  244. if err != nil {
  245. return userchange, err
  246. }
  247. // set password to encrypted password
  248. userchange.Password = string(hash)
  249. user.Password = userchange.Password
  250. }
  251. if (userchange.IsAdmin != user.IsAdmin) && !user.IsAdmin {
  252. user.IsAdmin = userchange.IsAdmin
  253. }
  254. err := ValidateUser(user)
  255. if err != nil {
  256. return &models.User{}, err
  257. }
  258. if err = database.DeleteRecord(database.USERS_TABLE_NAME, queryUser); err != nil {
  259. return &models.User{}, err
  260. }
  261. data, err := json.Marshal(&user)
  262. if err != nil {
  263. return &models.User{}, err
  264. }
  265. if err = database.Insert(user.UserName, string(data), database.USERS_TABLE_NAME); err != nil {
  266. return &models.User{}, err
  267. }
  268. logger.Log(1, "updated user", queryUser)
  269. return user, nil
  270. }
  271. // ValidateUser - validates a user model
  272. func ValidateUser(user *models.User) error {
  273. v := validator.New()
  274. _ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool {
  275. isgood := user.NameInCharSet()
  276. return isgood
  277. })
  278. err := v.Struct(user)
  279. if err != nil {
  280. for _, e := range err.(validator.ValidationErrors) {
  281. logger.Log(2, e.Error())
  282. }
  283. }
  284. return err
  285. }
  286. // DeleteUser - deletes a given user
  287. func DeleteUser(user string) (bool, error) {
  288. if userRecord, err := database.FetchRecord(database.USERS_TABLE_NAME, user); err != nil || len(userRecord) == 0 {
  289. return false, errors.New("user does not exist")
  290. }
  291. err := database.DeleteRecord(database.USERS_TABLE_NAME, user)
  292. if err != nil {
  293. return false, err
  294. }
  295. // == pro - remove user from all network user instances ==
  296. currentNets, err := GetNetworks()
  297. if err != nil {
  298. if database.IsEmptyRecord(err) {
  299. currentNets = []models.Network{}
  300. } else {
  301. return true, err
  302. }
  303. }
  304. for i := range currentNets {
  305. netID := currentNets[i].NetID
  306. if err = pro.DeleteNetworkUser(netID, user); err != nil {
  307. logger.Log(0, "failed to remove", user, "as network user from network", netID, err.Error())
  308. }
  309. }
  310. return true, nil
  311. }
  312. // FetchAuthSecret - manages secrets for oauth
  313. func FetchAuthSecret(key string, secret string) (string, error) {
  314. var record, err = database.FetchRecord(database.GENERATED_TABLE_NAME, key)
  315. if err != nil {
  316. if err = database.Insert(key, secret, database.GENERATED_TABLE_NAME); err != nil {
  317. return "", err
  318. } else {
  319. return secret, nil
  320. }
  321. }
  322. return record, nil
  323. }
  324. func isOauthUser(user *models.User) bool {
  325. var currentValue, err = FetchPassValue("")
  326. if err != nil {
  327. return false
  328. }
  329. var bCryptErr = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(currentValue))
  330. return bCryptErr == nil
  331. }
  332. // FetchPassValue - fetches oAuth user password
  333. func FetchPassValue(newValue string) (string, error) {
  334. type valueHolder struct {
  335. Value string `json:"value" bson:"value"`
  336. }
  337. var b64NewValue = base64.StdEncoding.EncodeToString([]byte(newValue))
  338. var newValueHolder = &valueHolder{
  339. Value: b64NewValue,
  340. }
  341. var data, marshalErr = json.Marshal(newValueHolder)
  342. if marshalErr != nil {
  343. return "", marshalErr
  344. }
  345. var currentValue, err = FetchAuthSecret(auth_key, string(data))
  346. if err != nil {
  347. return "", err
  348. }
  349. var unmarshErr = json.Unmarshal([]byte(currentValue), newValueHolder)
  350. if unmarshErr != nil {
  351. return "", unmarshErr
  352. }
  353. var b64CurrentValue, b64Err = base64.StdEncoding.DecodeString(newValueHolder.Value)
  354. if b64Err != nil {
  355. logger.Log(0, "could not decode pass")
  356. return "", nil
  357. }
  358. return string(b64CurrentValue), nil
  359. }
  360. // GetState - gets an SsoState from DB, if expired returns error
  361. func GetState(state string) (*models.SsoState, error) {
  362. var s models.SsoState
  363. record, err := database.FetchRecord(database.SSO_STATE_CACHE, state)
  364. if err != nil {
  365. return &s, err
  366. }
  367. if err = json.Unmarshal([]byte(record), &s); err != nil {
  368. return &s, err
  369. }
  370. if s.IsExpired() {
  371. return &s, fmt.Errorf("state expired")
  372. }
  373. return &s, nil
  374. }
  375. // SetState - sets a state with new expiration
  376. func SetState(state string) error {
  377. s := models.SsoState{
  378. Value: state,
  379. Expiration: time.Now().Add(models.DefaultExpDuration),
  380. }
  381. data, err := json.Marshal(&s)
  382. if err != nil {
  383. return err
  384. }
  385. return database.Insert(state, string(data), database.SSO_STATE_CACHE)
  386. }
  387. // IsStateValid - checks if given state is valid or not
  388. // deletes state after call is made to clean up, should only be called once per sign-in
  389. func IsStateValid(state string) (string, bool) {
  390. s, err := GetState(state)
  391. if err != nil {
  392. logger.Log(2, "error retrieving oauth state:", err.Error())
  393. return "", false
  394. }
  395. if s.Value != "" {
  396. if err = delState(state); err != nil {
  397. logger.Log(2, "error deleting oauth state:", err.Error())
  398. return "", false
  399. }
  400. }
  401. return s.Value, true
  402. }
  403. // delState - removes a state from cache/db
  404. func delState(state string) error {
  405. return database.DeleteRecord(database.SSO_STATE_CACHE, state)
  406. }
  407. // PRO
  408. // AdjustGroupPermissions - adjusts a given user's network access based on group changes
  409. func AdjustGroupPermissions(user *models.ReturnUser) error {
  410. networks, err := GetNetworks()
  411. if err != nil {
  412. return err
  413. }
  414. // UPDATE
  415. // go through all networks and see if new group is in
  416. // if access level of current user is greater (value) than network's default
  417. // assign network's default
  418. // DELETE
  419. // if user not allowed on network a
  420. for i := range networks {
  421. AdjustNetworkUserPermissions(user, &networks[i])
  422. }
  423. return nil
  424. }
  425. // AdjustNetworkUserPermissions - adjusts a given user's network access based on group changes
  426. func AdjustNetworkUserPermissions(user *models.ReturnUser, network *models.Network) error {
  427. networkUser, err := pro.GetNetworkUser(
  428. network.NetID,
  429. promodels.NetworkUserID(user.UserName),
  430. )
  431. if err == nil && network.ProSettings != nil {
  432. if pro.IsUserAllowed(network, user.UserName, user.Groups) {
  433. if networkUser.AccessLevel > network.ProSettings.DefaultAccessLevel {
  434. networkUser.AccessLevel = network.ProSettings.DefaultAccessLevel
  435. }
  436. if networkUser.NodeLimit < network.ProSettings.DefaultUserNodeLimit {
  437. networkUser.NodeLimit = network.ProSettings.DefaultUserNodeLimit
  438. }
  439. if networkUser.ClientLimit < network.ProSettings.DefaultUserClientLimit {
  440. networkUser.ClientLimit = network.ProSettings.DefaultUserClientLimit
  441. }
  442. } else {
  443. networkUser.AccessLevel = pro.NO_ACCESS
  444. networkUser.NodeLimit = 0
  445. networkUser.ClientLimit = 0
  446. }
  447. pro.UpdateNetworkUser(network.NetID, networkUser)
  448. }
  449. return err
  450. }