From 9603dce46984c75a50158e12919a8ebd73352b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 9 Sep 2015 17:21:25 +0200 Subject: [PATCH] feat(dataproxy): added whitelist setting and feature for data proxies, closes #2626 --- conf/defaults.ini | 3 +++ conf/sample.ini | 5 ++++- pkg/api/dataproxy.go | 28 ++++++++++++++++++---------- pkg/setting/setting.go | 8 ++++++++ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index 689a6334b30..234f8b7529d 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -121,6 +121,9 @@ cookie_remember_name = grafana_remember # disable gravatar profile images disable_gravatar = false +# data source proxy whitelist (ip_or_domain:port seperated by spaces) +data_source_proxy_whitelist = + #################################### Users #################################### [users] # disable user signup / registration diff --git a/conf/sample.ini b/conf/sample.ini index c92656481b1..ed3cbff6f76 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -3,7 +3,7 @@ # Everything has defaults so you only need to uncomment things you want to # change -# possible values : production, development +# possible values : production, development ; app_mode = production #################################### Paths #################################### @@ -117,6 +117,9 @@ # disable gravatar profile images ;disable_gravatar = false +# data source proxy whitelist (ip_or_domain:port seperated by spaces) +;data_source_proxy_whitelist = + #################################### Users #################################### [users] # disable user signup / registration diff --git a/pkg/api/dataproxy.go b/pkg/api/dataproxy.go index 22ca88148ca..97eaa00d378 100644 --- a/pkg/api/dataproxy.go +++ b/pkg/api/dataproxy.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) @@ -24,30 +25,28 @@ var dataProxyTransport = &http.Transport{ TLSHandshakeTimeout: 10 * time.Second, } -func NewReverseProxy(ds *m.DataSource, proxyPath string) *httputil.ReverseProxy { - target, _ := url.Parse(ds.Url) - +func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *httputil.ReverseProxy { director := func(req *http.Request) { - req.URL.Scheme = target.Scheme - req.URL.Host = target.Host - req.Host = target.Host + req.URL.Scheme = targetUrl.Scheme + req.URL.Host = targetUrl.Host + req.Host = targetUrl.Host reqQueryVals := req.URL.Query() if ds.Type == m.DS_INFLUXDB_08 { - req.URL.Path = util.JoinUrlFragments(target.Path, "db/"+ds.Database+"/"+proxyPath) + req.URL.Path = util.JoinUrlFragments(targetUrl.Path, "db/"+ds.Database+"/"+proxyPath) reqQueryVals.Add("u", ds.User) reqQueryVals.Add("p", ds.Password) req.URL.RawQuery = reqQueryVals.Encode() } else if ds.Type == m.DS_INFLUXDB { - req.URL.Path = util.JoinUrlFragments(target.Path, proxyPath) + req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath) reqQueryVals.Add("db", ds.Database) req.URL.RawQuery = reqQueryVals.Encode() if !ds.BasicAuth { req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.User, ds.Password)) } } else { - req.URL.Path = util.JoinUrlFragments(target.Path, proxyPath) + req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath) } if ds.BasicAuth { @@ -72,11 +71,20 @@ func ProxyDataSourceRequest(c *middleware.Context) { return } + ds := query.Result + targetUrl, _ := url.Parse(ds.Url) + if len(setting.DataProxyWhiteList) > 0 { + if _, exists := setting.DataProxyWhiteList[targetUrl.Host]; !exists { + c.JsonApiErr(403, "Data proxy hostname and ip are not included in whitelist", nil) + return + } + } + if query.Result.Type == m.DS_CLOUDWATCH { ProxyCloudWatchDataSourceRequest(c) } else { proxyPath := c.Params("*") - proxy := NewReverseProxy(&query.Result, proxyPath) + proxy := NewReverseProxy(&ds, proxyPath, targetUrl) proxy.Transport = dataProxyTransport proxy.ServeHTTP(c.RW(), c.Req.Request) } diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index cc74456971e..a8b3383270e 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -73,6 +73,7 @@ var ( CookieRememberName string DisableGravatar bool EmailCodeValidMinutes int + DataProxyWhiteList map[string]bool // User settings AllowUserSignUp bool @@ -378,6 +379,7 @@ func NewConfigContext(args *CommandLineArgs) { EnableGzip = server.Key("enable_gzip").MustBool(false) EnforceDomain = server.Key("enforce_domain").MustBool(false) + // read security settings security := Cfg.Section("security") SecretKey = security.Key("secret_key").String() LogInRememberDays = security.Key("login_remember_days").MustInt() @@ -385,6 +387,12 @@ func NewConfigContext(args *CommandLineArgs) { CookieRememberName = security.Key("cookie_remember_name").String() DisableGravatar = security.Key("disable_gravatar").MustBool(true) + // read data source proxy white list + DataProxyWhiteList = make(map[string]bool) + for _, hostAndIp := range security.Key("data_source_proxy_whitelist").Strings(" ") { + DataProxyWhiteList[hostAndIp] = true + } + // admin AdminUser = security.Key("admin_user").String() AdminPassword = security.Key("admin_password").String()