security.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. package logic
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "strings"
  7. "github.com/gorilla/mux"
  8. "github.com/gravitl/netmaker/logger"
  9. "github.com/gravitl/netmaker/models"
  10. "github.com/gravitl/netmaker/servercfg"
  11. )
  12. const (
  13. MasterUser = "masteradministrator"
  14. Forbidden_Msg = "forbidden"
  15. Forbidden_Err = models.Error(Forbidden_Msg)
  16. Unauthorized_Msg = "unauthorized"
  17. Unauthorized_Err = models.Error(Unauthorized_Msg)
  18. )
  19. func GetSubjectsFromURL(URL string) (rsrcType models.RsrcType, rsrcID models.RsrcID) {
  20. urlSplit := strings.Split(URL, "/")
  21. rsrcType = models.RsrcType(urlSplit[1])
  22. if len(urlSplit) > 1 {
  23. rsrcID = models.RsrcID(urlSplit[2])
  24. }
  25. return
  26. }
  27. func networkPermissionsCheck(username string, r *http.Request) error {
  28. // at this point global checks should be completed
  29. user, err := GetUser(username)
  30. if err != nil {
  31. return err
  32. }
  33. // get info from header to determine the target rsrc
  34. targetRsrc := r.Header.Get("TARGET_RSRC")
  35. targetRsrcID := r.Header.Get("TARGET_RSRC_ID")
  36. netID := r.Header.Get("NET_ID")
  37. if targetRsrc == "" {
  38. return errors.New("target rsrc is missing")
  39. }
  40. if netID == "" {
  41. return errors.New("network id is missing")
  42. }
  43. if r.Method == "" {
  44. r.Method = http.MethodGet
  45. }
  46. // check if user has scope for target resource
  47. // TODO - differentitate between global scope and network scope apis
  48. networkPermissionScope, err := GetRole(user.NetworkRoles[models.NetworkID(netID)].String())
  49. if err != nil {
  50. return errors.New("access denied")
  51. }
  52. if networkPermissionScope.FullAccess {
  53. return nil
  54. }
  55. rsrcPermissionScope, ok := networkPermissionScope.NetworkLevelAccess[models.RsrcType(targetRsrc)]
  56. if !ok {
  57. return fmt.Errorf("access denied to %s rsrc", targetRsrc)
  58. }
  59. if allRsrcsTypePermissionScope, ok := rsrcPermissionScope[models.RsrcID(fmt.Sprintf("all_%s", targetRsrc))]; ok {
  60. return checkPermissionScopeWithReqMethod(allRsrcsTypePermissionScope, r.Method)
  61. }
  62. if targetRsrcID == "" {
  63. return errors.New("target rsrc is missing")
  64. }
  65. if scope, ok := rsrcPermissionScope[models.RsrcID(targetRsrcID)]; ok {
  66. return checkPermissionScopeWithReqMethod(scope, r.Method)
  67. }
  68. return errors.New("access denied")
  69. }
  70. func globalPermissionsCheck(username string, r *http.Request) error {
  71. user, err := GetUser(username)
  72. if err != nil {
  73. return err
  74. }
  75. userRole, err := GetRole(user.PlatformRoleID.String())
  76. if err != nil {
  77. return errors.New("access denied")
  78. }
  79. if userRole.FullAccess {
  80. return nil
  81. }
  82. targetRsrc := r.Header.Get("TARGET_RSRC")
  83. targetRsrcID := r.Header.Get("TARGET_RSRC_ID")
  84. if targetRsrc == "" {
  85. return errors.New("target rsrc is missing")
  86. }
  87. if r.Method == "" {
  88. r.Method = http.MethodGet
  89. }
  90. rsrcPermissionScope, ok := userRole.GlobalLevelAccess[models.RsrcType(targetRsrc)]
  91. if !ok {
  92. return fmt.Errorf("access denied to %s rsrc", targetRsrc)
  93. }
  94. if allRsrcsTypePermissionScope, ok := rsrcPermissionScope[models.RsrcID(fmt.Sprintf("all_%s", targetRsrc))]; ok {
  95. return checkPermissionScopeWithReqMethod(allRsrcsTypePermissionScope, r.Method)
  96. }
  97. if targetRsrcID == "" {
  98. return errors.New("target rsrc id is missing")
  99. }
  100. if scope, ok := rsrcPermissionScope[models.RsrcID(targetRsrcID)]; ok {
  101. return checkPermissionScopeWithReqMethod(scope, r.Method)
  102. }
  103. return errors.New("access denied")
  104. }
  105. func checkPermissionScopeWithReqMethod(scope models.RsrcPermissionScope, reqmethod string) error {
  106. if reqmethod == http.MethodGet && scope.Read {
  107. return nil
  108. }
  109. if (reqmethod == http.MethodPatch || reqmethod == http.MethodPut) && scope.Update {
  110. return nil
  111. }
  112. if reqmethod == http.MethodDelete && scope.Delete {
  113. return nil
  114. }
  115. if reqmethod == http.MethodPost && scope.Create {
  116. return nil
  117. }
  118. return errors.New("operation not permitted")
  119. }
  120. // SecurityCheck - Check if user has appropriate permissions
  121. func SecurityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
  122. return func(w http.ResponseWriter, r *http.Request) {
  123. logger.Log(0, "SECURITY CHECK - 1")
  124. r.Header.Set("ismaster", "no")
  125. bearerToken := r.Header.Get("Authorization")
  126. isGlobalAccesss := r.Header.Get("IS_GLOBAL_ACCESS") == "yes"
  127. username, err := UserPermissions(reqAdmin, bearerToken)
  128. if err != nil {
  129. logger.Log(0, "SECURITY CHECK - 2", err.Error())
  130. ReturnErrorResponse(w, r, FormatError(err, err.Error()))
  131. return
  132. }
  133. // detect masteradmin
  134. if username == MasterUser {
  135. r.Header.Set("ismaster", "yes")
  136. } else {
  137. if isGlobalAccesss {
  138. err = globalPermissionsCheck(username, r)
  139. } else {
  140. err = networkPermissionsCheck(username, r)
  141. }
  142. }
  143. w.Header().Set("TARGET_RSRC", r.Header.Get("TARGET_RSRC"))
  144. w.Header().Set("TARGET_RSRC_ID", r.Header.Get("TARGET_RSRC_ID"))
  145. w.Header().Set("RSRC_TYPE", r.Header.Get("RSRC_TYPE"))
  146. w.Header().Set("IS_GLOBAL_ACCESS", r.Header.Get("IS_GLOBAL_ACCESS"))
  147. w.Header().Set("ACCESS_PERM", err.Error())
  148. r.Header.Set("user", username)
  149. logger.Log(0, "SECURITY CHECK - 3")
  150. next.ServeHTTP(w, r)
  151. }
  152. }
  153. // UserPermissions - checks token stuff
  154. func UserPermissions(reqAdmin bool, token string) (string, error) {
  155. var tokenSplit = strings.Split(token, " ")
  156. var authToken = ""
  157. if len(tokenSplit) < 2 {
  158. return "", Unauthorized_Err
  159. } else {
  160. authToken = tokenSplit[1]
  161. }
  162. //all endpoints here require master so not as complicated
  163. if authenticateMaster(authToken) {
  164. // TODO log in as an actual admin user
  165. return MasterUser, nil
  166. }
  167. username, issuperadmin, isadmin, err := VerifyUserToken(authToken)
  168. if err != nil {
  169. return username, Unauthorized_Err
  170. }
  171. if reqAdmin && !(issuperadmin || isadmin) {
  172. return username, Forbidden_Err
  173. }
  174. return username, nil
  175. }
  176. // Consider a more secure way of setting master key
  177. func authenticateMaster(tokenString string) bool {
  178. return tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != ""
  179. }
  180. func ContinueIfUserMatch(next http.Handler) http.HandlerFunc {
  181. return func(w http.ResponseWriter, r *http.Request) {
  182. var errorResponse = models.ErrorResponse{
  183. Code: http.StatusForbidden, Message: Forbidden_Msg,
  184. }
  185. var params = mux.Vars(r)
  186. var requestedUser = params["username"]
  187. if requestedUser != r.Header.Get("user") {
  188. ReturnErrorResponse(w, r, errorResponse)
  189. return
  190. }
  191. next.ServeHTTP(w, r)
  192. }
  193. }