Commit 18167f1c by Marcus Efraimsson Committed by GitHub

Merge pull request #12299 from grafana/10707_whitelist

auth proxy: whitelist proxy ip instead of client ip
parents a2ff7629 b418e14b
...@@ -2,7 +2,6 @@ package middleware ...@@ -2,7 +2,6 @@ package middleware
import ( import (
"fmt" "fmt"
"net"
"net/mail" "net/mail"
"reflect" "reflect"
"strings" "strings"
...@@ -29,7 +28,7 @@ func initContextWithAuthProxy(ctx *m.ReqContext, orgID int64) bool { ...@@ -29,7 +28,7 @@ func initContextWithAuthProxy(ctx *m.ReqContext, orgID int64) bool {
} }
// if auth proxy ip(s) defined, check if request comes from one of those // if auth proxy ip(s) defined, check if request comes from one of those
if err := checkAuthenticationProxy(ctx.Req.RemoteAddr, proxyHeaderValue); err != nil { if err := checkAuthenticationProxy(ctx.RemoteAddr(), proxyHeaderValue); err != nil {
ctx.Handle(407, "Proxy authentication required", err) ctx.Handle(407, "Proxy authentication required", err)
return true return true
} }
...@@ -197,18 +196,23 @@ func checkAuthenticationProxy(remoteAddr string, proxyHeaderValue string) error ...@@ -197,18 +196,23 @@ func checkAuthenticationProxy(remoteAddr string, proxyHeaderValue string) error
return nil return nil
} }
proxies := strings.Split(setting.AuthProxyWhitelist, ",") // Multiple ip addresses? Right-most IP address is the IP address of the most recent proxy
sourceIP, _, err := net.SplitHostPort(remoteAddr) if strings.Contains(remoteAddr, ",") {
if err != nil { sourceIPs := strings.Split(remoteAddr, ",")
return err remoteAddr = strings.TrimSpace(sourceIPs[len(sourceIPs)-1])
} }
remoteAddr = strings.TrimPrefix(remoteAddr, "[")
remoteAddr = strings.TrimSuffix(remoteAddr, "]")
proxies := strings.Split(setting.AuthProxyWhitelist, ",")
// Compare allowed IP addresses to actual address // Compare allowed IP addresses to actual address
for _, proxyIP := range proxies { for _, proxyIP := range proxies {
if sourceIP == strings.TrimSpace(proxyIP) { if remoteAddr == strings.TrimSpace(proxyIP) {
return nil return nil
} }
} }
return fmt.Errorf("Request for user (%s) from %s is not from the authentication proxy", proxyHeaderValue, sourceIP) return fmt.Errorf("Request for user (%s) from %s is not from the authentication proxy", proxyHeaderValue, remoteAddr)
} }
...@@ -293,6 +293,61 @@ func TestMiddlewareContext(t *testing.T) { ...@@ -293,6 +293,61 @@ 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) { middlewareScenario("When session exists for previous user, create a new session", func(sc *scenarioContext) {
setting.AuthProxyEnabled = true setting.AuthProxyEnabled = true
setting.AuthProxyHeaderName = "X-WEBAUTH-USER" setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment