middleware.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. package middleware
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "github.com/Unknwon/macaron"
  7. "github.com/grafana/grafana/pkg/bus"
  8. "github.com/grafana/grafana/pkg/components/apikeygen"
  9. "github.com/grafana/grafana/pkg/log"
  10. "github.com/grafana/grafana/pkg/metrics"
  11. m "github.com/grafana/grafana/pkg/models"
  12. "github.com/grafana/grafana/pkg/setting"
  13. "github.com/grafana/grafana/pkg/util"
  14. )
  15. type Context struct {
  16. *macaron.Context
  17. *m.SignedInUser
  18. Session SessionStore
  19. IsSignedIn bool
  20. AllowAnonymous bool
  21. }
  22. func GetContextHandler() macaron.Handler {
  23. return func(c *macaron.Context) {
  24. ctx := &Context{
  25. Context: c,
  26. SignedInUser: &m.SignedInUser{},
  27. Session: GetSession(),
  28. IsSignedIn: false,
  29. AllowAnonymous: false,
  30. }
  31. // the order in which these are tested are important
  32. // look for api key in Authorization header first
  33. // then init session and look for userId in session
  34. // then look for api key in session (special case for render calls via api)
  35. // then test if anonymous access is enabled
  36. if initContextWithApiKey(ctx) ||
  37. initContextWithBasicAuth(ctx) ||
  38. initContextWithAuthProxy(ctx) ||
  39. initContextWithUserSessionCookie(ctx) ||
  40. initContextWithApiKeyFromSession(ctx) ||
  41. initContextWithAnonymousUser(ctx) {
  42. }
  43. c.Map(ctx)
  44. }
  45. }
  46. func initContextWithAnonymousUser(ctx *Context) bool {
  47. if !setting.AnonymousEnabled {
  48. return false
  49. }
  50. orgQuery := m.GetOrgByNameQuery{Name: setting.AnonymousOrgName}
  51. if err := bus.Dispatch(&orgQuery); err != nil {
  52. log.Error(3, "Anonymous access organization error: '%s': %s", setting.AnonymousOrgName, err)
  53. return false
  54. } else {
  55. ctx.IsSignedIn = false
  56. ctx.AllowAnonymous = true
  57. ctx.SignedInUser = &m.SignedInUser{}
  58. ctx.OrgRole = m.RoleType(setting.AnonymousOrgRole)
  59. ctx.OrgId = orgQuery.Result.Id
  60. ctx.OrgName = orgQuery.Result.Name
  61. return true
  62. }
  63. }
  64. func initContextWithUserSessionCookie(ctx *Context) bool {
  65. // initialize session
  66. if err := ctx.Session.Start(ctx); err != nil {
  67. log.Error(3, "Failed to start session", err)
  68. return false
  69. }
  70. var userId int64
  71. if userId = getRequestUserId(ctx); userId == 0 {
  72. return false
  73. }
  74. query := m.GetSignedInUserQuery{UserId: userId}
  75. if err := bus.Dispatch(&query); err != nil {
  76. log.Error(3, "Failed to get user with id %v", userId)
  77. return false
  78. } else {
  79. ctx.SignedInUser = query.Result
  80. ctx.IsSignedIn = true
  81. return true
  82. }
  83. }
  84. func initContextWithApiKey(ctx *Context) bool {
  85. var keyString string
  86. if keyString = getApiKey(ctx); keyString == "" {
  87. return false
  88. }
  89. // base64 decode key
  90. decoded, err := apikeygen.Decode(keyString)
  91. if err != nil {
  92. ctx.JsonApiErr(401, "Invalid API key", err)
  93. return true
  94. }
  95. // fetch key
  96. keyQuery := m.GetApiKeyByNameQuery{KeyName: decoded.Name, OrgId: decoded.OrgId}
  97. if err := bus.Dispatch(&keyQuery); err != nil {
  98. ctx.JsonApiErr(401, "Invalid API key", err)
  99. return true
  100. } else {
  101. apikey := keyQuery.Result
  102. // validate api key
  103. if !apikeygen.IsValid(decoded, apikey.Key) {
  104. ctx.JsonApiErr(401, "Invalid API key", err)
  105. return true
  106. }
  107. ctx.IsSignedIn = true
  108. ctx.SignedInUser = &m.SignedInUser{}
  109. ctx.OrgRole = apikey.Role
  110. ctx.ApiKeyId = apikey.Id
  111. ctx.OrgId = apikey.OrgId
  112. return true
  113. }
  114. }
  115. func initContextWithBasicAuth(ctx *Context) bool {
  116. if !setting.BasicAuthEnabled {
  117. return false
  118. }
  119. header := ctx.Req.Header.Get("Authorization")
  120. if header == "" {
  121. return false
  122. }
  123. username, password, err := util.DecodeBasicAuthHeader(header)
  124. if err != nil {
  125. ctx.JsonApiErr(401, "Invalid Basic Auth Header", err)
  126. return true
  127. }
  128. loginQuery := m.GetUserByLoginQuery{LoginOrEmail: username}
  129. if err := bus.Dispatch(&loginQuery); err != nil {
  130. ctx.JsonApiErr(401, "Basic auth failed", err)
  131. return true
  132. }
  133. user := loginQuery.Result
  134. // validate password
  135. if util.EncodePassword(password, user.Salt) != user.Password {
  136. ctx.JsonApiErr(401, "Invalid username or password", nil)
  137. return true
  138. }
  139. query := m.GetSignedInUserQuery{UserId: user.Id}
  140. if err := bus.Dispatch(&query); err != nil {
  141. ctx.JsonApiErr(401, "Authentication error", err)
  142. return true
  143. } else {
  144. ctx.SignedInUser = query.Result
  145. ctx.IsSignedIn = true
  146. return true
  147. }
  148. }
  149. // special case for panel render calls with api key
  150. func initContextWithApiKeyFromSession(ctx *Context) bool {
  151. keyId := ctx.Session.Get(SESS_KEY_APIKEY)
  152. if keyId == nil {
  153. return false
  154. }
  155. keyQuery := m.GetApiKeyByIdQuery{ApiKeyId: keyId.(int64)}
  156. if err := bus.Dispatch(&keyQuery); err != nil {
  157. log.Error(3, "Failed to get api key by id", err)
  158. return false
  159. } else {
  160. apikey := keyQuery.Result
  161. ctx.IsSignedIn = true
  162. ctx.SignedInUser = &m.SignedInUser{}
  163. ctx.OrgRole = apikey.Role
  164. ctx.ApiKeyId = apikey.Id
  165. ctx.OrgId = apikey.OrgId
  166. return true
  167. }
  168. }
  169. // Handle handles and logs error by given status.
  170. func (ctx *Context) Handle(status int, title string, err error) {
  171. if err != nil {
  172. log.Error(4, "%s: %v", title, err)
  173. if setting.Env != setting.PROD {
  174. ctx.Data["ErrorMsg"] = err
  175. }
  176. }
  177. switch status {
  178. case 200:
  179. metrics.M_Page_Status_200.Inc(1)
  180. case 404:
  181. metrics.M_Page_Status_404.Inc(1)
  182. case 500:
  183. metrics.M_Page_Status_500.Inc(1)
  184. }
  185. ctx.Data["Title"] = title
  186. ctx.HTML(status, strconv.Itoa(status))
  187. }
  188. func (ctx *Context) JsonOK(message string) {
  189. resp := make(map[string]interface{})
  190. resp["message"] = message
  191. ctx.JSON(200, resp)
  192. }
  193. func (ctx *Context) IsApiRequest() bool {
  194. return strings.HasPrefix(ctx.Req.URL.Path, "/api")
  195. }
  196. func (ctx *Context) JsonApiErr(status int, message string, err error) {
  197. resp := make(map[string]interface{})
  198. if err != nil {
  199. log.Error(4, "%s: %v", message, err)
  200. if setting.Env != setting.PROD {
  201. resp["error"] = err.Error()
  202. }
  203. }
  204. switch status {
  205. case 404:
  206. metrics.M_Api_Status_404.Inc(1)
  207. resp["message"] = "Not Found"
  208. case 500:
  209. metrics.M_Api_Status_500.Inc(1)
  210. resp["message"] = "Internal Server Error"
  211. }
  212. if message != "" {
  213. resp["message"] = message
  214. }
  215. ctx.JSON(status, resp)
  216. }
  217. func Quota(target string) macaron.Handler {
  218. return func(c *Context) {
  219. limitReached, err := QuotaReached(c, target)
  220. if err != nil {
  221. c.JsonApiErr(500, "failed to get quota", err)
  222. return
  223. }
  224. if limitReached {
  225. c.JsonApiErr(403, fmt.Sprintf("%s Quota reached", target), nil)
  226. return
  227. }
  228. }
  229. }
  230. func QuotaReached(c *Context, target string) (bool, error) {
  231. if !setting.Quota.Enabled {
  232. return false, nil
  233. }
  234. // get the list of scopes that this target is valid for. Org, User, Global
  235. scopes, err := m.GetQuotaScopes(target)
  236. if err != nil {
  237. return false, err
  238. }
  239. log.Info(fmt.Sprintf("checking quota for %s in scopes %v", target, scopes))
  240. for _, scope := range scopes {
  241. log.Info(fmt.Sprintf("checking scope %s", scope.Name))
  242. switch scope.Name {
  243. case "global":
  244. if scope.DefaultLimit < 0 {
  245. continue
  246. }
  247. if scope.DefaultLimit == 0 {
  248. return true, nil
  249. }
  250. if target == "session" {
  251. usedSessions := sessionManager.Count()
  252. if int64(usedSessions) > scope.DefaultLimit {
  253. log.Info(fmt.Sprintf("%d sessions active, limit is %d", usedSessions, scope.DefaultLimit))
  254. return true, nil
  255. }
  256. continue
  257. }
  258. query := m.GetGlobalQuotaByTargetQuery{Target: scope.Target}
  259. if err := bus.Dispatch(&query); err != nil {
  260. return true, err
  261. }
  262. if query.Result.Used >= scope.DefaultLimit {
  263. return true, nil
  264. }
  265. case "org":
  266. if !c.IsSignedIn {
  267. continue
  268. }
  269. query := m.GetOrgQuotaByTargetQuery{OrgId: c.OrgId, Target: scope.Target, Default: scope.DefaultLimit}
  270. if err := bus.Dispatch(&query); err != nil {
  271. return true, err
  272. }
  273. if query.Result.Limit < 0 {
  274. continue
  275. }
  276. if query.Result.Limit == 0 {
  277. return true, nil
  278. }
  279. if query.Result.Used >= query.Result.Limit {
  280. return true, nil
  281. }
  282. case "user":
  283. if !c.IsSignedIn || c.UserId == 0 {
  284. continue
  285. }
  286. query := m.GetUserQuotaByTargetQuery{UserId: c.UserId, Target: scope.Target, Default: scope.DefaultLimit}
  287. if err := bus.Dispatch(&query); err != nil {
  288. return true, err
  289. }
  290. if query.Result.Limit < 0 {
  291. continue
  292. }
  293. if query.Result.Limit == 0 {
  294. return true, nil
  295. }
  296. if query.Result.Used >= query.Result.Limit {
  297. return true, nil
  298. }
  299. }
  300. }
  301. return false, nil
  302. }