Skip to content

Commit c3001cf

Browse files
committed
fix tests
Signed-off-by: Sylwester Piskozub <sylwesterpiskozub@gmail.com>
1 parent 4c7a319 commit c3001cf

1 file changed

Lines changed: 51 additions & 66 deletions

File tree

pkg/policies/engine/rego/rego.go

Lines changed: 51 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"context"
2121
"encoding/json"
2222
"fmt"
23-
"strings"
2423

2524
"github.com/chainloop-dev/chainloop/pkg/policies/engine"
2625
"github.com/open-policy-agent/opa/ast"
@@ -92,8 +91,8 @@ const (
9291
EnvironmentModePermissive EnvironmentMode = 1
9392
inputArgs = "args"
9493
inputElements = "elements"
95-
deprecatedRule = "violations"
96-
mainRule = "result"
94+
deprecatedRule = ".violations"
95+
mainRule = ".result"
9796
)
9897

9998
// builtinFuncNotAllowed is a list of builtin functions that are not allowed in the compiler
@@ -113,12 +112,6 @@ func (r *Engine) Verify(ctx context.Context, policy *engine.Policy, input []byte
113112
return nil, fmt.Errorf("failed to parse rego policy: %w", err)
114113
}
115114

116-
// Extract package name
117-
pkgPath := parsedModule.Package.Path.String()
118-
if pkgPath == "" {
119-
return nil, fmt.Errorf("policy has no package declaration")
120-
}
121-
122115
// Decode input as json
123116
decoder := json.NewDecoder(bytes.NewReader(input))
124117
decoder.UseNumber()
@@ -134,7 +127,7 @@ func (r *Engine) Verify(ctx context.Context, policy *engine.Policy, input []byte
134127
decodedInput = inputMap
135128
}
136129

