Datasource: Fix allowed cookies to be forwarded as header to backend datasources (#49541)

Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
pull/49938/head
Marcus Efraimsson 3 years ago committed by GitHub
parent e82784bff0
commit 1196b4a609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      pkg/api/dtos/models.go
  2. 2
      pkg/api/metrics.go
  3. 20
      pkg/services/query/query.go
  4. 37
      pkg/services/query/query_test.go

@ -3,6 +3,7 @@ package dtos
import (
"crypto/md5"
"fmt"
"net/http"
"regexp"
"strings"
@ -68,6 +69,8 @@ type MetricRequest struct {
Queries []*simplejson.Json `json:"queries"`
// required: false
Debug bool `json:"debug"`
HTTPRequest *http.Request `json:"-"`
}
func GetGravatarUrl(text string) string {

@ -44,6 +44,8 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext) response.Response {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
reqDTO.HTTPRequest = c.Req
resp, err := hs.queryDataService.QueryData(c.Req.Context(), c.SignedInUser, c.SkipCache, reqDTO, true)
if err != nil {
return hs.handleQueryMetricsError(err)

@ -3,6 +3,7 @@ package query
import (
"context"
"fmt"
"net/http"
"strings"
"time"
@ -18,6 +19,7 @@ import (
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/grafanads"
"github.com/grafana/grafana/pkg/tsdb/legacydata"
"github.com/grafana/grafana/pkg/util/proxyutil"
"github.com/grafana/grafana-plugin-sdk-go/backend"
)
@ -149,6 +151,19 @@ func (s *Service) handleQueryData(ctx context.Context, user *models.SignedInUser
req.Headers[k] = v
}
if parsedReq.httpRequest != nil && parsedReq.httpRequest.Header.Get("Cookie") != "" && ds.JsonData != nil {
keepCookieNames := []string{}
if keepCookies := ds.JsonData.Get("keepCookies"); keepCookies != nil {
keepCookieNames = keepCookies.MustStringArray()
}
proxyutil.ClearCookieHeader(parsedReq.httpRequest, keepCookieNames)
if cookieStr := parsedReq.httpRequest.Header.Get("Cookie"); cookieStr != "" {
req.Headers["Cookie"] = cookieStr
}
}
for _, q := range parsedReq.parsedQueries {
req.Queries = append(req.Queries, q.query)
}
@ -164,6 +179,7 @@ type parsedQuery struct {
type parsedRequest struct {
hasExpression bool
parsedQueries []parsedQuery
httpRequest *http.Request
}
func customHeaders(jsonData *simplejson.Json, decryptedJsonData map[string]string) map[string]string {
@ -243,6 +259,10 @@ func (s *Service) parseMetricRequest(ctx context.Context, user *models.SignedInU
}
}
if reqDTO.HTTPRequest != nil {
req.httpRequest = reqDTO.HTTPRequest
}
return req, nil
}

@ -61,6 +61,43 @@ func TestQueryData(t *testing.T) {
}
require.Equal(t, expected, tc.pluginContext.req.Headers)
})
t.Run("it doesn't add cookie header to the request when keepCookies configured and no cookies provided", func(t *testing.T) {
tc := setup(t)
json, err := simplejson.NewJson([]byte(`{"keepCookies": [ "foo", "bar" ]}`))
require.NoError(t, err)
tc.dataSourceCache.ds.JsonData = json
metricReq := metricRequest()
httpReq, err := http.NewRequest(http.MethodGet, "/", nil)
require.NoError(t, err)
metricReq.HTTPRequest = httpReq
_, err = tc.queryService.QueryData(context.Background(), nil, true, metricReq, false)
require.NoError(t, err)
require.Empty(t, tc.pluginContext.req.Headers)
})
t.Run("it adds cookie header to the request when keepCookies configured and cookie provided", func(t *testing.T) {
tc := setup(t)
json, err := simplejson.NewJson([]byte(`{"keepCookies": [ "foo", "bar" ]}`))
require.NoError(t, err)
tc.dataSourceCache.ds.JsonData = json
metricReq := metricRequest()
httpReq, err := http.NewRequest(http.MethodGet, "/", nil)
require.NoError(t, err)
httpReq.AddCookie(&http.Cookie{Name: "a"})
httpReq.AddCookie(&http.Cookie{Name: "bar", Value: "rab"})
httpReq.AddCookie(&http.Cookie{Name: "b"})
httpReq.AddCookie(&http.Cookie{Name: "foo", Value: "oof"})
httpReq.AddCookie(&http.Cookie{Name: "c"})
metricReq.HTTPRequest = httpReq
_, err = tc.queryService.QueryData(context.Background(), nil, true, metricReq, false)
require.NoError(t, err)
require.Equal(t, map[string]string{"Cookie": "bar=rab; foo=oof"}, tc.pluginContext.req.Headers)
})
}
func setup(t *testing.T) *testContext {

Loading…
Cancel
Save