Access Control: refactor permission evaluator to be more flexible (#35996)

* add a more flexible way to create permissions

* update interface for accesscontrol to use new eval interface

* use new eval interface

* update middleware to use new eval interface

* remove evaluator function and move metrics to service

* add tests for accesscontrol middleware

* Remove failed function from interface and update inejct to create a new
evaluator

* Change name

* Support Several sopes for a permission


* use evaluator and update fakeAccessControl

* Implement String that will return string representation of permissions
for an evaluator

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>

Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
This commit is contained in:
Karl Persson
2021-08-24 11:36:28 +02:00
committed by GitHub
co-authored by Gabriel MABILLE Emil Tullstedt
parent 9d8f61c738
commit 7ebf4027a7
15 changed files with 869 additions and 349 deletions
@@ -8,7 +8,6 @@ import (
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/evaluator"
"github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus"
)
@@ -55,9 +54,17 @@ func (ac *OSSAccessControlService) getUsageMetrics() interface{} {
return 1
}
// Evaluate evaluates access to the given resource
func (ac *OSSAccessControlService) Evaluate(ctx context.Context, user *models.SignedInUser, permission string, scope ...string) (bool, error) {
return evaluator.Evaluate(ctx, ac, user, permission, scope...)
// Evaluate evaluates access to the given resources
func (ac *OSSAccessControlService) Evaluate(ctx context.Context, user *models.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
timer := prometheus.NewTimer(metrics.MAccessEvaluationsSummary)
defer timer.ObserveDuration()
metrics.MAccessEvaluationCount.Inc()
permissions, err := ac.GetUserPermissions(ctx, user)
if err != nil {
return false, err
}
return evaluator.Evaluate(accesscontrol.GroupScopesByAction(permissions))
}
// GetUserPermissions returns user permissions based on built-in roles
@@ -94,8 +94,7 @@ type userTestCase struct {
}
type endpointTestCase struct {
permission string
scope []string
evaluator accesscontrol.Evaluator
}
func TestEvaluatingPermissions(t *testing.T) {
@@ -108,8 +107,8 @@ func TestEvaluatingPermissions(t *testing.T) {
isGrafanaAdmin: false,
},
endpoints: []endpointTestCase{
{permission: accesscontrol.ActionUsersDisable, scope: []string{accesscontrol.ScopeGlobalUsersAll}},
{permission: accesscontrol.ActionUsersEnable, scope: []string{accesscontrol.ScopeGlobalUsersAll}},
{evaluator: accesscontrol.EvalPermission(accesscontrol.ActionUsersDisable, accesscontrol.ScopeGlobalUsersAll)},
{evaluator: accesscontrol.EvalPermission(accesscontrol.ActionUsersEnable, accesscontrol.ScopeGlobalUsersAll)},
},
evalResult: true,
},
@@ -121,7 +120,7 @@ func TestEvaluatingPermissions(t *testing.T) {
isGrafanaAdmin: false,
},
endpoints: []endpointTestCase{
{permission: accesscontrol.ActionUsersCreate, scope: []string{accesscontrol.ScopeGlobalUsersAll}},
{evaluator: accesscontrol.EvalPermission(accesscontrol.ActionUsersCreate, accesscontrol.ScopeGlobalUsersAll)},
},
evalResult: false,
},
@@ -140,7 +139,7 @@ func TestEvaluatingPermissions(t *testing.T) {
}
for _, endpoint := range tc.endpoints {
result, err := ac.Evaluate(context.Background(), user, endpoint.permission, endpoint.scope...)
result, err := ac.Evaluate(context.Background(), user, endpoint.evaluator)
require.NoError(t, err)
assert.Equal(t, tc.evalResult, result)
}