AccessControl: Resolve attribute based scopes to id based scopes (#40742)

* AccessControl: POC scope attribute resolution

Refactor based on ScopeMutators

test errors and calls to cache

Add comments to tests

Rename logger

Create keywordMutator only once

* AccessControl: Add AttributeScopeResolver registration

Co-authored-by: gamab <gabriel.mabille@grafana.com>

* AccessControl: Add AttributeScopeResolver to datasources

Co-authored-by: gamab <gabriel.mabille@grafana.com>

* Test evaluation with translation

* fix imports

* AccessControl: Test attribute resolver

* Fix trailing white space

* Make ScopeResolver public for enterprise redefine

* Handle wildcard

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

Co-authored-by: jguer <joao.guerreiro@grafana.com>
This commit is contained in:
Gabriel MABILLE
2022-01-18 17:34:35 +01:00
committed by GitHub
co-authored by gamab Jguer
parent 7a622422a9
commit 54280fc9d7
14 changed files with 548 additions and 110 deletions
@@ -18,7 +18,7 @@ func ProvideService(cfg *setting.Cfg, usageStats usagestats.Service) *OSSAccessC
Cfg: cfg,
UsageStats: usageStats,
Log: log.New("accesscontrol"),
scopeResolver: accesscontrol.NewScopeResolver(),
ScopeResolver: accesscontrol.NewScopeResolver(),
}
s.registerUsageMetrics()
return s
@@ -30,7 +30,7 @@ type OSSAccessControlService struct {
UsageStats usagestats.Service
Log log.Logger
registrations accesscontrol.RegistrationList
scopeResolver accesscontrol.ScopeResolver
ScopeResolver accesscontrol.ScopeResolver
}
func (ac *OSSAccessControlService) IsDisabled() bool {
@@ -74,7 +74,12 @@ func (ac *OSSAccessControlService) Evaluate(ctx context.Context, user *models.Si
user.Permissions[user.OrgId] = accesscontrol.GroupScopesByAction(permissions)
}
return evaluator.Evaluate(user.Permissions[user.OrgId])
attributeMutator := ac.ScopeResolver.GetResolveAttributeScopeMutator(user.OrgId)
resolvedEvaluator, err := evaluator.MutateScopes(ctx, attributeMutator)
if err != nil {
return false, err
}
return resolvedEvaluator.Evaluate(user.Permissions[user.OrgId])
}
// GetUserRoles returns user permissions based on built-in roles
@@ -87,6 +92,9 @@ func (ac *OSSAccessControlService) GetUserPermissions(ctx context.Context, user
timer := prometheus.NewTimer(metrics.MAccessPermissionsSummary)
defer timer.ObserveDuration()
var err error
keywordMutator := ac.ScopeResolver.GetResolveKeywordScopeMutator(user)
builtinRoles := ac.GetUserBuiltInRoles(user)
permissions := make([]*accesscontrol.Permission, 0)
for _, builtin := range builtinRoles {
@@ -96,13 +104,14 @@ func (ac *OSSAccessControlService) GetUserPermissions(ctx context.Context, user
if !exists {
continue
}
for _, p := range role.Permissions {
for i := range role.Permissions {
// if the permission has a keyword in its scope it will be resolved
permission, err := ac.scopeResolver.ResolveKeyword(user, p)
p := (role.Permissions[i])
p.Scope, err = keywordMutator(ctx, p.Scope)
if err != nil {
return nil, err
}
permissions = append(permissions, permission)
permissions = append(permissions, &p)
}
}
}
@@ -201,3 +210,9 @@ func (ac *OSSAccessControlService) DeclareFixedRoles(registrations ...accesscont
return nil
}
// RegisterAttributeScopeResolver allows the caller to register scope resolvers for a
// specific scope prefix (ex: datasources:name:)
func (ac *OSSAccessControlService) RegisterAttributeScopeResolver(scopePrefix string, resolver accesscontrol.AttributeScopeResolveFunc) {
ac.ScopeResolver.AddAttributeResolver(scopePrefix, resolver)
}