| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-06-01 17:00:05 +08:00
										 |  |  | 	"crypto/tls" | 
					
						
							|  |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"net/http/httputil" | 
					
						
							|  |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2015-06-01 17:00:05 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 17:10:21 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/api/cloudwatch" | 
					
						
							| 
									
										
										
										
											2015-02-05 17:37:13 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/bus" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/middleware" | 
					
						
							|  |  |  | 	m "github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											2015-09-09 23:21:25 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							| 
									
										
										
										
											2015-02-05 17:37:13 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-01 17:00:05 +08:00
										 |  |  | var dataProxyTransport = &http.Transport{ | 
					
						
							|  |  |  | 	TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | 
					
						
							|  |  |  | 	Proxy:           http.ProxyFromEnvironment, | 
					
						
							|  |  |  | 	Dial: (&net.Dialer{ | 
					
						
							|  |  |  | 		Timeout:   30 * time.Second, | 
					
						
							|  |  |  | 		KeepAlive: 30 * time.Second, | 
					
						
							|  |  |  | 	}).Dial, | 
					
						
							|  |  |  | 	TLSHandshakeTimeout: 10 * time.Second, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 23:21:25 +08:00
										 |  |  | func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *httputil.ReverseProxy { | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	director := func(req *http.Request) { | 
					
						
							| 
									
										
										
										
											2015-09-09 23:21:25 +08:00
										 |  |  | 		req.URL.Scheme = targetUrl.Scheme | 
					
						
							|  |  |  | 		req.URL.Host = targetUrl.Host | 
					
						
							|  |  |  | 		req.Host = targetUrl.Host | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		reqQueryVals := req.URL.Query() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-28 15:25:13 +08:00
										 |  |  | 		if ds.Type == m.DS_INFLUXDB_08 { | 
					
						
							| 
									
										
										
										
											2015-09-09 23:21:25 +08:00
										 |  |  | 			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, "db/"+ds.Database+"/"+proxyPath) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 			reqQueryVals.Add("u", ds.User) | 
					
						
							|  |  |  | 			reqQueryVals.Add("p", ds.Password) | 
					
						
							|  |  |  | 			req.URL.RawQuery = reqQueryVals.Encode() | 
					
						
							| 
									
										
										
										
											2015-02-28 15:25:13 +08:00
										 |  |  | 		} else if ds.Type == m.DS_INFLUXDB { | 
					
						
							| 
									
										
										
										
											2015-09-09 23:21:25 +08:00
										 |  |  | 			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath) | 
					
						
							| 
									
										
										
										
											2015-02-26 01:43:44 +08:00
										 |  |  | 			reqQueryVals.Add("db", ds.Database) | 
					
						
							|  |  |  | 			req.URL.RawQuery = reqQueryVals.Encode() | 
					
						
							| 
									
										
										
										
											2015-08-07 17:01:59 +08:00
										 |  |  | 			if !ds.BasicAuth { | 
					
						
							| 
									
										
										
										
											2015-09-19 18:32:35 +08:00
										 |  |  | 				req.Header.Del("Authorization") | 
					
						
							| 
									
										
										
										
											2015-08-07 17:01:59 +08:00
										 |  |  | 				req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.User, ds.Password)) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2015-09-09 23:21:25 +08:00
										 |  |  | 			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-02 16:58:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if ds.BasicAuth { | 
					
						
							| 
									
										
										
										
											2015-09-19 18:32:35 +08:00
										 |  |  | 			req.Header.Del("Authorization") | 
					
						
							| 
									
										
										
										
											2015-03-02 16:58:35 +08:00
										 |  |  | 			req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-08-10 18:11:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// clear cookie headers
 | 
					
						
							|  |  |  | 		req.Header.Del("Cookie") | 
					
						
							|  |  |  | 		req.Header.Del("Set-Cookie") | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &httputil.ReverseProxy{Director: director} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-08 23:30:13 +08:00
										 |  |  | var dsMap map[int64]*m.DataSource = make(map[int64]*m.DataSource) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func getDatasource(id int64, orgId int64) (*m.DataSource, error) { | 
					
						
							|  |  |  | 	// ds, exists := dsMap[id]
 | 
					
						
							|  |  |  | 	// if exists && ds.OrgId == orgId {
 | 
					
						
							|  |  |  | 	// 	return ds, nil
 | 
					
						
							|  |  |  | 	// }
 | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-08 23:30:13 +08:00
										 |  |  | 	query := m.GetDataSourceByIdQuery{Id: id, OrgId: orgId} | 
					
						
							| 
									
										
										
										
											2015-03-12 00:34:11 +08:00
										 |  |  | 	if err := bus.Dispatch(&query); err != nil { | 
					
						
							| 
									
										
										
										
											2015-10-08 23:30:13 +08:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dsMap[id] = &query.Result | 
					
						
							|  |  |  | 	return &query.Result, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func ProxyDataSourceRequest(c *middleware.Context) { | 
					
						
							|  |  |  | 	ds, err := getDatasource(c.ParamsInt64(":id"), c.OrgId) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 		c.JsonApiErr(500, "Unable to load datasource meta data", err) | 
					
						
							| 
									
										
										
										
											2015-03-12 00:34:11 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 23:21:25 +08:00
										 |  |  | 	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 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-08 23:30:13 +08:00
										 |  |  | 	if ds.Type == m.DS_CLOUDWATCH { | 
					
						
							| 
									
										
										
										
											2015-10-29 18:44:34 +08:00
										 |  |  | 		cloudwatch.HandleRequest(c, ds) | 
					
						
							| 
									
										
										
										
											2015-08-13 20:20:47 +08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		proxyPath := c.Params("*") | 
					
						
							| 
									
										
										
										
											2015-10-08 23:30:13 +08:00
										 |  |  | 		proxy := NewReverseProxy(ds, proxyPath, targetUrl) | 
					
						
							| 
									
										
										
										
											2015-08-13 20:20:47 +08:00
										 |  |  | 		proxy.Transport = dataProxyTransport | 
					
						
							|  |  |  | 		proxy.ServeHTTP(c.RW(), c.Req.Request) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | } |