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:
co-authored by
Gabriel MABILLE
Emil Tullstedt
parent
9d8f61c738
commit
7ebf4027a7
@@ -8,13 +8,13 @@ import (
|
||||
)
|
||||
|
||||
type AccessControl interface {
|
||||
// Evaluate evaluates access to the given resource.
|
||||
Evaluate(ctx context.Context, user *models.SignedInUser, permission string, scope ...string) (bool, error)
|
||||
// Evaluate evaluates access to the given resources.
|
||||
Evaluate(ctx context.Context, user *models.SignedInUser, evaluator Evaluator) (bool, error)
|
||||
|
||||
// GetUserPermissions returns user permissions.
|
||||
GetUserPermissions(ctx context.Context, user *models.SignedInUser) ([]*Permission, error)
|
||||
|
||||
// Middleware checks if service disabled or not to switch to fallback authorization.
|
||||
//IsDisabled returns if access control is enabled or not
|
||||
IsDisabled() bool
|
||||
|
||||
// DeclareFixedRoles allow the caller to declare, to the service, fixed roles and their
|
||||
@@ -22,13 +22,13 @@ type AccessControl interface {
|
||||
DeclareFixedRoles(...RoleRegistration) error
|
||||
}
|
||||
|
||||
func HasAccess(ac AccessControl, c *models.ReqContext) func(fallback func(*models.ReqContext) bool, permission string, scopes ...string) bool {
|
||||
return func(fallback func(*models.ReqContext) bool, permission string, scopes ...string) bool {
|
||||
func HasAccess(ac AccessControl, c *models.ReqContext) func(fallback func(*models.ReqContext) bool, evaluator Evaluator) bool {
|
||||
return func(fallback func(*models.ReqContext) bool, evaluator Evaluator) bool {
|
||||
if ac.IsDisabled() {
|
||||
return fallback(c)
|
||||
}
|
||||
|
||||
hasAccess, err := ac.Evaluate(c.Req.Context(), c.SignedInUser, permission, scopes...)
|
||||
hasAccess, err := ac.Evaluate(c.Req.Context(), c.SignedInUser, evaluator)
|
||||
if err != nil {
|
||||
c.Logger.Error("Error from access control system", "error", err)
|
||||
return false
|
||||
@@ -55,6 +55,19 @@ func BuildPermissionsMap(permissions []*Permission) map[string]bool {
|
||||
return permissionsMap
|
||||
}
|
||||
|
||||
// GroupScopesByAction will group scopes on action
|
||||
func GroupScopesByAction(permissions []*Permission) map[string]map[string]struct{} {
|
||||
m := make(map[string]map[string]struct{})
|
||||
for _, p := range permissions {
|
||||
if _, ok := m[p.Action]; ok {
|
||||
m[p.Action][p.Scope] = struct{}{}
|
||||
} else {
|
||||
m[p.Action] = map[string]struct{}{p.Scope: {}}
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func ValidateScope(scope string) bool {
|
||||
prefix, last := scope[:len(scope)-1], scope[len(scope)-1]
|
||||
// verify that last char is either ':' or '/' if last character of scope is '*'
|
||||
|
||||
Reference in New Issue
Block a user