middleware_test.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. package middleware
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "net/http/httptest"
  6. "path/filepath"
  7. "testing"
  8. "time"
  9. msession "github.com/go-macaron/session"
  10. "github.com/grafana/grafana/pkg/bus"
  11. m "github.com/grafana/grafana/pkg/models"
  12. "github.com/grafana/grafana/pkg/services/auth"
  13. "github.com/grafana/grafana/pkg/services/auth/authtoken"
  14. "github.com/grafana/grafana/pkg/services/session"
  15. "github.com/grafana/grafana/pkg/setting"
  16. "github.com/grafana/grafana/pkg/util"
  17. . "github.com/smartystreets/goconvey/convey"
  18. "gopkg.in/macaron.v1"
  19. )
  20. func TestMiddlewareContext(t *testing.T) {
  21. setting.ERR_TEMPLATE_NAME = "error-template"
  22. Convey("Given the grafana middleware", t, func() {
  23. middlewareScenario("middleware should add context to injector", func(sc *scenarioContext) {
  24. sc.fakeReq("GET", "/").exec()
  25. So(sc.context, ShouldNotBeNil)
  26. })
  27. middlewareScenario("Default middleware should allow get request", func(sc *scenarioContext) {
  28. sc.fakeReq("GET", "/").exec()
  29. So(sc.resp.Code, ShouldEqual, 200)
  30. })
  31. middlewareScenario("middleware should add Cache-Control header for GET requests to API", func(sc *scenarioContext) {
  32. sc.fakeReq("GET", "/api/search").exec()
  33. So(sc.resp.Header().Get("Cache-Control"), ShouldEqual, "no-cache")
  34. So(sc.resp.Header().Get("Pragma"), ShouldEqual, "no-cache")
  35. So(sc.resp.Header().Get("Expires"), ShouldEqual, "-1")
  36. })
  37. middlewareScenario("middleware should not add Cache-Control header to for non-API GET requests", func(sc *scenarioContext) {
  38. sc.fakeReq("GET", "/").exec()
  39. So(sc.resp.Header().Get("Cache-Control"), ShouldBeEmpty)
  40. })
  41. middlewareScenario("Invalid api key", func(sc *scenarioContext) {
  42. sc.apiKey = "invalid_key_test"
  43. sc.fakeReq("GET", "/").exec()
  44. Convey("Should not init session", func() {
  45. So(sc.resp.Header().Get("Set-Cookie"), ShouldBeEmpty)
  46. })
  47. Convey("Should return 401", func() {
  48. So(sc.resp.Code, ShouldEqual, 401)
  49. So(sc.respJson["message"], ShouldEqual, "Invalid API key")
  50. })
  51. })
  52. middlewareScenario("Using basic auth", func(sc *scenarioContext) {
  53. bus.AddHandler("test", func(query *m.GetUserByLoginQuery) error {
  54. query.Result = &m.User{
  55. Password: util.EncodePassword("myPass", "salt"),
  56. Salt: "salt",
  57. }
  58. return nil
  59. })
  60. bus.AddHandler("test", func(loginUserQuery *m.LoginUserQuery) error {
  61. return nil
  62. })
  63. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  64. query.Result = &m.SignedInUser{OrgId: 2, UserId: 12}
  65. return nil
  66. })
  67. setting.BasicAuthEnabled = true
  68. authHeader := util.GetBasicAuthHeader("myUser", "myPass")
  69. sc.fakeReq("GET", "/").withAuthorizationHeader(authHeader).exec()
  70. Convey("Should init middleware context with user", func() {
  71. So(sc.context.IsSignedIn, ShouldEqual, true)
  72. So(sc.context.OrgId, ShouldEqual, 2)
  73. So(sc.context.UserId, ShouldEqual, 12)
  74. })
  75. })
  76. middlewareScenario("Valid api key", func(sc *scenarioContext) {
  77. keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd")
  78. bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
  79. query.Result = &m.ApiKey{OrgId: 12, Role: m.ROLE_EDITOR, Key: keyhash}
  80. return nil
  81. })
  82. sc.fakeReq("GET", "/").withValidApiKey().exec()
  83. Convey("Should return 200", func() {
  84. So(sc.resp.Code, ShouldEqual, 200)
  85. })
  86. Convey("Should init middleware context", func() {
  87. So(sc.context.IsSignedIn, ShouldEqual, true)
  88. So(sc.context.OrgId, ShouldEqual, 12)
  89. So(sc.context.OrgRole, ShouldEqual, m.ROLE_EDITOR)
  90. })
  91. })
  92. middlewareScenario("Valid api key, but does not match db hash", func(sc *scenarioContext) {
  93. keyhash := "something_not_matching"
  94. bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
  95. query.Result = &m.ApiKey{OrgId: 12, Role: m.ROLE_EDITOR, Key: keyhash}
  96. return nil
  97. })
  98. sc.fakeReq("GET", "/").withValidApiKey().exec()
  99. Convey("Should return api key invalid", func() {
  100. So(sc.resp.Code, ShouldEqual, 401)
  101. So(sc.respJson["message"], ShouldEqual, "Invalid API key")
  102. })
  103. })
  104. middlewareScenario("Valid api key via Basic auth", func(sc *scenarioContext) {
  105. keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd")
  106. bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
  107. query.Result = &m.ApiKey{OrgId: 12, Role: m.ROLE_EDITOR, Key: keyhash}
  108. return nil
  109. })
  110. authHeader := util.GetBasicAuthHeader("api_key", "eyJrIjoidjVuQXdwTWFmRlA2em5hUzR1cmhkV0RMUzU1MTFNNDIiLCJuIjoiYXNkIiwiaWQiOjF9")
  111. sc.fakeReq("GET", "/").withAuthorizationHeader(authHeader).exec()
  112. Convey("Should return 200", func() {
  113. So(sc.resp.Code, ShouldEqual, 200)
  114. })
  115. Convey("Should init middleware context", func() {
  116. So(sc.context.IsSignedIn, ShouldEqual, true)
  117. So(sc.context.OrgId, ShouldEqual, 12)
  118. So(sc.context.OrgRole, ShouldEqual, m.ROLE_EDITOR)
  119. })
  120. })
  121. middlewareScenario("Non-expired auth token in cookie which not are being rotated", func(sc *scenarioContext) {
  122. sc.withTokenSessionCookie("token")
  123. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  124. query.Result = &m.SignedInUser{OrgId: 2, UserId: 12}
  125. return nil
  126. })
  127. sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (auth.UserToken, error) {
  128. return &userTokenImpl{
  129. userId: 12,
  130. token: unhashedToken,
  131. }, nil
  132. }
  133. sc.fakeReq("GET", "/").exec()
  134. Convey("should init context with user info", func() {
  135. So(sc.context.IsSignedIn, ShouldBeTrue)
  136. So(sc.context.UserId, ShouldEqual, 12)
  137. So(sc.context.UserToken.GetUserId(), ShouldEqual, 12)
  138. So(sc.context.UserToken.GetToken(), ShouldEqual, "token")
  139. })
  140. Convey("should not set cookie", func() {
  141. So(sc.resp.Header().Get("Set-Cookie"), ShouldEqual, "")
  142. })
  143. })
  144. middlewareScenario("Non-expired auth token in cookie which are being rotated", func(sc *scenarioContext) {
  145. sc.withTokenSessionCookie("token")
  146. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  147. query.Result = &m.SignedInUser{OrgId: 2, UserId: 12}
  148. return nil
  149. })
  150. sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (auth.UserToken, error) {
  151. return &userTokenImpl{
  152. userId: 12,
  153. token: unhashedToken,
  154. }, nil
  155. }
  156. sc.userAuthTokenService.tryRotateTokenProvider = func(userToken auth.UserToken, clientIP, userAgent string) (bool, error) {
  157. userToken.(fakeUserToken).SetToken("rotated")
  158. return true, nil
  159. }
  160. maxAgeHours := (time.Duration(setting.LoginMaxLifetimeDays) * 24 * time.Hour)
  161. maxAge := (maxAgeHours + time.Hour).Seconds()
  162. expectedCookie := &http.Cookie{
  163. Name: setting.LoginCookieName,
  164. Value: "rotated",
  165. Path: setting.AppSubUrl + "/",
  166. HttpOnly: true,
  167. MaxAge: int(maxAge),
  168. Secure: setting.CookieSecure,
  169. SameSite: setting.CookieSameSite,
  170. }
  171. sc.fakeReq("GET", "/").exec()
  172. Convey("should init context with user info", func() {
  173. So(sc.context.IsSignedIn, ShouldBeTrue)
  174. So(sc.context.UserId, ShouldEqual, 12)
  175. So(sc.context.UserToken.GetUserId(), ShouldEqual, 12)
  176. So(sc.context.UserToken.GetToken(), ShouldEqual, "rotated")
  177. })
  178. Convey("should set cookie", func() {
  179. So(sc.resp.Header().Get("Set-Cookie"), ShouldEqual, expectedCookie.String())
  180. })
  181. })
  182. middlewareScenario("Invalid/expired auth token in cookie", func(sc *scenarioContext) {
  183. sc.withTokenSessionCookie("token")
  184. sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (auth.UserToken, error) {
  185. return nil, authtoken.ErrAuthTokenNotFound
  186. }
  187. sc.fakeReq("GET", "/").exec()
  188. Convey("should not init context with user info", func() {
  189. So(sc.context.IsSignedIn, ShouldBeFalse)
  190. So(sc.context.UserId, ShouldEqual, 0)
  191. So(sc.context.UserToken, ShouldBeNil)
  192. })
  193. })
  194. middlewareScenario("When anonymous access is enabled", func(sc *scenarioContext) {
  195. setting.AnonymousEnabled = true
  196. setting.AnonymousOrgName = "test"
  197. setting.AnonymousOrgRole = string(m.ROLE_EDITOR)
  198. bus.AddHandler("test", func(query *m.GetOrgByNameQuery) error {
  199. So(query.Name, ShouldEqual, "test")
  200. query.Result = &m.Org{Id: 2, Name: "test"}
  201. return nil
  202. })
  203. sc.fakeReq("GET", "/").exec()
  204. Convey("should init context with org info", func() {
  205. So(sc.context.UserId, ShouldEqual, 0)
  206. So(sc.context.OrgId, ShouldEqual, 2)
  207. So(sc.context.OrgRole, ShouldEqual, m.ROLE_EDITOR)
  208. })
  209. Convey("context signed in should be false", func() {
  210. So(sc.context.IsSignedIn, ShouldBeFalse)
  211. })
  212. })
  213. middlewareScenario("When auth_proxy is enabled enabled and user exists", func(sc *scenarioContext) {
  214. setting.AuthProxyEnabled = true
  215. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  216. setting.AuthProxyHeaderProperty = "username"
  217. setting.LdapEnabled = false
  218. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  219. query.Result = &m.SignedInUser{OrgId: 2, UserId: 12}
  220. return nil
  221. })
  222. bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
  223. cmd.Result = &m.User{Id: 12}
  224. return nil
  225. })
  226. setting.SessionOptions = msession.Options{}
  227. sc.fakeReq("GET", "/")
  228. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  229. sc.exec()
  230. Convey("should init context with user info", func() {
  231. So(sc.context.IsSignedIn, ShouldBeTrue)
  232. So(sc.context.UserId, ShouldEqual, 12)
  233. So(sc.context.OrgId, ShouldEqual, 2)
  234. })
  235. })
  236. middlewareScenario("When auth_proxy is enabled enabled and user does not exists", func(sc *scenarioContext) {
  237. setting.AuthProxyEnabled = true
  238. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  239. setting.AuthProxyHeaderProperty = "username"
  240. setting.AuthProxyAutoSignUp = true
  241. setting.LdapEnabled = false
  242. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  243. if query.UserId > 0 {
  244. query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
  245. return nil
  246. }
  247. return m.ErrUserNotFound
  248. })
  249. bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
  250. cmd.Result = &m.User{Id: 33}
  251. return nil
  252. })
  253. sc.fakeReq("GET", "/")
  254. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  255. sc.exec()
  256. Convey("Should create user if auto sign up is enabled", func() {
  257. So(sc.context.IsSignedIn, ShouldBeTrue)
  258. So(sc.context.UserId, ShouldEqual, 33)
  259. So(sc.context.OrgId, ShouldEqual, 4)
  260. })
  261. })
  262. middlewareScenario("When auth_proxy is enabled and IPv4 request RemoteAddr is not trusted", func(sc *scenarioContext) {
  263. setting.AuthProxyEnabled = true
  264. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  265. setting.AuthProxyHeaderProperty = "username"
  266. setting.AuthProxyWhitelist = "192.168.1.1, 2001::23"
  267. sc.fakeReq("GET", "/")
  268. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  269. sc.req.RemoteAddr = "192.168.3.1:12345"
  270. sc.exec()
  271. Convey("should return 407 status code", func() {
  272. So(sc.resp.Code, ShouldEqual, 407)
  273. So(sc.resp.Body.String(), ShouldContainSubstring, "Request for user (torkelo) from 192.168.3.1 is not from the authentication proxy")
  274. })
  275. })
  276. middlewareScenario("When auth_proxy is enabled and IPv4 request RemoteAddr is not within trusted CIDR block", func(sc *scenarioContext) {
  277. setting.AuthProxyEnabled = true
  278. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  279. setting.AuthProxyHeaderProperty = "username"
  280. setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
  281. sc.fakeReq("GET", "/")
  282. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  283. sc.req.RemoteAddr = "192.168.3.1:12345"
  284. sc.exec()
  285. Convey("should return 407 status code", func() {
  286. So(sc.resp.Code, ShouldEqual, 407)
  287. So(sc.resp.Body.String(), ShouldContainSubstring, "Request for user (torkelo) from 192.168.3.1 is not from the authentication proxy")
  288. })
  289. })
  290. middlewareScenario("When auth_proxy is enabled and IPv6 request RemoteAddr is not trusted", func(sc *scenarioContext) {
  291. setting.AuthProxyEnabled = true
  292. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  293. setting.AuthProxyHeaderProperty = "username"
  294. setting.AuthProxyWhitelist = "192.168.1.1, 2001::23"
  295. sc.fakeReq("GET", "/")
  296. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  297. sc.req.RemoteAddr = "[2001:23]:12345"
  298. sc.exec()
  299. Convey("should return 407 status code", func() {
  300. So(sc.resp.Code, ShouldEqual, 407)
  301. So(sc.resp.Body.String(), ShouldContainSubstring, "Request for user (torkelo) from 2001:23 is not from the authentication proxy")
  302. })
  303. })
  304. middlewareScenario("When auth_proxy is enabled and IPv6 request RemoteAddr is not within trusted CIDR block", func(sc *scenarioContext) {
  305. setting.AuthProxyEnabled = true
  306. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  307. setting.AuthProxyHeaderProperty = "username"
  308. setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
  309. sc.fakeReq("GET", "/")
  310. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  311. sc.req.RemoteAddr = "[2001:23]:12345"
  312. sc.exec()
  313. Convey("should return 407 status code", func() {
  314. So(sc.resp.Code, ShouldEqual, 407)
  315. So(sc.resp.Body.String(), ShouldContainSubstring, "Request for user (torkelo) from 2001:23 is not from the authentication proxy")
  316. })
  317. })
  318. middlewareScenario("When auth_proxy is enabled and request RemoteAddr is trusted", func(sc *scenarioContext) {
  319. setting.AuthProxyEnabled = true
  320. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  321. setting.AuthProxyHeaderProperty = "username"
  322. setting.AuthProxyWhitelist = "192.168.1.1, 2001::23"
  323. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  324. query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
  325. return nil
  326. })
  327. bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
  328. cmd.Result = &m.User{Id: 33}
  329. return nil
  330. })
  331. sc.fakeReq("GET", "/")
  332. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  333. sc.req.RemoteAddr = "[2001::23]:12345"
  334. sc.exec()
  335. Convey("Should init context with user info", func() {
  336. So(sc.context.IsSignedIn, ShouldBeTrue)
  337. So(sc.context.UserId, ShouldEqual, 33)
  338. So(sc.context.OrgId, ShouldEqual, 4)
  339. })
  340. })
  341. middlewareScenario("When auth_proxy is enabled and IPv4 request RemoteAddr is within trusted CIDR block", func(sc *scenarioContext) {
  342. setting.AuthProxyEnabled = true
  343. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  344. setting.AuthProxyHeaderProperty = "username"
  345. setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
  346. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  347. query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
  348. return nil
  349. })
  350. bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
  351. cmd.Result = &m.User{Id: 33}
  352. return nil
  353. })
  354. sc.fakeReq("GET", "/")
  355. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  356. sc.req.RemoteAddr = "192.168.1.10:12345"
  357. sc.exec()
  358. Convey("Should init context with user info", func() {
  359. So(sc.context.IsSignedIn, ShouldBeTrue)
  360. So(sc.context.UserId, ShouldEqual, 33)
  361. So(sc.context.OrgId, ShouldEqual, 4)
  362. })
  363. })
  364. middlewareScenario("When auth_proxy is enabled and IPv6 request RemoteAddr is within trusted CIDR block", func(sc *scenarioContext) {
  365. setting.AuthProxyEnabled = true
  366. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  367. setting.AuthProxyHeaderProperty = "username"
  368. setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
  369. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  370. query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
  371. return nil
  372. })
  373. bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
  374. cmd.Result = &m.User{Id: 33}
  375. return nil
  376. })
  377. sc.fakeReq("GET", "/")
  378. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  379. sc.req.RemoteAddr = "[2001::23]:12345"
  380. sc.exec()
  381. Convey("Should init context with user info", func() {
  382. So(sc.context.IsSignedIn, ShouldBeTrue)
  383. So(sc.context.UserId, ShouldEqual, 33)
  384. So(sc.context.OrgId, ShouldEqual, 4)
  385. })
  386. })
  387. middlewareScenario("When session exists for previous user, create a new session", func(sc *scenarioContext) {
  388. setting.AuthProxyEnabled = true
  389. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  390. setting.AuthProxyHeaderProperty = "username"
  391. setting.AuthProxyWhitelist = ""
  392. bus.AddHandler("test", func(query *m.UpsertUserCommand) error {
  393. query.Result = &m.User{Id: 32}
  394. return nil
  395. })
  396. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  397. query.Result = &m.SignedInUser{OrgId: 4, UserId: 32}
  398. return nil
  399. })
  400. // create session
  401. sc.fakeReq("GET", "/").handler(func(c *m.ReqContext) {
  402. c.Session.Set(session.SESS_KEY_USERID, int64(33))
  403. }).exec()
  404. oldSessionID := sc.context.Session.ID()
  405. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  406. sc.exec()
  407. newSessionID := sc.context.Session.ID()
  408. Convey("Should not share session with other user", func() {
  409. So(oldSessionID, ShouldNotEqual, newSessionID)
  410. })
  411. })
  412. middlewareScenario("When auth_proxy and ldap enabled call sync with ldap user", func(sc *scenarioContext) {
  413. setting.AuthProxyEnabled = true
  414. setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
  415. setting.AuthProxyHeaderProperty = "username"
  416. setting.AuthProxyWhitelist = ""
  417. setting.LdapEnabled = true
  418. called := false
  419. syncGrafanaUserWithLdapUser = func(query *m.LoginUserQuery) error {
  420. called = true
  421. query.User = &m.User{Id: 32}
  422. return nil
  423. }
  424. bus.AddHandler("test", func(query *m.UpsertUserCommand) error {
  425. query.Result = &m.User{Id: 32}
  426. return nil
  427. })
  428. bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
  429. query.Result = &m.SignedInUser{OrgId: 4, UserId: 32}
  430. return nil
  431. })
  432. sc.fakeReq("GET", "/")
  433. sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
  434. sc.exec()
  435. Convey("Should call syncGrafanaUserWithLdapUser", func() {
  436. So(called, ShouldBeTrue)
  437. })
  438. })
  439. })
  440. }
  441. func middlewareScenario(desc string, fn scenarioFunc) {
  442. Convey(desc, func() {
  443. defer bus.ClearBusHandlers()
  444. setting.LoginCookieName = "grafana_session"
  445. setting.LoginMaxLifetimeDays = 30
  446. sc := &scenarioContext{}
  447. viewsPath, _ := filepath.Abs("../../public/views")
  448. sc.m = macaron.New()
  449. sc.m.Use(macaron.Renderer(macaron.RenderOptions{
  450. Directory: viewsPath,
  451. Delims: macaron.Delims{Left: "[[", Right: "]]"},
  452. }))
  453. session.Init(&msession.Options{}, 0)
  454. sc.userAuthTokenService = newFakeUserAuthTokenService()
  455. sc.m.Use(GetContextHandler(sc.userAuthTokenService))
  456. // mock out gc goroutine
  457. session.StartSessionGC = func() {}
  458. setting.SessionOptions = msession.Options{}
  459. sc.m.Use(OrgRedirect())
  460. sc.m.Use(AddDefaultResponseHeaders())
  461. sc.defaultHandler = func(c *m.ReqContext) {
  462. sc.context = c
  463. if sc.handlerFunc != nil {
  464. sc.handlerFunc(sc.context)
  465. }
  466. }
  467. sc.m.Get("/", sc.defaultHandler)
  468. fn(sc)
  469. })
  470. }
  471. type scenarioContext struct {
  472. m *macaron.Macaron
  473. context *m.ReqContext
  474. resp *httptest.ResponseRecorder
  475. apiKey string
  476. authHeader string
  477. tokenSessionCookie string
  478. respJson map[string]interface{}
  479. handlerFunc handlerFunc
  480. defaultHandler macaron.Handler
  481. url string
  482. userAuthTokenService *fakeUserAuthTokenService
  483. req *http.Request
  484. }
  485. func (sc *scenarioContext) withValidApiKey() *scenarioContext {
  486. sc.apiKey = "eyJrIjoidjVuQXdwTWFmRlA2em5hUzR1cmhkV0RMUzU1MTFNNDIiLCJuIjoiYXNkIiwiaWQiOjF9"
  487. return sc
  488. }
  489. func (sc *scenarioContext) withTokenSessionCookie(unhashedToken string) *scenarioContext {
  490. sc.tokenSessionCookie = unhashedToken
  491. return sc
  492. }
  493. func (sc *scenarioContext) withAuthorizationHeader(authHeader string) *scenarioContext {
  494. sc.authHeader = authHeader
  495. return sc
  496. }
  497. func (sc *scenarioContext) fakeReq(method, url string) *scenarioContext {
  498. sc.resp = httptest.NewRecorder()
  499. req, err := http.NewRequest(method, url, nil)
  500. So(err, ShouldBeNil)
  501. sc.req = req
  502. // add session cookie from last request
  503. if sc.context != nil {
  504. if sc.context.Session.ID() != "" {
  505. req.Header.Add("Cookie", "grafana_sess="+sc.context.Session.ID()+";")
  506. }
  507. }
  508. return sc
  509. }
  510. func (sc *scenarioContext) fakeReqWithParams(method, url string, queryParams map[string]string) *scenarioContext {
  511. sc.resp = httptest.NewRecorder()
  512. req, err := http.NewRequest(method, url, nil)
  513. q := req.URL.Query()
  514. for k, v := range queryParams {
  515. q.Add(k, v)
  516. }
  517. req.URL.RawQuery = q.Encode()
  518. So(err, ShouldBeNil)
  519. sc.req = req
  520. return sc
  521. }
  522. func (sc *scenarioContext) handler(fn handlerFunc) *scenarioContext {
  523. sc.handlerFunc = fn
  524. return sc
  525. }
  526. func (sc *scenarioContext) exec() {
  527. if sc.apiKey != "" {
  528. sc.req.Header.Add("Authorization", "Bearer "+sc.apiKey)
  529. }
  530. if sc.authHeader != "" {
  531. sc.req.Header.Add("Authorization", sc.authHeader)
  532. }
  533. if sc.tokenSessionCookie != "" {
  534. sc.req.AddCookie(&http.Cookie{
  535. Name: setting.LoginCookieName,
  536. Value: sc.tokenSessionCookie,
  537. })
  538. }
  539. sc.m.ServeHTTP(sc.resp, sc.req)
  540. if sc.resp.Header().Get("Content-Type") == "application/json; charset=UTF-8" {
  541. err := json.NewDecoder(sc.resp.Body).Decode(&sc.respJson)
  542. So(err, ShouldBeNil)
  543. }
  544. }
  545. type scenarioFunc func(c *scenarioContext)
  546. type handlerFunc func(c *m.ReqContext)
  547. type fakeUserToken interface {
  548. auth.UserToken
  549. SetToken(token string)
  550. }
  551. type userTokenImpl struct {
  552. userId int64
  553. token string
  554. }
  555. func (ut *userTokenImpl) GetUserId() int64 {
  556. return ut.userId
  557. }
  558. func (ut *userTokenImpl) GetToken() string {
  559. return ut.token
  560. }
  561. func (ut *userTokenImpl) SetToken(token string) {
  562. ut.token = token
  563. }
  564. type fakeUserAuthTokenService struct {
  565. createTokenProvider func(userId int64, clientIP, userAgent string) (auth.UserToken, error)
  566. tryRotateTokenProvider func(token auth.UserToken, clientIP, userAgent string) (bool, error)
  567. lookupTokenProvider func(unhashedToken string) (auth.UserToken, error)
  568. revokeTokenProvider func(token auth.UserToken) error
  569. }
  570. func newFakeUserAuthTokenService() *fakeUserAuthTokenService {
  571. return &fakeUserAuthTokenService{
  572. createTokenProvider: func(userId int64, clientIP, userAgent string) (auth.UserToken, error) {
  573. return &userTokenImpl{
  574. userId: 0,
  575. token: "",
  576. }, nil
  577. },
  578. tryRotateTokenProvider: func(token auth.UserToken, clientIP, userAgent string) (bool, error) {
  579. return false, nil
  580. },
  581. lookupTokenProvider: func(unhashedToken string) (auth.UserToken, error) {
  582. return &userTokenImpl{
  583. userId: 0,
  584. token: "",
  585. }, nil
  586. },
  587. revokeTokenProvider: func(token auth.UserToken) error {
  588. return nil
  589. },
  590. }
  591. }
  592. func (s *fakeUserAuthTokenService) CreateToken(userId int64, clientIP, userAgent string) (auth.UserToken, error) {
  593. return s.createTokenProvider(userId, clientIP, userAgent)
  594. }
  595. func (s *fakeUserAuthTokenService) LookupToken(unhashedToken string) (auth.UserToken, error) {
  596. return s.lookupTokenProvider(unhashedToken)
  597. }
  598. func (s *fakeUserAuthTokenService) TryRotateToken(token auth.UserToken, clientIP, userAgent string) (bool, error) {
  599. return s.tryRotateTokenProvider(token, clientIP, userAgent)
  600. }
  601. func (s *fakeUserAuthTokenService) RevokeToken(token auth.UserToken) error {
  602. return s.revokeTokenProvider(token)
  603. }