mirror of https://github.com/grafana/grafana
Plugins: Remove various custom headers logic (#54146)
Removes various custom headers logic sprinkled around in the backend. It should automatically be applied to outgoing HTTP requests via the CustomHeadersMiddleware. This also removes decryption of SecureJSONData to populate custom headers in ngalert which seemed to have caused a ton of CPU usage.pull/54283/head
parent
2f4c8e1b3d
commit
87afd9cadc
@ -0,0 +1,221 @@ |
||||
package prometheus |
||||
|
||||
import ( |
||||
"bytes" |
||||
"context" |
||||
"encoding/json" |
||||
"fmt" |
||||
"io" |
||||
"net/http" |
||||
"net/http/httptest" |
||||
"testing" |
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos" |
||||
"github.com/grafana/grafana/pkg/components/simplejson" |
||||
"github.com/grafana/grafana/pkg/services/datasources" |
||||
"github.com/grafana/grafana/pkg/services/org" |
||||
"github.com/grafana/grafana/pkg/services/sqlstore" |
||||
"github.com/grafana/grafana/pkg/services/user" |
||||
"github.com/grafana/grafana/pkg/tests/testinfra" |
||||
"github.com/stretchr/testify/require" |
||||
) |
||||
|
||||
func TestIntegrationPrometheusBuffered(t *testing.T) { |
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ |
||||
DisableAnonymous: true, |
||||
}) |
||||
|
||||
grafanaListeningAddr, testEnv := testinfra.StartGrafanaEnv(t, dir, path) |
||||
ctx := context.Background() |
||||
|
||||
createUser(t, testEnv.SQLStore, user.CreateUserCommand{ |
||||
DefaultOrgRole: string(org.RoleAdmin), |
||||
Password: "admin", |
||||
Login: "admin", |
||||
}) |
||||
|
||||
var outgoingRequest *http.Request |
||||
outgoingServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
||||
outgoingRequest = r |
||||
w.WriteHeader(http.StatusUnauthorized) |
||||
})) |
||||
t.Cleanup(outgoingServer.Close) |
||||
|
||||
jsonData := simplejson.NewFromAny(map[string]interface{}{ |
||||
"httpMethod": "post", |
||||
"httpHeaderName1": "X-CUSTOM-HEADER", |
||||
"customQueryParameters": "q1=1&q2=2", |
||||
}) |
||||
secureJSONData := map[string]string{ |
||||
"basicAuthPassword": "basicAuthPassword", |
||||
"httpHeaderValue1": "custom-header-value", |
||||
} |
||||
|
||||
uid := "prometheus" |
||||
err := testEnv.Server.HTTPServer.DataSourcesService.AddDataSource(ctx, &datasources.AddDataSourceCommand{ |
||||
OrgId: 1, |
||||
Access: datasources.DS_ACCESS_PROXY, |
||||
Name: "Prometheus", |
||||
Type: datasources.DS_PROMETHEUS, |
||||
Uid: uid, |
||||
Url: outgoingServer.URL, |
||||
BasicAuth: true, |
||||
BasicAuthUser: "basicAuthUser", |
||||
JsonData: jsonData, |
||||
SecureJsonData: secureJSONData, |
||||
}) |
||||
require.NoError(t, err) |
||||
|
||||
t.Run("When calling /api/ds/query should set expected headers on outgoing HTTP request", func(t *testing.T) { |
||||
query := simplejson.NewFromAny(map[string]interface{}{ |
||||
"datasource": map[string]interface{}{ |
||||
"uid": uid, |
||||
}, |
||||
"expr": "up", |
||||
"instantQuery": true, |
||||
}) |
||||
buf1 := &bytes.Buffer{} |
||||
err = json.NewEncoder(buf1).Encode(dtos.MetricRequest{ |
||||
From: "now-1h", |
||||
To: "now", |
||||
Queries: []*simplejson.Json{query}, |
||||
}) |
||||
require.NoError(t, err) |
||||
u := fmt.Sprintf("http://admin:admin@%s/api/ds/query", grafanaListeningAddr) |
||||
// nolint:gosec
|
||||
resp, err := http.Post(u, "application/json", buf1) |
||||
require.NoError(t, err) |
||||
require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
||||
t.Cleanup(func() { |
||||
err := resp.Body.Close() |
||||
require.NoError(t, err) |
||||
}) |
||||
_, err = io.ReadAll(resp.Body) |
||||
require.NoError(t, err) |
||||
|
||||
require.NotNil(t, outgoingRequest) |
||||
require.Equal(t, "/api/v1/query_range?q1=1&q2=2", outgoingRequest.URL.String()) |
||||
require.Equal(t, "custom-header-value", outgoingRequest.Header.Get("X-CUSTOM-HEADER")) |
||||
username, pwd, ok := outgoingRequest.BasicAuth() |
||||
require.True(t, ok) |
||||
require.Equal(t, "basicAuthUser", username) |
||||
require.Equal(t, "basicAuthPassword", pwd) |
||||
}) |
||||
} |
||||
|
||||
func TestIntegrationPrometheusClient(t *testing.T) { |
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ |
||||
EnableFeatureToggles: []string{"prometheusStreamingJSONParser"}, |
||||
}) |
||||
|
||||
grafanaListeningAddr, testEnv := testinfra.StartGrafanaEnv(t, dir, path) |
||||
ctx := context.Background() |
||||
|
||||
createUser(t, testEnv.SQLStore, user.CreateUserCommand{ |
||||
DefaultOrgRole: string(org.RoleAdmin), |
||||
Password: "admin", |
||||
Login: "admin", |
||||
}) |
||||
|
||||
var outgoingRequest *http.Request |
||||
outgoingServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
||||
outgoingRequest = r |
||||
w.WriteHeader(http.StatusUnauthorized) |
||||
})) |
||||
t.Cleanup(outgoingServer.Close) |
||||
|
||||
jsonData := simplejson.NewFromAny(map[string]interface{}{ |
||||
"httpMethod": "post", |
||||
"httpHeaderName1": "X-CUSTOM-HEADER", |
||||
"customQueryParameters": "q1=1&q2=2", |
||||
}) |
||||
secureJSONData := map[string]string{ |
||||
"basicAuthPassword": "basicAuthPassword", |
||||
"httpHeaderValue1": "custom-header-value", |
||||
} |
||||
|
||||
uid := "prometheus" |
||||
err := testEnv.Server.HTTPServer.DataSourcesService.AddDataSource(ctx, &datasources.AddDataSourceCommand{ |
||||
OrgId: 1, |
||||
Access: datasources.DS_ACCESS_PROXY, |
||||
Name: "Prometheus", |
||||
Type: datasources.DS_PROMETHEUS, |
||||
Uid: uid, |
||||
Url: outgoingServer.URL, |
||||
BasicAuth: true, |
||||
BasicAuthUser: "basicAuthUser", |
||||
JsonData: jsonData, |
||||
SecureJsonData: secureJSONData, |
||||
}) |
||||
require.NoError(t, err) |
||||
|
||||
t.Run("When calling /api/ds/query should set expected headers on outgoing HTTP request", func(t *testing.T) { |
||||
query := simplejson.NewFromAny(map[string]interface{}{ |
||||
"datasource": map[string]interface{}{ |
||||
"uid": uid, |
||||
}, |
||||
"expr": "up", |
||||
"instantQuery": true, |
||||
}) |
||||
buf1 := &bytes.Buffer{} |
||||
err = json.NewEncoder(buf1).Encode(dtos.MetricRequest{ |
||||
From: "now-1h", |
||||
To: "now", |
||||
Queries: []*simplejson.Json{query}, |
||||
}) |
||||
require.NoError(t, err) |
||||
u := fmt.Sprintf("http://admin:admin@%s/api/ds/query", grafanaListeningAddr) |
||||
// nolint:gosec
|
||||
resp, err := http.Post(u, "application/json", buf1) |
||||
require.NoError(t, err) |
||||
require.Equal(t, http.StatusInternalServerError, resp.StatusCode) |
||||
t.Cleanup(func() { |
||||
err := resp.Body.Close() |
||||
require.NoError(t, err) |
||||
}) |
||||
_, err = io.ReadAll(resp.Body) |
||||
require.NoError(t, err) |
||||
|
||||
require.NotNil(t, outgoingRequest) |
||||
require.Equal(t, "/api/v1/query_range", outgoingRequest.URL.Path) |
||||
require.Contains(t, outgoingRequest.URL.String(), "&q1=1&q2=2") |
||||
require.Equal(t, "custom-header-value", outgoingRequest.Header.Get("X-CUSTOM-HEADER")) |
||||
username, pwd, ok := outgoingRequest.BasicAuth() |
||||
require.True(t, ok) |
||||
require.Equal(t, "basicAuthUser", username) |
||||
require.Equal(t, "basicAuthPassword", pwd) |
||||
}) |
||||
|
||||
t.Run("When calling /api/datasources/uid/{uid}/resources/api/v1/labels should set expected headers on outgoing HTTP request", func(t *testing.T) { |
||||
u := fmt.Sprintf("http://%s/api/datasources/uid/%s/resources/api/v1/labels", grafanaListeningAddr, uid) |
||||
// nolint:gosec
|
||||
resp, err := http.Post(u, "application/json", nil) |
||||
require.NoError(t, err) |
||||
require.Equal(t, http.StatusUnauthorized, resp.StatusCode) |
||||
t.Cleanup(func() { |
||||
err := resp.Body.Close() |
||||
require.NoError(t, err) |
||||
}) |
||||
_, err = io.ReadAll(resp.Body) |
||||
require.NoError(t, err) |
||||
|
||||
require.NotNil(t, outgoingRequest) |
||||
require.Equal(t, "/api/v1/labels?q1=1&q2=2", outgoingRequest.URL.String()) |
||||
require.Equal(t, "custom-header-value", outgoingRequest.Header.Get("X-CUSTOM-HEADER")) |
||||
username, pwd, ok := outgoingRequest.BasicAuth() |
||||
require.True(t, ok) |
||||
require.Equal(t, "basicAuthUser", username) |
||||
require.Equal(t, "basicAuthPassword", pwd) |
||||
}) |
||||
} |
||||
|
||||
func createUser(t *testing.T, store *sqlstore.SQLStore, cmd user.CreateUserCommand) int64 { |
||||
t.Helper() |
||||
|
||||
store.Cfg.AutoAssignOrg = true |
||||
store.Cfg.AutoAssignOrgId = 1 |
||||
|
||||
u, err := store.CreateUser(context.Background(), cmd) |
||||
require.NoError(t, err) |
||||
return u.ID |
||||
} |
Loading…
Reference in new issue