Skip to content

Commit

Permalink
fix: multiple eval() in matcher
Browse files Browse the repository at this point in the history
Signed-off-by: Zixuan Liu <nodeces@gmail.com>
  • Loading branch information
nodece committed Oct 12, 2020
1 parent d0d65d8 commit 6791033
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 8 deletions.
15 changes: 7 additions & 8 deletions enforcer.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,21 +441,20 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac

if hasEval {
ruleNames := util.GetEvalValue(expString)
var expWithRule = expString
replacements := make(map[string]string)
for _, ruleName := range ruleNames {
if j, ok := parameters.pTokens[ruleName]; ok {
rule := util.EscapeAssertion(pvals[j])
expWithRule = util.ReplaceEval(expWithRule, rule)
replacements[ruleName] = rule
} else {
return false, errors.New("please make sure rule exists in policy when using eval() in matcher")
}

expression, err = govaluate.NewEvaluableExpressionWithFunctions(expWithRule, functions)
if err != nil {
return false, fmt.Errorf("p.sub_rule should satisfy the syntax of matcher: %s", err)
}
}

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)
Expand Down
16 changes: 16 additions & 0 deletions util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,22 @@ func ReplaceEval(s string, rule string) string {
return evalReg.ReplaceAllString(s, "("+rule+")")
}

// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
func ReplaceEvalWithMap(src string, sets map[string]string) string {
return evalReg.ReplaceAllStringFunc(src, func(s string) string {
subs := evalReg.FindStringSubmatch(s)
if subs == nil {
return s
}
key := subs[1]
value, found := sets[key]
if !found {
return s
}
return evalReg.ReplaceAllString(s, value)
})
}

// GetEvalValue returns the parameters of function eval
func GetEvalValue(s string) []string {
subMatch := evalReg.FindAllStringSubmatch(s, -1)
Expand Down
24 changes: 24 additions & 0 deletions util/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,27 @@ func TestGetEvalValue(t *testing.T) {
testGetEvalValue(t, "eval(a) && eval(b) && a && b && c", []string{"a", "b"})
testGetEvalValue(t, "a && eval(a) && eval(b) && b && c", []string{"a", "b"})
}

func testReplaceEvalWithMap(t *testing.T, s string, sets map[string]string, res string) {
t.Helper()
myRes := ReplaceEvalWithMap(s, sets)

if myRes != res {
t.Errorf("%s: %s supposed to be %s", s, myRes, res)
}
}

func TestReplaceEvalWithMap(t *testing.T) {
testReplaceEvalWithMap(t, "eval(rule1)", map[string]string{"rule1": "a == b"}, "a == b")
testReplaceEvalWithMap(t, "eval(rule1) && c && d", map[string]string{"rule1": "a == b"}, "a == b && c && d")
testReplaceEvalWithMap(t, "eval(rule1)", nil, "eval(rule1)")
testReplaceEvalWithMap(t, "eval(rule1) && c && d", nil, "eval(rule1) && c && d")
testReplaceEvalWithMap(t, "eval(rule1) || eval(rule2)", map[string]string{"rule1": "a == b", "rule2": "a == c"}, "a == b || a == c")
testReplaceEvalWithMap(t, "eval(rule1) || eval(rule2) && c && d", map[string]string{"rule1": "a == b", "rule2": "a == c"}, "a == b || a == c && c && d")
testReplaceEvalWithMap(t, "eval(rule1) || eval(rule2)", map[string]string{"rule1": "a == b"}, "a == b || eval(rule2)")
testReplaceEvalWithMap(t, "eval(rule1) || eval(rule2) && c && d", map[string]string{"rule1": "a == b"}, "a == b || eval(rule2) && c && d")
testReplaceEvalWithMap(t, "eval(rule1) || eval(rule2)", map[string]string{"rule2": "a == b"}, "eval(rule1) || a == b")
testReplaceEvalWithMap(t, "eval(rule1) || eval(rule2) && c && d", map[string]string{"rule2": "a == b"}, "eval(rule1) || a == b && c && d")
testReplaceEvalWithMap(t, "eval(rule1) || eval(rule2)", nil, "eval(rule1) || eval(rule2)")
testReplaceEvalWithMap(t, "eval(rule1) || eval(rule2) && c && d", nil, "eval(rule1) || eval(rule2) && c && d")
}

0 comments on commit 6791033

Please sign in to comment.