|
@@ -2,6 +2,7 @@ package middleware
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
"encoding/json"
|
|
"encoding/json"
|
|
|
|
|
+ "fmt"
|
|
|
"net/http"
|
|
"net/http"
|
|
|
"net/http/httptest"
|
|
"net/http/httptest"
|
|
|
"path/filepath"
|
|
"path/filepath"
|
|
@@ -10,6 +11,7 @@ import (
|
|
|
|
|
|
|
|
msession "github.com/go-macaron/session"
|
|
msession "github.com/go-macaron/session"
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
|
|
|
+ "github.com/grafana/grafana/pkg/infra/remotecache"
|
|
|
m "github.com/grafana/grafana/pkg/models"
|
|
m "github.com/grafana/grafana/pkg/models"
|
|
|
"github.com/grafana/grafana/pkg/services/auth"
|
|
"github.com/grafana/grafana/pkg/services/auth"
|
|
|
"github.com/grafana/grafana/pkg/services/session"
|
|
"github.com/grafana/grafana/pkg/services/session"
|
|
@@ -23,29 +25,29 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
setting.ERR_TEMPLATE_NAME = "error-template"
|
|
setting.ERR_TEMPLATE_NAME = "error-template"
|
|
|
|
|
|
|
|
Convey("Given the grafana middleware", t, func() {
|
|
Convey("Given the grafana middleware", t, func() {
|
|
|
- middlewareScenario("middleware should add context to injector", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "middleware should add context to injector", func(sc *scenarioContext) {
|
|
|
sc.fakeReq("GET", "/").exec()
|
|
sc.fakeReq("GET", "/").exec()
|
|
|
So(sc.context, ShouldNotBeNil)
|
|
So(sc.context, ShouldNotBeNil)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Default middleware should allow get request", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Default middleware should allow get request", func(sc *scenarioContext) {
|
|
|
sc.fakeReq("GET", "/").exec()
|
|
sc.fakeReq("GET", "/").exec()
|
|
|
So(sc.resp.Code, ShouldEqual, 200)
|
|
So(sc.resp.Code, ShouldEqual, 200)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("middleware should add Cache-Control header for GET requests to API", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "middleware should add Cache-Control header for GET requests to API", func(sc *scenarioContext) {
|
|
|
sc.fakeReq("GET", "/api/search").exec()
|
|
sc.fakeReq("GET", "/api/search").exec()
|
|
|
So(sc.resp.Header().Get("Cache-Control"), ShouldEqual, "no-cache")
|
|
So(sc.resp.Header().Get("Cache-Control"), ShouldEqual, "no-cache")
|
|
|
So(sc.resp.Header().Get("Pragma"), ShouldEqual, "no-cache")
|
|
So(sc.resp.Header().Get("Pragma"), ShouldEqual, "no-cache")
|
|
|
So(sc.resp.Header().Get("Expires"), ShouldEqual, "-1")
|
|
So(sc.resp.Header().Get("Expires"), ShouldEqual, "-1")
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("middleware should not add Cache-Control header to for non-API GET requests", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "middleware should not add Cache-Control header to for non-API GET requests", func(sc *scenarioContext) {
|
|
|
sc.fakeReq("GET", "/").exec()
|
|
sc.fakeReq("GET", "/").exec()
|
|
|
So(sc.resp.Header().Get("Cache-Control"), ShouldBeEmpty)
|
|
So(sc.resp.Header().Get("Cache-Control"), ShouldBeEmpty)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Invalid api key", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Invalid api key", func(sc *scenarioContext) {
|
|
|
sc.apiKey = "invalid_key_test"
|
|
sc.apiKey = "invalid_key_test"
|
|
|
sc.fakeReq("GET", "/").exec()
|
|
sc.fakeReq("GET", "/").exec()
|
|
|
|
|
|
|
@@ -59,7 +61,7 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Using basic auth", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Using basic auth", func(sc *scenarioContext) {
|
|
|
|
|
|
|
|
bus.AddHandler("test", func(query *m.GetUserByLoginQuery) error {
|
|
bus.AddHandler("test", func(query *m.GetUserByLoginQuery) error {
|
|
|
query.Result = &m.User{
|
|
query.Result = &m.User{
|
|
@@ -89,7 +91,7 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Valid api key", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Valid api key", func(sc *scenarioContext) {
|
|
|
keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd")
|
|
keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd")
|
|
|
|
|
|
|
|
bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
|
|
bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
|
|
@@ -110,7 +112,7 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Valid api key, but does not match db hash", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Valid api key, but does not match db hash", func(sc *scenarioContext) {
|
|
|
keyhash := "something_not_matching"
|
|
keyhash := "something_not_matching"
|
|
|
|
|
|
|
|
bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
|
|
bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
|
|
@@ -126,7 +128,7 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Valid api key via Basic auth", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Valid api key via Basic auth", func(sc *scenarioContext) {
|
|
|
keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd")
|
|
keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd")
|
|
|
|
|
|
|
|
bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
|
|
bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
|
|
@@ -148,7 +150,7 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Non-expired auth token in cookie which not are being rotated", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Non-expired auth token in cookie which not are being rotated", func(sc *scenarioContext) {
|
|
|
sc.withTokenSessionCookie("token")
|
|
sc.withTokenSessionCookie("token")
|
|
|
|
|
|
|
|
bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
@@ -177,7 +179,7 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Non-expired auth token in cookie which are being rotated", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Non-expired auth token in cookie which are being rotated", func(sc *scenarioContext) {
|
|
|
sc.withTokenSessionCookie("token")
|
|
sc.withTokenSessionCookie("token")
|
|
|
|
|
|
|
|
bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
@@ -224,7 +226,7 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("Invalid/expired auth token in cookie", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "Invalid/expired auth token in cookie", func(sc *scenarioContext) {
|
|
|
sc.withTokenSessionCookie("token")
|
|
sc.withTokenSessionCookie("token")
|
|
|
|
|
|
|
|
sc.userAuthTokenService.LookupTokenProvider = func(unhashedToken string) (*m.UserToken, error) {
|
|
sc.userAuthTokenService.LookupTokenProvider = func(unhashedToken string) (*m.UserToken, error) {
|
|
@@ -240,7 +242,7 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("When anonymous access is enabled", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ middlewareScenario(t, "When anonymous access is enabled", func(sc *scenarioContext) {
|
|
|
setting.AnonymousEnabled = true
|
|
setting.AnonymousEnabled = true
|
|
|
setting.AnonymousOrgName = "test"
|
|
setting.AnonymousOrgName = "test"
|
|
|
setting.AnonymousOrgRole = string(m.ROLE_EDITOR)
|
|
setting.AnonymousOrgRole = string(m.ROLE_EDITOR)
|
|
@@ -265,287 +267,192 @@ func TestMiddlewareContext(t *testing.T) {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled enabled and user exists", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.LdapEnabled = false
|
|
|
|
|
-
|
|
|
|
|
- bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
- query.Result = &m.SignedInUser{OrgId: 2, UserId: 12}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
- cmd.Result = &m.User{Id: 12}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- setting.SessionOptions = msession.Options{}
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.exec()
|
|
|
|
|
-
|
|
|
|
|
- Convey("should init context with user info", func() {
|
|
|
|
|
- So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
- So(sc.context.UserId, ShouldEqual, 12)
|
|
|
|
|
- So(sc.context.OrgId, ShouldEqual, 2)
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled enabled and user does not exists", func(sc *scenarioContext) {
|
|
|
|
|
|
|
+ Convey("auth_proxy", func() {
|
|
|
setting.AuthProxyEnabled = true
|
|
setting.AuthProxyEnabled = true
|
|
|
|
|
+ setting.AuthProxyWhitelist = ""
|
|
|
|
|
+ setting.AuthProxyAutoSignUp = true
|
|
|
|
|
+ setting.LdapEnabled = true
|
|
|
setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
setting.AuthProxyHeaderProperty = "username"
|
|
setting.AuthProxyHeaderProperty = "username"
|
|
|
- setting.AuthProxyAutoSignUp = true
|
|
|
|
|
- setting.LdapEnabled = false
|
|
|
|
|
|
|
+ name := "markelog"
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
- if query.UserId > 0 {
|
|
|
|
|
- query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
|
|
|
|
|
|
|
+ middlewareScenario(t, "should sync the user if it's not in the cache", func(sc *scenarioContext) {
|
|
|
|
|
+ called := false
|
|
|
|
|
+ syncGrafanaUserWithLdapUser = func(query *m.LoginUserQuery) error {
|
|
|
|
|
+ called = true
|
|
|
|
|
+ query.User = &m.User{Id: 32}
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
|
- return m.ErrUserNotFound
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
- cmd.Result = &m.User{Id: 33}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.exec()
|
|
|
|
|
-
|
|
|
|
|
- Convey("Should create user if auto sign up is enabled", func() {
|
|
|
|
|
- So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
- So(sc.context.UserId, ShouldEqual, 33)
|
|
|
|
|
- So(sc.context.OrgId, ShouldEqual, 4)
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled and IPv4 request RemoteAddr is not trusted", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = "192.168.1.1, 2001::23"
|
|
|
|
|
-
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.req.RemoteAddr = "192.168.3.1:12345"
|
|
|
|
|
- sc.exec()
|
|
|
|
|
-
|
|
|
|
|
- Convey("should return 407 status code", func() {
|
|
|
|
|
- So(sc.resp.Code, ShouldEqual, 407)
|
|
|
|
|
- So(sc.resp.Body.String(), ShouldContainSubstring, "Request for user (torkelo) from 192.168.3.1 is not from the authentication proxy")
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled and IPv4 request RemoteAddr is not within trusted CIDR block", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
|
|
|
|
|
-
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.req.RemoteAddr = "192.168.3.1:12345"
|
|
|
|
|
- sc.exec()
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(query *m.UpsertUserCommand) error {
|
|
|
|
|
+ query.Result = &m.User{Id: 32}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- Convey("should return 407 status code", func() {
|
|
|
|
|
- So(sc.resp.Code, ShouldEqual, 407)
|
|
|
|
|
- So(sc.resp.Body.String(), ShouldContainSubstring, "Request for user (torkelo) from 192.168.3.1 is not from the authentication proxy")
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
+ query.Result = &m.SignedInUser{OrgId: 4, UserId: 32}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled and IPv6 request RemoteAddr is not trusted", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = "192.168.1.1, 2001::23"
|
|
|
|
|
|
|
+ sc.fakeReq("GET", "/")
|
|
|
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.req.RemoteAddr = "[2001:23]:12345"
|
|
|
|
|
- sc.exec()
|
|
|
|
|
|
|
+ sc.req.Header.Add(setting.AuthProxyHeaderName, name)
|
|
|
|
|
+ sc.exec()
|
|
|
|
|
|
|
|
- Convey("should return 407 status code", func() {
|
|
|
|
|
- So(sc.resp.Code, ShouldEqual, 407)
|
|
|
|
|
- So(sc.resp.Body.String(), ShouldContainSubstring, "Request for user (torkelo) from 2001:23 is not from the authentication proxy")
|
|
|
|
|
|
|
+ Convey("Should init user via ldap", func() {
|
|
|
|
|
+ So(called, ShouldBeTrue)
|
|
|
|
|
+ So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
+ So(sc.context.UserId, ShouldEqual, 32)
|
|
|
|
|
+ So(sc.context.OrgId, ShouldEqual, 4)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled and IPv6 request RemoteAddr is not within trusted CIDR block", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
|
|
|
|
|
-
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.req.RemoteAddr = "[2001:23]:12345"
|
|
|
|
|
- sc.exec()
|
|
|
|
|
|
|
|
|
|
- Convey("should return 407 status code", func() {
|
|
|
|
|
- So(sc.resp.Code, ShouldEqual, 407)
|
|
|
|
|
- So(sc.resp.Body.String(), ShouldContainSubstring, "Request for user (torkelo) from 2001:23 is not from the authentication proxy")
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ middlewareScenario(t, "should not sync the user if it's in the cache", func(sc *scenarioContext) {
|
|
|
|
|
+ called := false
|
|
|
|
|
+ syncGrafanaUserWithLdapUser = func(query *m.LoginUserQuery) error {
|
|
|
|
|
+ called = true
|
|
|
|
|
+ query.User = &m.User{Id: 32}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled and request RemoteAddr is trusted", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = "192.168.1.1, 2001::23"
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(query *m.UpsertUserCommand) error {
|
|
|
|
|
+ query.Result = &m.User{Id: 32}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
- query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
+ query.Result = &m.SignedInUser{OrgId: 4, UserId: 32}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
- cmd.Result = &m.User{Id: 33}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ key := fmt.Sprintf(cachePrefix, name)
|
|
|
|
|
+ sc.remoteCacheService.Set(key, int64(33), 0)
|
|
|
|
|
+ sc.fakeReq("GET", "/")
|
|
|
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.req.RemoteAddr = "[2001::23]:12345"
|
|
|
|
|
- sc.exec()
|
|
|
|
|
|
|
+ sc.req.Header.Add(setting.AuthProxyHeaderName, name)
|
|
|
|
|
+ sc.exec()
|
|
|
|
|
|
|
|
- Convey("Should init context with user info", func() {
|
|
|
|
|
- So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
- So(sc.context.UserId, ShouldEqual, 33)
|
|
|
|
|
- So(sc.context.OrgId, ShouldEqual, 4)
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ cacheValue, cacheErr := sc.remoteCacheService.Get(key)
|
|
|
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled and IPv4 request RemoteAddr is within trusted CIDR block", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
|
|
|
|
|
|
|
+ Convey("Should init user via cache", func() {
|
|
|
|
|
+ So(called, ShouldBeFalse)
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
- query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
+ So(sc.context.UserId, ShouldEqual, 32)
|
|
|
|
|
+ So(sc.context.OrgId, ShouldEqual, 4)
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
- cmd.Result = &m.User{Id: 33}
|
|
|
|
|
- return nil
|
|
|
|
|
|
|
+ So(cacheValue, ShouldEqual, 33)
|
|
|
|
|
+ So(cacheErr, ShouldBeNil)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.req.RemoteAddr = "192.168.1.10:12345"
|
|
|
|
|
- sc.exec()
|
|
|
|
|
|
|
+ middlewareScenario(t, "should create an user from a header", func(sc *scenarioContext) {
|
|
|
|
|
+ setting.LdapEnabled = false
|
|
|
|
|
+ setting.AuthProxyAutoSignUp = true
|
|
|
|
|
|
|
|
- Convey("Should init context with user info", func() {
|
|
|
|
|
- So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
- So(sc.context.UserId, ShouldEqual, 33)
|
|
|
|
|
- So(sc.context.OrgId, ShouldEqual, 4)
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
+ if query.UserId > 0 {
|
|
|
|
|
+ query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+ return m.ErrUserNotFound
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- middlewareScenario("When auth_proxy is enabled and IPv6 request RemoteAddr is within trusted CIDR block", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
+ cmd.Result = &m.User{Id: 33}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
- query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ sc.fakeReq("GET", "/")
|
|
|
|
|
+ sc.req.Header.Add(setting.AuthProxyHeaderName, name)
|
|
|
|
|
+ sc.exec()
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
- cmd.Result = &m.User{Id: 33}
|
|
|
|
|
- return nil
|
|
|
|
|
|
|
+ Convey("Should create user from header info", func() {
|
|
|
|
|
+ So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
+ So(sc.context.UserId, ShouldEqual, 33)
|
|
|
|
|
+ So(sc.context.OrgId, ShouldEqual, 4)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.req.RemoteAddr = "[2001::23]:12345"
|
|
|
|
|
- sc.exec()
|
|
|
|
|
|
|
+ middlewareScenario(t, "should get an existing user from header", func(sc *scenarioContext) {
|
|
|
|
|
+ setting.LdapEnabled = false
|
|
|
|
|
|
|
|
- Convey("Should init context with user info", func() {
|
|
|
|
|
- So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
- So(sc.context.UserId, ShouldEqual, 33)
|
|
|
|
|
- So(sc.context.OrgId, ShouldEqual, 4)
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
+ query.Result = &m.SignedInUser{OrgId: 2, UserId: 12}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- middlewareScenario("When session exists for previous user, create a new session", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = ""
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
+ cmd.Result = &m.User{Id: 12}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(query *m.UpsertUserCommand) error {
|
|
|
|
|
- query.Result = &m.User{Id: 32}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ sc.fakeReq("GET", "/")
|
|
|
|
|
+ sc.req.Header.Add(setting.AuthProxyHeaderName, name)
|
|
|
|
|
+ sc.exec()
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
- query.Result = &m.SignedInUser{OrgId: 4, UserId: 32}
|
|
|
|
|
- return nil
|
|
|
|
|
|
|
+ Convey("should init context with user info", func() {
|
|
|
|
|
+ So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
+ So(sc.context.UserId, ShouldEqual, 12)
|
|
|
|
|
+ So(sc.context.OrgId, ShouldEqual, 2)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- // create session
|
|
|
|
|
- sc.fakeReq("GET", "/").handler(func(c *m.ReqContext) {
|
|
|
|
|
- c.Session.Set(session.SESS_KEY_USERID, int64(33))
|
|
|
|
|
- }).exec()
|
|
|
|
|
|
|
+ middlewareScenario(t, "should allow the request from whitelist IP", func(sc *scenarioContext) {
|
|
|
|
|
+ setting.AuthProxyWhitelist = "192.168.1.0/24, 2001::0/120"
|
|
|
|
|
+ setting.LdapEnabled = false
|
|
|
|
|
|
|
|
- oldSessionID := sc.context.Session.ID()
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
+ query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.exec()
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
+ cmd.Result = &m.User{Id: 33}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- newSessionID := sc.context.Session.ID()
|
|
|
|
|
|
|
+ sc.fakeReq("GET", "/")
|
|
|
|
|
+ sc.req.Header.Add(setting.AuthProxyHeaderName, name)
|
|
|
|
|
+ sc.req.RemoteAddr = "[2001::23]:12345"
|
|
|
|
|
+ sc.exec()
|
|
|
|
|
|
|
|
- Convey("Should not share session with other user", func() {
|
|
|
|
|
- So(oldSessionID, ShouldNotEqual, newSessionID)
|
|
|
|
|
|
|
+ Convey("Should init context with user info", func() {
|
|
|
|
|
+ So(sc.context.IsSignedIn, ShouldBeTrue)
|
|
|
|
|
+ So(sc.context.UserId, ShouldEqual, 33)
|
|
|
|
|
+ So(sc.context.OrgId, ShouldEqual, 4)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
- })
|
|
|
|
|
|
|
|
|
|
- middlewareScenario("When auth_proxy and ldap enabled call sync with ldap user", func(sc *scenarioContext) {
|
|
|
|
|
- setting.AuthProxyEnabled = true
|
|
|
|
|
- setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
|
|
|
- setting.AuthProxyHeaderProperty = "username"
|
|
|
|
|
- setting.AuthProxyWhitelist = ""
|
|
|
|
|
- setting.LdapEnabled = true
|
|
|
|
|
-
|
|
|
|
|
- called := false
|
|
|
|
|
- syncGrafanaUserWithLdapUser = func(query *m.LoginUserQuery) error {
|
|
|
|
|
- called = true
|
|
|
|
|
- query.User = &m.User{Id: 32}
|
|
|
|
|
- return nil
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ middlewareScenario(t, "should not allow the request from whitelist IP", func(sc *scenarioContext) {
|
|
|
|
|
+ setting.AuthProxyWhitelist = "8.8.8.8"
|
|
|
|
|
+ setting.LdapEnabled = false
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(query *m.UpsertUserCommand) error {
|
|
|
|
|
- query.Result = &m.User{Id: 32}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
+ query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
|
|
|
|
|
- query.Result = &m.SignedInUser{OrgId: 4, UserId: 32}
|
|
|
|
|
- return nil
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
|
|
|
|
|
+ cmd.Result = &m.User{Id: 33}
|
|
|
|
|
+ return nil
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- sc.fakeReq("GET", "/")
|
|
|
|
|
- sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
|
|
|
|
|
- sc.exec()
|
|
|
|
|
|
|
+ sc.fakeReq("GET", "/")
|
|
|
|
|
+ sc.req.Header.Add(setting.AuthProxyHeaderName, name)
|
|
|
|
|
+ sc.req.RemoteAddr = "[2001::23]:12345"
|
|
|
|
|
+ sc.exec()
|
|
|
|
|
|
|
|
- Convey("Should call syncGrafanaUserWithLdapUser", func() {
|
|
|
|
|
- So(called, ShouldBeTrue)
|
|
|
|
|
|
|
+ Convey("should return 407 status code", func() {
|
|
|
|
|
+ So(sc.resp.Code, ShouldEqual, 407)
|
|
|
|
|
+ So(sc.context, ShouldBeNil)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func middlewareScenario(desc string, fn scenarioFunc) {
|
|
|
|
|
|
|
+func middlewareScenario(t *testing.T, desc string, fn scenarioFunc) {
|
|
|
Convey(desc, func() {
|
|
Convey(desc, func() {
|
|
|
defer bus.ClearBusHandlers()
|
|
defer bus.ClearBusHandlers()
|
|
|
|
|
|
|
@@ -562,9 +469,10 @@ func middlewareScenario(desc string, fn scenarioFunc) {
|
|
|
Delims: macaron.Delims{Left: "[[", Right: "]]"},
|
|
Delims: macaron.Delims{Left: "[[", Right: "]]"},
|
|
|
}))
|
|
}))
|
|
|
|
|
|
|
|
- session.Init(&msession.Options{}, 0)
|
|
|
|
|
sc.userAuthTokenService = auth.NewFakeUserAuthTokenService()
|
|
sc.userAuthTokenService = auth.NewFakeUserAuthTokenService()
|
|
|
- sc.m.Use(GetContextHandler(sc.userAuthTokenService))
|
|
|
|
|
|
|
+ sc.remoteCacheService = remotecache.NewFakeStore(t)
|
|
|
|
|
+
|
|
|
|
|
+ sc.m.Use(GetContextHandler(sc.userAuthTokenService, sc.remoteCacheService))
|
|
|
// mock out gc goroutine
|
|
// mock out gc goroutine
|
|
|
session.StartSessionGC = func() {}
|
|
session.StartSessionGC = func() {}
|
|
|
setting.SessionOptions = msession.Options{}
|
|
setting.SessionOptions = msession.Options{}
|
|
@@ -597,6 +505,7 @@ type scenarioContext struct {
|
|
|
defaultHandler macaron.Handler
|
|
defaultHandler macaron.Handler
|
|
|
url string
|
|
url string
|
|
|
userAuthTokenService *auth.FakeUserAuthTokenService
|
|
userAuthTokenService *auth.FakeUserAuthTokenService
|
|
|
|
|
+ remoteCacheService *remotecache.RemoteCache
|
|
|
|
|
|
|
|
req *http.Request
|
|
req *http.Request
|
|
|
}
|
|
}
|
|
@@ -622,13 +531,6 @@ func (sc *scenarioContext) fakeReq(method, url string) *scenarioContext {
|
|
|
So(err, ShouldBeNil)
|
|
So(err, ShouldBeNil)
|
|
|
sc.req = req
|
|
sc.req = req
|
|
|
|
|
|
|
|
- // add session cookie from last request
|
|
|
|
|
- if sc.context != nil {
|
|
|
|
|
- if sc.context.Session.ID() != "" {
|
|
|
|
|
- req.Header.Add("Cookie", "grafana_sess="+sc.context.Session.ID()+";")
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
return sc
|
|
return sc
|
|
|
}
|
|
}
|
|
|
|
|
|