Skip to content

Commit 67c6b1d

Browse files
nikpivkinsimar7
andauthoredMay 7, 2024··
perf(misconf): parse rego input once (#6615)
Signed-off-by: Simar <[email protected]> Co-authored-by: Simar <[email protected]>
1 parent a2c522d commit 67c6b1d

File tree

2 files changed

+33
-10
lines changed

2 files changed

+33
-10
lines changed
 

‎pkg/iac/rego/exceptions.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package rego
33
import (
44
"context"
55
"fmt"
6+
7+
"github.com/open-policy-agent/opa/ast"
68
)
79

8-
func (s *Scanner) isIgnored(ctx context.Context, namespace, ruleName string, input interface{}) (bool, error) {
10+
func (s *Scanner) isIgnored(ctx context.Context, namespace, ruleName string, input ast.Value) (bool, error) {
911
if ignored, err := s.isNamespaceIgnored(ctx, namespace, input); err != nil {
1012
return false, err
1113
} else if ignored {
@@ -14,7 +16,7 @@ func (s *Scanner) isIgnored(ctx context.Context, namespace, ruleName string, inp
1416
return s.isRuleIgnored(ctx, namespace, ruleName, input)
1517
}
1618

17-
func (s *Scanner) isNamespaceIgnored(ctx context.Context, namespace string, input interface{}) (bool, error) {
19+
func (s *Scanner) isNamespaceIgnored(ctx context.Context, namespace string, input ast.Value) (bool, error) {
1820
exceptionQuery := fmt.Sprintf("data.namespace.exceptions.exception[_] == %q", namespace)
1921
result, _, err := s.runQuery(ctx, exceptionQuery, input, true)
2022
if err != nil {
@@ -23,7 +25,7 @@ func (s *Scanner) isNamespaceIgnored(ctx context.Context, namespace string, inpu
2325
return result.Allowed(), nil
2426
}
2527

26-
func (s *Scanner) isRuleIgnored(ctx context.Context, namespace, ruleName string, input interface{}) (bool, error) {
28+
func (s *Scanner) isRuleIgnored(ctx context.Context, namespace, ruleName string, input ast.Value) (bool, error) {
2729
exceptionQuery := fmt.Sprintf("endswith(%q, data.%s.exception[_][_])", ruleName, namespace)
2830
result, _, err := s.runQuery(ctx, exceptionQuery, input, true)
2931
if err != nil {

‎pkg/iac/rego/scanner.go

+28-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/open-policy-agent/opa/ast"
1414
"github.com/open-policy-agent/opa/rego"
1515
"github.com/open-policy-agent/opa/storage"
16+
"github.com/open-policy-agent/opa/util"
1617

1718
"github.com/aquasecurity/trivy/pkg/iac/debug"
1819
"github.com/aquasecurity/trivy/pkg/iac/framework"
@@ -161,7 +162,7 @@ func (s *Scanner) SetParentDebugLogger(l debug.Logger) {
161162
s.debug = l.Extend("rego")
162163
}
163164

164-
func (s *Scanner) runQuery(ctx context.Context, query string, input interface{}, disableTracing bool) (rego.ResultSet, []string, error) {
165+
func (s *Scanner) runQuery(ctx context.Context, query string, input ast.Value, disableTracing bool) (rego.ResultSet, []string, error) {
165166

166167
trace := (s.traceWriter != nil || s.tracePerResult) && !disableTracing
167168

@@ -180,7 +181,7 @@ func (s *Scanner) runQuery(ctx context.Context, query string, input interface{},
180181
}
181182

182183
if input != nil {
183-
regoOptions = append(regoOptions, rego.Input(input))
184+
regoOptions = append(regoOptions, rego.ParsedInput(input))
184185
}
185186

186187
instance := rego.New(regoOptions...)
@@ -342,6 +343,14 @@ func isPolicyApplicable(staticMetadata *StaticMetadata, inputs ...Input) bool {
342343
return false
343344
}
344345

346+
func parseRawInput(input any) (ast.Value, error) {
347+
if err := util.RoundTrip(&input); err != nil {
348+
return nil, err
349+
}
350+
351+
return ast.InterfaceToValue(input)
352+
}
353+
345354
func (s *Scanner) applyRule(ctx context.Context, namespace, rule string, inputs []Input, combined bool) (scan.Results, error) {
346355

347356
// handle combined evaluations if possible
@@ -354,7 +363,12 @@ func (s *Scanner) applyRule(ctx context.Context, namespace, rule string, inputs
354363
qualified := fmt.Sprintf("data.%s.%s", namespace, rule)
355364
for _, input := range inputs {
356365
s.trace("INPUT", input)
357-
if ignored, err := s.isIgnored(ctx, namespace, rule, input.Contents); err != nil {
366+
parsedInput, err := parseRawInput(input.Contents)
367+
if err != nil {
368+
s.debug.Log("Error occurred while parsing input: %s", err)
369+
continue
370+
}
371+
if ignored, err := s.isIgnored(ctx, namespace, rule, parsedInput); err != nil {
358372
return nil, err
359373
} else if ignored {
360374
var result regoResult
@@ -364,7 +378,7 @@ func (s *Scanner) applyRule(ctx context.Context, namespace, rule string, inputs
364378
results.AddIgnored(result)
365379
continue
366380
}
367-
set, traces, err := s.runQuery(ctx, qualified, input.Contents, false)
381+
set, traces, err := s.runQuery(ctx, qualified, parsedInput, false)
368382
if err != nil {
369383
return nil, err
370384
}
@@ -388,9 +402,15 @@ func (s *Scanner) applyRuleCombined(ctx context.Context, namespace, rule string,
388402
if len(inputs) == 0 {
389403
return nil, nil
390404
}
405+
406+
parsed, err := parseRawInput(inputs)
407+
if err != nil {
408+
return nil, fmt.Errorf("failed to parse input: %w", err)
409+
}
410+
391411
var results scan.Results
392-
qualified := fmt.Sprintf("data.%s.%s", namespace, rule)
393-
if ignored, err := s.isIgnored(ctx, namespace, rule, inputs); err != nil {
412+
413+
if ignored, err := s.isIgnored(ctx, namespace, rule, parsed); err != nil {
394414
return nil, err
395415
} else if ignored {
396416
for _, input := range inputs {
@@ -402,7 +422,8 @@ func (s *Scanner) applyRuleCombined(ctx context.Context, namespace, rule string,
402422
}
403423
return results, nil
404424
}
405-
set, traces, err := s.runQuery(ctx, qualified, inputs, false)
425+
qualified := fmt.Sprintf("data.%s.%s", namespace, rule)
426+
set, traces, err := s.runQuery(ctx, qualified, parsed, false)
406427
if err != nil {
407428
return nil, err
408429
}

0 commit comments

Comments
 (0)
Please sign in to comment.