Skip to content

Commit 890a360

Browse files
nikpivkinsimar7
andauthored
feat(misconf): add option to pass Rego scanner to IaC scanner (#8369)
Signed-off-by: nikpivkin <[email protected]> Co-authored-by: simar7 <[email protected]> Co-authored-by: Simar <[email protected]>
1 parent ad1c379 commit 890a360

File tree

12 files changed

+156
-154
lines changed

12 files changed

+156
-154
lines changed

pkg/commands/artifact/run.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ func initMisconfScannerOption(ctx context.Context, opts flag.Options) (misconf.S
662662
return misconf.ScannerOption{}, xerrors.Errorf("load schemas error: %w", err)
663663
}
664664

665-
return misconf.ScannerOption{
665+
misconfOpts := misconf.ScannerOption{
666666
Trace: opts.Trace,
667667
Namespaces: append(opts.CheckNamespaces, rego.BuiltinNamespaces()...),
668668
PolicyPaths: policyPaths,
@@ -684,5 +684,13 @@ func initMisconfScannerOption(ctx context.Context, opts flag.Options) (misconf.S
684684
ConfigFileSchemas: configSchemas,
685685
SkipFiles: opts.SkipFiles,
686686
SkipDirs: opts.SkipDirs,
687-
}, nil
687+
}
688+
689+
regoScanner, err := misconf.InitRegoScanner(misconfOpts)
690+
if err != nil {
691+
return misconf.ScannerOption{}, xerrors.Errorf("init Rego scanner: %w", err)
692+
}
693+
694+
misconfOpts.RegoScanner = regoScanner
695+
return misconfOpts, nil
688696
}

pkg/iac/rego/provider.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package rego
2+
3+
import (
4+
"fmt"
5+
"io/fs"
6+
"sync"
7+
8+
"github.com/aquasecurity/trivy/pkg/iac/scanners/options"
9+
)
10+
11+
func WithRegoScanner(rs *Scanner) options.ScannerOption {
12+
return func(s options.ConfigurableScanner) {
13+
if ss, ok := s.(*RegoScannerProvider); ok {
14+
ss.regoScanner = rs
15+
}
16+
}
17+
}
18+
19+
type RegoScannerProvider struct {
20+
mu sync.Mutex
21+
regoScanner *Scanner
22+
}
23+
24+
func NewRegoScannerProvider(opts ...options.ScannerOption) *RegoScannerProvider {
25+
s := &RegoScannerProvider{}
26+
for _, o := range opts {
27+
o(s)
28+
}
29+
return s
30+
}
31+
32+
func (s *RegoScannerProvider) InitRegoScanner(fsys fs.FS, opts []options.ScannerOption) (*Scanner, error) {
33+
s.mu.Lock()
34+
defer s.mu.Unlock()
35+
if s.regoScanner != nil {
36+
return s.regoScanner, nil
37+
}
38+
s.regoScanner = NewScanner(opts...)
39+
if err := s.regoScanner.LoadPolicies(fsys); err != nil {
40+
return nil, fmt.Errorf("load checks: %w", err)
41+
}
42+
return s.regoScanner, nil
43+
}

pkg/iac/scanners/azure/arm/scanner.go

+14-32
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66
"io/fs"
7-
"sync"
87

98
"github.com/aquasecurity/trivy/pkg/iac/adapters/arm"
109
"github.com/aquasecurity/trivy/pkg/iac/rego"
@@ -13,7 +12,6 @@ import (
1312
"github.com/aquasecurity/trivy/pkg/iac/scanners/azure"
1413
"github.com/aquasecurity/trivy/pkg/iac/scanners/azure/arm/parser"
1514
"github.com/aquasecurity/trivy/pkg/iac/scanners/options"
16-
"github.com/aquasecurity/trivy/pkg/iac/state"
1715
"github.com/aquasecurity/trivy/pkg/iac/types"
1816
"github.com/aquasecurity/trivy/pkg/log"
1917
)
@@ -22,16 +20,16 @@ var _ scanners.FSScanner = (*Scanner)(nil)
2220
var _ options.ConfigurableScanner = (*Scanner)(nil)
2321

2422
type Scanner struct {
25-
mu sync.Mutex
26-
scannerOptions []options.ScannerOption
27-
logger *log.Logger
28-
regoScanner *rego.Scanner
23+
*rego.RegoScannerProvider
24+
opts []options.ScannerOption
25+
logger *log.Logger
2926
}
3027

3128
func New(opts ...options.ScannerOption) *Scanner {
3229
scanner := &Scanner{
33-
scannerOptions: opts,
34-
logger: log.WithPrefix("azure-arm"),
30+
RegoScannerProvider: rego.NewRegoScannerProvider(opts...),
31+
opts: opts,
32+
logger: log.WithPrefix("azure-arm"),
3533
}
3634
for _, opt := range opts {
3735
opt(scanner)
@@ -43,29 +41,12 @@ func (s *Scanner) Name() string {
4341
return "Azure ARM"
4442
}
4543

46-
func (s *Scanner) initRegoScanner(srcFS fs.FS) error {
47-
s.mu.Lock()
48-
defer s.mu.Unlock()
49-
if s.regoScanner != nil {
50-
return nil
51-
}
52-
regoScanner := rego.NewScanner(s.scannerOptions...)
53-
if err := regoScanner.LoadPolicies(srcFS); err != nil {
54-
return err
55-
}
56-
s.regoScanner = regoScanner
57-
return nil
58-
}
59-
6044
func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (scan.Results, error) {
6145
p := parser.New(fsys)
6246
deployments, err := p.ParseFS(ctx, dir)
6347
if err != nil {
6448
return nil, err
6549
}
66-
if err := s.initRegoScanner(fsys); err != nil {
67-
return nil, err
68-
}
6950

7051
return s.scanDeployments(ctx, deployments, fsys)
7152
}
@@ -87,20 +68,21 @@ func (s *Scanner) scanDeployments(ctx context.Context, deployments []azure.Deplo
8768
}
8869

8970
func (s *Scanner) scanDeployment(ctx context.Context, deployment azure.Deployment, fsys fs.FS) (scan.Results, error) {
90-
deploymentState := s.adaptDeployment(ctx, deployment)
71+
state := arm.Adapt(ctx, deployment)
9172

92-
results, err := s.regoScanner.ScanInput(ctx, types.SourceCloud, rego.Input{
73+
rs, err := s.InitRegoScanner(fsys, s.opts)
74+
if err != nil {
75+
return nil, fmt.Errorf("init rego scanner: %w", err)
76+
}
77+
78+
results, err := rs.ScanInput(ctx, types.SourceCloud, rego.Input{
9379
Path: deployment.Metadata.Range().GetFilename(),
9480
FS: fsys,
95-
Contents: deploymentState.ToRego(),
81+
Contents: state.ToRego(),
9682
})
9783
if err != nil {
9884
return nil, fmt.Errorf("rego scan error: %w", err)
9985
}
10086

10187
return results, nil
10288
}
103-
104-
func (s *Scanner) adaptDeployment(ctx context.Context, deployment azure.Deployment) *state.State {
105-
return arm.Adapt(ctx, deployment)
106-
}

pkg/iac/scanners/cloudformation/scanner.go

+10-25
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"io/fs"
77
"sort"
8-
"sync"
98

109
adapter "github.com/aquasecurity/trivy/pkg/iac/adapters/cloudformation"
1110
"github.com/aquasecurity/trivy/pkg/iac/rego"
@@ -45,10 +44,9 @@ var _ scanners.FSScanner = (*Scanner)(nil)
4544
var _ options.ConfigurableScanner = (*Scanner)(nil)
4645

4746
type Scanner struct {
48-
mu sync.Mutex
47+
*rego.RegoScannerProvider
4948
logger *log.Logger
5049
parser *parser.Parser
51-
regoScanner *rego.Scanner
5250
options []options.ScannerOption
5351
parserOptions []parser.Option
5452
}
@@ -64,8 +62,9 @@ func (s *Scanner) Name() string {
6462
// New creates a new Scanner
6563
func New(opts ...options.ScannerOption) *Scanner {
6664
s := &Scanner{
67-
options: opts,
68-
logger: log.WithPrefix("cloudformation scanner"),
65+
RegoScannerProvider: rego.NewRegoScannerProvider(opts...),
66+
options: opts,
67+
logger: log.WithPrefix("cloudformation scanner"),
6968
}
7069
for _, opt := range opts {
7170
opt(s)
@@ -74,20 +73,6 @@ func New(opts ...options.ScannerOption) *Scanner {
7473
return s
7574
}
7675

77-
func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) {
78-
s.mu.Lock()
79-
defer s.mu.Unlock()
80-
if s.regoScanner != nil {
81-
return s.regoScanner, nil
82-
}
83-
regoScanner := rego.NewScanner(s.options...)
84-
if err := regoScanner.LoadPolicies(srcFS); err != nil {
85-
return nil, err
86-
}
87-
s.regoScanner = regoScanner
88-
return regoScanner, nil
89-
}
90-
9176
func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (results scan.Results, err error) {
9277

9378
contexts, err := s.parser.ParseFS(ctx, fsys, dir)
@@ -99,16 +84,16 @@ func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (results s
9984
return nil, nil
10085
}
10186

102-
regoScanner, err := s.initRegoScanner(fsys)
87+
rs, err := s.InitRegoScanner(fsys, s.options)
10388
if err != nil {
104-
return nil, err
89+
return nil, fmt.Errorf("init rego scanner: %w", err)
10590
}
10691

10792
for _, cfCtx := range contexts {
10893
if cfCtx == nil {
10994
continue
11095
}
111-
fileResults, err := s.scanFileContext(ctx, regoScanner, cfCtx, fsys)
96+
fileResults, err := s.scanFileContext(ctx, rs, cfCtx, fsys)
11297
if err != nil {
11398
return nil, err
11499
}
@@ -127,12 +112,12 @@ func (s *Scanner) ScanFile(ctx context.Context, fsys fs.FS, path string) (scan.R
127112
return nil, err
128113
}
129114

130-
regoScanner, err := s.initRegoScanner(fsys)
115+
rs, err := s.InitRegoScanner(fsys, s.options)
131116
if err != nil {
132-
return nil, err
117+
return nil, fmt.Errorf("init rego scanner: %w", err)
133118
}
134119

135-
results, err := s.scanFileContext(ctx, regoScanner, cfCtx, fsys)
120+
results, err := s.scanFileContext(ctx, rs, cfCtx, fsys)
136121
if err != nil {
137122
return nil, err
138123
}

pkg/iac/scanners/dockerfile/scanner_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ COPY --from=dep /binary /`
572572

573573
results, err := scanner.ScanFS(t.Context(), fsys, "code")
574574
if tc.expectedError != "" && err != nil {
575-
require.Equal(t, tc.expectedError, err.Error(), tc.name)
575+
require.ErrorContainsf(t, err, tc.expectedError, tc.name)
576576
} else {
577577
require.NoError(t, err)
578578
require.Len(t, results.GetFailed(), 1)

pkg/iac/scanners/generic/scanner.go

+14-29
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"io/fs"
1010
"path/filepath"
1111
"strings"
12-
"sync"
1312

1413
"github.com/BurntSushi/toml"
1514
"github.com/samber/lo"
@@ -41,12 +40,11 @@ type configParser interface {
4140

4241
// GenericScanner is a scanner that scans a file as is without processing it
4342
type GenericScanner struct {
44-
mu sync.Mutex
45-
name string
46-
source types.Source
47-
logger *log.Logger
48-
options []options.ScannerOption
49-
regoScanner *rego.Scanner
43+
*rego.RegoScannerProvider
44+
name string
45+
source types.Source
46+
logger *log.Logger
47+
options []options.ScannerOption
5048

5149
parser configParser
5250
}
@@ -59,11 +57,12 @@ func (f ParseFunc) Parse(ctx context.Context, r io.Reader, path string) (any, er
5957

6058
func NewScanner(name string, source types.Source, parser configParser, opts ...options.ScannerOption) *GenericScanner {
6159
s := &GenericScanner{
62-
name: name,
63-
options: opts,
64-
source: source,
65-
logger: log.WithPrefix(fmt.Sprintf("%s scanner", source)),
66-
parser: parser,
60+
RegoScannerProvider: rego.NewRegoScannerProvider(opts...),
61+
name: name,
62+
options: opts,
63+
source: source,
64+
logger: log.WithPrefix(fmt.Sprintf("%s scanner", source)),
65+
parser: parser,
6766
}
6867

6968
for _, opt := range opts {
@@ -113,13 +112,13 @@ func (s *GenericScanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (sc
113112
}
114113
}
115114

116-
regoScanner, err := s.initRegoScanner(fsys)
115+
rs, err := s.InitRegoScanner(fsys, s.options)
117116
if err != nil {
118-
return nil, err
117+
return nil, fmt.Errorf("init rego scanner: %w", err)
119118
}
120119

121120
s.logger.Debug("Scanning files...", log.Int("count", len(inputs)))
122-
results, err := regoScanner.ScanInput(ctx, s.source, inputs...)
121+
results, err := rs.ScanInput(ctx, s.source, inputs...)
123122
if err != nil {
124123
return nil, err
125124
}
@@ -170,20 +169,6 @@ func (s *GenericScanner) parseFS(ctx context.Context, fsys fs.FS, path string) (
170169
return files, nil
171170
}
172171

173-
func (s *GenericScanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) {
174-
s.mu.Lock()
175-
defer s.mu.Unlock()
176-
if s.regoScanner != nil {
177-
return s.regoScanner, nil
178-
}
179-
regoScanner := rego.NewScanner(s.options...)
180-
if err := regoScanner.LoadPolicies(srcFS); err != nil {
181-
return nil, err
182-
}
183-
s.regoScanner = regoScanner
184-
return regoScanner, nil
185-
}
186-
187172
func (s *GenericScanner) applyIgnoreRules(fsys fs.FS, results scan.Results) error {
188173
if !s.supportsIgnoreRules() {
189174
return nil

0 commit comments

Comments
 (0)