137-
// put arguments embedded in the input
130+
// put arguments embedded in the input object
138131
if args != nil {
139132
inputMap, ok := decodedInput.(map[string]interface{})
140133
if !ok {
@@ -144,72 +137,59 @@ func (r *Engine) Verify(ctx context.Context, policy *engine.Policy, input []byte
144137
decodedInput = inputMap
145138
}
146139

147-
// Prepare rego options
148-
options := []func(*rego.Rego){
149-
rego.ParsedModule(parsedModule),
150-
rego.Input(decodedInput),
151-
rego.Capabilities(r.Capabilities()),
152-
}
140+
// add input
141+
regoInput := rego.Input(decodedInput)
142+
143+
// add module
144+
regoFunc := rego.ParsedModule(parsedModule)
153145

154-
if r.operatingMode == EnvironmentModeRestrictive {
155-
options = append(options, rego.StrictBuiltinErrors(true))
146+
var res rego.ResultSet
147+
// Function to execute the query with appropriate parameters
148+
executeQuery := func(rule string, strict bool) error {
149+
if strict {
150+
res, err = queryRego(ctx, rule, parsedModule, regoInput, regoFunc, rego.Capabilities(r.Capabilities()), rego.StrictBuiltinErrors(true))
151+
} else {
152+
res, err = queryRego(ctx, rule, parsedModule, regoInput, regoFunc, rego.Capabilities(r.Capabilities()))
153+
}
154+
return err
156155
}
157156

158-
// First try evaluating the entire package
159-
res, err := r.evaluatePackage(ctx, pkgPath, options)
160-
if err != nil {
157+
// Get raw results first
158+
if err := executeQuery("", r.operatingMode == EnvironmentModeRestrictive); err != nil {
161159
return nil, err
162160
}
163161

164-
// If we got results, parse them
165-
if res != nil {
166-
return parseResultRule(res, policy, decodedInput)
162+
rawData := &engine.RawData{
163+
Input: decodedInput,
164+
Output: regoResultSetToRawResults(res),
167165
}
168166

169-
// Fallback to evaluating specific rules if package evaluation returned nothing
170-
return r.evaluateSpecificRules(ctx, parsedModule, options, policy, decodedInput)
171-
}
172-
173-
// Evaluate the entire package by querying data.<package>
174-
func (r *Engine) evaluatePackage(ctx context.Context, pkgPath string, options []func(*rego.Rego)) (rego.ResultSet, error) {
175-
query := fmt.Sprintf("data.%s", strings.TrimPrefix(pkgPath, "data."))
176-
regoEval := rego.New(append(options, rego.Query(query))...)
177-
return regoEval.Eval(ctx)
178-
}
179-
180-
func (r *Engine) evaluateSpecificRules(ctx context.Context, module *ast.Module, options []func(*rego.Rego), policy *engine.Policy, decodedInput interface{}) (*engine.EvaluationResult, error) {
181-
// Try the result rule first
182-
res, err := queryRego(ctx, mainRule, module, options...)
183-
if err != nil {
167+
// Try the main rule first
168+
if err := executeQuery(mainRule, r.operatingMode == EnvironmentModeRestrictive); err != nil {
184169
return nil, err
185170
}
186171

187-
if res != nil {
188-
return parseResultRule(res, policy, decodedInput)
189-
}
172+
// If res is nil, it means that the rule hasn't been found
173+
// TODO: Remove when this deprecated rule is not used anymore
174+
if res == nil {
175+
// Try with the deprecated main rule
176+
if err := executeQuery(deprecatedRule, r.operatingMode == EnvironmentModeRestrictive); err != nil {
177+
return nil, err
178+
}
190179

191-
// Fallback to deprecated violations rule
192-
res, err = queryRego(ctx, deprecatedRule, module, options...)
193-
if err != nil {
194-
return nil, err
195-
}
180+
if res == nil {
181+
return nil, fmt.Errorf("failed to evaluate policy: neither '%s' nor '%s' rule found", mainRule, deprecatedRule)
182+
}
196183

197-
if res != nil {
198-
return parseViolationsRule(res, policy, decodedInput)
184+
return parseViolationsRule(res, policy, rawData)
199185
}
200186

201-
return nil, fmt.Errorf("failed to evaluate policy: no results from package or rule evaluation")
202-
}
203-
204-
func queryRego(ctx context.Context, ruleName string, module *ast.Module, options ...func(*rego.Rego)) (rego.ResultSet, error) {
205-
query := fmt.Sprintf("data.%s.%s", strings.TrimPrefix(module.Package.Path.String(), "data."), ruleName)
206-
regoEval := rego.New(append(options, rego.Query(query))...)
207-
return regoEval.Eval(ctx)
187+
return parseResultRule(res, policy, rawData)
208188
}
209189

210190
// Parse deprecated list of violations.
211191
// TODO: Remove this path once `result` rule is consolidated
212-
func parseViolationsRule(res rego.ResultSet, policy *engine.Policy, decodedInput interface{}) (*engine.EvaluationResult, error) {
192+
func parseViolationsRule(res rego.ResultSet, policy *engine.Policy, rawData *engine.RawData) (*engine.EvaluationResult, error) {
213193
violations := make([]*engine.PolicyViolation, 0)
214194
for _, exp := range res {
215195
for _, val := range exp.Expressions {
@@ -237,20 +217,14 @@ func parseViolationsRule(res rego.ResultSet, policy *engine.Policy, decodedInput
237217
Skipped: false, // best effort
238218
SkipReason: "",
239219
Ignore: false, // Assume old rules should not be ignored
240-
RawData: &engine.RawData{
241-
Input: decodedInput,
242-
Output: regoResultSetToRawResults(res),
243-
},
220+
RawData: rawData,
244221
}, nil
245222
}
246223

247224
// parse `result` rule
248-
func parseResultRule(res rego.ResultSet, policy *engine.Policy, decodedInput interface{}) (*engine.EvaluationResult, error) {
225+
func parseResultRule(res rego.ResultSet, policy *engine.Policy, rawData *engine.RawData) (*engine.EvaluationResult, error) {
249226
result := &engine.EvaluationResult{Violations: make([]*engine.PolicyViolation, 0)}
250-
result.RawData = &engine.RawData{
251-
Input: decodedInput,
252-
Output: regoResultSetToRawResults(res),
253-
}
227+
result.RawData = rawData
254228
for _, exp := range res {
255229
for _, val := range exp.Expressions {
256230
ruleResult, ok := val.Value.(map[string]any)
@@ -295,6 +269,17 @@ func parseResultRule(res rego.ResultSet, policy *engine.Policy, decodedInput int
295269
return result, nil
296270
}
297271

272+
func queryRego(ctx context.Context, ruleName string, parsedModule *ast.Module, options ...func(r *rego.Rego)) (rego.ResultSet, error) {
273+
query := rego.Query(fmt.Sprintf("%v%s\n", parsedModule.Package.Path, ruleName))
274+
regoEval := rego.New(append(options, query)...)
275+
res, err := regoEval.Eval(ctx)
276+
if err != nil {
277+
return nil, fmt.Errorf("failed to evaluate policy: %w", err)
278+
}
279+
280+
return res, nil
281+
}
282+
298283
// Capabilities returns the capabilities of the environment based on the mode of operation
299284
// defaulting to EnvironmentModeRestrictive if not provided.
300285
func (r *Engine) Capabilities() *ast.Capabilities {

0 commit comments

Comments
 (0)