mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: update rule test endpoints to respect data source permissions (#47169)
* make eval.Evaluator an interface * inject Evaluator to TestingApiSrv * move conditionEval to RouteTestGrafanaRuleConfig because it is the only place where it is used * update rule test api to check data source permissions
This commit is contained in:
@@ -8,32 +8,65 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/expr"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
type TestingApiSrv struct {
|
||||
*AlertingProxy
|
||||
Cfg *setting.Cfg
|
||||
ExpressionService *expr.Service
|
||||
DatasourceCache datasources.CacheService
|
||||
log log.Logger
|
||||
secretsService secrets.Service
|
||||
accessControl accesscontrol.AccessControl
|
||||
evaluator eval.Evaluator
|
||||
}
|
||||
|
||||
func (srv TestingApiSrv) RouteTestGrafanaRuleConfig(c *models.ReqContext, body apimodels.TestRulePayload) response.Response {
|
||||
if body.Type() != apimodels.GrafanaBackend || body.GrafanaManagedCondition == nil {
|
||||
return ErrResp(http.StatusBadRequest, errors.New("unexpected payload"), "")
|
||||
}
|
||||
return conditionEval(c, *body.GrafanaManagedCondition, srv.DatasourceCache, srv.ExpressionService, srv.secretsService, srv.Cfg, srv.log)
|
||||
|
||||
if !authorizeDatasourceAccessForRule(&ngmodels.AlertRule{Data: body.GrafanaManagedCondition.Data}, func(evaluator accesscontrol.Evaluator) bool {
|
||||
return accesscontrol.HasAccess(srv.accessControl, c)(accesscontrol.ReqSignedIn, evaluator)
|
||||
}) {
|
||||
return ErrResp(http.StatusUnauthorized, fmt.Errorf("%w to query one or many data sources used by the rule", ErrAuthorization), "")
|
||||
}
|
||||
|
||||
evalCond := ngmodels.Condition{
|
||||
Condition: body.GrafanaManagedCondition.Condition,
|
||||
OrgID: c.SignedInUser.OrgId,
|
||||
Data: body.GrafanaManagedCondition.Data,
|
||||
}
|
||||
|
||||
if err := validateCondition(c.Req.Context(), evalCond, c.SignedInUser, c.SkipCache, srv.DatasourceCache); err != nil {
|
||||
return ErrResp(http.StatusBadRequest, err, "invalid condition")
|
||||
}
|
||||
|
||||
now := body.GrafanaManagedCondition.Now
|
||||
if now.IsZero() {
|
||||
now = timeNow()
|
||||
}
|
||||
|
||||
evalResults, err := srv.evaluator.ConditionEval(&evalCond, now, srv.ExpressionService)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusBadRequest, err, "Failed to evaluate conditions")
|
||||
}
|
||||
|
||||
frame := evalResults.AsDataFrame()
|
||||
return response.JSONStreaming(http.StatusOK, util.DynMap{
|
||||
"instances": []*data.Frame{&frame},
|
||||
})
|
||||
}
|
||||
|
||||
func (srv TestingApiSrv) RouteTestRuleConfig(c *models.ReqContext, body apimodels.TestRulePayload) response.Response {
|
||||
@@ -84,12 +117,17 @@ func (srv TestingApiSrv) RouteEvalQueries(c *models.ReqContext, cmd apimodels.Ev
|
||||
now = timeNow()
|
||||
}
|
||||
|
||||
if !authorizeDatasourceAccessForRule(&ngmodels.AlertRule{Data: cmd.Data}, func(evaluator accesscontrol.Evaluator) bool {
|
||||
return accesscontrol.HasAccess(srv.accessControl, c)(accesscontrol.ReqSignedIn, evaluator)
|
||||
}) {
|
||||
return ErrResp(http.StatusUnauthorized, fmt.Errorf("%w to query one or many data sources used by the rule", ErrAuthorization), "")
|
||||
}
|
||||
|
||||
if _, err := validateQueriesAndExpressions(c.Req.Context(), cmd.Data, c.SignedInUser, c.SkipCache, srv.DatasourceCache); err != nil {
|
||||
return ErrResp(http.StatusBadRequest, err, "invalid queries or expressions")
|
||||
}
|
||||
|
||||
evaluator := eval.NewEvaluator(srv.Cfg, srv.log, srv.DatasourceCache, srv.secretsService)
|
||||
evalResults, err := evaluator.QueriesAndExpressionsEval(c.SignedInUser.OrgId, cmd.Data, now, srv.ExpressionService)
|
||||
evalResults, err := srv.evaluator.QueriesAndExpressionsEval(c.SignedInUser.OrgId, cmd.Data, now, srv.ExpressionService)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusBadRequest, err, "Failed to evaluate queries and expressions")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user