Browse Source

Merge pull request #11643 from mrsiano/generic_oauth

Pass configured/auth headers to a Datasource.
Carl Bergquist 7 years ago
parent
commit
828fb39ee2

+ 3 - 0
conf/provisioning/datasources/sample.yaml

@@ -40,11 +40,14 @@ apiVersion: 1
 #      graphiteVersion: "1.1"
 #      tlsAuth: true
 #      tlsAuthWithCACert: true
+#      httpHeaderName1: "Authorization"
 #   # <string> json object of data that will be encrypted.
 #   secureJsonData:
 #     tlsCACert: "..."
 #     tlsClientCert: "..."
 #     tlsClientKey: "..."
+#     # <openshift\kubernetes token example>
+#     httpHeaderValue1: "Bearer xf5yhfkpsnmgo"
 #   version: 1
 #   # <bool> allow users to edit datasources from the UI.
 #   editable: false

+ 27 - 0
pkg/api/pluginproxy/ds_proxy.go

@@ -117,6 +117,28 @@ func (proxy *DataSourceProxy) addTraceFromHeaderValue(span opentracing.Span, hea
 	}
 }
 
+func (proxy *DataSourceProxy) useCustomHeaders(req *http.Request) {
+	decryptSdj := proxy.ds.SecureJsonData.Decrypt()
+	index := 1
+	for {
+		headerNameSuffix := fmt.Sprintf("httpHeaderName%d", index)
+		headerValueSuffix := fmt.Sprintf("httpHeaderValue%d", index)
+		if key := proxy.ds.JsonData.Get(headerNameSuffix).MustString(); key != "" {
+			if val, ok := decryptSdj[headerValueSuffix]; ok {
+				// remove if exists
+				if req.Header.Get(key) != "" {
+					req.Header.Del(key)
+				}
+				req.Header.Add(key, val)
+				logger.Debug("Using custom header ", "CustomHeaders", key)
+			}
+		} else {
+			break
+		}
+		index += 1
+	}
+}
+
 func (proxy *DataSourceProxy) getDirector() func(req *http.Request) {
 	return func(req *http.Request) {
 		req.URL.Scheme = proxy.targetUrl.Scheme
@@ -146,6 +168,11 @@ func (proxy *DataSourceProxy) getDirector() func(req *http.Request) {
 			req.Header.Add("Authorization", util.GetBasicAuthHeader(proxy.ds.BasicAuthUser, proxy.ds.BasicAuthPassword))
 		}
 
+		// Lookup and use custom headers
+		if proxy.ds.SecureJsonData != nil {
+			proxy.useCustomHeaders(req)
+		}
+
 		dsAuth := req.Header.Get("X-DS-Authorization")
 		if len(dsAuth) > 0 {
 			req.Header.Del("X-DS-Authorization")

+ 32 - 0
pkg/api/pluginproxy/ds_proxy_test.go

@@ -12,6 +12,7 @@ import (
 	macaron "gopkg.in/macaron.v1"
 
 	"github.com/grafana/grafana/pkg/components/simplejson"
+	"github.com/grafana/grafana/pkg/log"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/plugins"
 	"github.com/grafana/grafana/pkg/setting"
@@ -322,6 +323,37 @@ func TestDSRouteRule(t *testing.T) {
 			So(interpolated, ShouldEqual, "0asd+asd")
 		})
 
+		Convey("When proxying a data source with custom headers specified", func() {
+			plugin := &plugins.DataSourcePlugin{}
+
+			encryptedData, err := util.Encrypt([]byte(`Bearer xf5yhfkpsnmgo`), setting.SecretKey)
+			ds := &m.DataSource{
+				Type: m.DS_PROMETHEUS,
+				Url:  "http://prometheus:9090",
+				JsonData: simplejson.NewFromAny(map[string]interface{}{
+					"httpHeaderName1": "Authorization",
+				}),
+				SecureJsonData: map[string][]byte{
+					"httpHeaderValue1": encryptedData,
+				},
+			}
+
+			ctx := &m.ReqContext{}
+			proxy := NewDataSourceProxy(ds, plugin, ctx, "")
+
+			requestURL, _ := url.Parse("http://grafana.com/sub")
+			req := http.Request{URL: requestURL, Header: make(http.Header)}
+			proxy.getDirector()(&req)
+
+			if err != nil {
+				log.Fatal(4, err.Error())
+			}
+
+			Convey("Match header value after decryption", func() {
+				So(req.Header.Get("Authorization"), ShouldEqual, "Bearer xf5yhfkpsnmgo")
+			})
+		})
+
 	})
 }
 

+ 1 - 0
public/app/features/plugins/ds_edit_ctrl.ts

@@ -13,6 +13,7 @@ var defaults = {
   access: 'proxy',
   jsonData: {},
   secureJsonFields: {},
+  secureJsonData: {},
 };
 
 var datasourceCreated = false;