grafana/pkg/services/ngalert/api/api_testing_test.go

281 lines
8.4 KiB
Go
Raw Normal View History

package api
import (
"net/http"
"testing"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
models2 "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
acMock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/datasources"
Secrets: Implement basic unified secret store service (#45804) * wip: Implement kvstore for secrets * wip: Refactor kvstore for secrets * wip: Add format key function to secrets kvstore sql * wip: Add migration for secrets kvstore * Remove unused Key field from secrets kvstore * Remove secret values from debug logs * Integrate unified secrets with datasources * Fix minor issues and tests for kvstore * Create test service helper for secret store * Remove encryption tests from datasources * Move secret operations after datasources * Fix datasource proxy tests * Fix legacy data tests * Add Name to all delete data source commands * Implement decryption cache on sql secret store * Fix minor issue with cache and tests * Use secret type on secret store datasource operations * Add comments to make create and update clear * Rename itemFound variable to isFound * Improve secret deletion and cache management * Add base64 encoding to sql secret store * Move secret retrieval to decrypted values function * Refactor decrypt secure json data functions * Fix expr tests * Fix datasource tests * Fix plugin proxy tests * Fix query tests * Fix metrics api tests * Remove unused fake secrets service from query tests * Add rename function to secret store * Add check for error renaming secret * Remove bus from tests to fix merge conflicts * Add background secrets migration to datasources * Get datasource secure json fields from secrets * Move migration to secret store * Revert "Move migration to secret store" This reverts commit 7c3f872072e9aff601fb9d639127d468c03f97ef. * Add secret service to datasource service on tests * Fix datasource tests * Remove merge conflict on wire * Add ctx to data source http transport on prometheus stats collector * Add ctx to data source http transport on stats collector test
2022-04-25 11:57:45 -05:00
fakes "github.com/grafana/grafana/pkg/services/datasources/fakes"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/services/ngalert/eval"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/web"
)
func TestRouteTestGrafanaRuleConfig(t *testing.T) {
t.Run("when fine-grained access is enabled", func(t *testing.T) {
rc := &models2.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
SignedInUser: &user.SignedInUser{
OrgID: 1,
},
}
t.Run("should return 401 if user cannot query a data source", func(t *testing.T) {
data1 := models.GenerateAlertQuery()
data2 := models.GenerateAlertQuery()
ac := acMock.New().WithPermissions([]accesscontrol.Permission{
{Action: datasources.ActionQuery, Scope: datasources.ScopeProvider.GetResourceScopeUID(data1.DatasourceUID)},
})
srv := createTestingApiSrv(nil, ac, nil)
response := srv.RouteTestGrafanaRuleConfig(rc, definitions.TestRulePayload{
Expr: "",
GrafanaManagedCondition: &definitions.EvalAlertConditionCommand{
Condition: data1.RefID,
Data: []models.AlertQuery{data1, data2},
Now: time.Time{},
},
})
require.Equal(t, http.StatusUnauthorized, response.Status())
})
t.Run("should return 200 if user can query all data sources", func(t *testing.T) {
data1 := models.GenerateAlertQuery()
data2 := models.GenerateAlertQuery()
ac := acMock.New().WithPermissions([]accesscontrol.Permission{
{Action: datasources.ActionQuery, Scope: datasources.ScopeProvider.GetResourceScopeUID(data1.DatasourceUID)},
{Action: datasources.ActionQuery, Scope: datasources.ScopeProvider.GetResourceScopeUID(data2.DatasourceUID)},
})
ds := &fakes.FakeCacheService{DataSources: []*datasources.DataSource{
{Uid: data1.DatasourceUID},
{Uid: data2.DatasourceUID},
}}
evaluator := &eval.FakeEvaluator{}
var result []eval.Result
evaluator.EXPECT().ConditionEval(mock.Anything, mock.Anything).Return(result)
srv := createTestingApiSrv(ds, ac, evaluator)
response := srv.RouteTestGrafanaRuleConfig(rc, definitions.TestRulePayload{
Expr: "",
GrafanaManagedCondition: &definitions.EvalAlertConditionCommand{
Condition: data1.RefID,
Data: []models.AlertQuery{data1, data2},
Now: time.Time{},
},
})
require.Equal(t, http.StatusOK, response.Status())
evaluator.AssertCalled(t, "ConditionEval", mock.Anything, mock.Anything, mock.Anything)
})
})
t.Run("when fine-grained access is disabled", func(t *testing.T) {
rc := &models2.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
IsSignedIn: false,
SignedInUser: &user.SignedInUser{
OrgID: 1,
},
}
ac := acMock.New().WithDisabled()
t.Run("should require user to be signed in", func(t *testing.T) {
data1 := models.GenerateAlertQuery()
ds := &fakes.FakeCacheService{DataSources: []*datasources.DataSource{
{Uid: data1.DatasourceUID},
}}
evaluator := &eval.FakeEvaluator{}
var result []eval.Result
evaluator.EXPECT().ConditionEval(mock.Anything, mock.Anything).Return(result)
srv := createTestingApiSrv(ds, ac, evaluator)
response := srv.RouteTestGrafanaRuleConfig(rc, definitions.TestRulePayload{
Expr: "",
GrafanaManagedCondition: &definitions.EvalAlertConditionCommand{
Condition: data1.RefID,
Data: []models.AlertQuery{data1},
Now: time.Time{},
},
})
require.Equal(t, http.StatusUnauthorized, response.Status())
evaluator.AssertNotCalled(t, "ConditionEval", mock.Anything, mock.Anything, mock.Anything)
rc.IsSignedIn = true
response = srv.RouteTestGrafanaRuleConfig(rc, definitions.TestRulePayload{
Expr: "",
GrafanaManagedCondition: &definitions.EvalAlertConditionCommand{
Condition: data1.RefID,
Data: []models.AlertQuery{data1},
Now: time.Time{},
},
})
require.Equal(t, http.StatusOK, response.Status())
evaluator.AssertCalled(t, "ConditionEval", mock.Anything, mock.Anything, mock.Anything)
})
})
}
func TestRouteEvalQueries(t *testing.T) {
t.Run("when fine-grained access is enabled", func(t *testing.T) {
rc := &models2.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
SignedInUser: &user.SignedInUser{
OrgID: 1,
},
}
t.Run("should return 401 if user cannot query a data source", func(t *testing.T) {
data1 := models.GenerateAlertQuery()
data2 := models.GenerateAlertQuery()
ac := acMock.New().WithPermissions([]accesscontrol.Permission{
{Action: datasources.ActionQuery, Scope: datasources.ScopeProvider.GetResourceScopeUID(data1.DatasourceUID)},
})
srv := &TestingApiSrv{
accessControl: ac,
}
response := srv.RouteEvalQueries(rc, definitions.EvalQueriesPayload{
Data: []models.AlertQuery{data1, data2},
Now: time.Time{},
})
require.Equal(t, http.StatusUnauthorized, response.Status())
})
t.Run("should return 200 if user can query all data sources", func(t *testing.T) {
data1 := models.GenerateAlertQuery()
data2 := models.GenerateAlertQuery()
ac := acMock.New().WithPermissions([]accesscontrol.Permission{
{Action: datasources.ActionQuery, Scope: datasources.ScopeProvider.GetResourceScopeUID(data1.DatasourceUID)},
{Action: datasources.ActionQuery, Scope: datasources.ScopeProvider.GetResourceScopeUID(data2.DatasourceUID)},
})
ds := &fakes.FakeCacheService{DataSources: []*datasources.DataSource{
{Uid: data1.DatasourceUID},
{Uid: data2.DatasourceUID},
}}
evaluator := &eval.FakeEvaluator{}
result := &backend.QueryDataResponse{
Responses: map[string]backend.DataResponse{
"test": {
Frames: nil,
Error: nil,
},
},
}
evaluator.EXPECT().QueriesAndExpressionsEval(mock.Anything, mock.Anything, mock.Anything).Return(result, nil)
srv := createTestingApiSrv(ds, ac, evaluator)
response := srv.RouteEvalQueries(rc, definitions.EvalQueriesPayload{
Data: []models.AlertQuery{data1, data2},
Now: time.Time{},
})
require.Equal(t, http.StatusOK, response.Status())
evaluator.AssertCalled(t, "QueriesAndExpressionsEval", mock.Anything, mock.Anything, mock.Anything, mock.Anything)
})
})
t.Run("when fine-grained access is disabled", func(t *testing.T) {
rc := &models2.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
IsSignedIn: false,
SignedInUser: &user.SignedInUser{
OrgID: 1,
},
}
ac := acMock.New().WithDisabled()
t.Run("should require user to be signed in", func(t *testing.T) {
data1 := models.GenerateAlertQuery()
ds := &fakes.FakeCacheService{DataSources: []*datasources.DataSource{
{Uid: data1.DatasourceUID},
}}
evaluator := &eval.FakeEvaluator{}
result := &backend.QueryDataResponse{
Responses: map[string]backend.DataResponse{
"test": {
Frames: nil,
Error: nil,
},
},
}
evaluator.EXPECT().QueriesAndExpressionsEval(mock.Anything, mock.Anything, mock.Anything).Return(result, nil)
srv := createTestingApiSrv(ds, ac, evaluator)
response := srv.RouteEvalQueries(rc, definitions.EvalQueriesPayload{
Data: []models.AlertQuery{data1},
Now: time.Time{},
})
require.Equal(t, http.StatusUnauthorized, response.Status())
evaluator.AssertNotCalled(t, "QueriesAndExpressionsEval", mock.Anything, mock.Anything, mock.Anything, mock.Anything)
rc.IsSignedIn = true
response = srv.RouteEvalQueries(rc, definitions.EvalQueriesPayload{
Data: []models.AlertQuery{data1},
Now: time.Time{},
})
require.Equal(t, http.StatusOK, response.Status())
evaluator.AssertCalled(t, "QueriesAndExpressionsEval", mock.Anything, mock.Anything, mock.Anything, mock.Anything)
})
})
}
Secrets: Implement basic unified secret store service (#45804) * wip: Implement kvstore for secrets * wip: Refactor kvstore for secrets * wip: Add format key function to secrets kvstore sql * wip: Add migration for secrets kvstore * Remove unused Key field from secrets kvstore * Remove secret values from debug logs * Integrate unified secrets with datasources * Fix minor issues and tests for kvstore * Create test service helper for secret store * Remove encryption tests from datasources * Move secret operations after datasources * Fix datasource proxy tests * Fix legacy data tests * Add Name to all delete data source commands * Implement decryption cache on sql secret store * Fix minor issue with cache and tests * Use secret type on secret store datasource operations * Add comments to make create and update clear * Rename itemFound variable to isFound * Improve secret deletion and cache management * Add base64 encoding to sql secret store * Move secret retrieval to decrypted values function * Refactor decrypt secure json data functions * Fix expr tests * Fix datasource tests * Fix plugin proxy tests * Fix query tests * Fix metrics api tests * Remove unused fake secrets service from query tests * Add rename function to secret store * Add check for error renaming secret * Remove bus from tests to fix merge conflicts * Add background secrets migration to datasources * Get datasource secure json fields from secrets * Move migration to secret store * Revert "Move migration to secret store" This reverts commit 7c3f872072e9aff601fb9d639127d468c03f97ef. * Add secret service to datasource service on tests * Fix datasource tests * Remove merge conflict on wire * Add ctx to data source http transport on prometheus stats collector * Add ctx to data source http transport on stats collector test
2022-04-25 11:57:45 -05:00
func createTestingApiSrv(ds *fakes.FakeCacheService, ac *acMock.Mock, evaluator *eval.FakeEvaluator) *TestingApiSrv {
if ac == nil {
ac = acMock.New().WithDisabled()
}
return &TestingApiSrv{
DatasourceCache: ds,
accessControl: ac,
evaluator: evaluator,
}
}