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

rego: Fix constraints evaluation type and prettify result #863

Merged
merged 1 commit into from
Sep 6, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/engine/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
)

// ErrEvaluationFailed is an error that occurs during evaluation of a rule.
var ErrEvaluationFailed = errors.New("evaluation error")
var ErrEvaluationFailed = errors.New("evaluation failure")

// NewErrEvaluationFailed creates a new evaluation error
func NewErrEvaluationFailed(sfmt string, args ...any) error {
Expand Down
36 changes: 36 additions & 0 deletions internal/engine/eval/rego/rego_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,42 @@ violations[{"msg": msg}] {
require.ErrorContains(t, err, "data did not contain foo", "should have failed the evaluation")
}

func TestEvaluatorDenyByConstraintsEvalMultiple(t *testing.T) {
t.Parallel()

e, err := rego.NewRegoEvaluator(
&pb.RuleType_Definition_Eval_Rego{
Type: rego.ConstraintsEvaluationType.String(),
Def: `
package mediator

violations[{"msg": msg}] {
input.ingested.data == "foo"
msg := "data should not contain foo"
}

violations[{"msg": msg}] {
input.ingested.datum == "bar"
msg := "datum should not contain bar"
}
`,
},
)
require.NoError(t, err, "could not create evaluator")

emptyPol := map[string]any{}

err = e.Eval(context.Background(), emptyPol, &engif.Result{
Object: map[string]any{
"data": "foo",
"datum": "bar",
},
})
require.ErrorIs(t, err, engerrors.ErrEvaluationFailed, "should have failed the evaluation")
require.ErrorContains(t, err, "- evaluation failure: data should not contain foo\n")
require.ErrorContains(t, err, "- evaluation failure: datum should not contain bar")
}

// Evaluates a simple query against a simple policy
// In this case, the policy is a simple "allow" rule.
// The given policy map has a value for the "data" key
Expand Down
9 changes: 5 additions & 4 deletions internal/engine/eval/rego/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package rego
import (
"errors"
"fmt"
"strings"

"github.com/open-policy-agent/opa/rego"

Expand Down Expand Up @@ -82,17 +83,17 @@ func (*constraintsEvaluator) parseResult(rs rego.ResultSet) error {
}

// Gather violations into one
violations := make([]error, len(rs))
violations := make([]string, 0, len(rs))
for _, r := range rs {
v := resultToViolation(r)
if errors.Is(v, engerrors.ErrEvaluationFailed) {
violations = append(violations, v)
violations = append(violations, v.Error())
} else {
return fmt.Errorf("unexpected error in rego violation: %w", v)
}
}

return engerrors.NewErrEvaluationFailed("Evaluation failed: %s", violations)
return engerrors.NewErrEvaluationFailed("Evaluation failures: \n - %s", strings.Join(violations, "\n - "))
}

func resultToViolation(r rego.Result) error {
Expand All @@ -116,5 +117,5 @@ func resultToViolation(r rego.Result) error {
return fmt.Errorf("msg is not a string")
}

return engerrors.NewErrEvaluationFailed("Evaluation failed: %s", msgstr)
return engerrors.NewErrEvaluationFailed(msgstr)
}