Merge branch 'master' of https://github.com/grafana/grafana into macros/sql

This commit is contained in:
Austin Winstanley
2018-06-29 03:31:23 +00:00
45 changed files with 3106 additions and 1672 deletions

View File

@@ -272,9 +272,9 @@ func canSaveByDashboardID(c *m.ReqContext, dashboardID int64) (bool, error) {
return false, nil
}
if dashboardID > 0 {
guardian := guardian.New(dashboardID, c.OrgId, c.SignedInUser)
if canEdit, err := guardian.CanEdit(); err != nil || !canEdit {
if dashboardID != 0 {
guard := guardian.New(dashboardID, c.OrgId, c.SignedInUser)
if canEdit, err := guard.CanEdit(); err != nil || !canEdit {
return false, err
}
}

View File

@@ -42,7 +42,7 @@ type RouteRegister interface {
// Register iterates over all routes added to the RouteRegister
// and add them to the `Router` pass as an parameter.
Register(Router) *macaron.Router
Register(Router)
}
type RegisterNamedMiddleware func(name string) macaron.Handler
@@ -101,7 +101,7 @@ func (rr *routeRegister) Group(pattern string, fn func(rr RouteRegister), handle
rr.groups = append(rr.groups, group)
}
func (rr *routeRegister) Register(router Router) *macaron.Router {
func (rr *routeRegister) Register(router Router) {
for _, r := range rr.routes {
// GET requests have to be added to macaron routing using Get()
// Otherwise HEAD requests will not be allowed.
@@ -116,8 +116,6 @@ func (rr *routeRegister) Register(router Router) *macaron.Router {
for _, g := range rr.groups {
g.Register(router)
}
return &macaron.Router{}
}
func (rr *routeRegister) route(pattern, method string, handlers ...macaron.Handler) {

View File

@@ -308,9 +308,6 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) {
} else {
filter_replace = getLdapAttr(a.server.GroupSearchFilterUserAttribute, searchResult)
}
if a.server.GroupSearchFilterUserAttribute == "dn" {
filter_replace = searchResult.Entries[0].DN
}
filter := strings.Replace(a.server.GroupSearchFilter, "%s", ldap.EscapeFilter(filter_replace), -1)
@@ -334,11 +331,7 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) {
if len(groupSearchResult.Entries) > 0 {
for i := range groupSearchResult.Entries {
if a.server.Attr.MemberOf == "dn" {
memberOf = append(memberOf, groupSearchResult.Entries[i].DN)
} else {
memberOf = append(memberOf, getLdapAttrN(a.server.Attr.MemberOf, groupSearchResult, i))
}
memberOf = append(memberOf, getLdapAttrN(a.server.Attr.MemberOf, groupSearchResult, i))
}
break
}
@@ -356,7 +349,7 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) {
}
func getLdapAttrN(name string, result *ldap.SearchResult, n int) string {
if name == "DN" {
if strings.ToLower(name) == "dn" {
return result.Entries[n].DN
}
for _, attr := range result.Entries[n].Attributes {

View File

@@ -9,6 +9,7 @@ import (
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/session"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
type AuthOptions struct {
@@ -34,6 +35,11 @@ func getApiKey(c *m.ReqContext) string {
return key
}
username, password, err := util.DecodeBasicAuthHeader(header)
if err == nil && username == "api_key" {
return password
}
return ""
}

View File

@@ -2,6 +2,7 @@ package middleware
import (
"fmt"
"net"
"net/mail"
"reflect"
"strings"
@@ -28,7 +29,7 @@ func initContextWithAuthProxy(ctx *m.ReqContext, orgID int64) bool {
}
// if auth proxy ip(s) defined, check if request comes from one of those
if err := checkAuthenticationProxy(ctx.RemoteAddr(), proxyHeaderValue); err != nil {
if err := checkAuthenticationProxy(ctx.Req.RemoteAddr, proxyHeaderValue); err != nil {
ctx.Handle(407, "Proxy authentication required", err)
return true
}
@@ -196,23 +197,18 @@ func checkAuthenticationProxy(remoteAddr string, proxyHeaderValue string) error
return nil
}
// Multiple ip addresses? Right-most IP address is the IP address of the most recent proxy
if strings.Contains(remoteAddr, ",") {
sourceIPs := strings.Split(remoteAddr, ",")
remoteAddr = strings.TrimSpace(sourceIPs[len(sourceIPs)-1])
}
remoteAddr = strings.TrimPrefix(remoteAddr, "[")
remoteAddr = strings.TrimSuffix(remoteAddr, "]")
proxies := strings.Split(setting.AuthProxyWhitelist, ",")
sourceIP, _, err := net.SplitHostPort(remoteAddr)
if err != nil {
return err
}
// Compare allowed IP addresses to actual address
for _, proxyIP := range proxies {
if remoteAddr == strings.TrimSpace(proxyIP) {
if sourceIP == strings.TrimSpace(proxyIP) {
return nil
}
}
return fmt.Errorf("Request for user (%s) from %s is not from the authentication proxy", proxyHeaderValue, remoteAddr)
return fmt.Errorf("Request for user (%s) from %s is not from the authentication proxy", proxyHeaderValue, sourceIP)
}

View File

@@ -82,7 +82,7 @@ func TestMiddlewareContext(t *testing.T) {
setting.BasicAuthEnabled = true
authHeader := util.GetBasicAuthHeader("myUser", "myPass")
sc.fakeReq("GET", "/").withAuthoriziationHeader(authHeader).exec()
sc.fakeReq("GET", "/").withAuthorizationHeader(authHeader).exec()
Convey("Should init middleware context with user", func() {
So(sc.context.IsSignedIn, ShouldEqual, true)
@@ -128,6 +128,28 @@ func TestMiddlewareContext(t *testing.T) {
})
})
middlewareScenario("Valid api key via Basic auth", func(sc *scenarioContext) {
keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd")
bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error {
query.Result = &m.ApiKey{OrgId: 12, Role: m.ROLE_EDITOR, Key: keyhash}
return nil
})
authHeader := util.GetBasicAuthHeader("api_key", "eyJrIjoidjVuQXdwTWFmRlA2em5hUzR1cmhkV0RMUzU1MTFNNDIiLCJuIjoiYXNkIiwiaWQiOjF9")
sc.fakeReq("GET", "/").withAuthorizationHeader(authHeader).exec()
Convey("Should return 200", func() {
So(sc.resp.Code, ShouldEqual, 200)
})
Convey("Should init middleware context", func() {
So(sc.context.IsSignedIn, ShouldEqual, true)
So(sc.context.OrgId, ShouldEqual, 12)
So(sc.context.OrgRole, ShouldEqual, m.ROLE_EDITOR)
})
})
middlewareScenario("UserId in session", func(sc *scenarioContext) {
sc.fakeReq("GET", "/").handler(func(c *m.ReqContext) {
@@ -293,61 +315,6 @@ func TestMiddlewareContext(t *testing.T) {
})
})
middlewareScenario("When auth_proxy is enabled and request has X-Forwarded-For that 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"
bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
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.req.Header.Add("X-Forwarded-For", "client-ip, 192.168.1.1, 192.168.1.2")
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.1.2 is not from the authentication proxy")
})
})
middlewareScenario("When auth_proxy is enabled and request has X-Forwarded-For that 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.GetSignedInUserQuery) error {
query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
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.req.Header.Add("X-Forwarded-For", "client-ip, 192.168.1.2, 192.168.1.1")
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)
})
})
middlewareScenario("When session exists for previous user, create a new session", func(sc *scenarioContext) {
setting.AuthProxyEnabled = true
setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
@@ -473,7 +440,7 @@ func (sc *scenarioContext) withInvalidApiKey() *scenarioContext {
return sc
}
func (sc *scenarioContext) withAuthoriziationHeader(authHeader string) *scenarioContext {
func (sc *scenarioContext) withAuthorizationHeader(authHeader string) *scenarioContext {
sc.authHeader = authHeader
return sc
}