Commit 391868c5 by Julian Kornberger

Use net.SplitHostPort to support IPv6

- Add some tests
- Make error message more helpful
parent a20f3d19
package middleware package middleware
import ( import (
"errors"
"fmt" "fmt"
"net"
"strings" "strings"
"time" "time"
...@@ -25,7 +25,7 @@ func initContextWithAuthProxy(ctx *m.ReqContext, orgID int64) bool { ...@@ -25,7 +25,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, proxyHeaderValue); err != nil { if err := checkAuthenticationProxy(ctx.Req.RemoteAddr, proxyHeaderValue); err != nil {
ctx.Handle(407, "Proxy authentication required", err) ctx.Handle(407, "Proxy authentication required", err)
return true return true
} }
...@@ -123,29 +123,25 @@ var syncGrafanaUserWithLdapUser = func(ctx *m.ReqContext, query *m.GetSignedInUs ...@@ -123,29 +123,25 @@ var syncGrafanaUserWithLdapUser = func(ctx *m.ReqContext, query *m.GetSignedInUs
return nil return nil
} }
func checkAuthenticationProxy(ctx *m.ReqContext, proxyHeaderValue string) error { func checkAuthenticationProxy(remoteAddr string, proxyHeaderValue string) error {
if len(strings.TrimSpace(setting.AuthProxyWhitelist)) == 0 { if len(strings.TrimSpace(setting.AuthProxyWhitelist)) == 0 {
return nil return nil
} }
proxies := strings.Split(setting.AuthProxyWhitelist, ",") proxies := strings.Split(setting.AuthProxyWhitelist, ",")
remoteAddrSplit := strings.Split(ctx.Req.RemoteAddr, ":") sourceIP, _, err := net.SplitHostPort(remoteAddr)
sourceIP := remoteAddrSplit[0] if err != nil {
return err
}
found := false // Compare allowed IP addresses to actual address
for _, proxyIP := range proxies { for _, proxyIP := range proxies {
if sourceIP == strings.TrimSpace(proxyIP) { if sourceIP == strings.TrimSpace(proxyIP) {
found = true return nil
break
}
} }
if !found {
msg := fmt.Sprintf("Request for user (%s) is not from the authentication proxy", proxyHeaderValue)
err := errors.New(msg)
return err
} }
return nil return fmt.Errorf("Request for user (%s) from %s is not from the authentication proxy", proxyHeaderValue, sourceIP)
} }
func getSignedInUserQueryForProxyAuth(headerVal string) *m.GetSignedInUserQuery { func getSignedInUserQueryForProxyAuth(headerVal string) *m.GetSignedInUserQuery {
......
...@@ -226,11 +226,11 @@ func TestMiddlewareContext(t *testing.T) { ...@@ -226,11 +226,11 @@ func TestMiddlewareContext(t *testing.T) {
}) })
}) })
middlewareScenario("When auth_proxy is enabled and request RemoteAddr is not trusted", func(sc *scenarioContext) { middlewareScenario("When auth_proxy is enabled and IPv4 request RemoteAddr is not trusted", func(sc *scenarioContext) {
setting.AuthProxyEnabled = true setting.AuthProxyEnabled = true
setting.AuthProxyHeaderName = "X-WEBAUTH-USER" setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
setting.AuthProxyHeaderProperty = "username" setting.AuthProxyHeaderProperty = "username"
setting.AuthProxyWhitelist = "192.168.1.1, 192.168.2.1" setting.AuthProxyWhitelist = "192.168.1.1, 2001::23"
sc.fakeReq("GET", "/") sc.fakeReq("GET", "/")
sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
...@@ -239,6 +239,24 @@ func TestMiddlewareContext(t *testing.T) { ...@@ -239,6 +239,24 @@ func TestMiddlewareContext(t *testing.T) {
Convey("should return 407 status code", func() { Convey("should return 407 status code", func() {
So(sc.resp.Code, ShouldEqual, 407) 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 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.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")
}) })
}) })
...@@ -246,7 +264,7 @@ func TestMiddlewareContext(t *testing.T) { ...@@ -246,7 +264,7 @@ func TestMiddlewareContext(t *testing.T) {
setting.AuthProxyEnabled = true setting.AuthProxyEnabled = true
setting.AuthProxyHeaderName = "X-WEBAUTH-USER" setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
setting.AuthProxyHeaderProperty = "username" setting.AuthProxyHeaderProperty = "username"
setting.AuthProxyWhitelist = "192.168.1.1, 192.168.2.1" setting.AuthProxyWhitelist = "192.168.1.1, 2001::23"
bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
query.Result = &m.SignedInUser{OrgId: 4, UserId: 33} query.Result = &m.SignedInUser{OrgId: 4, UserId: 33}
...@@ -255,7 +273,7 @@ func TestMiddlewareContext(t *testing.T) { ...@@ -255,7 +273,7 @@ func TestMiddlewareContext(t *testing.T) {
sc.fakeReq("GET", "/") sc.fakeReq("GET", "/")
sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
sc.req.RemoteAddr = "192.168.2.1:12345" sc.req.RemoteAddr = "[2001::23]:12345"
sc.exec() sc.exec()
Convey("Should init context with user info", func() { Convey("Should init context with user info", func() {
......
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