Access Control: Refactor scope resolvers with support to resolve into several scopes (#48202)

* Refactor Scope resolver to support resolving into several scopes

* Change permission evaluator to match at least one of passed scopes
This commit is contained in:
Karl Persson
2022-05-02 09:29:30 +02:00
committed by GitHub
parent 9622e7457e
commit de50f39c12
18 changed files with 453 additions and 434 deletions
+19 -33
View File
@@ -14,7 +14,7 @@ type Evaluator interface {
// Evaluate permissions that are grouped by action
Evaluate(permissions map[string][]string) (bool, error)
// MutateScopes executes a sequence of ScopeModifier functions on all embedded scopes of an evaluator and returns a new Evaluator
MutateScopes(context.Context, ...ScopeMutator) (Evaluator, error)
MutateScopes(ctx context.Context, mutate ScopeAttributeMutator) (Evaluator, error)
// String returns a string representation of permission required by the evaluator
fmt.Stringer
fmt.GoStringer
@@ -22,7 +22,7 @@ type Evaluator interface {
var _ Evaluator = new(permissionEvaluator)
// EvalPermission returns an evaluator that will require all scopes in combination with action to match
// EvalPermission returns an evaluator that will require at least one of passed scopes to match
func EvalPermission(action string, scopes ...string) Evaluator {
return permissionEvaluator{Action: action, Scopes: scopes}
}
@@ -43,29 +43,19 @@ func (p permissionEvaluator) Evaluate(permissions map[string][]string) (bool, er
}
for _, target := range p.Scopes {
var err error
var matches bool
for _, scope := range userScopes {
matches, err = match(scope, target)
if err != nil {
return false, err
if match(scope, target) {
return true, nil
}
if matches {
break
}
}
if !matches {
return false, nil
}
}
return true, nil
return false, nil
}
func match(scope, target string) (bool, error) {
func match(scope, target string) bool {
if scope == "" {
return false, nil
return false
}
if !ValidateScope(scope) {
@@ -74,7 +64,7 @@ func match(scope, target string) (bool, error) {
"scope", scope,
"reason", "scopes should not contain meta-characters like * or ?, except in the last position",
)
return false, nil
return false
}
prefix, last := scope[:len(scope)-1], scope[len(scope)-1]
@@ -82,29 +72,25 @@ func match(scope, target string) (bool, error) {
if last == '*' {
if strings.HasPrefix(target, prefix) {
logger.Debug("matched scope", "user scope", scope, "target scope", target)
return true, nil
return true
}
}
return scope == target, nil
return scope == target
}
func (p permissionEvaluator) MutateScopes(ctx context.Context, modifiers ...ScopeMutator) (Evaluator, error) {
var err error
func (p permissionEvaluator) MutateScopes(ctx context.Context, mutate ScopeAttributeMutator) (Evaluator, error) {
if p.Scopes == nil {
return EvalPermission(p.Action), nil
}
scopes := make([]string, 0, len(p.Scopes))
for _, scope := range p.Scopes {
modified := scope
for _, modifier := range modifiers {
modified, err = modifier(ctx, modified)
if err != nil {
return nil, err
}
mutated, err := mutate(ctx, scope)
if err != nil {
return nil, err
}
scopes = append(scopes, modified)
scopes = append(scopes, mutated...)
}
return EvalPermission(p.Action, scopes...), nil
}
@@ -137,10 +123,10 @@ func (a allEvaluator) Evaluate(permissions map[string][]string) (bool, error) {
return true, nil
}
func (a allEvaluator) MutateScopes(ctx context.Context, modifiers ...ScopeMutator) (Evaluator, error) {
func (a allEvaluator) MutateScopes(ctx context.Context, mutate ScopeAttributeMutator) (Evaluator, error) {
var modified []Evaluator
for _, e := range a.allOf {
i, err := e.MutateScopes(ctx, modifiers...)
i, err := e.MutateScopes(ctx, mutate)
if err != nil {
return nil, err
}
@@ -191,10 +177,10 @@ func (a anyEvaluator) Evaluate(permissions map[string][]string) (bool, error) {
return false, nil
}
func (a anyEvaluator) MutateScopes(ctx context.Context, modifiers ...ScopeMutator) (Evaluator, error) {
func (a anyEvaluator) MutateScopes(ctx context.Context, mutate ScopeAttributeMutator) (Evaluator, error) {
var modified []Evaluator
for _, e := range a.anyOf {
i, err := e.MutateScopes(ctx, modifiers...)
i, err := e.MutateScopes(ctx, mutate)
if err != nil {
return nil, err
}