Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: add eval to function map #1005

Merged
merged 1 commit into from May 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
60 changes: 31 additions & 29 deletions enforcer.go
Expand Up @@ -517,16 +517,6 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac
expString = util.RemoveComments(util.EscapeAssertion(matcher))
}

var expression *govaluate.EvaluableExpression
hasEval := util.HasEval(expString)

if !hasEval {
expression, err = govaluate.NewEvaluableExpressionWithFunctions(expString, functions)
if err != nil {
return false, err
}
}

rTokens := make(map[string]int, len(e.model["r"][rType].Tokens))
for i, token := range e.model["r"][rType].Tokens {
rTokens[token] = i
Expand All @@ -543,6 +533,18 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac
pTokens: pTokens,
}

var expression *govaluate.EvaluableExpression
hasEval := util.HasEval(expString)

if hasEval {
functions["eval"] = generateEvalFunction(functions, &parameters)
}

expression, err = govaluate.NewEvaluableExpressionWithFunctions(expString, functions)
if err != nil {
return false, err
}

if len(e.model["r"][rType].Tokens) != len(rvals) {
return false, fmt.Errorf(
"invalid request size: expected %d, got %d, rvals: %v",
Expand Down Expand Up @@ -573,25 +575,6 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac

parameters.pVals = pvals

if hasEval {
ruleNames := util.GetEvalValue(expString)
replacements := make(map[string]string)
for _, ruleName := range ruleNames {
if j, ok := parameters.pTokens[ruleName]; ok {
rule := util.EscapeAssertion(pvals[j])
// Increase the evaluate priority of the rule
replacements[ruleName] = "(" + rule + ")"
} else {
return false, errors.New("please make sure rule exists in policy when using eval() in matcher")
}
}
expWithRule := util.ReplaceEvalWithMap(expString, replacements)
expression, err = govaluate.NewEvaluableExpressionWithFunctions(expWithRule, functions)
if err != nil {
return false, fmt.Errorf("p.sub_rule should satisfy the syntax of matcher: %s", err)
}
}

result, err := expression.Eval(parameters)
// log.LogPrint("Result: ", result)

Expand Down Expand Up @@ -792,3 +775,22 @@ func (p enforceParameters) Get(name string) (interface{}, error) {
return nil, errors.New("No parameter '" + name + "' found.")
}
}

func generateEvalFunction(functions map[string]govaluate.ExpressionFunction, parameters *enforceParameters) govaluate.ExpressionFunction {
return func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, fmt.Errorf("Function eval(subrule string) expected %d arguments, but got %d", 1, len(args))
}

expression, ok := args[0].(string)
if !ok {
return nil, errors.New("Argument of eval(subrule string) must be a string")
}
expression = util.EscapeAssertion(expression)
expr, err := govaluate.NewEvaluableExpressionWithFunctions(expression, functions)
if err != nil {
return nil, fmt.Errorf("Error while parsing eval parameter: %s, %s", expression, err.Error())
}
return expr.Eval(parameters)
}
}
14 changes: 14 additions & 0 deletions model_b_test.go
Expand Up @@ -239,6 +239,20 @@ func BenchmarkABACModel(b *testing.B) {
}
}

func BenchmarkABACRuleModel(b *testing.B) {
e, _ := NewEnforcer("examples/abac_rule_model.conf", false)
sub := newTestSubject("alice", 18)

for i := 0; i < 1000; i++ {
_, _ = e.AddPolicy("r.sub.Age > 20", fmt.Sprintf("data%d", i), "read")
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = e.Enforce(sub, "data100", "read")
}
}

func BenchmarkKeyMatchModel(b *testing.B) {
e, _ := NewEnforcer("examples/keymatch_model.conf", "examples/keymatch_policy.csv", false)

Expand Down