2022-05-05 05:42:50 -05:00
|
|
|
package loki
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
2022-10-27 11:05:06 -05:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2022-05-05 05:42:50 -05:00
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
|
|
|
)
|
|
|
|
|
|
|
|
type mockedRoundTripperForOauth struct {
|
|
|
|
requestCallback func(req *http.Request)
|
|
|
|
body []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mockedRT *mockedRoundTripperForOauth) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
|
|
mockedRT.requestCallback(req)
|
|
|
|
return &http.Response{
|
|
|
|
StatusCode: http.StatusOK,
|
|
|
|
Header: http.Header{},
|
|
|
|
Body: io.NopCloser(bytes.NewReader(mockedRT.body)),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockedCallResourceResponseSenderForOauth struct {
|
|
|
|
Response *backend.CallResourceResponse
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *mockedCallResourceResponseSenderForOauth) Send(resp *backend.CallResourceResponse) error {
|
|
|
|
s.Response = resp
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-06-02 04:52:27 -05:00
|
|
|
func makeMockedDsInfoForOauth(body []byte, requestCallback func(req *http.Request)) datasourceInfo {
|
2022-05-05 05:42:50 -05:00
|
|
|
client := http.Client{
|
|
|
|
Transport: &mockedRoundTripperForOauth{requestCallback: requestCallback, body: body},
|
|
|
|
}
|
|
|
|
|
|
|
|
return datasourceInfo{
|
2022-06-02 04:52:27 -05:00
|
|
|
HTTPClient: &client,
|
2022-05-05 05:42:50 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestOauthForwardIdentity(t *testing.T) {
|
|
|
|
tt := []struct {
|
2022-06-02 04:52:27 -05:00
|
|
|
name string
|
|
|
|
auth bool
|
|
|
|
cookie bool
|
2022-05-05 05:42:50 -05:00
|
|
|
}{
|
2022-06-02 04:52:27 -05:00
|
|
|
{name: "when auth header exists => add auth header", auth: true, cookie: false},
|
|
|
|
{name: "when cookie header exists => add cookie header", auth: false, cookie: true},
|
|
|
|
{name: "when cookie&auth headers exist => add cookie&auth headers", auth: true, cookie: true},
|
|
|
|
{name: "when no header exists => do not add headers", auth: false, cookie: false},
|
2022-05-05 05:42:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
authName := "Authorization"
|
|
|
|
authValue := "auth"
|
2022-06-02 04:52:27 -05:00
|
|
|
cookieName := "Cookie"
|
|
|
|
cookieValue := "a=1"
|
2022-05-05 05:42:50 -05:00
|
|
|
|
|
|
|
for _, test := range tt {
|
|
|
|
t.Run("QueryData: "+test.name, func(t *testing.T) {
|
|
|
|
response := []byte(`
|
|
|
|
{
|
|
|
|
"status": "success",
|
|
|
|
"data": {
|
|
|
|
"resultType": "streams",
|
|
|
|
"result": [
|
|
|
|
{
|
|
|
|
"stream": {},
|
|
|
|
"values": [
|
|
|
|
["1", "line1"]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`)
|
|
|
|
|
|
|
|
clientUsed := false
|
2022-06-02 04:52:27 -05:00
|
|
|
dsInfo := makeMockedDsInfoForOauth(response, func(req *http.Request) {
|
2022-05-05 05:42:50 -05:00
|
|
|
clientUsed = true
|
2022-06-02 04:52:27 -05:00
|
|
|
// we need to check for "header does not exist",
|
|
|
|
// and the only way i can find is to get the values
|
|
|
|
// as an array
|
|
|
|
authValues := req.Header.Values(authName)
|
|
|
|
cookieValues := req.Header.Values(cookieName)
|
|
|
|
if test.auth {
|
|
|
|
require.Equal(t, []string{authValue}, authValues)
|
2022-05-05 05:42:50 -05:00
|
|
|
} else {
|
2022-06-02 04:52:27 -05:00
|
|
|
require.Len(t, authValues, 0)
|
|
|
|
}
|
|
|
|
if test.cookie {
|
|
|
|
require.Equal(t, []string{cookieValue}, cookieValues)
|
|
|
|
} else {
|
|
|
|
require.Len(t, cookieValues, 0)
|
2022-05-05 05:42:50 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
req := backend.QueryDataRequest{
|
|
|
|
Headers: map[string]string{},
|
|
|
|
Queries: []backend.DataQuery{
|
|
|
|
{
|
|
|
|
RefID: "A",
|
|
|
|
JSON: []byte("{}"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2022-06-02 04:52:27 -05:00
|
|
|
if test.auth {
|
2022-05-05 05:42:50 -05:00
|
|
|
req.Headers[authName] = authValue
|
|
|
|
}
|
|
|
|
|
2022-06-02 04:52:27 -05:00
|
|
|
if test.cookie {
|
|
|
|
req.Headers[cookieName] = cookieValue
|
|
|
|
}
|
|
|
|
|
2022-06-15 05:40:41 -05:00
|
|
|
tracer := tracing.InitializeTracerForTest()
|
2022-05-05 05:42:50 -05:00
|
|
|
|
2022-10-27 11:05:06 -05:00
|
|
|
data, err := queryData(context.Background(), &req, &dsInfo, tracer)
|
2022-05-05 05:42:50 -05:00
|
|
|
// we do a basic check that the result is OK
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, data.Responses, 1)
|
|
|
|
res := data.Responses["A"]
|
|
|
|
require.NoError(t, res.Error)
|
|
|
|
require.Len(t, res.Frames, 1)
|
|
|
|
require.Equal(t, "line1", res.Frames[0].Fields[2].At(0))
|
|
|
|
|
|
|
|
// we need to be sure the client-callback was triggered
|
|
|
|
require.True(t, clientUsed)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tt {
|
|
|
|
t.Run("CallResource: "+test.name, func(t *testing.T) {
|
|
|
|
response := []byte("mocked resource response")
|
|
|
|
|
|
|
|
clientUsed := false
|
2022-06-02 04:52:27 -05:00
|
|
|
dsInfo := makeMockedDsInfoForOauth(response, func(req *http.Request) {
|
2022-05-05 05:42:50 -05:00
|
|
|
clientUsed = true
|
2022-06-02 04:52:27 -05:00
|
|
|
authValues := req.Header.Values(authName)
|
|
|
|
cookieValues := req.Header.Values(cookieName)
|
|
|
|
// we need to check for "header does not exist",
|
|
|
|
// and the only way i can find is to get the values
|
|
|
|
// as an array
|
|
|
|
if test.auth {
|
|
|
|
require.Equal(t, []string{authValue}, authValues)
|
2022-05-05 05:42:50 -05:00
|
|
|
} else {
|
2022-06-02 04:52:27 -05:00
|
|
|
require.Len(t, authValues, 0)
|
|
|
|
}
|
|
|
|
if test.cookie {
|
|
|
|
require.Equal(t, []string{cookieValue}, cookieValues)
|
|
|
|
} else {
|
|
|
|
require.Len(t, cookieValues, 0)
|
2022-05-05 05:42:50 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
req := backend.CallResourceRequest{
|
|
|
|
Headers: map[string][]string{},
|
|
|
|
Method: "GET",
|
|
|
|
URL: "labels?",
|
|
|
|
}
|
|
|
|
|
2022-06-02 04:52:27 -05:00
|
|
|
if test.auth {
|
2022-05-05 05:42:50 -05:00
|
|
|
req.Headers[authName] = []string{authValue}
|
|
|
|
}
|
2022-06-02 04:52:27 -05:00
|
|
|
if test.cookie {
|
|
|
|
req.Headers[cookieName] = []string{cookieValue}
|
|
|
|
}
|
2022-05-05 05:42:50 -05:00
|
|
|
|
|
|
|
sender := &mockedCallResourceResponseSenderForOauth{}
|
|
|
|
|
|
|
|
err := callResource(context.Background(), &req, sender, &dsInfo, log.New("testlog"))
|
|
|
|
// we do a basic check that the result is OK
|
|
|
|
require.NoError(t, err)
|
|
|
|
sent := sender.Response
|
|
|
|
require.NotNil(t, sent)
|
|
|
|
require.Equal(t, http.StatusOK, sent.Status)
|
|
|
|
require.Equal(t, response, sent.Body)
|
|
|
|
|
|
|
|
// we need to be sure the client-callback was triggered
|
|
|
|
require.True(t, clientUsed)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|