Alerting: Fix alerting evaluation to use proper permissions (#55127)
* access control to log user name if it does not have permissions * update ngalert Evaluator to accept user instead of creating a pseudo one * update alerting eval (rule\query testing) API to provide the real user to the Evaluator * update scheduler to create a pseudo user with proper permissions
This commit is contained in:
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
|
||||
@@ -27,9 +26,9 @@ import (
|
||||
//go:generate mockery --name Evaluator --structname FakeEvaluator --inpackage --filename evaluator_mock.go --with-expecter
|
||||
type Evaluator interface {
|
||||
// ConditionEval executes conditions and evaluates the result.
|
||||
ConditionEval(ctx context.Context, condition models.Condition, now time.Time) Results
|
||||
ConditionEval(ctx context.Context, user *user.SignedInUser, condition models.Condition, now time.Time) Results
|
||||
// QueriesAndExpressionsEval executes queries and expressions and returns the result.
|
||||
QueriesAndExpressionsEval(ctx context.Context, orgID int64, data []models.AlertQuery, now time.Time) (*backend.QueryDataResponse, error)
|
||||
QueriesAndExpressionsEval(ctx context.Context, user *user.SignedInUser, data []models.AlertQuery, now time.Time) (*backend.QueryDataResponse, error)
|
||||
}
|
||||
|
||||
type evaluatorImpl struct {
|
||||
@@ -151,7 +150,7 @@ func (s State) String() string {
|
||||
|
||||
// AlertExecCtx is the context provided for executing an alert condition.
|
||||
type AlertExecCtx struct {
|
||||
OrgID int64
|
||||
User *user.SignedInUser
|
||||
ExpressionsEnabled bool
|
||||
Log log.Logger
|
||||
|
||||
@@ -161,7 +160,7 @@ type AlertExecCtx struct {
|
||||
// getExprRequest validates the condition, gets the datasource information and creates an expr.Request from it.
|
||||
func getExprRequest(ctx AlertExecCtx, data []models.AlertQuery, now time.Time, dsCacheService datasources.CacheService) (*expr.Request, error) {
|
||||
req := &expr.Request{
|
||||
OrgId: ctx.OrgID,
|
||||
OrgId: ctx.User.OrgID,
|
||||
Headers: map[string]string{
|
||||
// Some data sources check this in query method as sometimes alerting needs special considerations.
|
||||
"FromAlert": "true",
|
||||
@@ -191,10 +190,7 @@ func getExprRequest(ctx AlertExecCtx, data []models.AlertQuery, now time.Time, d
|
||||
if expr.IsDataSource(q.DatasourceUID) {
|
||||
ds = expr.DataSourceModel()
|
||||
} else {
|
||||
ds, err = dsCacheService.GetDatasourceByUID(ctx.Ctx, q.DatasourceUID, &user.SignedInUser{
|
||||
OrgID: ctx.OrgID,
|
||||
OrgRole: org.RoleAdmin, // Get DS as admin for service, API calls (test/post) must check permissions based on user.
|
||||
}, true)
|
||||
ds, err = dsCacheService.GetDatasourceByUID(ctx.Ctx, q.DatasourceUID, ctx.User, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -552,8 +548,8 @@ func (evalResults Results) AsDataFrame() data.Frame {
|
||||
}
|
||||
|
||||
// ConditionEval executes conditions and evaluates the result.
|
||||
func (e *evaluatorImpl) ConditionEval(ctx context.Context, condition models.Condition, now time.Time) Results {
|
||||
execResp, err := e.QueriesAndExpressionsEval(ctx, condition.OrgID, condition.Data, now)
|
||||
func (e *evaluatorImpl) ConditionEval(ctx context.Context, user *user.SignedInUser, condition models.Condition, now time.Time) Results {
|
||||
execResp, err := e.QueriesAndExpressionsEval(ctx, user, condition.Data, now)
|
||||
var execResults ExecutionResults
|
||||
if err != nil {
|
||||
execResults = ExecutionResults{Error: err}
|
||||
@@ -564,11 +560,11 @@ func (e *evaluatorImpl) ConditionEval(ctx context.Context, condition models.Cond
|
||||
}
|
||||
|
||||
// QueriesAndExpressionsEval executes queries and expressions and returns the result.
|
||||
func (e *evaluatorImpl) QueriesAndExpressionsEval(ctx context.Context, orgID int64, data []models.AlertQuery, now time.Time) (*backend.QueryDataResponse, error) {
|
||||
func (e *evaluatorImpl) QueriesAndExpressionsEval(ctx context.Context, user *user.SignedInUser, data []models.AlertQuery, now time.Time) (*backend.QueryDataResponse, error) {
|
||||
alertCtx, cancelFn := context.WithTimeout(ctx, e.cfg.UnifiedAlerting.EvaluationTimeout)
|
||||
defer cancelFn()
|
||||
|
||||
alertExecCtx := AlertExecCtx{OrgID: orgID, Ctx: alertCtx, ExpressionsEnabled: e.cfg.ExpressionsEnabled, Log: e.log}
|
||||
alertExecCtx := AlertExecCtx{User: user, Ctx: alertCtx, ExpressionsEnabled: e.cfg.ExpressionsEnabled, Log: e.log}
|
||||
|
||||
execResult, err := executeQueriesAndExpressions(alertExecCtx, data, now, e.expressionService, e.dataSourceCache)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user